HLS是高层综合(High level Synthesis)
是将C或者c++语言编译为FPGA能够读懂和运行的RTL级别的语言
与VHDL或者verilog的比较
优点:用高级语言完成期望在硬件电路上实现的功能,更加抽象和容易实现。
缺点:尽管是用高级语言描述实现在硬件电路上实现功能,但会有很多限制,例如动态分配内存等函数或定义的禁用,也有很多不足,例如循环的优化始终是个大难题。
HLS关键技术
1、将高级语言转化为RTL电路
2、循环优化,并行处理
环境:xilinx20.2
板子: Z7-Lite7020
1、新建工程
选择定成函数 这里直接next
添加c仿真文件,testbench文件,next
这里选择xc7z020clg400-2,对应Z7-Lite7020
新建工程完成页面
2、添加源文件
同样方法添加头文件
led.h代码
#ifndef _SHIFT_LED_H_ #define _SHIFT_LED_H_ #define CNT_MAX 100000000 //#define CNT_MAX 100 #define FLASH_FLAG CNT_MAX-2 typedef int led_t; typedef int cnt_t; void flash_led(led_t *led_o , led_t led_i); #endif
其中计数最大值 CNT_MAX 100000000
是在 100M 时钟频率下计数一秒钟所需要的计数次数
FLASH_FLAG
是 LED 闪烁的标志,当计数到该值
时,LED 发生变化
flash_led
是该工程需要设计的定成函数
后续优化代码
led.h
#ifndef _SHIFT_LED_H_ #define _SHIFT_LED_H_ #include "ap_int.h" #define CNT_MAX 100000000 //#define CNT_MAX 100 #define FLASH_FLAG CNT_MAX-2 //typedef int led_t; //typedef int cnt_t; typedef ap_int<1>led_t; typedef ap_int<32>cnt_t; void flash_led(led_t *led_o , led_t led_i); #endif
led.h代码
#include "led.h" void flash_led(led_t *led_o , led_t led_i){ cnt_t i; for(i=0;i<CNT_MAX;i++){ if(i==FLASH_FLAG){ *led_o = ~led_i; } } }
变量 i 计数到 FLASH_FLAG
时 led_o
的状态发生变化
3、添加c仿真文件
test_led.cpp代码
#include "led.h" #include <stdio.h> int main(){ led_t led_i=0x01; led_t led_o; const int SHIFT_TIME = 4; int i; for(i=0;i<SHIFT_TIME;i++){ flash_led(&led_o , led_i); led_i = led_o; printf("shift_out is %d \n",(int)(led_o&0x01)); } }
后续优化设置
4、进行 C 仿真与 C 综合
选择 flash_led 作为顶层函数
c仿真
c仿真结果与预期相符
c综合
结果成功
Latency 指的是,设计电路完成一次任务需要的时间
Interval 指的是两次任务之间的时间间隔
FF触发器数量:62
LUT查找表数量:105
其余生成结果暂时不关注(因为的确不懂,这个工程也不需要关注)
联合仿真
和c仿真结果一致
1、导出 HLS 工程生成的 IP 核
不做改变,直接OK
导出的 IP 核将在 Solution 这个文件夹中可以找到
vivado工程导入ip
打开vivado,新建工程
添加ip
定位到solution
添加成功后应用
添加成功
在 IP Catalog 中选中由 HLS 生成的 IP,双击并生成该 IP
向工程中添加一个新的文件,用于完成本次实验
led.v是代码将生成的 HLS IP 例化进工程当中
// // Company: // Engineer: // // Create Date: 2021/05/22 14:40:22 // Design Name: // Module Name: led // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // `timescale 1ns / 1ps module flash_led( input wire clk , input wire rst_n , output wire led_o ); wire rst ;//同步复位 wire ap_ready ;//当前可以接收下一次数据 reg ap_start ;//IP 开始工作 reg led_i_vld ;//输入数据有效 wire led_o_vld ; reg led_i ;//输入的 led 信号 wire led_o_r ; wire ap_done ; wire ap_idle ; reg [1:0] delay_cnt ; assign rst = ~rst_n ; assign led_o = led_o_r ; //----------------delay_cnt------------------ always @(posedge clk) begin if (rst==1'b1) begin delay_cnt <= 'd0; end else if(delay_cnt[1]==1'b0) begin delay_cnt <= delay_cnt + 1'b1; end end //----------------ap_start------------------ always @(posedge clk) begin if (rst==1'b1) begin ap_start <= 1'b0; end else if(delay_cnt[1]==1'b1)begin ap_start <= 1'b1; end end //----------------led_i_vld------------------ always @(posedge clk) begin if (rst==1'b1) begin led_i_vld <= 1'b0; end else if(delay_cnt[1]==1'b1)begin led_i_vld <= 1'b1; end end //----------------ap_i------------------ always @(posedge clk) begin if (rst==1'b1) begin led_i <= 1'b0; end else if(led_o_vld==1'b1)begin led_i <= led_o_r ; end end flash_led_0 inst_flash_led ( .led_o_ap_vld(led_o_vld), // output wire led_o_V_ap_vld .led_i_ap_vld(led_i_vld), // input wire led_i_V_ap_vld .ap_clk(clk), // input wire ap_clk .ap_rst(rst), // input wire ap_rst .ap_start(ap_start), // input wire ap_start .ap_done(ap_done), // output wire ap_done .ap_idle(ap_idle), // output wire ap_idle .ap_ready(ap_ready), // output wire ap_ready .led_o_V(led_o_r), // output wire [0 : 0] led_o_V .led_i_V(led_i) // input wire [0 : 0] led_i_V ); endmodule
接下来是添加约束文件
top_pin.xdc
##############LED define################## set_property PACKAGE_PIN P15 [get_ports {led_o}] set_property IOSTANDARD LVCMOS33 [get_ports {led_o}] ##############Reset define################## set_property PACKAGE_PIN P16 [get_ports {rst_n}] set_property IOSTANDARD LVCMOS33 [get_ports {rst_n}] ##############50M CLK define################## create_clock -period 20.000 -name clk -waveform {0.000 10.000} [get_ports clk] set_property PACKAGE_PIN N18 [get_ports {clk}] set_property IOSTANDARD LVCMOS33 [get_ports {clk}]
添加ila观察中间过程
这个ip对应.v文件中的
生成bit流文件
完成后打开硬件烧录页面
将板子连接电脑,点击自动连接就会自动寻找已连接的板子
右键点击Program Device
这里就会自动将可烧录的程序填入,点击Program即可烧录
结果
视频太大 传不上来
总结:还是有很多没懂的操作,但大体做完后,对使用xilinx的hls的套路有了一定的了解,不会像没做之前完全抓瞎,至于原理部分,只能说少部分懂了,大部分还是该啥样就啥样。
学习来源:微相板子教程,包括视频,pdf等