1. 课程信息
- 实验地点:******
- 实验时间:2021.03.25
- 实验时长: 3小时(4节课)
2. 实验要求
驱动板上LED1 ~LED8按如下2个模式循环闪烁:
① 每个灯亮1s灭1s,从右至左依次闪烁,共8次
② 每个灯亮1s灭0.5s,从左至右间隔闪烁,共4次
思考(加分项):
- 如何使用按键控制流水灯的闪烁时间?
如:按一次亮1s,再按一次变为亮0.5s。
2. 如何使用按键控制流水模式?
如:按一次8个灯依次闪烁,再按一次LED2/4/6/8间隔闪烁
3. 设计与实现
3.1 实验步骤
- 在Vivado中创建工程,并添加.v文件
- 阅读实验提供的源码文件并完善部分代码
- 添加testbeach文件,做仿真分析
- 添加.xdc文件(将模块引脚与开发板引脚绑定),并下板验证
3.2 电路功能说明
(包括各个模块功能、关键代码分析,可以使用文字、框图、功能表、状态图等进行说明)
3.2.1 关键代码分析
计数器模块
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
counter1 <= 32'd0;
else if(!led_control)//led_control==0为状态1
if (counter1 < 32'd200_000_000)//系统时钟100M,计数器计200M次即2s
counter1 <= counter1 + 1'b1;
else
counter1 <= 32'd0;
else
counter1 <= 32'd0; //状态2时,counter1置零不计数
end
//通过led_control信号来控制计数器2秒或1.5秒,并分别记为counter1和counter2
模式控制模块
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt<=32'd0;
else if(cnt<32'd2200_000_000)
cnt<=cnt+1;
else
cnt<=0;
end
//cnt计数器来记录一轮循环,cnt<1600_000_000,即小于16秒为左移,cnt>1600_000_000时为右移。
led移动
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led1<=8'b00000001;
else if (!led_control) begin
if (counter1 == 32'd200_000_000)
led1 <= led1<<1; //左移1位
else
led1 <= led1;
end
else led1 <= 8'b00000001;//状态2时led1就在led2基础上左移,状态转换时即可无缝衔接
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
led <= 8'b00000001;
else case (led_control)
0 : if(counter1 < 32'd100_000_000) led = led1; else led = 8'b0; //进入状态1时,先让灯亮1s,再将移位寄存器led1的值赋值给led
1 : if(counter2 < 32'd100_000_000) led = led2; else led = 8'b0; //进入状态2时,先让灯亮1s,再将移位寄存器led2的值赋值给led
default : led <= led;
endcase
end
//分别用led1和led2来表示两种状态下的led状态,led_control为0时,当达到2秒时,led1进行左移。通过counter1的值判断是否达到1秒,未达到时,将led1的值赋给led,否则led置为8’b0。led_control为1同理
3.2.2 系统级表示
3.3 电路接口定义
flowled模块的接口信号定义如下表 1所示。
表 1 flowled模块接口定义
信号名称 | 信号位宽(bit) | 信号方向(I/O) | 信号功能描述 |
sys_clk | 1 | Input | 时钟同步信号 |
sys_rst_n | 1 | Input | 复位信号 |
[7:0] led | 8 | Output | 输出的led信号,与外部引脚进行绑定 |
[31:0] counter1, counter2 | 32 | 中间信号 | 计数器分别计数2秒和1.5秒 |
[31:0] cnt | 32 | 中间信号 | 计数器记录一个循环22秒 |
led_control | 1 | 中间信号 | 控制信号,控制流水灯的工作模式 |
[7:0] led1,led2 | 8 | 中间信号 | 两种不同模式下的led |
4. 验证与分析
4.1 验证平台设计
(包括测试向量说明,可以使用带注释的testbench关键代码等实验过程截屏)
testbeach分析
`timescale 1ns / 1ps
module tb_flowled();
reg clk=0, rst=0;
wire [7:0] led;
flowled u_flowled(
.sys_clk (clk),
.sys_rst_n (rst),
.led (led)
);
initial # 20 rst=1;
always # 1 clk = ~clk;
endmodule
系统时钟为100MHz,testbeach文件的仿真范围有限,因而需要将flowled.v文件中的时间单位缩小,同时将testbeach中的clk加快。
4.2 仿真结果分析
(可以使用带注释的仿真波形图等)
如图所示,在每两个时间间隔,led[7:0]由[0]到[7]依次发光并在一个时间间隔后熄灭。之后,每隔1.5个时间间隔,由[7]到[1]间隔闪烁,且亮一个时间间隔灭0.5个时间间隔,符合实验要求。
5. 实验结果
(可以使用综合后RTL图等实验过程截屏,实物照片等)
6. 实验中遇到的问题及解决方法
忽略了verlog语言的并行性特征,在多个模块中对cnt信号赋值,导致综合报错,在助教的帮助下找到问题并成功解决问题。开发板与电脑连接失败,更换了一块开发板后,成功下板。
7. 实验感想和建议
通过经典的流水灯实验,体验了Vivado开发环境下的FPGA开发流程,进一步熟悉verlog的语法,在缺少下板环境的情况下,学习通过仿真来进行设计的验证,同时收获了硬件设计的并行思想,这与软件设计还是存在较大差异。