当输出重叠时,种类卡在输出上
Kind stuck on the output when the output overlap
我对 verilog 很陌生。
所以这是我的问题:
Implement 16 bits ALU with 16 bit register. This project should meet the following requirement.
1. Design a 16 bitALU :
Design a 16 bit ALU that X as input (eg. A,B..) and produces one 16 bit result.The ALU should perform the following functions.
Minimum 5 operations for both ALU and LOGIC.
2. Design a 16x16 bit register file.
3. Design a control unit.
所以我的计划是制作一堆模块,每个模块都有操作。然后我在测试台上收集它。但问题是现在。输出似乎重叠并变成红色和 x。
这是我的添加模块。
module Add(A,B,Y,S,clk,enb);
parameter BITS=8;
input clk,enb;
input [BITS - 5:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 000))
begin
assign Y = A + B;
end
end
endmodule
Tolak 模块(负模块)
module Tolak(A,B,Y,S,clk,enb);
parameter BITS=8;
input clk,enb;
input [BITS - 5:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 010))
begin
assign Y = A - B;
end
end
endmodule
Darab 模块(乘法模块)
module Darab(A,B,Y,S,clk,enb);
parameter BITS=8;
input clk,enb;
input [BITS - 5:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 011))
begin
assign Y = A * B;
end
end
endmodule
GateOr 模块
module GateOr(A,B,Y,S,clk,enb);
parameter BITS=16;
input clk,enb;
input [BITS - 14:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 011))
begin
assign Y = A | B ;
end
end
endmodule
门及模块
module GateAnd(A,B,Y,S,clk,enb);
parameter BITS=16;
input clk,enb;
input [BITS - 14:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 100))
begin
assign Y = A & B;
end
end
endmodule
这是我的测试台
module Maintb ();
parameter SIZE=8;
reg clk, enb ;
reg [SIZE-6:0] S;
reg[SIZE-1:0] A,B;
wire[SIZE-1:0] Y;
initial
begin
clk = 1'b0; enb = 1'b0;
end
// generate clock
always
begin
#(10) clk = !clk;
end
always begin
//#(10);
#10; enb = 1'b1; A=00000001; B=00000000; S=000; //add
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=001; //tolak
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=010; //darab
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=011; //or
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=100; //and
//#(10);
end
defparam dut.BITS = SIZE;
defparam dut1.BITS = SIZE;
defparam dut2.BITS = SIZE;
defparam gate.BITS = SIZE;
defparam gate1.BITS = SIZE;
Add dut (A,B,Y,S,clk,enb); //000
Tolak dut1 (A,B,Y,S,clk,enb); //001
Darab dut2 (A,B,Y,S,clk,enb); //010
GateOr gate (A,B,Y,S,clk,enb); //011
GateAnd gate1 (A,B,Y,S,clk,enb);//100
Endmodule
HDL编码时注意以下几点:
- 对顺序硬件使用
<=
,对组合硬件使用=
- 永远不要在 s 内部使用赋值,反之亦然
- 以正确的方式实例化模块,即
<module name> #(parameter <paramters_list>) <instant_name >
- 指定输入转换到时钟边沿,避免显式使用#delay
块的分层拓扑结构:
从图中可以看出,ALU是顶层实体,包含子模块,它们相互连接或在顶层共享信号。
Testbench 具有最高级别的顶部,其中 DUT 的实例(设计的顶部将被测试)- 正在测试的设计。
这基本上是将信号激励到 DUT 并从中获得响应。
确保您没有从多个模块驱动相同的信号,就像您的情况一样,它是由 ALU 的 add、sub、mul、AND 和 OR 模块驱动的 Y
,这需要分开。
删除了clk
信号,因为组合电路根本不需要clk
。
用tb查看你干净的代码,按上面提到的修改:
module Add #(parameter BITS=8)(A,B,Y,S,enb);
input wire enb;
input wire [2:0] S;
input wire [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A + B) & {BITS{enb & (S == 3'b000)}};
endmodule
module Tolak #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A - B) & {BITS{enb & (S == 3'b001)}};
endmodule
module Darab #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A * B) & {BITS{enb & (S == 3'b010)}}; // truncated to 8 bit only
endmodule
module GateOr #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire[BITS - 1:0] Y;
assign Y = (A | B) & {BITS{enb & (S == 3'b011)}}; // truncated to 8 bit only
endmodule
module GateAnd #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A & B) & {BITS{enb & (S == 3'b100)}}; // truncated to 8 bit only
endmodule
module Maintb ();
parameter SIZE=8;
reg clk, enb ;
reg [2:0] S;
reg [SIZE -1:0] A,B;
wire [SIZE -1:0] Y,Y1,Y2,Y3,Y4,Y5;
Add #(SIZE) dut (A,B,Y1,S,enb); //000
Tolak #(SIZE) dut1 (A,B,Y2,S,enb); //001
Darab #(SIZE) dut2 (A,B,Y3,S,enb); //010
GateOr #(SIZE) gate (A,B,Y4,S,enb); //011
GateAnd #(SIZE) gate1 (A,B,Y5,S,enb);//100
assign Y = Y1 | Y2 | Y3 | Y4 | Y5;
initial
begin
clk = 1'b0;
enb = 1'b0;
enb = 1'b0; A=8'b0000_0000; B=8'b0001_0000; S=3'b000;
end
// generate clock
always #10 clk = ~clk;
initial
begin
@(posedge clk);
@(posedge clk);
@(posedge clk);
@(posedge clk);
@(posedge clk); enb = 1'b1; A=8'b0000_0001; B=8'b0000_0010; S=3'b000; //add
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b0000_0011; B=8'b0010_0000; S=3'b001; //tolak
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b0000_1001; B=8'b0000_0000; S=3'b010; //darab
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b0010_0001; B=8'b0100_0000; S=3'b011; //or
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b1000_0001; B=8'b0000_0000; S=3'b100; //and
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b0; A=8'b0000_0000; B=8'b0001_0000; S=3'b000; //and
#100 $finish;
end
initial
begin
$monitor("clk %b A-%b B-%b Y-%b S-%b enb-%b",clk, A, B, Y, S, enb);
end
endmodule
模拟:
首先,模块 GateOr 和 GateAnd 的 S 信号中会有非法范围...
input [BITS - 14:0] S;
BITS = 8 使它......好吧,[-6:0]。除此之外,您同时将所有输出驱动到 Y。假设您在模块中执行逻辑或,而不是与,所有这些都将立即激活。
很抱歉,您的设计完全错误。您应该使每个子块时钟独立(使用 always @(*)
块而不是时钟驱动块),然后在顶部模块中实例化所有子块,每个子块的输出驱动到 Y_Add
, Y_Tolak
, Y_Darab
, Y_GateOr
和 Y_GateAnd
信号。最后,在顶层,您可以有一个时钟块,内容如下:
always @(posedge clk)
begin:
if (enb == 1'b1):
case (S)
3'b000: Y <= Y_Add;
3'b001: Y <= Y_Tolak;
[...]
endcase
end
并确保 Y
是 reg
,而不是 wire
。基本上,您将实现一个寄存器,其值由多路复用器驱动。
我对 verilog 很陌生。 所以这是我的问题:
Implement 16 bits ALU with 16 bit register. This project should meet the following requirement.
1. Design a 16 bitALU : Design a 16 bit ALU that X as input (eg. A,B..) and produces one 16 bit result.The ALU should perform the following functions. Minimum 5 operations for both ALU and LOGIC.
2. Design a 16x16 bit register file.
3. Design a control unit.
所以我的计划是制作一堆模块,每个模块都有操作。然后我在测试台上收集它。但问题是现在。输出似乎重叠并变成红色和 x。
这是我的添加模块。
module Add(A,B,Y,S,clk,enb);
parameter BITS=8;
input clk,enb;
input [BITS - 5:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 000))
begin
assign Y = A + B;
end
end
endmodule
Tolak 模块(负模块)
module Tolak(A,B,Y,S,clk,enb);
parameter BITS=8;
input clk,enb;
input [BITS - 5:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 010))
begin
assign Y = A - B;
end
end
endmodule
Darab 模块(乘法模块)
module Darab(A,B,Y,S,clk,enb);
parameter BITS=8;
input clk,enb;
input [BITS - 5:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 011))
begin
assign Y = A * B;
end
end
endmodule
GateOr 模块
module GateOr(A,B,Y,S,clk,enb);
parameter BITS=16;
input clk,enb;
input [BITS - 14:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 011))
begin
assign Y = A | B ;
end
end
endmodule
门及模块
module GateAnd(A,B,Y,S,clk,enb);
parameter BITS=16;
input clk,enb;
input [BITS - 14:0] S;
input [BITS - 1:0] A ,B;
output [BITS - 1:0] Y;
reg [BITS - 1:0] Y;
always @(posedge clk)
begin
if
((enb==1) || (S == 100))
begin
assign Y = A & B;
end
end
endmodule
这是我的测试台
module Maintb ();
parameter SIZE=8;
reg clk, enb ;
reg [SIZE-6:0] S;
reg[SIZE-1:0] A,B;
wire[SIZE-1:0] Y;
initial
begin
clk = 1'b0; enb = 1'b0;
end
// generate clock
always
begin
#(10) clk = !clk;
end
always begin
//#(10);
#10; enb = 1'b1; A=00000001; B=00000000; S=000; //add
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=001; //tolak
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=010; //darab
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=011; //or
#(10); enb = 1'b0;
#10; enb = 1'b1; A=00000001; B=00000000; S=100; //and
//#(10);
end
defparam dut.BITS = SIZE;
defparam dut1.BITS = SIZE;
defparam dut2.BITS = SIZE;
defparam gate.BITS = SIZE;
defparam gate1.BITS = SIZE;
Add dut (A,B,Y,S,clk,enb); //000
Tolak dut1 (A,B,Y,S,clk,enb); //001
Darab dut2 (A,B,Y,S,clk,enb); //010
GateOr gate (A,B,Y,S,clk,enb); //011
GateAnd gate1 (A,B,Y,S,clk,enb);//100
Endmodule
HDL编码时注意以下几点:
- 对顺序硬件使用
<=
,对组合硬件使用=
- 永远不要在 s 内部使用赋值,反之亦然
- 以正确的方式实例化模块,即
<module name> #(parameter <paramters_list>) <instant_name >
- 指定输入转换到时钟边沿,避免显式使用#delay
块的分层拓扑结构:
从图中可以看出,ALU是顶层实体,包含子模块,它们相互连接或在顶层共享信号。
Testbench 具有最高级别的顶部,其中 DUT 的实例(设计的顶部将被测试)- 正在测试的设计。
这基本上是将信号激励到 DUT 并从中获得响应。
确保您没有从多个模块驱动相同的信号,就像您的情况一样,它是由 ALU 的 add、sub、mul、AND 和 OR 模块驱动的 Y
,这需要分开。
删除了clk
信号,因为组合电路根本不需要clk
。
用tb查看你干净的代码,按上面提到的修改:
module Add #(parameter BITS=8)(A,B,Y,S,enb);
input wire enb;
input wire [2:0] S;
input wire [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A + B) & {BITS{enb & (S == 3'b000)}};
endmodule
module Tolak #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A - B) & {BITS{enb & (S == 3'b001)}};
endmodule
module Darab #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A * B) & {BITS{enb & (S == 3'b010)}}; // truncated to 8 bit only
endmodule
module GateOr #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire[BITS - 1:0] Y;
assign Y = (A | B) & {BITS{enb & (S == 3'b011)}}; // truncated to 8 bit only
endmodule
module GateAnd #(parameter BITS=8) (A,B,Y,S,enb);
input enb;
input [2:0] S;
input [BITS - 1:0] A ,B;
output wire [BITS - 1:0] Y;
assign Y = (A & B) & {BITS{enb & (S == 3'b100)}}; // truncated to 8 bit only
endmodule
module Maintb ();
parameter SIZE=8;
reg clk, enb ;
reg [2:0] S;
reg [SIZE -1:0] A,B;
wire [SIZE -1:0] Y,Y1,Y2,Y3,Y4,Y5;
Add #(SIZE) dut (A,B,Y1,S,enb); //000
Tolak #(SIZE) dut1 (A,B,Y2,S,enb); //001
Darab #(SIZE) dut2 (A,B,Y3,S,enb); //010
GateOr #(SIZE) gate (A,B,Y4,S,enb); //011
GateAnd #(SIZE) gate1 (A,B,Y5,S,enb);//100
assign Y = Y1 | Y2 | Y3 | Y4 | Y5;
initial
begin
clk = 1'b0;
enb = 1'b0;
enb = 1'b0; A=8'b0000_0000; B=8'b0001_0000; S=3'b000;
end
// generate clock
always #10 clk = ~clk;
initial
begin
@(posedge clk);
@(posedge clk);
@(posedge clk);
@(posedge clk);
@(posedge clk); enb = 1'b1; A=8'b0000_0001; B=8'b0000_0010; S=3'b000; //add
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b0000_0011; B=8'b0010_0000; S=3'b001; //tolak
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b0000_1001; B=8'b0000_0000; S=3'b010; //darab
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b0010_0001; B=8'b0100_0000; S=3'b011; //or
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b1; A=8'b1000_0001; B=8'b0000_0000; S=3'b100; //and
@(posedge clk); enb = 1'b0;
@(posedge clk); enb = 1'b0; A=8'b0000_0000; B=8'b0001_0000; S=3'b000; //and
#100 $finish;
end
initial
begin
$monitor("clk %b A-%b B-%b Y-%b S-%b enb-%b",clk, A, B, Y, S, enb);
end
endmodule
模拟:
首先,模块 GateOr 和 GateAnd 的 S 信号中会有非法范围...
input [BITS - 14:0] S;
BITS = 8 使它......好吧,[-6:0]。除此之外,您同时将所有输出驱动到 Y。假设您在模块中执行逻辑或,而不是与,所有这些都将立即激活。
很抱歉,您的设计完全错误。您应该使每个子块时钟独立(使用 always @(*)
块而不是时钟驱动块),然后在顶部模块中实例化所有子块,每个子块的输出驱动到 Y_Add
, Y_Tolak
, Y_Darab
, Y_GateOr
和 Y_GateAnd
信号。最后,在顶层,您可以有一个时钟块,内容如下:
always @(posedge clk)
begin:
if (enb == 1'b1):
case (S)
3'b000: Y <= Y_Add;
3'b001: Y <= Y_Tolak;
[...]
endcase
end
并确保 Y
是 reg
,而不是 wire
。基本上,您将实现一个寄存器,其值由多路复用器驱动。