9.4 实战演练——半加器
9.4.1 实验目标
设计并实现一个半加器,使用开发板上的按键KEY1、KEY2作为被加数输入,选择开发板上的LED灯D6表示相加和的输出,LED灯D7表示进位输出。
9.4.2 硬件资源
我们使用开发板上的按键和LED灯进行半加器的验证,选取KEY1、KEY2分别作为被加数in1、被加数in2的信号输入,以LED灯D6作为和的输出sum,以LED灯D7作为进位的输出cout,如图9-21所示。
图9-21 硬件资源
由图9-2可知,征途Pro开发板的按键未按下时为高电平,按下后为低电平,LED灯为低电平点亮。
9.4.3 程序设计
1. 模块框图
根据功能分析,该工程只需实现一个半加器的功能,所以设计成一个模块即可。将模块命名为half_adder,半加器有两个1bit的加数,分别命名为in1和in2,输出也有两个信号。为什么会是两个呢?不要忘记两个数加和后,除了求得的“和”以外,会有“进位”的情况,这里我们把进位信号单独拉出来,所以输出就有两个信号,分别为1bit的sum和cout信号,该模块的功能是实现输入任意两个1bit加数的组合都能求得正确的和与进位值。根据上面的分析设计出的Visio框图如图9-22所示。
图9-22 模块框图
端口列表与功能总结如表9-5所示。
表9-5 输入输出信号描述
2. 波形图绘制
经分析得,in1和in2均为1bit输入信号,其任意组合有4种,就能够全覆盖验证所有的输入情况。这里我们任意画了4种输入情况,每种输入情况的组合根据相加的结果会对应输出4种求得的和与进位关系,根据这种关系可以轻松地列出如表9-6所示的真值表,然后再根据真值表的输入与输出的对应关系画出波形图。其波形如图9-23所示,与真值表的关系一一对应。
表9-6 半加器真值表
图9-23 信号波形关系图
3. 代码编写
半加器参考代码如代码清单9-8所示。
代码清单9-8 半加器参考代码(half_adder.v)
1 module half_adder 2 ( 3 input wire in1 , //加数1 4 input wire in2 , //加数2 5 6 output wire sum , //两个数的加和 7 output wire cout //两个数加和后的进位 8 ); 9 10 //sum:两个数加和的输出 11 //cout:两个数进位的输出 12 assign {cout, sum} = in1 + in2; 13 14 endmodule
根据上面RTL代码综合出的RTL视图如图9-24所示,可以看到加法器被抽象为一个“ADDER”的基本单元。
图9-24 RTL视图
4. 仿真验证
(1)仿真文件编写
半加器仿真参考代码如代码清单9-9所示。
代码清单9-9 半加器仿真参考代码(tb_half_adder.v)
1 `timescale 1ns/1ns 2 module tb_half_adder(); 3 4 //reg define 5 reg in1; 6 reg in2; 7 8 //wire define 9 wire sum; 10 wire cout; 11 12 //初始化输入信号 13 initial begin 14 in1 <= 1'b0; 15 in2 <= 1'b0; 16 end 17 18 //in1:产生输入随机数,模拟加数1的输入情况 19 //取模求余数,产生随机数1'b0、1'b1,每隔10ns产生一次随机数 20 always #10 in1 <= {$random} % 2; 21 22 //in2:产生输入随机数,模拟加数2的输入情况 23 always #10 in2 <= {$random} % 2; 24 25 //------------------------------------------------------------ 26 initial begin 27 $timeformat(-9, 0, "ns", 6); 28 $monitor("@time %t:in1=%b in2=%b sum=%b cout=%b",$time,in1,in2,sum,cout); 29 end 30 //------------------------------------------------------------ 31 32 //--------------------half_adder_inst----------------- 33 half_adder half_adder_inst 34 ( 35 .in1 (in1 ), //input in1 36 .in2 (in2 ), //input in2 37 38 .sum (sum ), //output sum 39 .cout (cout ) //output cout 40 ); 41 42 endmodule
(2)仿真波形分析
Testbench编写完成后,启动ModelSim进行功能仿真验证。同样,我们也让波形运行了500ns,通过图9-25所示的波形可以观察到,in1和in2输入的值均为1bit随机数,而与之对应的sum和cout都是在输入变化的同一时刻立即变化,仔细核对每一组输入和输出之间的对应关系,发现波形中的“+”计算结果都是正确的,完全符合代码中的逻辑设计。
图9-25 仿真波形图
我们通过观察“Transcript”界面中打印的结果见图9-26发现与前面绘制真值表的结果一一对应,从而进一步验证了RTL代码设计的正确性。
图9-26 打印结果
5. 上板验证
仿真验证通过后,绑定引脚,对工程进行重新编译。将开发板连接12V直流电源和USB-Blaster下载器JTAG端口,线路正确连接后,打开开关为板卡上电,随后为开发板下载程序。
程序下载完毕后,开始进行结果验证。如图9-27所示,当按键KEY1、KEY2同时按下,in1和in2输出均为低电平,得到和sum为0,进位cout为0,D6、D7均被点亮。
图9-27 上板验证——同时按下KEY1和KEY2
如图9-28和图9-29所示,只按下按键KEY1或KEY2,in1或in2输出低电平,得到和sum为1,进位cout为0,D7被点亮。
图9-28 上板验证——只按下KEY1
图9-29 上板验证——只按下KEY2
如图9-30所示,两按键均未按下,in1和in2输出均为高电平,得到和sum为0,进位cout为1,D6被点亮。
图9-30 上板验证KEY1、KEY2均未按下