05_层次化设计全加器

该文详细介绍了如何使用Verilog进行层次化设计,以实现全加器。首先,通过实验目标阐述设计意图,接着展示模块框图,包括顶层模块和整体模块。然后,定义输入输出信号、真值表和波形图。在RTL部分,展示了half_adder和full_adder的代码实现,full_adder模块利用了half_adder的实例化。最后,提供了testbench模块用于仿真验证全加器的正确性。
摘要由CSDN通过智能技术生成

1. 实验目标

使用上一章节实现的半加器,结合层次化设计思想,设计并实现一个全加器。

2. 模块框图

2.1 顶层模块框图

在这里插入图片描述

2.2 模块整体框图

在这里插入图片描述

3. 输入输出信号描述

在这里插入图片描述

4. 真值表

在这里插入图片描述

5. 波形图

在这里插入图片描述

6. RTL

6.1 half_adder.v

module half_adder
(
	input   wire  in1, //位宽为1,可以省略
	input   wire  in2,
	
	output  wire  sum,
	output  wire  cout
);
 //sum:两个数加和的输出
 //cout:两个数进位的输出
 //{cout, sum} 就是2位
assign {cout, sum} = in1 + in2;

endmodule

6.2 full_adder.v

module full_adder
(
	input   wire  in1, //位宽为1,可以省略
	input   wire  in2,
	input   wire  cin,
	
	output  wire  sum,
	output  wire  cout
);
// 上面的端口定义完了以后,开始定义布线连接
 //wire define
 //在顶层中作为 half_adder_inst0 的 sum 信号和 half_adder_inst1 的 in1 信号的中间连线

wire h0_sum;
 //在顶层中作为 half_adder_inst0 的 cout 信号和或门的中间连线
wire h0_cout;
//在顶层中作为 half_adder_inst1 的 cout 信号和或门的中间连线
wire h1_cout;

//------------------------half_adder_inst0------------------------
// 实例化第一个半加器
//前面是实例化(调用)的模块的名字相当于是
//告诉顶层我要使用来自 half_adder 这个模块的功能
half_adder half_adder_inst0
(
	.in1(in1), 
	.in2(in2),
	
	.sum(h0_sum),
	.cout(h0_cout)
);

half_adder half_adder_inst1
(
	.in1(h0_sum), 
	.in2(cin),
	
	.sum(sum),
	.cout(h1_cout)
);

assign cout = h0_cout | h1_cout;

endmodule

7. testbench

`timescale 1ns/1ns
// 在这里面不需要对端口进行定义
module tb_full_adder();

//因为 testbench 不对外进行信号的输入输出,只是自己产生
//激励信号提供给内部实例化待测 RTL 模块使用,所以端口列表
//中没有内容,只是列出“()”,当然可以将“()”省略,括号
//后有个“;”不要忘记
//要在 initial 块和 always 块中被赋值的变量一定要是 reg 型
//在 testbench 中待测试 RTL 模块的输入永远是 reg 型变量


 //输出信号,我们直接观察,也不用在任何地方进行赋值
 //所以是 wire 型变量(在 testbench 中待测试 RTL 模块的输出永远是 wire 型变量)

reg in1;
reg in2;
reg cin;

 //输出信号,我们直接观察,也不用在任何地方进行赋值
 //所以是 wire 型变量(在 testbench 中待测试 RTL 模块的输出永远是 wire 型变量)
wire sum;
wire cout;

//初始化值在没有特殊要求的情况下给 0 或 1 都可以。如果不赋初值,仿真时信号
//会显示为不定态(ModelSim 中的波形显示红色)

initial
//在仿真中 begin...end 块中的内容都是顺序执行的,
//在没有延时的情况下几乎没有差别,看上去是同时执行的,
//如果有延时才能表达的比较明了;
//而在 rtl 代码中 begin...end 相当于括号的作用,
//在同一个 always 块中给多个变量赋值的时候要加上
	begin 
		in1 <= 1'b0;
		in2 <= 1'b0;
		cin <= 1'b0;
	end
//in1:产生输入随机数,模拟输入端 1 的输入情况
always #10 in1 <= {$random} % 2;//取模求余数,产生随机数 1'b0、1'b1//每隔 10ns 产生一次随机数
//in2:产生输入随机数,模拟输入端 2 的输入情况
always #10 in2 <= {$random} % 2;
 //cin:产生输入随机数,模拟前级进位的输入情况
always #10 cin <= {$random} % 2;

//下面的语句是为了在 ModelSim 仿真中直接打印出来信息便于观察信号变化的状态
//也可以不使用下面的语句而直接观察仿真出的波形

initial 
	begin
		$timeformat(-9, 0, "ns", 6);//设置显示的时间格式,此处表示的是(打印时间单
		//位为纳秒,小数点后打印的小数位为 0 位,时间值
		//后打印的字符串为“ns”,打印的最小数量字符为 6 个)

		//只要监测的变量(时间、in1, in2, sel, out)发生变化,就会打印出相应的信息
		$monitor("@time %t:in1=%b in2=%b cin=%b sum=%b cout=%b",$time,in1,in2,cin,sum,cout);
	end
//------------------------------------------------------------
//待测试 RTL 模块的实例化,相当于将待测试模块放到测试模块中,并将输入输出对应连接上
//测试模块中产生激励信号给待测试模块的输入,以观察待测试模块的输出信号是否正确
//------------------------------------------------
full_adder full_adder_inst //第一个是被实例化模块的名子,第二个是我们自己定义的在另一个
//模块中实例化后的名字。同一个模块可以在另一个模块中或不同的
//另外模块中被多次实例化,第一个名字相同,第二个名字不同
(
	//前面的“in1”表示被实例化模块中的信号,后面的“in1”表示实例化该模块并要和这个
	//模块的该信号相连接的信号(可以取名不同,一般取名相同,方便连接和观察)
	//“.”可以理解为将这两个信号连接在一起
	.in1(in1), //input in1
	.in2(in2), //input in2
	.cin(cin),
	.sum(sum),
	 
	.cout(cout) 
);
 
endmodule						 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@大宁字

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值