64 位 ALU 输出在 TestBench 波形上显示高阻抗
64-bit ALU outputs are showing high impedance on TestBench waves
我必须制作一个 64 位 ALU,它接收 A 和 B 64 位输入、一个 carry_in 输入并输出一个 64 位结果和一个 1 位 carry_out。还有一个5位的函数——selectFS。其中 FS[0] 控制 B 是否反转(使用 2to1 多路复用器)。F[1] 对 A 做同样的事情。FS[4:2] 决定哪个操作(加法、减法、逻辑运算等)使用 8to1 多路复用器。下面是 ALU 和 Testbench 的代码。
我很确定我的测试台很好,ALU 的所有独立组件也很好。我对实例化和连接所有 inputs/outputs 的顶层不太自信。是什么导致波形中的高阻抗?
module ALU(A, B, FS, cin, cout, result);
input [63:0] A, B;
input [4:0] FS;
input cin;
output cout;
output [63:0] result;
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 1'b0, 1'b0, FS[4:2], result);
adder u6 (firstoutA, secoutB, cin, sum, cout);
firstmux u1 (A, !A, FS[1], firstoutA);
secmux u2 (B, !B, FS[0], secoutB);
Alu_shifter u5 (A, left, right);
endmodule
//--------------------------------------------------------------------------------//
//These are the two muxes to split into input and inverted input A,B
module firstmux(a, nota, firstS, firstoutA);
input [63:0] a, nota;
input firstS;
output reg [63:0] firstoutA;
always @(a or nota or firstS)
begin
case(firstS)
0 : firstoutA = a;
1 : firstoutA = nota;
default : firstoutA = 1'bx;
endcase
end
endmodule
//<><><><><><><>//
module secmux(b, notb, secS, secoutB);
input [63:0] b, notb;
input secS;
output reg [63:0] secoutB;
always @(b or notb or secS)
begin
case(secS)
0 : secoutB = b;
1 : secoutB = notb;
default : secoutB = 1'bx;
endcase
end
endmodule
//--------------------------------------------------------------------------------//
//This is the Shifter Blocks
module Alu_shifter (shiftA, right, left); //This shifter block shifts the A input once right or left
input [63:0] shiftA;
output [63:0] right;
output [63:0] left;
shift_right w1 ( //instantiate right shifter block
.a_R(shiftA),
.R(right)
);
shift_left w2 ( //instantiate left shifter block
.a_L(shiftA),
.L(left)
);
endmodule
////////><><><><><><><><><><><><><><><///////
module shift_right (a_R, R); // right shifter block
input [63:0] a_R;
output [63:0] R;
assign R = a_R >> 1; //shift A right once (shift in a 0)
endmodule
module shift_left (a_L, L); //left shifter block
input [63:0] a_L;
output [63:0] L;
assign L = a_L << 1; //shift A left once (shift in a 0)
endmodule
//End shifter blocks (3 total modules)
//----------------------------------------------------//////////////////////
//This is the Adder that Adds A, B and cin
module adder(addA, addB, nic, sum, cout);
input [63:0] addA, addB;
input nic;
output [63:0] sum;
output cout;
assign {cout, sum} = addA + addB + nic;
endmodule
//----------------------------------------------------//////////////////////
//This is the 8to1 Mux that decides which operation is put forward
module eight_one_mux(D0, D1, D2, D3, D4, D5, D6, D7, S, out);
input [63:0] D0, D1, D2, D3, D4, D5, D6, D7;
input [2:0] S;
output reg [63:0] out;
always @(D0 or D1 or D2 or D3 or D4 or D5 or D6 or D7 or S)
begin
case(S)
0 : out = D0; //And
1 : out = D1; //Or
2 : out = D2; //Adder
3 : out = D3; //xor
4 : out = D4; //lefter
5 : out = D5; //righter
6 : out = D6; //GND
7 : out = D7; //GND
default : out = 1'bx;
endcase
end
endmodule
////////////-------------------------------////////////////////////////////
module ALU_tb();
reg [63:0] A, B;
reg [4:0] FS;
reg cin;
wire cout;
wire [63:0] result;
ALU dut (
.A(A),
.B(B),
.FS(FS),
.cin(cin),
.cout(cout),
.result(result)
);
initial begin
A = 8'b11001100;
B = 8'b11001101;
FS = 5'b01101;
cin = 1;
end
always
#5 cin <= ~cin;
always begin
#5
A <= A + 1;
B <= B + 2;
#5;
end
initial begin
#100 $finish;
end
endmodule
```
意外的高阻抗 (z
) 值通常是未驱动信号的结果,这就是您的代码的问题。
adder u6 (firstoutA, secoutB, cin, sum, cout);
在上面的行中,您将 1 位信号 firstoutA
连接到 64 位 addA
输入端口。这将 firstoutA
连接到 addA[0]
,留下其他 63 位未驱动。因此,addA[63:1]
都是 z
.
firstoutA
是一个 1 位信号,因为你没有明确声明它。此外,未声明的信号被假定为 wire
类型,默认为 z
。
声明所有信号是一种很好的做法。
要查找所有未声明的信号,请将其添加到代码顶部:
`default_nettype none
你应该得到如下编译错误:
Error-[IND] Identifier not declared
Identifier 'firstoutA' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
Error-[IND] Identifier not declared
Identifier 'secoutB' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
首先您需要为模块之间的连接定义信号 (wire
)。例如,您有 left
和 right
作为 Alu_shifter
模块的输出,它们连接到 firstmux
和 secmux
模块;但是,它们未在您的顶级模块中定义。您应该将以下信号定义添加到您的顶层模块:
wire [63:0] left,right;
wire [63:0] firstoutA;
wire [63:0] secoutB;
wire [63:0] sum;
此外,eight_one_mux
模块采用八个 64 位输入。但是,您将其中的最后两个设置为 1'b0
。您应该将它们更改为 64'b0
,如下所示。
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 64'b0, 64'b0, FS[4:2], result);
最后,!A
不会反转 A
的所有位(B
也是如此)。它应用归约运算并生成 1 位信号(并且 firstmux
模块在其第二个输入端口中期望 64 位信号)。
我必须制作一个 64 位 ALU,它接收 A 和 B 64 位输入、一个 carry_in 输入并输出一个 64 位结果和一个 1 位 carry_out。还有一个5位的函数——selectFS。其中 FS[0] 控制 B 是否反转(使用 2to1 多路复用器)。F[1] 对 A 做同样的事情。FS[4:2] 决定哪个操作(加法、减法、逻辑运算等)使用 8to1 多路复用器。下面是 ALU 和 Testbench 的代码。
我很确定我的测试台很好,ALU 的所有独立组件也很好。我对实例化和连接所有 inputs/outputs 的顶层不太自信。是什么导致波形中的高阻抗?
module ALU(A, B, FS, cin, cout, result);
input [63:0] A, B;
input [4:0] FS;
input cin;
output cout;
output [63:0] result;
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 1'b0, 1'b0, FS[4:2], result);
adder u6 (firstoutA, secoutB, cin, sum, cout);
firstmux u1 (A, !A, FS[1], firstoutA);
secmux u2 (B, !B, FS[0], secoutB);
Alu_shifter u5 (A, left, right);
endmodule
//--------------------------------------------------------------------------------//
//These are the two muxes to split into input and inverted input A,B
module firstmux(a, nota, firstS, firstoutA);
input [63:0] a, nota;
input firstS;
output reg [63:0] firstoutA;
always @(a or nota or firstS)
begin
case(firstS)
0 : firstoutA = a;
1 : firstoutA = nota;
default : firstoutA = 1'bx;
endcase
end
endmodule
//<><><><><><><>//
module secmux(b, notb, secS, secoutB);
input [63:0] b, notb;
input secS;
output reg [63:0] secoutB;
always @(b or notb or secS)
begin
case(secS)
0 : secoutB = b;
1 : secoutB = notb;
default : secoutB = 1'bx;
endcase
end
endmodule
//--------------------------------------------------------------------------------//
//This is the Shifter Blocks
module Alu_shifter (shiftA, right, left); //This shifter block shifts the A input once right or left
input [63:0] shiftA;
output [63:0] right;
output [63:0] left;
shift_right w1 ( //instantiate right shifter block
.a_R(shiftA),
.R(right)
);
shift_left w2 ( //instantiate left shifter block
.a_L(shiftA),
.L(left)
);
endmodule
////////><><><><><><><><><><><><><><><///////
module shift_right (a_R, R); // right shifter block
input [63:0] a_R;
output [63:0] R;
assign R = a_R >> 1; //shift A right once (shift in a 0)
endmodule
module shift_left (a_L, L); //left shifter block
input [63:0] a_L;
output [63:0] L;
assign L = a_L << 1; //shift A left once (shift in a 0)
endmodule
//End shifter blocks (3 total modules)
//----------------------------------------------------//////////////////////
//This is the Adder that Adds A, B and cin
module adder(addA, addB, nic, sum, cout);
input [63:0] addA, addB;
input nic;
output [63:0] sum;
output cout;
assign {cout, sum} = addA + addB + nic;
endmodule
//----------------------------------------------------//////////////////////
//This is the 8to1 Mux that decides which operation is put forward
module eight_one_mux(D0, D1, D2, D3, D4, D5, D6, D7, S, out);
input [63:0] D0, D1, D2, D3, D4, D5, D6, D7;
input [2:0] S;
output reg [63:0] out;
always @(D0 or D1 or D2 or D3 or D4 or D5 or D6 or D7 or S)
begin
case(S)
0 : out = D0; //And
1 : out = D1; //Or
2 : out = D2; //Adder
3 : out = D3; //xor
4 : out = D4; //lefter
5 : out = D5; //righter
6 : out = D6; //GND
7 : out = D7; //GND
default : out = 1'bx;
endcase
end
endmodule
////////////-------------------------------////////////////////////////////
module ALU_tb();
reg [63:0] A, B;
reg [4:0] FS;
reg cin;
wire cout;
wire [63:0] result;
ALU dut (
.A(A),
.B(B),
.FS(FS),
.cin(cin),
.cout(cout),
.result(result)
);
initial begin
A = 8'b11001100;
B = 8'b11001101;
FS = 5'b01101;
cin = 1;
end
always
#5 cin <= ~cin;
always begin
#5
A <= A + 1;
B <= B + 2;
#5;
end
initial begin
#100 $finish;
end
endmodule
```
意外的高阻抗 (z
) 值通常是未驱动信号的结果,这就是您的代码的问题。
adder u6 (firstoutA, secoutB, cin, sum, cout);
在上面的行中,您将 1 位信号 firstoutA
连接到 64 位 addA
输入端口。这将 firstoutA
连接到 addA[0]
,留下其他 63 位未驱动。因此,addA[63:1]
都是 z
.
firstoutA
是一个 1 位信号,因为你没有明确声明它。此外,未声明的信号被假定为 wire
类型,默认为 z
。
声明所有信号是一种很好的做法。
要查找所有未声明的信号,请将其添加到代码顶部:
`default_nettype none
你应该得到如下编译错误:
Error-[IND] Identifier not declared
Identifier 'firstoutA' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
Error-[IND] Identifier not declared
Identifier 'secoutB' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
首先您需要为模块之间的连接定义信号 (wire
)。例如,您有 left
和 right
作为 Alu_shifter
模块的输出,它们连接到 firstmux
和 secmux
模块;但是,它们未在您的顶级模块中定义。您应该将以下信号定义添加到您的顶层模块:
wire [63:0] left,right;
wire [63:0] firstoutA;
wire [63:0] secoutB;
wire [63:0] sum;
此外,eight_one_mux
模块采用八个 64 位输入。但是,您将其中的最后两个设置为 1'b0
。您应该将它们更改为 64'b0
,如下所示。
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 64'b0, 64'b0, FS[4:2], result);
最后,!A
不会反转 A
的所有位(B
也是如此)。它应用归约运算并生成 1 位信号(并且 firstmux
模块在其第二个输入端口中期望 64 位信号)。