简答

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

HLS代表高级综合(High-Level Synthesis),是一种用于硬件设计的编程方法。它允许工程师使用高级编程语言(如C、C++)描述硬件功能,然后通过自动化工具将其转换为硬件描述语言(如VHDL或Verilog)的等效表示形式。

HLS的主要目标是提高硬件设计的生产力和效率。相比于传统的手工编写硬件描述语言的方式,使用HLS可以更快速地完成设计,并减少设计中的错误。它还使软件工程师能够利用他们已经熟悉的高级编程语言的优势来进行硬件设计。

VHDL(VHSIC Hardware Description Language)和Verilog是两种常用的硬件描述语言,用于描述电子系统的行为和结构。它们在硬件设计中扮演着重要角色,工程师可以使用它们编写逻辑电路、控制器和其他硬件组件的描述。

HLS与VHDL/Verilog编程技术之间存在紧密的关系。通过使用HLS,工程师可以将高级编程语言中的代码转换为VHDL或Verilog代码,从而以硬件描述语言的形式进行进一步的设计和验证。HLS工具可以将高级代码转换为等效的硬件电路描述,其中包括逻辑门、寄存器、数据通路等。因此,HLS为软件工程师提供了一种更高层次的抽象,使他们能够使用高级编程语言来描述硬件功能,并将其转换为VHDL/Verilog以进行实际的硬件设计。这样做可以提高设计的速度和可靠性,并减少设计中的错误。

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

关键技术:
高级语言映射:HLS需要将高级编程语言中的代码映射到等效的硬件电路描述。这个映射过程需要考虑如何将高级语言的抽象概念映射到硬件的并行结构,以及如何优化资源利用和性能。

时序约束:在HLS中,时序约束是一个重要问题。时序约束用于定义电路中不同部分之间的时序关系,例如数据的传输和处理速度。合理的时序约束可以确保生成的硬件电路满足预期的性能要求。

内存和存储管理:在HLS中,对内存和存储器的管理是一个挑战。合理的存储器访问模式和数据流管理对于生成高效的硬件电路至关重要。

并行性和流水线:HLS的一个关键目标是实现硬件的并行性和流水线。这需要对算法进行并行化分析和优化,以实现最大的性能和吞吐量。

综合和优化:HLS工具通常提供综合和优化功能,以生成最优的硬件电路。然而,综合和优化的质量取决于工具的算法和设置,可能存在优化不充分或者生成不满足设计要求的电路的情况。

技术局限性:
复杂性:HLS适用于某些类型的设计,但对于特定类型的复杂硬件设计,如高性能处理器或复杂的通信接口,可能会面临挑战。

时序约束和时序分析:时序约束的定义和时序分析仍然是HLS中的一个难题。正确定义时序约束并进行准确的时序分析对于生成符合时序要求的硬件电路至关重要。

资源利用:自动生成的硬件电路可能无法充分利用FPGA或ASIC等目标设备的资源。需要对资源分配和利用进行进一步的优化。

调试和验证:由于HLS生成的硬件电路较为复杂,调试和验证也变得更加困难。缺乏强大的调试和验证工具限制了HLS的广泛应用。

HLS实现led灯闪烁

①新建项目

在这里插入图片描述

②项目工程名

在这里插入图片描述

③一直点击netx

④选择对应的板子

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

⑤右键 Source,点击 New file,新建 led.cpp 等文件

在这里插入图片描述
led.cpp

#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;
		} 
	}
}


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


test_led.cpp

#include "led.h"       //引入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函数
		flash_led(&led_o , led_i);
		led_i = led_o;               //给激励
		printf("shift_out is %d \n",(int)(led_o&0x01));
	}
}

⑥选择顶层函数,进行c仿真

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
Console 窗口结果如下,仿真结果无误
在这里插入图片描述

⑦进行c综合

在这里插入图片描述
在这里插入图片描述
(Latency 指的是,设计电路完成一次任务需要
的时间,Interval 指的是两次任务之间的时间间隔)

⑧导出IP核

在这里插入图片描述

Vivado导入HLS的IP核

①新建项目(省略的直接点next就行)

在这里插入图片描述

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

②导入IP核

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

③对导入的IP核进行验证

在这里插入图片描述

④将IP核添加到工程中

在这里插入图片描述

⑤添加一个新文件

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

⑥代码编写

`timescale 1ns / 1ps
module Lab_HLS_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_V_ap_vld(led_o_vld), // output wire led_o_V_ap_vld
    .led_i_V_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


⑦添加约束文件

在这里插入图片描述

在这里插入图片描述

##############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}]

编译烧录

①生成bit流文件

在这里插入图片描述

②接线,设备自动连接

在这里插入图片描述

③进行烧录

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

④效果展示

在这里插入图片描述

总结

本次作业简单来说,实现了一个封装IP核并拿来用的过程。具体的实现过程还是有些许复杂,比如编写源文件,仿真文件,进行c仿真和综合,还有映射到RTL电路上等,不过也算不上难,本人也对HLS的使用有了初步的了解,这些东西应该对于我今后的fpga数字电路设计和开发工作具有重要的引导作用吧。

参考

https://blog.csdn.net/qq_43279579/article/details/117084706?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168412164216800215083023%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=168412164216800215083023&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-1-117084706-null-null.blog_rank_default&utm_term=HLS&spm=1018.2226.3001.4450

https://blog.csdn.net/chenyu128/article/details/130658829?spm=1001.2014.3001.5501

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐