Bootstrap

基于ZYNQ-7000系列的FPGA学习笔记4——流水灯

上期我们完成了FPGA的开发环境搭建,这一期我们学习流水灯

1. 硬件设计

想要实现流水灯,需要先了解一下开发板上的LED资源:
在这里插入图片描述

可以看到:开发板上只有两个PL控制的led,分别为led1和led2,分别连接到ZYNQ芯片的L15和L19,那么我们就可以根据板上的资源,实现一个跑马灯,具体要求如下:

2. 任务要求

  • 根据开发板上的资源,实现一个跑马灯
  • 跑马灯的闪烁间隔为0.5s
  • 可以通过复位按键重置跑马灯的效果
    在这里插入图片描述

3. 实现思路

需要实现跑马灯,我们需要有以下内容:

  • 输入的时钟信号,实现0.5s的计时

  • 复位信号,用来恢复led的状态

  • 输出控制led的端口,这里有两个led,所以有两个输出端口

  • 最后还有一个led状态变化控制的逻辑部分

  • 在这里插入图片描述

4. 波形图

根据上述的实现思路,我们可以模拟出输入的输出之间的波形关系,如下:
在这里插入图片描述

5. 代码编写

1. rtl代码编写:flow_led.v

//模块名
module flow_led (
input               sys_clk,    //时钟输入
input               sys_rst_n,  //复位输入
output reg [1:0]     led        //led输出
);
//计数值:记录时钟的节拍数,用来完成0.5s的延时
reg [24:0] cnt;

//计数器计时0.5s
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
    cnt <= 25'd0;   //复位值为0
    else if(cnt < (25'd2500_0000 - 25'd1))
    cnt <= cnt + 25'd1;     //还没到达0.5s
    else    
    cnt <= 25'd0;           //到达了0.5s
end

//对led输出进行移位操作
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
    led = 2'b01;    //复位值为0'b01
    else if(cnt == (25'd2500_0000 - 25'd1))
    led = {led[0],led[1]};      //0.5s移位拼接一次,翻转led的状态
    else 
    led = led;                  //否则保持不变
end

endmodule

2. 测试文件编写:tb_flow_led.v

//模块定义
module tb_flow_led();

//宏定义时钟周期
parameter CLK_PERIOD = 20;

//定义变量
reg sys_clk;
reg sys_rst_n;

wire[1:0] led;

//初始化:clk和rst引脚置0,延时200ns,之后rst引脚拉高
initial begin
    sys_clk <= 1'b0;
    sys_rst_n <= 1'b0;
    #200
    sys_rst_n <= 1'b1;
end

//产生时钟
always #(CLK_PERIOD / 2)    sys_clk = ~sys_clk;

//例化模块
flow_led u_flow_led(
    .sys_clk    (sys_clk),
    .sys_rst_n  (sys_rst_n),
    .led        (led)
    );
endmodule

6. 代码仿真

仿真结果如下:
在这里插入图片描述
可以看到,仿真结果和代码移植,可以进行下一步:引脚约束

7.0 添加约束文件并分析综合

  1. 添加约束文件,约束如下:
//时序约束
create_clock -period 20.000 -name sys_clk - waveform {0.000 10.000} [get_ports sys_clk]
//管脚约束
set_property PACKAGE_PIN H15 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property PACKAGE_PIN L15 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property PACKAGE_PIN U18 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property PACKAGE_PIN N16 [get_ports sys_rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports sys_rst_n]

【注1】:这里除了引脚约束之外,还添加了时序约束,主要针对的是时钟线:

  • 对时钟的约束最简单的理解就是,设计者需要告诉 EDA 工具设计中所使用的时钟的频率是多少;然后工具才能按照所要求的时钟频率去优化布局布线,使设计能够在要求的时钟频率下正常工作。本次实验sys_clk 的时钟频率为 50MHz,周期为 20ns,在做约束时可以等于这个值或者略低于这个值,不建议周期设置的太小,否则软件在布局布线时很难满足这个要求。

【注2】:这里再之前的基础上,布局添加了led的两个管脚约束,还有对时钟线的约束和复位信号的约束,它们的具体原理图如下:
在这里插入图片描述
2. 完成约束之后,下一步进行分析综合:
在这里插入图片描述
【注】:如图是分析综合之后的内部电路连接图,很复杂,但是我们需要了解,直接下载到板子上,验证实验结果即可。

8. 上板验证

根据上一期的内容,生成比特流文件,如下载到芯片内容即可实现一个简单的跑马灯,由于不方便录视频,所以效果这里不好展示,简单的放两个图片吧。

在这里插入图片描述

9.总结

本期内容我们实现了一个简单的跑马灯实验,过程写的比较简略,如果有记录的不详细的地方,可以查看:基于ZYNQ-7000系列的FPGA学习笔记3——开发环境搭建&点亮一个LED,这里只记录重要的内容,关于软件操作和Verilog语法,这里不做介绍,还请原谅!!!

以上就是本期的所有内容,创造不易,点个关注再走呗。

在这里插入图片描述

;