Verilog - 加法器主模块的问题
Verilog - Issue with Main Module for Adder
我正在尝试编写代码来模拟一个 8 位输入寄存器,输出输入数据的总和。该模型还包含时钟、启用和复位引脚。
我首先制作一个 1 位和 8 位加法器来开始这个问题,如下所示。 (请注意,我不关心 MSB 的执行引脚)。
module adder_1bit(A,B,Cin,S,Cout);
input A,B,Cin;
output Cout,S;
wire W1, W2, W3;
assign W1 = A ^ B;
assign W2 = Cin & W1;
assign W3 = A & B;
assign S = Cin ^ W1;
assign Cout = W2 | W3;
endmodule
module adder_8bit(Din,Sum);
input [7:0] Din;
output [7:0] Sum;
wire [7:0] C;
adder_1bit M1(Din[0],Din[0],1'b0,Sum[0],C[0]);
adder_1bit M2(Din[1],Din[1],C[0],Sum[1],C[1]);
adder_1bit M3(Din[2],Din[2],C[1],Sum[2],C[2]);
adder_1bit M4(Din[3],Din[3],C[2],Sum[3],C[3]);
adder_1bit M5(Din[4],Din[4],C[3],Sum[4],C[4]);
adder_1bit M6(Din[5],Din[5],C[4],Sum[5],C[5]);
adder_1bit M7(Din[6],Din[6],C[5],Sum[6],C[6]);
adder_1bit M8(Din[7],Din[7],C[6],Sum[7],C[7]);
endmodule
然后我做了一个测试台,一切正常。我的主要问题是将这些模块与我的 clk、enable 和 rst 代码结合起来。这是我目前拥有的。当我的复位引脚为高时,我的输出为 0。我还必须检查 MSB 是否为负,以确保我将其转换为正值(我的问题的一部分)。
module Main(Data_in,Start,rst,clk,Sum_Abs);
input rst, clk, Start;
input [7:0] Data_in;
output [7:0] Sum_Abs;
reg [7:0] Sum_Abs;
reg [7:0] Data_in_buffer;
adder_8bit M9(Data_in_buffer,Sum_abs);
always @(posedge clk)
begin
if(rst == 1'b1)
begin
Sum_Abs = 8'b00000000;
end
else if(Start == 1'b1)
begin
case(Data_in)
8'b1xxxxxxx: Data_in_buffer = ~Data_in + 1'b1;
8'b0xxxxxxx: Data_in_buffer = Data_in;
endcase
end
end
endmodule
这就是我的问题所在。当我创建如下所示的测试台时,我的总和输出始终为 'x'。我的问题必须来自主模块,因为我之前的测试没有遇到这个问题。我对verilog比较陌生,如果有任何提示或帮助将不胜感激,谢谢!
module Main_tb;
integer k;
reg signed [7:0] Din_tb;
reg str, rst_tb, clk_tb;
wire signed [7:0] Sum_tb;
Main DUT(Din_tb,str,rst_tb,clk_tb,Sum_tb);
initial begin
$display("\tData,\tOutput");
$monitor("\t%d,\t%d",Din_tb,Sum_tb);
Din_tb = 8'b00000001;
clk_tb = 0;
str = 1'b1;
rst_tb = 1'b0;
#5 clk_tb = 1;
#5 Din_tb = 8'b00000010;
#5 clk_tb = 0;
#5 Din_tb = 8'b00000100;
#5 clk_tb = 1;
#5 Din_tb = 8'b00001000;
#5 clk_tb = 0;
#5 Din_tb = 8'b00100000;
#5 clk_tb = 1;
end
endmodule
你有几个地方有错误:
在模块 Main Sum_Abs
中,从两个地方驱动。通过重置,它从 M9 模块中出来。你不能那样做。将 HDL 视为硬件:您刚刚将两个输出端口连接在一起,都驱动相同的电线。
做到这一点:
if(rst == 1'b1)
Data_in_buffer <= 8'b00000000;
然后你在 Main 中出现拼写错误:
output [7:0] Sum_Abs;
// ^Upper case!
adder_8bit M9(Data_in_buffer,Sum_abs);
// ^ Lower case
下一个错误是可以理解的,它在这里:
case(Data_in)
8'b1xxxxxxx: Data_in_buffer = ~Data_in + 1'b1;
8'b0xxxxxxx: Data_in_buffer = Data_in;
endcase
您假设忽略了 LS 7 位。但是 case 语句实际上是在寻找文字值 8'b1xxxxxxx 因此 with x-es.
您可以使用:
casez(Data_in)
8'b1zzzzzzz: Data_in_buffer <= ~Data_in + 1'b1;
8'b0zzzzzzz: Data_in_buffer <= Data_in;
endcase
但更简单的是看MS位:
if (Data_in[7]=1'b1)
....
第四个错误是您在时钟部分使用阻塞分配。如果你注意了,你会发现我在新代码中用 <= 替换了你所有的 =。
第五个错误在您的测试台中:您没有足够快地更改时钟。该代码仅查看上升沿,您可以更改上升沿和下降沿的输入。这不是制作时钟的最佳方法。如果你需要模拟一百万个时钟怎么办?
这就是你制作时钟的方式:
initial
begin
clk_tb= 1'b0;
forever
#50 clk_tb= ~clk_tb; // clock period of 100 time units
end
毕竟有些东西出来了,但我还没有检查是否出现了正确的值。我把它留给你。
我正在尝试编写代码来模拟一个 8 位输入寄存器,输出输入数据的总和。该模型还包含时钟、启用和复位引脚。
我首先制作一个 1 位和 8 位加法器来开始这个问题,如下所示。 (请注意,我不关心 MSB 的执行引脚)。
module adder_1bit(A,B,Cin,S,Cout);
input A,B,Cin;
output Cout,S;
wire W1, W2, W3;
assign W1 = A ^ B;
assign W2 = Cin & W1;
assign W3 = A & B;
assign S = Cin ^ W1;
assign Cout = W2 | W3;
endmodule
module adder_8bit(Din,Sum);
input [7:0] Din;
output [7:0] Sum;
wire [7:0] C;
adder_1bit M1(Din[0],Din[0],1'b0,Sum[0],C[0]);
adder_1bit M2(Din[1],Din[1],C[0],Sum[1],C[1]);
adder_1bit M3(Din[2],Din[2],C[1],Sum[2],C[2]);
adder_1bit M4(Din[3],Din[3],C[2],Sum[3],C[3]);
adder_1bit M5(Din[4],Din[4],C[3],Sum[4],C[4]);
adder_1bit M6(Din[5],Din[5],C[4],Sum[5],C[5]);
adder_1bit M7(Din[6],Din[6],C[5],Sum[6],C[6]);
adder_1bit M8(Din[7],Din[7],C[6],Sum[7],C[7]);
endmodule
然后我做了一个测试台,一切正常。我的主要问题是将这些模块与我的 clk、enable 和 rst 代码结合起来。这是我目前拥有的。当我的复位引脚为高时,我的输出为 0。我还必须检查 MSB 是否为负,以确保我将其转换为正值(我的问题的一部分)。
module Main(Data_in,Start,rst,clk,Sum_Abs);
input rst, clk, Start;
input [7:0] Data_in;
output [7:0] Sum_Abs;
reg [7:0] Sum_Abs;
reg [7:0] Data_in_buffer;
adder_8bit M9(Data_in_buffer,Sum_abs);
always @(posedge clk)
begin
if(rst == 1'b1)
begin
Sum_Abs = 8'b00000000;
end
else if(Start == 1'b1)
begin
case(Data_in)
8'b1xxxxxxx: Data_in_buffer = ~Data_in + 1'b1;
8'b0xxxxxxx: Data_in_buffer = Data_in;
endcase
end
end
endmodule
这就是我的问题所在。当我创建如下所示的测试台时,我的总和输出始终为 'x'。我的问题必须来自主模块,因为我之前的测试没有遇到这个问题。我对verilog比较陌生,如果有任何提示或帮助将不胜感激,谢谢!
module Main_tb;
integer k;
reg signed [7:0] Din_tb;
reg str, rst_tb, clk_tb;
wire signed [7:0] Sum_tb;
Main DUT(Din_tb,str,rst_tb,clk_tb,Sum_tb);
initial begin
$display("\tData,\tOutput");
$monitor("\t%d,\t%d",Din_tb,Sum_tb);
Din_tb = 8'b00000001;
clk_tb = 0;
str = 1'b1;
rst_tb = 1'b0;
#5 clk_tb = 1;
#5 Din_tb = 8'b00000010;
#5 clk_tb = 0;
#5 Din_tb = 8'b00000100;
#5 clk_tb = 1;
#5 Din_tb = 8'b00001000;
#5 clk_tb = 0;
#5 Din_tb = 8'b00100000;
#5 clk_tb = 1;
end
endmodule
你有几个地方有错误:
在模块 Main Sum_Abs
中,从两个地方驱动。通过重置,它从 M9 模块中出来。你不能那样做。将 HDL 视为硬件:您刚刚将两个输出端口连接在一起,都驱动相同的电线。
做到这一点:
if(rst == 1'b1)
Data_in_buffer <= 8'b00000000;
然后你在 Main 中出现拼写错误:
output [7:0] Sum_Abs;
// ^Upper case!
adder_8bit M9(Data_in_buffer,Sum_abs);
// ^ Lower case
下一个错误是可以理解的,它在这里:
case(Data_in)
8'b1xxxxxxx: Data_in_buffer = ~Data_in + 1'b1;
8'b0xxxxxxx: Data_in_buffer = Data_in;
endcase
您假设忽略了 LS 7 位。但是 case 语句实际上是在寻找文字值 8'b1xxxxxxx 因此 with x-es.
您可以使用:
casez(Data_in)
8'b1zzzzzzz: Data_in_buffer <= ~Data_in + 1'b1;
8'b0zzzzzzz: Data_in_buffer <= Data_in;
endcase
但更简单的是看MS位:
if (Data_in[7]=1'b1)
....
第四个错误是您在时钟部分使用阻塞分配。如果你注意了,你会发现我在新代码中用 <= 替换了你所有的 =。
第五个错误在您的测试台中:您没有足够快地更改时钟。该代码仅查看上升沿,您可以更改上升沿和下降沿的输入。这不是制作时钟的最佳方法。如果你需要模拟一百万个时钟怎么办?
这就是你制作时钟的方式:
initial
begin
clk_tb= 1'b0;
forever
#50 clk_tb= ~clk_tb; // clock period of 100 time units
end
毕竟有些东西出来了,但我还没有检查是否出现了正确的值。我把它留给你。