实验练习
说明
- 每一次实验我们会为大家准备若干练习题目。不同的题目有着不同的难度,请大家量力而行;
- 你可以查阅任何开源资料完成实验练习,但不能直接抄袭。一经发现,我们将取消所有抄袭参与者本次的实验成绩。情节特别严重的,我们将按照学校的有关规定进行处理;
- 部分题目我们提供了代码框架,你需要在框架指定的位置完成代码内容。你也可以自由修改框架代码,但需要根据题目要求完成练习;
- 如果你使用了我们预料之外的方法完成练习也没有关系,我们将根据思考量与任务量单独确定给分情况;
- 本次实验的必做部分与选择性必做第二题都需要上板验证,具体的端口变量与对应关系请按照题目要求设定。
提醒
为了保证效率,请大家在找助教 Debug 前务必编写对应的仿真文件。我们不接受没有仿真波形的 Debug 请求。
必做内容
每一名同学都需要完成必做部分的内容。
题目 1:编码器 Pro(2 分)
在教程中,我们介绍了普通编码器的一种 Verilog 实现。该编码器的真值表如下图所示:
对应的 Verilog 代码为:
module encode(
input [3:0] I,
output reg [1:0] Y
);
always @(*) begin
case (I)
4'b1000: Y = 2'b11;
4'b0100: Y = 2'b10;
4'b0010: Y = 2'b01;
4'b0001: Y = 2'b00;
default: Y = 2'b00;
endcase
end
endmodule
现在,我们希望增加一个输出信号 en
,在当前输入有效(I != 4'b0000
)时输出 1,无效时输出 0。其他未列在真值表中的输入可自行指定输出。请将下面的 Verilog 代码补充完整,以实现预期的功能。你可以根据需要调整端口为 wire/reg 类型。
module encode(
input [3:0] I,
output reg [1:0] Y,
output reg en
);
// Write your codes here
// End of your codes
endmodule
为了检验结果的正确性,你需要在 FPGAOL 平台上运行该代码。相关外设约定为 I = sw[3:0]
,led = {{en}, {5'b0}, {Y}}
。
题目 2:2bits 半加器(3 分)
我们已经介绍了一个 1bit 的全加器,现在我们希望设计一个 2bits 半加器,其真值表如下图所示:
请将下面的 Verilog 代码补充完整,以实现预期的功能。注意:不允许直接使用加号和减号!
module adder2bit(
input [1:0] a,
input [1:0] b,
output reg [1:0] out,
output reg Cout
);
// Write your code here
// End of your code
endmodule
为了检验结果的正确性,你需要在 FPGAOL 平台上运行该代码。相关外设约定为 a = sw[3:2]
,b = sw[1:0]
,led = {{5'b0}, {Cout}, {out}}
。
选择性必做内容
选择性必做内容是针对不同层次学生设计的分层内容。不同难度的题目对应不同的分值,请大家根据自身实际情况进行选择。
请在下面的题目中任选一题完成。多选按选择的第一题计分。
题目 1:三位十进制加法器(4 分)
虽然计算机中的运算都是二进制,我们更加熟悉的事实上是十进制数的表示。比起二进制十进制的复杂转化,一个更简单的硬件表示方式是每四位二进制数作为十进制数的一位,这种编码称为 BCD 码。此处我们只考虑最简单的 BCD 码,也即四位二进制数用无符号二进制数的方式表示 0 到 9,这种编码称为 8421 码。
具体来说,
10001001_{BCD} + 00000111_{BCD} = 10010110_{BCD}
即表示十进制的 \(89+7=96\)。
假设两个 12 位的二进制输入 a、b 表示两个 3 位十进制数,我们希望计算出它们的和,并用 3 位十进制数 sum 与一个进位标记 cout 表示。
提示
可以仿照二进制加法器的过程,依次构造一位十进制半加器、一位十进制全加器。正确完成一位十进制半加器可得到 2 分,正确完成一位十进制全加器可得到 3 分。
请将下面的 Verilog 代码补充完整,以实现预期的功能。本题允许使用 Verilog 自带的加减号进行运算。
module adder3_10(
input [11:0] a,
input [11:0] b,
output reg [11:0] sum,
output reg cout
);
// Write your code here
// End of your code
endmodule
你可以结合仿真波形验证自己的结果。
题目 2:8bits 5 的倍数检测器(5 分)
我们已经介绍了一个 6bits 5 的倍数检测器,现在我们希望设计一个 8bits 5 的倍数检测器。
上述方法采用了模拟竖式除法的方法,但是这种方法的缺点是需要大量的逻辑门,因此不太适合实际应用。我们可以使用更加巧妙的方法来实现。
还有方法吗?当然有!我们只需要知道一点点初等数论的知识就好!
补充介绍:关于 11 的倍数检测
一个十进制数能否被 11 整除,只需要判断奇数位上的数字相加,再减去偶数位上的数字相加是不是 11 的倍数即可。这是因为对于个位数来讲,假设该数位的数字是 x,那么其对 11 取模的贡献就是正 x,例如 x=9,显然 9 对 11 取模余 9,如果该数位是十位,数字为 y,那么显然其对 11 取模的贡献就是负 y,例如 y=9,显然 90 对 11 取模余 -9(2)。因此,我们只需要将奇数位上的数字相加,再减去偶数位上的数字相加,如果结果是 11 的倍数,那么该数就是 11 的倍数。
那么同理,一个 8bits 的 2 进制数是否是 5 的倍数呢?我们期待大家的实现!
请注意:本题打表实现至多得 2 分,使用长除法实现至多得 4 分。我们不允许使用把该二进制数字转化成 10 进制数再直接看最后一位数的方法来完成这道题。这是因为我们希望大家能够把自己写的 2bits 加法器使用起来,调用自己写的模块解决一个实际的问题!(ps:使用这个方法的其他原因:①当问题规模扩大之后长除法和打表确实难以为继。②让大家感受一下在这个问题规模扩大之后组合逻辑和时序逻辑实现的区别)
请将下面的 Verilog 代码补充完整,以实现预期的功能。此外,为了验证设计的正确性,本题需要大家在 FPGAOL 上运行程序。相关外设的功能分配请自行指定。一种可行的方式是:用开关和按钮进行数据输入,用 LED 或数码管输出检测结果。
module multiple5(
input [7:0] num,
output reg ismultiple5
);
// Write your code here
// Use the 2-bits adder, or you will not get the score!
// End of your code
endmodule
提示
上面介绍了一下关于 11 的倍数检测的方法,同理我们可以模仿一下,把 8bits 数中的 1-2,3-4,5-6,7-8 看作 4 个 4 进制的数字,每一个 4 进制的数字对模 5 的贡献是多少呢?剩下的步骤就交给大家了!
选做内容
选做内容为扩展内容,不计入实验成绩。大家可以根据兴趣自行完成。
题目:闰年
2.2.1 小节的日期电路并没有考虑到闰年的影响。请编写代码,增加闰年对于 2 月日期的影响。