HLS入门实践

vivado和谐教程:

https://www.bilibili.com/read/cv15414254/

Vivado 2018.3 软件及license的下载地址:

链接:https://pan.baidu.com/s/1jkurhTLgnxavgRnmi-JLDA

提取码:sygh 作者:不吃葱的酸菜鱼 https://www.bilibili.com/read/cv15414254/
出处:bilibili

1. HLS是什么?与VHDL/Verilog编程技术有什么关系?

HLS是高层次综合的缩写,它是一种将高级语言(比如C/C++)描述的算法转换成数字电路的技术。在HLS中,用户可以使用高级语言描述其算法,然后自动将其转换成数字电路的形式。

VHDL和Verilog是用于数字电路描述的硬件语言,与HLS的关系是,HLS将高级语言转化为数字电路,而VHDL和Verilog则是直接用于数字电路的描述语言。在设计数字电路时,HLS可以作为一种辅助工具来快速设计和验证数字电路,而VHDL和Verilog则更为底层,需要对硬件的细节有深入的理解。

2. HLS有哪些关键技术问题?目前存在什么技术局限性?

HLS的关键技术问题包括算法建模、数据通路优化、资源分配和调度、存储器管理、高速数字信号处理等方面。具体来说,主要有以下几个方面:

高级语言到硬件描述语言的转换算法:实现从高级语言到硬件描述语言的自动转换算法是HLS的核心技术之一。

数据通路的优化:通过对数据通路的优化,可以实现更高效、更紧凑的电路设计。

资源分配和调度:资源分配和调度是为了最大化利用FPGA资源,并且实现设计的最佳性能。

存储器管理:在HLS设计中存储器多用于线缓存、阵列乘法器和存储器控制器等,因此存储器管理也是HLS关键技术之一。

目前,HLS存在一些技术局限性,如下所示:

1.HLS编译过程需要消耗大量时间,特别是当需要与其他工具集成时。

2.HLS可能会在代码优化、资源利用和平衡上存在问题,使得生成的电路并不是最优的。
HLS需要较高的掌握门槛,需要熟练掌握硬件描述语言和计算机体系结构,才能达到最佳效果。

3.HLS的使用场景还比较有限,在一些对性能、资源需求高的场景下,仍然需要手动编写硬件描述语言来实现最优电路设计。

3. 在win10(或者Ubuntu系统下)安装 Intel 或者 Xilinx 的支持HLS的FPGA编程开发软件(Quartus18或者Vivado18),设置好环境,完成一个入门级的HLS程序,并进行仿真或者实际开发板运行。

1:HLS工程建立
打开 Vivado HLS 开发工具, 单击 Creat New Project 创建一个新工程, 设置好工程路径和工程名, 一直点击 Next 按照默认设置

请添加图片描述
请添加图片描述
请添加图片描述
出现如下图所示界面,时钟周期 Clock Period 按照默认 10ns,Uncertaintly 和 Solution
Name 均按照默认设置, 点击红色圆圈部分选择芯片类型, 然后点击 OK。下图示是选择好后的界面。
请添加图片描述

请添加图片描述
工程建立完后的界面是这样的。下面就是导入工程里用到的源文件。
需要在工程添加3个源文件。都可以在文件开头介绍的下载地址下载。右键点击source , Add Files 分别添加shift_led.cpp 和 shift_led.h。 右键点击Test Bench , Add Files 添加Test_shift_led.cpp.请添加图片描述
shift_led.h代码:

#ifndef _SHIFT_LED_H_
#define _SHIFT_LED_H_
//
#include "ap_int.h"
//#define MAX_CNT 10000/2  //仿真时可以用这个代替下面的行介绍仿真等待时间
#define MAX_CNT 100000000/2
#define SHIFT_FLAG  MAX_CNT-2

//typedef int led_t;
typedef ap_fixed<4,4> led_t; // 1st: total width. 2nd: integer width
void shift_led(led_t *led_o,led_t led_i);
#endif

shift_led.cpp

#include "shift_led.h"
void shift_led(led_t *led_o,led_t led_i)
{
#pragma HLS INTERFACE ap_vld port=led_i
#pragma HLS INTERFACE ap_ovld port=led_o
    led_t tmp_led=led_i;
    int i;    //for cycle variables
    for(i = 0;i < MAX_CNT;i++)
    {
        if(i==SHIFT_FLAG)
        {
            //tmp_led = ((tmp_led>>7)&0x01) + ((tmp_led<<1)&0xFE);//left shift 8
            tmp_led = ((tmp_led>>4)&0x01) + ((tmp_led<<1)&0xFE);//left shift 4
            *led_o = tmp_led;
        }
    }
}

Test_shift.led.cpp

#include "shift_led.h"
#include <stdio.h>

using namespace std;
int main()
{
    led_t led_o;
    led_t led_i=0xfe;
    const int SHIFT_TIME =8 ;
    int i;
    for(i=0;i<SHIFT_TIME;i++)
    {
        shift_led(&led_o,led_i);
        led_i = led_o;
        char string[25];
        itoa((unsigned int)led_o & 0xf,string,2);
        fprintf(stdout,"shift_out=%s\n",string);
    }
}

2:工程综合

工程综合前,需要设置 Top Function。

点击 Project-> Project Settings
出现如下界面 ,在Syntheses 界面下选择综合的顶层函数名。
请添加图片描述
请添加图片描述
因为当前工程中只存在一个Solution, 我们选择Solution ->Run C Sytheses -> Active Solutions 进行综合,菜单旁有个快捷键的图标,所以也有快捷可以直接点取
3: 优化和添加约束

在原文中, led_t tmp_led=led_i; 最开始是int , 然后把他定义为4位整数。我这里一开始就是这样,也就没有什么优化了。

但这里做一下他的约束添加,或者也是优化的内容。

在主页面里,点击如下3出红箭,如果不是这个界面。选择文件 shift_led.cpp 文件, 选择 synthesis, 选择 directive。
请添加图片描述

请添加图片描述
请添加图片描述
3: 仿真实现

菜单Project -> Run C Simulation 或者点击快捷键(看菜单旁图示),就开始 C 仿真
仿真运行的情况是这样的:
请添加图片描述
波形仿真
请添加图片描述
请添加图片描述
5: HLS代码封装

通过前面的实验,我们进行了HLS的工程创建,仿真,但这只是把算法实现从C 到RTL的转换。下面我们开始把其打包成IP, 在硬件平台上进行测试,也方便Vivado 进行调用,应用。

菜单 Solution -> Export RTL 也可以点快捷(菜单图示)。
请添加图片描述
请添加图片描述
点击2次OK 之后,就开始IP 打包封装。

运行结束后,就在solution1 目录下多了一个impl 文件夹,并且在0等待一段时间后在 solution1 目录下多了一个 impl 文件夹, 并且在ip 文件夹中生成了一个压缩包,这就是我们需要的打包好的IP。
shift_led.v 的代码如下:

// ==============================================================
// RTL generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC
// Version: 2018.3
// Copyright (C) 1986-2018 Xilinx, Inc. All Rights Reserved.
// 
// ===========================================================

`timescale 1 ns / 1 ps 

(* CORE_GENERATION_INFO="shift_led,hls_ip_2018_3,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=1,HLS_INPUT_PART=xc7z010clg400-2,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=1.988500,HLS_SYN_LAT=50000001,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=32,HLS_SYN_LUT=57,HLS_VERSION=2018_3}" *)

module shift_led (
        ap_clk,
        ap_rst,
        ap_start,
        ap_done,
        ap_idle,
        ap_ready,
        led_o_V,
        led_o_V_ap_vld,
        led_i_V
);

parameter    ap_ST_fsm_state1 = 2'd1;
parameter    ap_ST_fsm_state2 = 2'd2;

input   ap_clk;
input   ap_rst;
input   ap_start;
output   ap_done;
output   ap_idle;
output   ap_ready;
output  [3:0] led_o_V;
output   led_o_V_ap_vld;
input  [3:0] led_i_V;

reg ap_done;
reg ap_idle;
reg ap_ready;
reg led_o_V_ap_vld;

(* fsm_encoding = "none" *) reg   [1:0] ap_CS_fsm;
wire    ap_CS_fsm_state1;
wire   [25:0] i_1_fu_73_p2;
wire    ap_CS_fsm_state2;
reg   [25:0] i_reg_51;
wire   [0:0] exitcond_fu_67_p2;
reg   [3:0] tmp_led_V_1_fu_34;
wire   [3:0] tmp_led_V_fu_100_p3;
wire   [0:0] tmp_fu_79_p2;
wire   [2:0] tmp_2_fu_96_p1;
wire   [0:0] tmp_1_fu_88_p3;
reg   [1:0] ap_NS_fsm;

// power-on initialization
initial begin
#0 ap_CS_fsm = 2'd1;
end

always @ (posedge ap_clk) begin
    if (ap_rst == 1'b1) begin
        ap_CS_fsm <= ap_ST_fsm_state1;
    end else begin
        ap_CS_fsm <= ap_NS_fsm;
    end
end

always @ (posedge ap_clk) begin
    if (((exitcond_fu_67_p2 == 1'd0) & (1'b1 == ap_CS_fsm_state2))) begin
        i_reg_51 <= i_1_fu_73_p2;
    end else if (((ap_start == 1'b1) & (1'b1 == ap_CS_fsm_state1))) begin
        i_reg_51 <= 26'd0;
    end
end

always @ (posedge ap_clk) begin
    if (((tmp_fu_79_p2 == 1'd1) & (exitcond_fu_67_p2 == 1'd0) & (1'b1 == ap_CS_fsm_state2))) begin
        tmp_led_V_1_fu_34 <= tmp_led_V_fu_100_p3;
    end else if (((ap_start == 1'b1) & (1'b1 == ap_CS_fsm_state1))) begin
        tmp_led_V_1_fu_34 <= led_i_V;
    end
end

always @ (*) begin
    if (((exitcond_fu_67_p2 == 1'd1) & (1'b1 == ap_CS_fsm_state2))) begin
        ap_done = 1'b1;
    end else begin
        ap_done = 1'b0;
    end
end

always @ (*) begin
    if (((ap_start == 1'b0) & (1'b1 == ap_CS_fsm_state1))) begin
        ap_idle = 1'b1;
    end else begin
        ap_idle = 1'b0;
    end
end

always @ (*) begin
    if (((exitcond_fu_67_p2 == 1'd1) & (1'b1 == ap_CS_fsm_state2))) begin
        ap_ready = 1'b1;
    end else begin
        ap_ready = 1'b0;
    end
end

always @ (*) begin
    if (((tmp_fu_79_p2 == 1'd1) & (exitcond_fu_67_p2 == 1'd0) & (1'b1 == ap_CS_fsm_state2))) begin
        led_o_V_ap_vld = 1'b1;
    end else begin
        led_o_V_ap_vld = 1'b0;
    end
end

always @ (*) begin
    case (ap_CS_fsm)
        ap_ST_fsm_state1 : begin
            if (((ap_start == 1'b1) & (1'b1 == ap_CS_fsm_state1))) begin
                ap_NS_fsm = ap_ST_fsm_state2;
            end else begin
                ap_NS_fsm = ap_ST_fsm_state1;
            end
        end
        ap_ST_fsm_state2 : begin
            if (((exitcond_fu_67_p2 == 1'd1) & (1'b1 == ap_CS_fsm_state2))) begin
                ap_NS_fsm = ap_ST_fsm_state1;
            end else begin
                ap_NS_fsm = ap_ST_fsm_state2;
            end
        end
        default : begin
            ap_NS_fsm = 'bx;
        end
    endcase
end

assign ap_CS_fsm_state1 = ap_CS_fsm[32'd0];

assign ap_CS_fsm_state2 = ap_CS_fsm[32'd1];

assign exitcond_fu_67_p2 = ((i_reg_51 == 26'd50000000) ? 1'b1 : 1'b0);

assign i_1_fu_73_p2 = (i_reg_51 + 26'd1);

assign led_o_V = {{tmp_2_fu_96_p1}, {tmp_1_fu_88_p3}};

assign tmp_1_fu_88_p3 = tmp_led_V_1_fu_34[32'd3];

assign tmp_2_fu_96_p1 = tmp_led_V_1_fu_34[2:0];

assign tmp_fu_79_p2 = ((i_reg_51 == 26'd49999998) ? 1'b1 : 1'b0);

assign tmp_led_V_fu_100_p3 = {{tmp_2_fu_96_p1}, {tmp_1_fu_88_p3}};

endmodule //shift_led

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值