1. 全加器(full_adder):是用门电路实现两个二进制数相加并求出和的组合线路,称为一位全加器,一位全加器可以处理低位进位,并输出本位加法进位。多个一位全加器进行级联可以得到多位全加器。
(1) 一位全加器的真值表如下:假设Ai,Bi,Ci-1是输入信号,s1和c1是输出信号,并且有Ai是被加数,Bi是加数,相邻低位来的进位数是Ci-1,输出本位和是Si,向相邻高位进位数是Ci
根据真值表可以看到:一位全加器的表达式如下:
Si=Ai⊕Bi⊕Ci-1
也可以用一个异或门来代替或门对其中两个输入信号求和:
也是可以这么来理解的:
sum = ~a&~b&cin + ~a&b&~cin + ~b&a&~cin + a&b&cin = a^b^cin
cout = ~a&b&c + ~b&a&c + ~c&a&b + a&b&c = (a&b)|(a&cin)|(b&cin)
(其中a,b,cin是输入信号,sum和cout分别是求和和进位)
(2) 现在我们还是分三种描述方式来进行说明:
① 结构化描述方式(创建工程的名称是full_add):
创建的仿真文件和测试文件分别是full_add1和full_adder1
现在我们一起看一下这个仿真w文件的代码吧:
//结构化描述方式
module full_add1
(
input a,b,cin,
output sum,cout
);
wire s1,m1,m2,m3;//这个还是表示线网型的
xor(s1,a,b);//s1 = a^b,接着sum = s1^cin
xor(sum,s1,cin);
and(m1,a,b);//这个是m1 = a&b,下面的是m2 = a&cin,再接着是m3 = b&cin
and(m2,a,cin);
and(m3,b,cin);
or(m1,m2,m3);
endmodule
测试文件是:
module full_adder1();
reg Ain,Bin,Cin;
reg clk;//时钟
wire sum1,cout1;
initial
begin
#1
Ain = 0;
Bin = 0;
clk = 0;
Cin = 0;
end
always #5 clk = ~clk;
always @(posedge clk)
begin
Ain = {$random} % 2;
Bin = {$random} % 2;
Cin = {$random} % 2;
end
full_add1 u1(Ain,Bin,Cin,sum1,cout1);
endmodule
波形图是:
RTL电路图是:
所以可以清晰地看到这个全加器由两个异或门、三个与门、一个或门构成,代码显示了用纯结构的建模方式,其中xor 、and、or 是Verilog HDL 内置的门器件。以 xor x1 (S1, A, B) 该例化语句为例:xor 表明调用一个内置的异或门,器件名称xor ,代码实例化名x1(类似原理图输入方式)。括号内的S1,A,B 表明该器件管脚的实际连接线(信号)的名称,其中 A、B是输入,S1是输出。
② 数据流描述(创建的工程名叫做Project_1):
创建的仿真文件和测试文件分别叫做full_add2和full_adder2
下面是仿真文件的源代码:
module full_add2
(
input a,b,cin,
output cout,sum
);
wire s1,m1,m2,m3;
assign #2 s1 = a^b;
assign #2 sum = s1&cin;
assign #2 m1 =a&b;
assign #2 m2 = a&cin;
assign #2 m3 = b$cin;
assign #2 cout = m1|m2|m3;
endmodule//在个assign语句之间,是并行执行的,即各语句的执行和语句之间的顺序无关,当a变化的时候,s1和m1、m2同时变化,s1的变化又会造成sum的变化
测试文件的代码:
module full_adder2();
reg Ain,Bin,Cin,clk;//其中clk是时钟模块
wire sum1,cout1;
initial
begin
#1
Ain = 0;
Bin = 0;
Cin = 0;
clk = 0;
end
always #5 clk = ~clk;
always @(posedge clk)
begin
Ain = {$random}%2;
Bin = {$random}%2;
Cin = {$random}%2;
end
full_adder2 u2(Ain,Bin,Cin,sum1,cout1);
endmodule
波形图如下显示:
RTL电路图如下:
③ 行为描述方式:(Project_2是新创建的工程)
创建的仿真文件和测试文件分别是:full_add3和full_adder3
下面,我们一起看一下仿真文件代码:
module full_add3
(
input a,b,cin,
output sum,cout
);
reg s1,s2,s3;
reg sum,cout;
always @(a or b or cin)
begin
sum = (a^b)^cin;
s1 = a&cin;
s2 = b&cin;
s3 = a&b;
cout = (s1|s2)|s3;
end
endmodule
测试文件如下:
module full_adder3();
reg Ain,Bin,Cin,clk;
wire sum3,cout3;
initial
begin
#1
Ain = 0;
Bin = 0;
Cin = 0;
clk = 0;
end
always #5 clk = ~clk;
always @(posedge clk)
begin
Ain = {$random}%2;
Bin = {$random}%2;
Cin = {$random}%2;
end
full_add3 u3(Ain,Bin,Cin,sum3,cout3);
endmodule