Verilog 全加器意外行为
Verilog Full Adder Unexpected Behavior
我正在尝试做一个非常基本的硬件 module/test 工作台来掌握 Verilog 的窍门。我试图实现一个全加器。
如果我没记错的话,你有三个输入,立即加数 a 和 b 以及 a 从第 2^n-1 位进位。
输出是求和和执行(它可以作为基本加法器中另一个模块的进位,或者调用非进位先行。)
如果我没记错的话输出逻辑是
总和 = (a&b) | (a&cin) | (b&cin) //或所有三个,其中任何一个都涵盖
cout = a^b^cin
这里是全加器模块
module FullAdder(
a,
b,
cin,
sum,
co
);
input a;
input b;
input cin;
output sum;
output co;
//wire a;
//wire b;
//wire ci;
wire sum;
wire co;
//At least two
assign co = (a & b) | (a & cin) | (b & cin);
//one or three
assign sum = a ^ b ^ cin; //(a & ~b & ~cin) | (~a & b & ~cin) | (~a & ~b & cin) | (a & b & cin);
endmodule
这里是测试台
module HalfAdderTB();
reg a_in;
reg b_in;
reg cin_in;
wire s_out;
wire cout_out;
FullAdder DUT(
a_in,
b_in,
cin_in,
s_out,
cout_out
);
initial begin
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b0;
#20
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b1;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b1;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b1;
b_in = 1'b0;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b1;
b_in = 1'b0;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
2,1 4%
a_in = 1'b1;
b_in = 1'b1;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
assign a_in = 1'b1;
assign b_in = 1'b1;
assign cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
$finish;
end
endmodule
我的输出是这样的
a:0,b:0,cin:0
s: 0, cout: 0
a:0,b:0,cin:1
s: 0, cout: 0
a:0,b:1,cin:0
s: 1, cout: 0
a:0,b:1,cin:1
s: 1, cout: 0
a:1,b:0,cin:0
s: 0, cout: 1
a:1,b:0,cin:1
s: 1, cout: 0
a:1,b:1,cin:0
s: 0, cout: 1
a:1,b:1,cin:1
s: 0, cout: 1
我相信我的代码中的逻辑语句与我在上面写的布尔方程式相匹配。我对自己的逻辑很有信心。我似乎无法弄清楚 Verilog 有什么问题。我是否遗漏了测试台对全加器的计时和输入?
您的代码没有问题,但是由于 $display
语句,您得到了这个奇怪的结果。如果您使用 $strobe
而不是 $display
,您的代码将工作正常。您也可以使用 $monitor
来显示结果。原因是 display 语句会立即执行,这样您的输出就不会更新为新值,而 strobe 只会在最后执行一个时刻,这样你的输出就会在那时更新。 monitor 用于在值发生变化时自动显示值。
由于您刚刚开始使用 verilog,我建议您通过这个 to understand how various display statements work in verilog and also to go through this link 了解特定时刻语句的执行顺序,以便您可以更好地规划您的代码
我正在尝试做一个非常基本的硬件 module/test 工作台来掌握 Verilog 的窍门。我试图实现一个全加器。
如果我没记错的话,你有三个输入,立即加数 a 和 b 以及 a 从第 2^n-1 位进位。
输出是求和和执行(它可以作为基本加法器中另一个模块的进位,或者调用非进位先行。)
如果我没记错的话输出逻辑是
总和 = (a&b) | (a&cin) | (b&cin) //或所有三个,其中任何一个都涵盖
cout = a^b^cin
这里是全加器模块
module FullAdder(
a,
b,
cin,
sum,
co
);
input a;
input b;
input cin;
output sum;
output co;
//wire a;
//wire b;
//wire ci;
wire sum;
wire co;
//At least two
assign co = (a & b) | (a & cin) | (b & cin);
//one or three
assign sum = a ^ b ^ cin; //(a & ~b & ~cin) | (~a & b & ~cin) | (~a & ~b & cin) | (a & b & cin);
endmodule
这里是测试台
module HalfAdderTB();
reg a_in;
reg b_in;
reg cin_in;
wire s_out;
wire cout_out;
FullAdder DUT(
a_in,
b_in,
cin_in,
s_out,
cout_out
);
initial begin
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b0;
#20
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b1;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b1;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b1;
b_in = 1'b0;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b1;
b_in = 1'b0;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
2,1 4%
a_in = 1'b1;
b_in = 1'b1;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
assign a_in = 1'b1;
assign b_in = 1'b1;
assign cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
$finish;
end
endmodule
我的输出是这样的
a:0,b:0,cin:0
s: 0, cout: 0
a:0,b:0,cin:1
s: 0, cout: 0
a:0,b:1,cin:0
s: 1, cout: 0
a:0,b:1,cin:1
s: 1, cout: 0
a:1,b:0,cin:0
s: 0, cout: 1
a:1,b:0,cin:1
s: 1, cout: 0
a:1,b:1,cin:0
s: 0, cout: 1
a:1,b:1,cin:1
s: 0, cout: 1
我相信我的代码中的逻辑语句与我在上面写的布尔方程式相匹配。我对自己的逻辑很有信心。我似乎无法弄清楚 Verilog 有什么问题。我是否遗漏了测试台对全加器的计时和输入?
您的代码没有问题,但是由于 $display
语句,您得到了这个奇怪的结果。如果您使用 $strobe
而不是 $display
,您的代码将工作正常。您也可以使用 $monitor
来显示结果。原因是 display 语句会立即执行,这样您的输出就不会更新为新值,而 strobe 只会在最后执行一个时刻,这样你的输出就会在那时更新。 monitor 用于在值发生变化时自动显示值。
由于您刚刚开始使用 verilog,我建议您通过这个