-
宏定义
typedef int led_t;
typedef int cnt32_t;//计数器 -
using namespace std;
itoa (int, char*, int);//函数# include
# include void main (void) { int num = 100; char str[25]; itoa(num, str, 10); printf("The number 'num' is %d and the string 'str' is %s. n" , num, str); } 第一个参数是要转换的数字,第二个参数是要写入转换结果的目标字符串,第三个参数是转移数字时 所用的基数。在上例中,转换基数为10。10:十进制;2:二进制…
-
指针
-
数据在内存中存储时是分块存储的。变量都是存储东西的
-
指针变量是存储了一个指针,int *p;同变量定义相同,定义了一个p变量,但他属于指针型,但他存储的是地址。
-
变量的指针和指针变量:前者是指变量的存储地址,指针理解为地址;后者是是一个变量,这个变量存储的是一个地址。
-
指针变量的定义
int *p;
使用
p = &a;//p是一个指针变量,指针变量是存储地址的一块空间,这块空间是存储变量a的地址 -
“&”和“*”的结合方向
-
-
打开 Vivado HLS 开发工具,单击 Creat New Project 创建一个新工程,设置好工程路径和工程名,一直点击Next
-
选择芯片型号,zynq7010,点击next
-
右单击 Source,选择 New file,添加一个设计源文件。
-
功能文件shift_led.cpp 一定要带上后缀
#include "shift_led.h" void shift_led(led_t *led_o,led_t led_i) { led_t tmp_led; cnt32_t i;//for循环的延时变量 tmp_led = led_i; for(i = 0;i < MAX_CNT;i++) { if(i==SHIFT_FLAG) { tmp_led = ((tmp_led>>3)&0x1) + ((tmp_led<<1)&0xE);//左移 *led_o = tmp_led; } } } -
添加一个 shift_led.h 文件
#ifndef _SHIFT_LED_H_ #define _SHIFT_LED_H_ //加入设置int自定义位宽的头文件 #include "ap_int.h" //设置灯半秒动一次,开发板时钟频率是100M //#define MAX_CNT 1000/2 //仅用于仿真,不然时间较长 #define MAX_CNT 100000000/2 #define SHIFT_FLAG MAX_CNT-2 typedef int led_t; typedef int cnt32_t;//计数器 //typedef ap_fixed<4,4> led_t; //第一个4代表总位宽,第二个4代表整数部分的位宽是4,则小数部分位宽=4-4=0 //typedef ap_fixed<32,32> cnt32_t; void shift_led(led_t *led_o,led_t led_i); #endif
-
单击 Test Bench,添加一个名为 Test_shift_led.cpp 的测试文件,并添加如下程序
#include "shift_led.h" #include
using namespace std; int main() { led_t led_o; led_t led_i = 0xE;// 1110 const int SHIFT_TIME = 4; 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);;//&oxF是为了取led_o的4位,转化为二进制数出 if(i == 2) fprintf(stdout,"shift_out= 0%sn",string);//数据对齐,高位补零 else fprintf(stdout,"shift_out= %sn",string); } }
- :点击 Project -> Project Settings在 Synthesis 界面下选择综合的顶层函数名
- 因为当前工程中只存在一个 Solution(解决方案),我们选择 Solution –> Run C Synthesis–>Active Solutions 或者直接点击 进行综合,等待一段时间,在未经优化的情况下综合报告如图所示,我们可以看到 FF 和 LUT 使用情况
- 单击方框选中的地方点击选择打开分析报告
- 在下图所示 1 的地方点击出现 2 所示的 shift_led,点击展开后可以看到 LED 输入和输出位宽均为 32 位,板载是 4 个 LED,那么该怎么去进行优化得到我们想要的结果呢?
- 点击 Synthesis 切换到工作空间主界面
另外再进行端口约束。约束方法如下,双击打开 shift_led.cpp,在需综合的 shift_led.cpp 文件中的 Directive目录下的 led_o 上右键选择 Insert Directive。
因为 led_o 是接口,所以 Directive 选择为 INTERFACE,Destination 选择为 Source File,那么有的会问了,这两个有什么区别吗?区别就是 Source File 是针对所有的 Solution 采用同一个优化手段,而 Directive File 是对当前的 Solution 有效,mode(optional)我们选为 ap_ovld,即输出使能。
完成后重新综合,查看资源明显减少。
仿真分为 C 代码仿真和 C/RTL 联合仿真。其中 C/RTL 联合仿真可以使用 Vivado 自带的仿真软件仿真,也可以使用第三方仿真软件 Modelsim 进行联合仿真。
C语言仿真
-
单击 Project 下的 Run C Simulation 或直接单击 开始 C 仿真
-
勾选 Optimized Compile,加载编译仿真窗口
-
等待一段时间,仿真结果如下,我们可以看到数据循环左移了一位,达到了我们想要的实验效果
-
加载调试窗口,出现调试界面,可以添加断点观察调试信号数据
C/RTL 联合仿真
vivado自带仿真工具-
单击 Solution 下的 Run C/RTL cosimulation 运行协同仿真
-
设置如下,点击 OK,开始仿真。Dump Trace 选择 all,可以查看到 RTL 仿真波形
-
点击图标,打开波形窗口,添加观察信号
这个过程非常花时间需要耐心等待
这可是非常卡卡卡卡!
-
-
波形文件位置
使用 Modelsim 联合仿真
-
单击 Solution 下的 Run C/RTL cosimulation 运行协同仿真
-
运行协同仿真一段时间后,我们可以发现在 solution1 目录下多了一个 sim 文件夹,在其 verilog 文件夹下可以看到生成的波形文件 shift_led.wlf
-
通过 modelsim 打开该文件,看关键接口的时序。首先打开 modelsim,然后单击 File 菜单下的 open命令
-
在 objects 设置区,按住 ctrl 键选中要查看波形的信号, Add wave
HLS 只是把你的算法实现从 C 到 RTL的转化,而不能在硬件平台上进行测试,需要把 HLS 工程打包成一个 IP 以便于 Vivado 进行调用。
-
单击 Solution 菜单下的 Export RTL 或直接单击 导出 RTL 级
-
点击 configuration 对一些参数进行补充
如果出现这种报错,把电脑时钟设置成2019年以前就能通过编译
-
等待一段时间后在 solution1 目录下多了一个 impl 文件夹,并且在 ip 文件夹生成了一个压缩包,这就是打包好的 IP,在 Vivado 中进行使用
-
按照zynq新建工程
-
完成后,压缩包解压然后,选择 IP->Repository,进入添加 IP 设置区、
设置IP名字,在顶层中例化IP
-
创建一个名为 shift_led 的 Verilog 文件
module shift_led #( parameter DATA_WIDTH = 4//数据位宽 ) ( input i_clk, input i_rst_n, output reg [DATA_WIDTH-1:0] led ); reg [1:0] cnt ; reg [DATA_WIDTH-1:0] led_i_V ; wire ap_start ; wire led_i_vld; wire [DATA_WIDTH-1:0] led_o_V ; always@(posedge i_clk or negedge i_rst_n)begin if(i_rst_n == 1'b0) cnt <= 2'd0; else if(cnt[1]==1'b0) cnt <= cnt + 1'b1; end always@(posedge i_clk or negedge i_rst_n)begin if(i_rst_n == 1'b0) led_i_V <= 4'd0; else if(cnt[0]==1'b1) led_i_V <= 4'h1; else if(led_o_vld == 1'b1) led_i_V <= led_o_V; end always@(posedge i_clk or negedge i_rst_n)begin if(i_rst_n == 1'b0) led <= 1'b0; else if(led_o_vld == 1'b1) led <= led_o_V; end assign ap_start = cnt[1]; assign led_i_vld = cnt[1]; shift_led_0 u_shift_led_0( .led_o_V_ap_vld (led_o_vld),// output wire led_o_vld .led_i_V_ap_vld (led_i_vld),// input wire led_i_vld .ap_clk (i_clk ),// input wire ap_clk .ap_rst (~i_rst_n ),// input wire ap_rst .ap_start (ap_start ),// input wire ap_start .ap_done ( ),// output wire ap_done .ap_idle ( ),// output wire ap_idle .ap_ready ( ),// output wire ap_ready .led_i_V (led_i_V ),// output wire [3 : 0] led_o_V .led_o_V (led_o_V ) // input wire [3 : 0] led_i_V ); endmodule
- 引脚约束,下载调试



