首页
社区
课程
招聘
[原创]基于Vivado开发FPGA程序快速入门
2023-3-17 20:13 13574

[原创]基于Vivado开发FPGA程序快速入门

2023-3-17 20:13
13574

本实验的主要目的是实现4个LED灯循环亮灭的逻辑,来体验典型的vivado FPGA程序编写流程,并采用仿真验证。主要涉及到这些步骤:项目创建流程、写RTL程序实现逻辑、写testbench验证逻辑、写XDC硬件管脚约束、烧写程序,并查看结果。

1、创建 vivado的项目工程

图片描述
图片描述
没有实现的文件,可以先不指定需要导入到项目的文件。

 

图片描述
根据实际情况选择开发板型号。笔者的开发板是这样的型号。

 

图片描述
检查一下没有问题,就可以finish了。

2、写RTL程序实现逻辑

图片描述
新建好项目之后,添加实现的RTL文件:
图片描述

 

选择添加design sources.
其中,第一个constraints是用于配置硬件的管脚约束的,也就是输入输出和硬件实际PIN/PORT映射关系;
第三个是添加testbench仿真文件。
图片描述

 

Vivado还是创建的是verilog的文件。不是verilog HDL。
图片描述

 

直接ok就行。

 

源代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/03/17 17:14:24
// Design Name:
// Module Name: flow_led_demo
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
 
 
module flow_led_demo#(
parameter T_INR_CNT_SET = 32'd999_999_999                     
)                                                              
(                                                              
 input          sysclk_p,                                     
 input          rstn_i,                                        
 output [3:0]   led_o                                          
);
 
reg [3:0] led_r;                                               
reg[24:0] t_cnt;
 
assign led_o = led_r;                                          
 
always @(posedge sysclk_p or negedge rstn_i)begin
    if(rstn_i==1'b0)                                           
       t_cnt <= 0;
    else if(t_cnt == T_INR_CNT_SET)                           
       t_cnt <= 0;
    else
       t_cnt <= t_cnt + 1'b1;                                    
end
 
always @(posedge sysclk_p or negedge rstn_i) begin                
    if(rstn_i==1'b0)
        led_r <= 4'b1000;                                        
    else if( t_cnt == 0)                                         
        led_r <= {led_r[0],led_r[3:1]};                          
end
 
endmodule

简单的逻辑。

 

图片描述

 

选择run synthesis综合一下:
图片描述

 

综合成功之后,会提示你下一步是否继续。可以先cancel,然后我们下面来写测试的逻辑。
图片描述

3、写testbench验证逻辑

同样的,也是添加source
图片描述
图片描述

 

图片描述
图片描述

 

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/03/17 17:21:05
// Design Name:
// Module Name: flow_led_demo_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
 
 
module flow_led_demo_tb();
 
reg sysclk_p,rstn_i;     
wire [3:0]  led_o;       
 
flow_led_demo#
(
.T_INR_CNT_SET(1000)      
)
run_led_inst(
 .sysclk_p(sysclk_p),     
 .rstn_i(rstn_i),         
 .led_o(led_o)            
);
 
initial begin
   sysclk_p  <= 1'b0;    
   rstn_i    <= 1'b0;    
   #100;                 
   rstn_i    <= 1'b1;    
end
 
always #20 sysclk_p=~sysclk_p;   
 
 
 
endmodule

核心就是启动激励就行。
图片描述

 

右键点击run simulation,我们先键入simulation settings进行必要的设定。进入之后,可以拉长仿真的时间,用于查看完整的仿真周期。此外,建议把simulate.log_all_signals也加上。这样的话,所有的信号波形都会被记录下来,我们后续在窗口中,按需添加想要查看的变量就行。
图片描述

 

左键点击,准备执行:
图片描述

 

查看仿真结果,并且对应调试。
图片描述
想要添加查看的变量,直接右键添加就行。
图片描述
--题外话:(对于状态机类型的RTL逻辑验证,可以考虑引入一个状态机自动分析的工具,辅助判断波形是否符合状态机的预期,从而加速调测。工具的输入:状态机定义文件、仿真的波形文件;输出:不符合状态机流转的前后状态、出问题的波形位置、出问题的代码位置)

4、写XDC硬件管脚约束

管脚约束是应用RTL程序到硬件上非常重要的一步,需要结合硬件的datasheet来填写。这里也有一个写好的xdc文件,可以直接导入。
图片描述

 

选择添加约束文件。
图片描述
图片描述

 

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#系统时钟周期约束
create_clock -period 10.000 -name sysclk [get_ports sysclk_p]
#时钟管脚物理,物理约束为具体的芯片管脚号约束
set_property PACKAGE_PIN L5 [get_ports sysclk_p]
#电平属性为LVCMOS33,代表了3V3 的IO BANK,电平约束不会改版实际的IO BANK 电平,如果电平约束和实际的BANK 电平不匹
配,可能会导致工作异常
set_property IOSTANDARD LVCMOS33 [get_ports sysclk_p]
#复位管脚约束,这里绑定到按键输入
set_property PACKAGE_PIN H5 [get_ports rstn_i]
#复位输入的电平约束为1V8 的IO BANK 电平
set_property IOSTANDARD LVCMOS18 [get_ports rstn_i]
#绑定led 输出管脚到FPGA IO 上
set_property PACKAGE_PIN V19 [get_ports {led_o[3]}]
set_property PACKAGE_PIN U19 [get_ports {led_o[2]}]
set_property PACKAGE_PIN U16 [get_ports {led_o[1]}]
set_property PACKAGE_PIN T16 [get_ports {led_o[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_o[*]}]
#对bit 大小进行压缩,可以节省程序存储空间
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]

查看导入XDC文件之后,管脚实际分配的情况:
图片描述
图片描述

 

对应形成的配置就是这样:
图片描述

5、烧写程序,并查看结果

生成bit文件,这个bit文件就是最终要烧录到FPGA上的。
图片描述

 

接着,给开发板通电。
选择连接都开发板:
图片描述

 

连接成功后显示:
图片描述

 

接着我们选择烧写程序,就可以把程序烧录上去了。
图片描述
图片描述

6、添加ILA的IP,实现上板调测

ILA是Integrated Logic Analyzer,集成逻辑分析器:即Vivado的在线逻辑分析仪,其借用了传统逻辑分析仪的理念以及大部分的功能,并利用FPGA 中的逻辑资源,将这些功能植入到FPGA 的设计当中。ILA是用IP核的形式实现的。
在线逻辑分析仪通过一个或多个探针(Probe)来采集希望观察的信号,然后通过片内的JTAG 硬核组件,来将捕获到的数据传送给下载器,进而上传到Vivado IDE 以供用户查看。Vivado IDE 也能够按照上述数据路径,反向地向FPGA 中的在线逻辑分析仪传送一些控制信号。
图片描述

 

首先在工程中,添加ILA的IP。打开IP catalog。
图片描述

 

找到ILA的IP,双击。
图片描述

 

Comparator数量:指每个probe可以配置的capture条件。
Probe数量:指捕获的探针数量。

 

我们当前这个程序,主要就是观测LED数值的变化。因此,就设定一个探针probe。
图片描述

 

LED是4bit的,所以设置probe探针长度为4bits。
图片描述
由于我们这个程序没有在Block design中设计,而是直接嵌入到verilog代码的,因此选择out of context per IP。不用做连线啥的操作。
图片描述

 

接下来就在代码中,实例化ILA的 IP。

1
2
3
4
ila_0 ila_debug (
    .clk(sysclk_p), // input wire clk
    .probe0(led_r)
);

当然,我们可以根据实际需求,生成多个probe,然后把变量分别放到不同的probe;或者生成一个probe,将多个变量聚合到这一个proble里面。下面的方式都是可行的。
多种设置probe探针的方式:

  • 一个Probe,每个probe可以是多位长度,然后把多个变量塞进去就行。
1
2
3
4
ila_0 ila_debug (
    .clk(sysclk_p), // input wire clk
    .probe0({t20us_done ,pwm_o }) // input wire [1:0]  probe0 
);
  • 多个Probe,每个probe 占用1bit。
1
2
3
4
5
6
ila_0 ila_debug (
    .clk(sysclk_p), // input wire clk
    .probe0(t20us_done), // input wire [1:0]  probe0 
    .probe1(pwm_o), // input wire [1:0]  probe0 
    .probe2(t20ms_done) // input wire [1:0]  probe0 
);

接下来,我们重新综合-implement-烧录程序到FPGA开发板上。

 

可以直接设置触发的条件:
图片描述
点击启动,就可以发现波形停留在了led_r ==4的位置。这个就是从开发板上实际获取的波形。
图片描述

 

还可以将波形图导出,方便后续分析:

 

图片描述


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2023-3-17 20:14 被二当家a编辑 ,原因:
收藏
点赞6
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回