Verilog——半加器详解
-
半加器:用于计算两个一位二进制相加,不考虑低位进位。
(1) 我们现在假设一下:a和b都是输入信号,cout是输出信号,sum是求和
(2) 那么它们的真值表可以表示为:
~~~~ 加数a 加数b 进位cout 和数sum
根据真值表,可以快速的得到输入输出关系(逻辑结构)是:
cout = a^b(表示a异或b)也就是(a&(b)+b&(a))
sum = a&b(表示a与b,也就是and(sum,a,b))
(3) 下面,我们分结构描述、行为描述和数据流描述来写半加器的源代码
在此之前,Vivado的安装说明以及使用说明参见微信公众号“空谷小莜蓝”获取
① 我们创建的新工程的名字就叫做:half_add,我们首先来看的就是结构描述:我们在Design Sources中创建一个新的仿真文件:half_add1,在Simulation Sources中创建一个新的测试文件:tb_half_add1,准备工作就是这样
② 在half_add1中写的仿真源代码是:module half_add1
(
input a,b,
output cout,sum
/开始在模块中声明了输入信号:a,b和输出信号cout和sum/
);
//下面开始结构描述,操作关键字(输出,输入1,输入2,…输入n)
xor(cout,a,b);
and(sum,a,b);
//上面的两行分别表示:a和b进行异或运算值传递给cout,a和b进行与运算值传递给sum
endmodule
③ 测试文件源代码是:
在tb_half_add1中:
module tb_half_add1();
reg Ain,Bin;//定义两个寄存器型的测试信号Ain和Bin
reg clk;//clk是时钟
wire sum1,cout1;//声明2个线网型的信号sum1和cout1
initial
begin//#表示时延,开始的时候电流可能有点不稳定,后面Ain和Bin代表信号的初始化
#1
Ain = 0;
Bin = 0;
clk = 0;
end
always #5 clk = ~clk;//这个#5也表示时延5个周期,并且always可以用于组合逻辑和时序逻辑,clk = ~clk必须有时延,否则会形成“死锁”,代表时序逻辑,信号在这儿停留5个周期
always @(posedge clk)//这个表示触发条件是:边沿触发
begin//这个表示产生随机数
Ain = {$random} % 2;
Bin = {$random} % 2;
end
half_add1 u1(Ain,Bin,sum1,cout1);//这个是调用原来的仿真文件,我们这个是顺序对应,所以不需要.a(a)这么写了
endmodule
④ 下面,我们就可以在Vivado中进行仿真测试了
可以得到RTL电路图:
和仿真波形图:
(4) 行为描述
创建的仿真文件和测试文件分别是:half_add2和tb_half_add2
① 仿真文件代码是:
module half_add2
(
input a,b,
output cout ,sum
);
reg sum ,cout;
always @(a or b)
begin
case({a,b})//表示多分支选择
2'b00:begin//2'b00之类的代表位宽为2的二进制数
sum = 0;
cout = 0;
end
2'b01:begin
sum = 1;
cout = 0;
end
2'b10:begin
sum = 1;
cout = 0;
end
2'b11:begin
sum = 0;
cout = 1;
end
endcase
end
endmodule
② 测试文件代码是:
module tb_half_add2();
reg Ain,Bin;
reg clk;//时钟
wire sum2,cout2;
initial
begin
#1
Ain = 0;
Bin = 0;
clk = 0;
end
always #5 clk = ~clk;
always @(posedge clk)
begin
Ain = {$random} % 2;
Bin = {$random} % 2;
end
half_add2 hadder2(Ain,Bin,sum2,cout2);
endmodule
仿真波形图是:
RTL电路图是:
(5) 数据流描述:
创建的仿真文件和测试文件分别是:half_add3和tb_half_add3
① 仿真文件源代码是:
module half_add3
(
input a,b,
output sum,cout
);
assign sum = a^b;
assign cout = a&b;
endmodule
② 测试文件源代码是:
module tb_half_add3();
reg Ain,Bin;
reg clk;
wire sum3,cout3;
initial
begin
#1
Ain = 0;
Bin = 0;
clk = 0;
end
always #5 clk = ~clk;
always @(posedge clk)
begin
Ain = {$random}%2;
Bin = {$random}%2;
end
half_add3 u3(Ain,Bin,sum,cout);
endmodule
仿真波形图是:
RTL电路图是:
然,这个RTL电路图可能不完全相同,但是仿真图结果都是一样的
觉得本文可以的同学可以关注一下微信公众号“空谷小莜蓝”,我相信后期微信公众号会越来越好看的,谢谢~~