1. 课程信息

  • 实验地点:******

  • **实验时间:**2021.03.25

  • 实验时长: 3小时(4节课)

2. 实验要求

驱动板上LED1 ~LED8按如下2个模式循环闪烁:

① 每个灯亮1s灭1s,从右至左依次闪烁,共8次

② 每个灯亮1s灭0.5s,从左至右间隔闪烁,共4次

思考(加分项):

  1. 如何使用按键控制流水灯的闪烁时间?

如:按一次亮1s,再按一次变为亮0.5s。

2. 如何使用按键控制流水模式?

如:按一次8个灯依次闪烁,再按一次LED2/4/6/8间隔闪烁

3. 设计与实现

3.1 实验步骤

  1. 在Vivado中创建工程,并添加.v文件

  2. 阅读实验提供的源码文件并完善部分代码

  3. 添加testbeach文件,做仿真分析

  4. 添加.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_clk1Input时钟同步信号
sys_rst_n1Input复位信号
[7:0] led8Output输出的led信号,与外部引脚进行绑定
[31:0] counter1, counter232中间信号计数器分别计数2秒和1.5秒
[31:0] cnt32中间信号计数器记录一个循环22秒
led_control1中间信号控制信号,控制流水灯的工作模式
[7:0] led1,led28中间信号两种不同模式下的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的语法,在缺少下板环境的情况下,学习通过仿真来进行设计的验证,同时收获了硬件设计的并行思想,这与软件设计还是存在较大差异。