实验练习
说明
- 每一次实验我们会为大家准备若干练习题目。不同的题目有着不同的难度,请大家量力而行;
- 你可以查阅任何开源资料完成实验练习,但不能直接抄袭。一经发现,我们将取消所有抄袭参与者本次的实验成绩。情节特别严重的,我们将按照学校的有关规定进行处理。
- 部分题目我们提供了代码框架,你需要在框架指定的位置完成代码内容。你也可以自由修改框架代码,但需要根据题目要求完成练习。
必做内容
每一名同学都需要完成必做部分的内容。
题目 1:if 语句与锁存器(1 分)
本题来自于 OJ ID-131。你可以在该平台上验证自己的设计。
有时候,语法正确的代码并不一定能产生功能正常的电路,一般来说都是因为不小心引入了锁存器造成的。例如下面的 Verilog 语句:
1 2 3 4 5 6 7 8 9 |
|
为消除锁存器,我们应当使组合逻辑过程块中的条件完备,即 if 语句后应加上 else 语句。试修改上述两段代码,以消除锁存器。
输入格式
- 输入信号 cpu_overheated, 位宽 1bit,控制 shut_off_computer 信号。
- 输入信号 arrived, 位宽 1bit,控制 keep_driving 信号。
- 输入信号 gas_tank_empty,位宽 1bit, 作为 keep_driving 的输入信号之一。
输出格式
- 输出信号 shut_off_computer,位宽 1bit,要求 cpu_overheated 为真时输出 1'b1,反之输出 1'b0。
- 输出信号 keep_driving,位宽 1bit,要求 arrived 为假时输出 ~gas_tank_empty,反之输出 1'b0。
代码框架如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
题目 2:case 语句与锁存器(1 分)
本题来自于 OJ ID-135。你可以在该平台上验证自己的设计。
假设您正在构建一个电路来处理游戏中 PS/2 键盘上的扫描码。现在给定接收到的扫描码的最后两个字节,您需要指示是否按下了键盘上的一个箭头键。这涉及到一个相当简单的映射,包含五种可能的情况:上、下、左、右,以及不属于任何一种。
您的电路有一个 16bits 输入和四个 1bit 输出,该电路识别这四个扫描码并确认正确的输出。为避免产生锁存,必须在所有情况下为四个输出指定一个值。这可能涉及许多不必要的输入。解决这个问题的一个简单方法是在 case 语句之前为输出分配一个『默认值』:
1 2 3 4 5 6 |
|
这种类型的代码确保在所有可能的情况下为输出赋值(0),除非 case 语句重写赋值。这也意味着 default 项变得不必要。请试着将上述代码补充完整,以实现期望的电路功能。
代码框架如下:
1 2 3 4 5 6 7 8 9 |
|
题目 3:计数器 Pro(3 分)
这是我们在实验教程中展示的计数器代码:
Counter.v | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
现在,我们需要对其进行一点改进。
-
现在的计数器复位值是 0,最小值是 0,最大值是 MAX_VALUE。请修改代码,使得计数器的最小值也可以由模块参数 MIN_VALUE 指定。
-
在 1 的基础上,增加一个 1bit 输入信号
enable
用于控制计数器的工作状态。要求:enable
为高电平时,计数器在 MIN_VALUE 至 MAX_VALUE 之间正常工作;enable
为低电平时,counter
变量复位并保持在 0。从enable
变为低电平开始到counter
复位并保持在 0 的间隔不超过三个时钟周期。此外,rst
信号的优先级应当高于enable
信号。你需要结合仿真波形证明自己设计的正确性。例如:下面是助教的仿真文件与结果:
q3_tb.v 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
module q3_tb(); reg clk, rst, en; wire out_TA; initial begin clk = 0; rst = 1; en = 0; #10; rst = 0; #10; en = 1; #20; en = 0; #20; en = 1; #20; rst = 1; #20; rst = 0; #200; en = 0; end always #5 clk = ~clk; Counter #( .MIN_VALUE(8'd10), .MAX_VALUE(8'd13) ) counter ( .clk(clk), .rst(rst), .enable(en), .out(out_TA) ); endmodule
题目 4:生成波形(2 分)
请编写仿真文件,生成下图所示的波形。时钟周期设定为 10ns,变量 bus 的位宽自行指定(图中存在偏差,实际上变量 bus 应在时钟上升沿变化)。图中的阴影部分代表电路状态不确定,你可以自行指定其状态。
本题的分数组成如下:
- 成功绘制出波形图:1分
- 不使用对时间打表的方式(
zero
除外)完成:1分
需要提示?
zero
是一个会归零a
的信号。- 所有跳变都发生在
clk
的上升沿。 - 回忆一下计数器的思想。
- 或许应该尝试一下
for
和repeat
循环?
选择性必做内容
选择性必做内容是针对不同层次学生设计的分层内容。不同难度的题目对应不同的分值,请大家根据自身实际情况进行选择。
请在下面的题目中任选一题完成。多选按选择的第一题计分。
题目 1:奇怪的代码(2 分)
下面是一段被加密的代码。请自行编写仿真文件,设计特定的输入,测试该模块的功能。
Foo.v | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
请在实验报告中指出该模块每个输入、输出端口的功能,并附上一些你的推理过程。
提示:位宽为 8bits 的信号为数据信号,其余为控制信号。
题目 2:计数器 天上天下天地无双版(2分)
格雷码是一种编码系统,相邻两位之间只有1个比特的区别,相较于普通的二进制编码,格雷码能避免出现竞争-冒险现象,更加稳定。格雷码甚至能在解决汉诺塔问题、遗传算法理论等地方得到应用。
请设计一个计数器模块,以 4 位格雷码计数,每个时钟周期增加 1 ,到达最大值后归零,并在这个周期内给out信号置1,长度为1个周期,不断循环。
模块的部分信息如下:
GrayCounter.v | |
---|---|
1 2 3 4 5 6 7 8 |
|
需要提示?
可以对4个比特一个一个分析,不一定要找出通用的规律。
题目 3:『众数』统计(3 分)
请设计一个模块,实时输出对于任意给定数目 8bits 无符号整数中出现次数超过一半的数(如果不存在则可以输出序列中任意一个数)。请结合 Vivado 仿真验证自己设计的正确性。方便起见,我们假定输入的数个数不超过 100。
模块的部分信息如下:
FindMode | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
其中:
- rst 有效时会清除先前的记录,视作从下一个数开始为第一个数;
- next 有效时代表此时通过 number 输入了一个数。输入过程是时钟同步的;
- out 输出截至目前输入的结果。
例如:对于输入序列,
10, 20, 30, 10, 10, 20, 30, 30, 30, 10, 10, 10
一个可接受的输出序列如下:
10, 20, 30, 10, 10, 10, 30, 30, 30, 30, 30, 10
对应的仿真波形如下: