其中A、B为输入,Ci-1为来自低位的进位,Ci为向高位的进位,S为输出的结果。
当有多位数相加时,可模仿笔算,用全加器构成串行进位加法器。
4位的乘法器就是用了3个4位串行进位加法器组成的。
module add_dataflow1(x,y,z,cin,cout);
input x,y,cin;
output z,cout;
assign z=x^y^cin;
assign cout=(x&y)|(x&cin)|(y&cin);
endmodule
这里定义了一个全加器模块,关于运算是根据真值表而来的,这里我直接用了。z表示输出的结果,cout表示进位。
module mul4_4(x, y, z);
input [3:0] x,y;
output [7:0] z;
wire [3:0]pp0,pp1,pp2,pp3;
wire a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,sum1,sum2,sum3,sum4,sum5,sum6;
assign pp0=x & {y[0],y[0],y[0],y[0]};
assign pp1=x & {y[1],y[1],y[1],y[1]};
assign pp2=x & {y[2],y[2],y[2],y[2]};
assign pp3=x & {y[3],y[3],y[3],y[3]};
assign z[0]=pp0[0];
add_dataflow1 add1_b(.x(pp0[1]),.y(pp1[0]),.z(z[1]),.cin(1'b0),.cout(a1));
add_dataflow1 add2_q(.x(pp0[2]),.y(pp1[1]),.z(sum1),.cin(a1),.cout(a2));
add_dataflow1 add3_b(.x(sum1),.y(pp2[0]),.z(z[2]),.cin(1'b0),.cout(a3));
add_dataflow1 add4_q(.x(pp0[3]),.y(pp1[2]),.z(sum2),.cin(a2),.cout(a4));
add_dataflow1 add5_q(.x(sum2),.y(pp2[1]),.z(sum3),.cin(a3),.cout(a5));
add_dataflow1 add6_b(.x(sum3),.y(pp3[0]),.z(z[3]),.cin(1'b0),.cout(a6));
add_dataflow1 add7_b(.x(pp1[3]),.y(a4),.z(sum4),.cin(1'b0),.cout(a7));
add_dataflow1 add8_q(.x(sum4),.y(pp2[2]),.z(sum5),.cin(a5),.cout(a8));
add_dataflow1 add9_q(.x(pp3[1]),.y(sum5),.z(z[4]),.cin(a6),.cout(a9));
add_dataflow1 add10_q(.x(a7),.y(pp2[3]),.z(sum6),.cin(a8),.cout(a10));
add_dataflow1 add11_q(.x(sum6),.y(pp3[2]),.z(z[5]),.cin(a9),.cout(a11));
add_dataflow1 add12_q(.x(a10),.y(pp3[3]),.z(z[6]),.cin(a11),.cout(a12));
assign z[7]=a12;
endmodule
这里就是不断调用加法器函数将与的结果和进位不断相加再输出。
`timescale 1ns/1ns
module mul_test;
reg [3:0] x;
reg [3:0] y;
wire [7:0] z;
mul4_4 u1(x,y,z);
initial
begin
x=4'b0000; y=4'b0000;
end
always #5
begin
y=y+1;
if(y==4'b1111)
begin
x=x+1;
y=4'b0000;
end
$monitor("x=%d y=%d z=%d",
$time,x,y,z,);
if(x==4'b1111)
begin
$stop;
end
end
endmodule
在quartus中的仿真结果如上所示,由数值可以发现结果准确。
分不清哪个加法器该用半加器还是全加器,导致代码出错,虽然有些结果一样,但是还是有很多不对的地方。或者忘记去定义一些变量。