FPGA Verilog开发实战指南:基于Intel Cyclone IV(基础篇)
上QQ阅读APP看书,第一时间看更新

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均未按下