问题
I am very new to Verilog and I have been given a task to create a module that implements a register file with subtraction functionality. I do have an basic idea (I think) I do know that I need to do this by supplying the output of a XOR gate bundle as the second operand of the adder and a cary-in that is 1 (high or true) when the operation is subtraction and 0 (low or false) when it is anything else. I dont know how to do this. Any help would be appreciated.
Here is what I have so far:
module gvectorRF(Dout, RS1, RS2, RD, WDATA, cntstart, op, clk, reset);
parameter SIZE = 128;
parameter WINBITS = 2;
parameter WIDTH = 32;
localparam IDLE = 3'b000;
localparam VADD = 3'b001;
localparam VIN = 3'b010;
localparam VOUT = 3'b011;
localparam VSUB = 3'b100;
localparam VMUL = 3'b101;
localparam VMULH= 3'b110;
output [WIDTH-1:0] Dout;
input [4:0] RS1, RS2, RD;
input [WIDTH-1:0] WDATA;
input [WINBITS-1:0] cntstart;
input [1:0] op;
input clk, reset;
wire [WIDTH-1:0] RD1, RD2, muxout, addout;
wire uncon;
wire [WINBITS-1:0] cntout;
reg [1:0] cntrctl;
reg [1:0] state;
winrf #(.SIZE(SIZE), .WINBITS(WINBITS+5), .WIDTH(WIDTH))
vecwinrf(RD1, RD2, RS1, RS2, RD, muxout, {cntout, 5'b0}, clk,
/*
* ( (state==IDLE)&&((op==VIN)||(op==VADD)) )||
*/
((state==VIN)||(state==VSUB))
);
assign Dout = RD1;
yAdder #(WIDTH) vecadder(addout, uncon, RD1, RD2, 1'b0);
yMux #(WIDTH) vecmux(muxout, addout, WDATA, (state!=VADD));
cntr #(WINBITS) veccntr(cntout, Zout, cntstart, cntrctl, clk, reset);
always @(posedge reset)
state = IDLE;
always @(posedge clk)
begin
case (state)
IDLE:
state <= op;
default : if (Zout==1'b1)
state <= IDLE;
endcase // case (state)
/* We can put in here debugging code, but we delete it in the end
* $display("state: %2b, Z=%1b, cntrctl = %2b, cntout = %2b",
state, Zout, cntrctl, cntout);
$display("addout = %d, vecwinrf[RS1=%d] = %d, vecwinrf[RS2=%d] = %d",
addout,{cntout, 5'b0}+RS1, RD1, {cntout, 5'b0}+RS2, RD2);
*/
end
always @(state)
begin
case (state)
IDLE: cntrctl = 2'b01; // initialize cntr
default: cntrctl = 2'b11; // decrement cntr
endcase // case (state)
end
endmodule
However when I run my testbench the subtraction does not work, instead I get an 'x' instead of the actual value. In addition, the clock cycle does not repeat three times. The Dout spits an 'x' instead of values.
WDATA = 36
WDATA = 129
WDATA = 9
WDATA = 99
WDATA = 13
Sec. inp. bundle
WDATA = 141
WDATA = 101
WDATA = 18
WDATA = 1
WDATA = 13
Compute bundle
Out bundle //issues from here to end.
Dout = x
Dout = x
Dout = x
Dout = x
Dout = x //end
This is the testbench:
module testbench;
parameter TSTWIDTH = 8;
wire [TSTWIDTH-1:0] Dout;
reg [4:0] RS1, RS2, RD;
reg [TSTWIDTH-1:0] WDATA;
reg clk, reset;
reg [2:0] vecop;
integer i;
gvectorRF #(.SIZE(128), .WINBITS(2), .WIDTH(TSTWIDTH))
tstvectorRF(Dout, RS1, RS2, RD, WDATA, 2'b11, vecop, clk, reset);
initial
begin
clk = 0;
vecop = 3'b010; // INP
reset = 1;
RS1 = 5'b00000;
RS2 = 5'b00010;
RD = 5'b00000;
#1;
reset = 0;
#1 repeat (5)
begin
WDATA = $random & 255;
$display("WDATA = %d",WDATA);
#1 clk = 1; #1 clk = 0; #1;
vecop = 3'b000; // IDLE
end
RD = 5'b00010;
vecop = 3'b010; // INP
$display("Sec. inp. bundle");
#1 repeat (5)
begin
WDATA = $random & 255;
$display("WDATA = %d",WDATA);
#1 clk = 1; #1 clk = 0; #1;
vecop = 3'b000; // IDLE
end
RD = 5'b00001;
vecop = 3'b001; // VADD
vecop = 3'b101; // VMUL
vecop = 3'b110; // VMULH
vecop = 3'b100; // VSUB
$display("Compute bundle");
#1 repeat (45)
begin
#1 clk = 1; #1 clk = 0; #1;
vecop = 3'b000; // IDLE
end
$display("Out bundle");
vecop = 3'b011; // VOUT
RS1 = 5'b00001;
#1 repeat (5)
begin
#1 clk = 1; #1 clk = 0; #1;
vecop = 2'b00; // IDLE
$display("Dout = %d",Dout);
end
for (i=0; i<128; i=i+1)
begin
$display("R[%3d] = %3d", i, tstvectorRF.vecwinrf.rbank[i]);
end
end
// initial
// $monitor("%4d: clk=%b, Dout= %3d, WDATA=%8d",
// $time, clk, Dout, WDATA);
endmodule
来源:https://stackoverflow.com/questions/60879069/error-while-creating-a-module-that-implements-a-register-file-that-does-vector-s