跳转至

实验练习

说明

  1. 每一次实验我们会为大家准备若干练习题目。不同的题目有着不同的难度,请大家量力而行;
  2. 你可以查阅任何开源资料完成实验练习,但不能直接抄袭。一经发现,我们将取消所有抄袭参与者本次的实验成绩。情节特别严重的,我们将按照学校的有关规定进行处理;
  3. 部分题目我们提供了代码框架,你需要在框架指定的位置完成代码内容。你也可以自由修改框架代码,但需要根据题目要求完成练习;
  4. 如果你使用了我们预料之外的方法完成练习也没有关系,我们将根据思考量与任务量单独确定给分情况;
  5. 本次实验的部分题目需要上板验证,具体的端口变量与对应关系请按照题目要求设定

提醒

为了保证效率,请大家在找助教 Debug 前务必编写对应的仿真文件。我们不接受没有仿真波形的 Debug 请求。


必做内容

每一名同学都需要完成必做部分的内容。

题目 1:寄存器堆(3 分)

请参照实验文档中对寄存器堆的描述,设计并编写一个寄存器堆,要求满足以下功能:

  1. 寄存器堆的规模为 32x32bits;

  2. 0 号寄存器始终保持 0;

  3. 当同时读写时,能读到正写入的最新数据

编号低的功能优先级更高(3号情况要在满足2号情况下才能实现)。

提示

注意寄存器为读时钟异步,写时钟同步。“同时读写”的意思是对于同一个地址下一周期即将写入数据时本周期就能读到即将写入的值。

本题要求自行编写仿真文件进行测试(不需要很复杂的仿真,能凸显模块特点即可),代码框架如下:

module Regfile (
    input                       clk,          // 时钟信号
    input           [4:0]       ra1,          // 读端口 1 地址
    input           [4:0]       ra2,          // 读端口 2 地址
    input           [4:0]       wa,           // 写端口地址
    input                       we,           // 写使能信号
    input           [31:0]      din,          // 写数据
    output  reg     [31:0]      dout1,        // 读端口 1 数据输出
    output  reg     [31:0]      dout2         // 读端口 2 数据输出
);
// Write your code here

// End of your code
endmodule

你可以参考如下的仿真文件和波形

    module RegFile_tb ();
        reg              clk;
        reg     [ 4 : 0] ra1, ra2, wa;
        reg     [ 0 : 0] we;
        reg     [31 : 0] din;
        wire    [31 : 0] dout1;
        wire    [31 : 0] dout2;

        RegFile regfile(
            .clk(clk),
            .ra1(ra1),
            .ra2(ra2),
            .wa(wa),
            .we(we),
            .din(din),
            .dout1(dout1),
            .dout2(dout2)
        );

        initial begin
            clk = 0;
            ra1 = 5'H0; ra2 = 5'H0; wa = 5'H0; we = 1'H0; din = 32'H0;

            #12
            ra1 = 5'H0; ra2 = 5'H0; wa = 5'H3; we = 1'H1; din = 32'H12345678;

            #5
            ra1 = 5'H0; ra2 = 5'H0; wa = 5'H0; we = 1'H0; din = 32'H0;

            #5
            ra1 = 5'H3; ra2 = 5'H2; wa = 5'H2; we = 1'H1; din = 32'H87654321;

            #5
            ra1 = 5'H0; ra2 = 5'H0; wa = 5'H0; we = 1'H0; din = 32'H0;

            #5
            ra1 = 5'H3; ra2 = 5'H0; wa = 5'H0; we = 1'H1; din = 32'H87654321;

            #10
            $finish;
        end
        always #5 clk = ~clk;
    endmodule

Image title

题目 2:数码管时钟(3 分)

请参照实验文档中案例部分实现七段数码管制作时钟的内容,制作实现一个五位时钟,精度为 1 秒,比如七段数码管上从左到右显示 12345,则表明时间为 1 小时 23 分钟 45 秒。除此之外,请实现按动按钮能够将时钟复位到 12345,也就是复位值为 1 小时 23 分钟 45 秒的功能。

提示

注意这次练习中的复位值不为 0,所以代码方面和案例中的示例有很大的不同。此外,可以利用之前实验完成的数码管显示模块。

本题要求上板验证,代码框架与约束文件如下:

module TIMER (
    input                           clk, rst,
    output      reg     [3:0]       out,
    output      reg     [2:0]       select
);
// Write your code here

// End of your code
endmodule
constraints.xdc
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { clk }];
set_property -dict { PACKAGE_PIN B18   IOSTANDARD LVCMOS33 } [get_ports { rst }];

set_property -dict { PACKAGE_PIN A14   IOSTANDARD LVCMOS33 } [get_ports { out[0] }];
set_property -dict { PACKAGE_PIN A13   IOSTANDARD LVCMOS33 } [get_ports { out[1] }];
set_property -dict { PACKAGE_PIN A16   IOSTANDARD LVCMOS33 } [get_ports { out[2] }];
set_property -dict { PACKAGE_PIN A15   IOSTANDARD LVCMOS33 } [get_ports { out[3] }];
set_property -dict { PACKAGE_PIN B17   IOSTANDARD LVCMOS33 } [get_ports { select[0] }];
set_property -dict { PACKAGE_PIN B16   IOSTANDARD LVCMOS33 } [get_ports { select[1] }];
set_property -dict { PACKAGE_PIN A18   IOSTANDARD LVCMOS33 } [get_ports { select[2] }];

选择性必做内容

选择性必做内容是针对不同层次学生设计的分层内容。不同难度的题目对应不同的分值,请大家根据自身实际情况进行选择。

请在下面的题目中任选一题完成。多选按选择的第一题计分。

题目 1:倍数检测器——再临(4 分)

我们在 Lab4 中学习了 5 的倍数检测器,在此次练习中,我们需要利用 FSM 来制作一个 32bits 7 的倍数检测器,并通过仿真测试。具体检测流程为:每次复位后,将输出有效位设置为 0,ready 位置为 1 ,等待输入有效位为 1 时接收输入并计算,计算过程中 ready 位保持 0 显示正在检测,此时输入会被忽略,计算出结果后输出并将输出有效位设置为 1, ready 位设为 1 并不再变化,直到下一次输入有效值变为 1 后进行下一次检测。

提示

在学习了 Lab5 的时序逻辑电路和运用 FSM 设计时序逻辑电路后,我们就不需要 Lab4 中介绍的复杂数论知识了,而是可以用 FSM 的方法,在有限周期内算出答案。你仍旧不被允许使用模运算(%),且你的倍数检测实现逻辑必须得跟状态机有关,你应当在 32 个周期内能够检测完。

请注意:每个时钟周期对输入减去特定的数值,最后判断是否为 0 的做法(以及与其类似的做法)不得分 :)

要求使用三段式结构描述状态机,自行编写仿真文件进行测试。代码框架如下:

MUL7.v
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
module MUL7(
    input                               clk,            // 时钟信号
    input                               rst,            // 复位信号,使状态机回到初始态
    input               [31 : 0]        src,            // 输入数据
    input                               src_valid,      // 表明输入结果是否有效
    output      reg                     ready,          // 表明是否正在检测
    output      reg                     res,            // 输出结果
    output      reg                     res_valid       // 表明输出结果是否有效
);

// Write your code here

// End of your code
endmodule

题目 2:投币机(3 分)

按照实验文档案例分析中的投币机分析过程,完成 verilog 代码的编写。

要求使用三段式结构描述状态机,自行编写仿真文件进行测试。代码框架如下:

module CoinMachine (
    input                   clk,
    input                   rst,
    input                   A,
    input                   B,
    output                  Y,
    output                  Z
);
// Write your code here

// End of your code
endmodule

题目 3:真-交通信号灯(3 分)

按照实验文档案例分析中的交通信号灯部分,完成一个交通信号灯的编写,并附加功能:绿灯保持 35 个时钟周期,黄灯保持 5 个时钟周期,红灯保持 40 个时钟周期。

要求使用三段式结构描述状态机,自行编写仿真文件进行测试。代码框架如下:

module TrafficLight (
    input                   clk,
    input                   rst,
    output                  is_red,
    output                  is_green,
    output                  is_yellow
);
// Write your code here

// End of your code
endmodule

选做内容

选做内容为扩展内容,不计入实验成绩。大家可以根据兴趣自行完成。

题目 1:字符串检测

假设输入为一个 100 位的 0 与 1 构成的串 a,我们希望确定 a 中是否有连续的 11011 子串。请根据数据结构知识,构造状态机解决此问题,各信号的作用类似选择性必做题目 1。

module FIND11011(
    input                               clk,            // 时钟信号
    input                               rst,            // 复位信号,使状态机回到初始态
    input               [99:0]          src,            // 输入数据
    input                               src_valid,      // 表明输入结果是否有效
    output      reg                     res,            // 输出结果
    output      reg                     res_valid       // 表明输出结果是否有效
);

// Write your code here

// End of your code
endmodule

最后更新: November 16, 2023

评论