vitis hls 初次使用

文章介绍了HLS(High-LevelSynthesis)技术,特别是Xilinx的VivadoHLS工具,如何将C/C++代码转换为Verilog硬件描述语言,以实现FPGA上的硬件加速。通过一个简单的流水灯项目示例,展示了从编写C代码、功能验证到生成RTL描述和Verilog文件的过程,以及进行RTL仿真以验证设计的正确性。
摘要由CSDN通过智能技术生成

hls简介

高级综合(high-level synthesis,简称 HLS)能自动把 C/C++ 之类的高级语言转化成 Verilog/VHDL 之类的底层硬件描述语言(RTL),生成定制硬件在 FPGA 上跑实现加速。这使得不懂硬件的软件工程师也可以拥有玩转硬件的能力。HLS 的存在已有多年,它的优点,极短的开发和验证时间
Xilinx 推出的 Vivado HLS 工具可以直接使用C、C++或 System C 来对 Xilinx 系列的 FPGA 进行编程,从而提高抽象的层级,大大减少了使用传统 RTL描述进行 FPGA 开发所需的时间。
在对 HLS 设计进行综合之前,我们要先对其进行“功能性验证”,也就是 C 仿真,其目的是验证 HLS 输入的 C 代码的功能是否正确。验证的方式就是在 TestBench 中调用 C 设计的函数,然后将其输出与“黄金参考”进行比对,如果与黄金参考有差异就需要先对 C 设计进行修改调试。

hls项目

接下来就是对设计进行高层综合,即 HLS 过程本身。该过程涉及到分析和处理基于 C 的代码,加上用户所给出的指令和约束,来创建 RTL 描述。高层综合结束后会产生一组输出文件,包括以 Veilog 或者VHDL 语言编写的 RTL 设计文件。
添加源文件:
在这里插入图片描述

示例代码

hls_hello.h:

#ifndef _HLS_HELLO_H_
#define _HLS_HELLO_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;
// 修改指定位宽,如果使用 int 则会默认使用 32 位宽,我们并不需要,所以选择自定义位宽
typedef 	ap_int<1> led_t;
typedef 	ap_int<32> cnt_t;
void flash_led(led_t *led_o , led_t led_i);
#endif

hls_hello.cpp:

#include "hls_hello.h"
void flash_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
	cnt_t i;
	for(i=0;i<CNT_MAX;i++){
//#pragma HLS PIPELINE
		if(i==FLASH_FLAG){
			*led_o = ~led_i;
		}
	}
}

添加测试文件:
在这里插入图片描述

选择开发板:
在这里插入图片描述
hls_hello_tb.cpp:

#include "hls_hello.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));
	}
}

project run c simulation
在这里插入图片描述
在这里插入图片描述
在设置里设置top function
在这里插入图片描述

solution,run c synthesis生成veriolg文件

在这里插入图片描述
在这里插入图片描述
这是生成的verilog文件:

// ==============================================================
// RTL generated by Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.2 (64-bit)
// Version: 2022.2
// Copyright (C) Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
// 
// ===========================================================

`timescale 1 ns / 1 ps 

(* CORE_GENERATION_INFO="flash_led_flash_led,hls_ip_2022_2,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0,HLS_INPUT_PART=xc7z020-clg400-2,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=3.265750,HLS_SYN_LAT=100000002,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=33,HLS_SYN_LUT=112,HLS_VERSION=2022_2}" *)

module flash_led (
        ap_clk,
        ap_rst,
        ap_start,
        ap_done,
        ap_idle,
        ap_ready,
        led_o,
        led_o_ap_vld,
        led_i,
        led_i_ap_vld
);

parameter    ap_ST_fsm_state1 = 3'd1;
parameter    ap_ST_fsm_state2 = 3'd2;
parameter    ap_ST_fsm_state3 = 3'd4;

input   ap_clk;
input   ap_rst;
input   ap_start;
output   ap_done;
output   ap_idle;
output   ap_ready;
output  [0:0] led_o;
output   led_o_ap_vld;
input  [0:0] led_i;
input   led_i_ap_vld;

reg ap_done;
reg ap_idle;
reg ap_ready;
reg led_o_ap_vld;

(* fsm_encoding = "none" *) reg   [2:0] ap_CS_fsm;
wire    ap_CS_fsm_state1;
reg   [0:0] led_i_preg;
reg   [0:0] led_i_in_sig;
reg    led_i_ap_vld_preg;
reg    led_i_ap_vld_in_sig;
reg    led_i_blk_n;
wire   [0:0] neg_i_fu_67_p2;
reg   [0:0] neg_i_reg_111;
reg   [26:0] i_V_fu_50;
wire   [26:0] i_V_2_fu_87_p2;
wire    ap_CS_fsm_state2;
wire   [0:0] icmp_ln1027_fu_81_p2;
reg    ap_block_state1;
wire   [0:0] icmp_ln1019_fu_93_p2;
wire    ap_CS_fsm_state3;
reg   [2:0] ap_NS_fsm;
reg    ap_ST_fsm_state1_blk;
wire    ap_ST_fsm_state2_blk;
wire    ap_ST_fsm_state3_blk;
wire    ap_ce_reg;

// power-on initialization
initial begin
#0 ap_CS_fsm = 3'd1;
#0 led_i_preg = 1'd0;
#0 led_i_ap_vld_preg = 1'b0;
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 (ap_rst == 1'b1) begin
        led_i_ap_vld_preg <= 1'b0;
    end else begin
        if ((1'b1 == ap_CS_fsm_state3)) begin
            led_i_ap_vld_preg <= 1'b0;
        end else if ((~((ap_start == 1'b0) & (1'b1 == ap_CS_fsm_state1)) & (led_i_ap_vld == 1'b1))) begin
            led_i_ap_vld_preg <= led_i_ap_vld;
        end
    end
end

always @ (posedge ap_clk) begin
    if (ap_rst == 1'b1) begin
        led_i_preg <= 1'd0;
    end else begin
        if ((~((ap_start == 1'b0) & (1'b1 == ap_CS_fsm_state1)) & (led_i_ap_vld == 1'b1))) begin
            led_i_preg <= led_i;
        end
    end
end

always @ (posedge ap_clk) begin
    if ((~((ap_start == 1'b0) | (led_i_ap_vld_in_sig == 1'b0)) & (1'b1 == ap_CS_fsm_state1))) begin
        i_V_fu_50 <= 27'd0;
    end else if (((icmp_ln1027_fu_81_p2 == 1'd0) & (1'b1 == ap_CS_fsm_state2))) begin
        i_V_fu_50 <= i_V_2_fu_87_p2;
    end
end

always @ (posedge ap_clk) begin
    if ((1'b1 == ap_CS_fsm_state1)) begin
        neg_i_reg_111 <= neg_i_fu_67_p2;
    end
end

always @ (*) begin
    if (((ap_start == 1'b0) | (led_i_ap_vld_in_sig == 1'b0))) begin
        ap_ST_fsm_state1_blk = 1'b1;
    end else begin
        ap_ST_fsm_state1_blk = 1'b0;
    end
end

assign ap_ST_fsm_state2_blk = 1'b0;

assign ap_ST_fsm_state3_blk = 1'b0;

always @ (*) begin
    if ((1'b1 == ap_CS_fsm_state3)) 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 ((1'b1 == ap_CS_fsm_state3)) begin
        ap_ready = 1'b1;
    end else begin
        ap_ready = 1'b0;
    end
end

always @ (*) begin
    if ((led_i_ap_vld == 1'b1)) begin
        led_i_ap_vld_in_sig = led_i_ap_vld;
    end else begin
        led_i_ap_vld_in_sig = led_i_ap_vld_preg;
    end
end

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

always @ (*) begin
    if ((led_i_ap_vld == 1'b1)) begin
        led_i_in_sig = led_i;
    end else begin
        led_i_in_sig = led_i_preg;
    end
end

always @ (*) begin
    if (((icmp_ln1019_fu_93_p2 == 1'd1) & (icmp_ln1027_fu_81_p2 == 1'd0) & (1'b1 == ap_CS_fsm_state2))) begin
        led_o_ap_vld = 1'b1;
    end else begin
        led_o_ap_vld = 1'b0;
    end
end

always @ (*) begin
    case (ap_CS_fsm)
        ap_ST_fsm_state1 : begin
            if ((~((ap_start == 1'b0) | (led_i_ap_vld_in_sig == 1'b0)) & (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 (((icmp_ln1027_fu_81_p2 == 1'd0) & (1'b1 == ap_CS_fsm_state2))) begin
                ap_NS_fsm = ap_ST_fsm_state2;
            end else begin
                ap_NS_fsm = ap_ST_fsm_state3;
            end
        end
        ap_ST_fsm_state3 : begin
            ap_NS_fsm = ap_ST_fsm_state1;
        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 ap_CS_fsm_state3 = ap_CS_fsm[32'd2];

always @ (*) begin
    ap_block_state1 = ((ap_start == 1'b0) | (led_i_ap_vld_in_sig == 1'b0));
end

assign i_V_2_fu_87_p2 = (i_V_fu_50 + 27'd1);

assign icmp_ln1019_fu_93_p2 = ((i_V_fu_50 == 27'd99999998) ? 1'b1 : 1'b0);

assign icmp_ln1027_fu_81_p2 = ((i_V_fu_50 == 27'd100000000) ? 1'b1 : 1'b0);

assign led_o = neg_i_reg_111;

assign neg_i_fu_67_p2 = (led_i_in_sig ^ 1'd1);

endmodule //flash_led

可以看到很简单的流水灯花了很大的篇幅,我感觉没有verilog自己动手写方便。

solution,run rtl cosimulation生成波形仿真文件
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值