HLS编程入门

2021/5/22 20:29:16

本文主要是介绍HLS编程入门,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • 一、HLS简介
  • 二、入门级HLS程序(点亮led灯)
    • (一)仿真
    • (二)烧录

一、HLS简介

HLS是高层综合(High level Synthesis)
是将C或者c++语言编译为FPGA能够读懂和运行的RTL级别的语言
与VHDL或者verilog的比较
优点:用高级语言完成期望在硬件电路上实现的功能,更加抽象和容易实现。
缺点:尽管是用高级语言描述实现在硬件电路上实现功能,但会有很多限制,例如动态分配内存等函数或定义的禁用,也有很多不足,例如循环的优化始终是个大难题。
HLS关键技术
1、将高级语言转化为RTL电路
2、循环优化,并行处理

二、入门级HLS程序(点亮led灯)

(一)仿真

环境: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_FLAGled_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等



这篇关于HLS编程入门的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程