I am building an ALU in Verilog and my self-checking testbench keeps receiving this continuous blue error? - verilog

I am tasked with building an ALU. However, I must not understand how the self-checking testbench with file.tv should run. I have run other simple testbenches just fine. I am sure there is a problem in the way that my testbench module is written,
code compiles (using quartus)
made a text file with binary and turned it into a "test.tv" file
opened modelsim and added file
when I run it, is has an issue where it just keeps running blue errors..
Here is my code:
module ALU(input [31:0] a,b,
input [2:0] f,
output reg [31:0] y ,
output reg zero);
always #(*) begin
case(f)
3'b000: y = a & b;
3'b001: y = a | b;
3'b010: y = a + b;
3'b011: y = 32'b0;
3'b100: y = a & ~b;
3'b101: y = a | ~b;
3'b110: y = a - b;
3'b111: y = a < b;
default: y = 32'b0;
endcase
if(y==0)
zero=1'b1;
else
zero=1'b0;
end
endmodule
//**********************
module ALUtest();
reg clk;
reg [31:0] a, b, yexpected;
wire [31:0] y;
reg [2:0] f;
reg zeroexpected;
wire zero;
reg [31:0] vectornum, errors;
reg [100:0] testvectors[10000:0];
ALU dut(a,b,f,y,zero);
always
begin
clk = 1; #5; clk = 0; #5;
end
initial
begin
$readmemb("test.tv", testvectors);
vectornum = 0; errors = 0;
end
always#(posedge clk)
begin
#1; {a,b,f, yexpected,zeroexpected} = testvectors[vectornum];
end
always #(negedge clk)
begin
if (y !== yexpected) begin
$display("Error: inputs = %b", {a,b,f});
$display(" outputs = %b (%b expected)", y, yexpected);
errors = errors + 1;
end
vectornum = vectornum + 1;
if (testvectors[vectornum] === 4'bx) begin
$display("%d tests completed with %d errors", vectornum, errors);
$stop;
end
end
endmodule
//*************************************
CONTINUOUS ERROR THAT KEEPS RUNNING UNTIL I STOP IT:
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
This is what my "test.tv" file looks like in binary
00000000000000000000000000000000_00000000000000000000000000000000_010_00000000000000000000000000000000_1
00000000000000000000000000000000_11111111111111111111111111111111_010_11111111111111111111111111111111_0
00000000000000000000000000000000_01010101010101010101010101010101_010_01010101010101010101010101010101_0
I know this might seem stupid and simple, but I am really trying to learn this and obviously do not understand something. Can someone please help? Thanks in advance!

testvectors is declared as:
reg [100:0] testvectors[10000:0];
100:0 means testvectors is 101 bits wide, but you are comparing it to a 4-bit value (4'bx is the same as 4'bxxxx).
Change:
if (testvectors[vectornum] === 4'bx) begin
to:
if (testvectors[vectornum] === {101{1'bx}}) begin
This stops for me using your 3-line test.tv file.
Note that the LHS (32*3+3+1) is 100 bits, but the RHS is 101 bits in the following expression:
{a,b,f, yexpected,zeroexpected} = testvectors[vectornum]
Also, you only specify 100 bits in the test.tv file. Perhaps you should declare testvectors as 100 bits wide:
reg [99:0] testvectors[10000:0];

Related

Problem with VCS simulation for MAC operation

I intended to write and simulate a module performing MAC operation. My code is shown below
module PE # (
parameter DW = 8
)
(
input clk,
input rst_n,
input [DW-1 : 0] cin,
input [DW-1 : 0] w,
output [DW-1 : 0] cin_out,
output [DW-1 : 0] w_out,
output [2*DW : 0] pe_out
);
reg [DW-1 : 0] cin_reg;
reg [DW-1 : 0] w_reg;
reg [2*DW : 0] m_reg;
reg [2*DW : 0] pe_reg;
always #(posedge clk) begin
if(rst_n==1'b0) begin
pe_reg <= 0;
cin_reg <= 0;
w_reg <= 0;
end
else begin
cin_reg <= cin;
w_reg <= w;
m_reg <= cin_reg * w_reg;
pe_reg <= pe_reg + m_reg;
end
end
assign cin_out = cin_reg;
assign w_out = w_reg;
assign pe_out = pe_reg;
endmodule
I used VCS to simulate, however, pe_out kept xxxxxxxx as shown in fig below.
false wave
I have asked my friend to use verilator to simulate, it can work as expected. And if I delete pe_reg <= pe_reg + m_reg, it still works. Therefore, the issue is likely to be caused by the add operation? But I haven't solved it yet.
I'll be appreciate if anyone can give me some instructions. It have confused me for hours.
My tb is written as below.
module tb_PE;
reg clk;
reg rst_n;
reg [7:0] cin;
reg [7:0] w;
wire [7:0] cin_out;
wire [7:0] w_out;
wire [16:0] pe_out;
wire [16:0] pe_out_tmp;
initial begin
clk = 0;
forever begin
#10;
clk = ~clk;
end
end
initial begin
rst_n = 1'b1;
#5;
rst_n = 1'b0;
#10;
rst_n = 1'b1;
#5;
cin = 8'h01;
w = 8'h02;
#15;
cin = 8'h03;
w = 8'h04;
#20;
cin = 8'h05;
w = 8'h03;
#20;
cin = 8'h90;
w = 8'h88;
#20;
cin = 8'h65;
w = 8'h20;
#100;
$finish;
PE PE_U (
.clk(clk),
.rst_n(rst_n),
.cin(cin),
.w(w),
.cin_out(cin_out),
.w_out(w_out),
.pe_out(pe_out)
);
end
As #mkrieger1 mentioned, you have not initialized m_reg. So, the following is happening:
at the first posedge you initialized some of the variables, including pe_reg, while m_reg is still x.
at the second posedge m_reg is still x. Using nonblocking assignment you schedule it to change later, but in this expression pe_reg <= pe_reg + m_reg; it is still x.
as a result, pe_reg becomes x again because m_reg is still x and it will stays same because it is used recursively in the expression.
So, the easiest way to handle it is to initialize m_reg in the same bucket as pe_reg. If for some reason it is not acceptable, you need to delay evaluation of pe_reg for another cycle.

Unexpected high impedance output

I'm writing an ALU for a processor I'm designing (first RTL project) and I'm getting a high impedance output on ALU_out when I run my testbench, even though the flags do get set and are output correctly.
module alu(
input clk,
input reset,
input [7:0] A, B,
input [3:0] Op_Sel,
output [7:0] ALU_out,
output C, V, N, Z
);
reg [8:0] Result = 0;
reg [8:0] cn_temp = 0;
reg [7:0] v_temp = 0;
reg carry = 0;
reg overflow = 0;
reg negative = 0;
reg zero = 0;
assign ALU_Out = Result[7:0];
assign C = carry;
assign V = overflow;
assign N = negative;
assign Z = zero;
always #*
begin
if (reset)
begin
Result = 0;
cn_temp = 0;
v_temp = 0;
carry = 0;
overflow = 0;
negative = 0;
zero = 0;
end
end
always #(posedge clk)
begin
case(Op_Sel)
4'b0000: // Addition
begin
Result = A + B;
negative = Result[7];
zero = (Result[7:0] == 8'b00000000);
carry = Result[8];
v_temp = A[6:0] + B[6:0];
overflow = v_temp[7] ^ carry;
end
.
.
//The rest of the instructions
.
.
.
endcase
end
endmodule
//My testbench
module alu_testbench();
reg clk;
reg reset;
reg [7:0] A;
reg [7:0] B;
reg [3:0] Op_Sel;
wire [7:0] ALU_out;
wire C, V, N, Z;
always begin
#1
clk = ~clk;
end
initial begin
clk = 0;
reset = 0;
#1
reset = 1;
#1
reset = 0;
end
initial begin
#10
A=2;
B=3;
Op_Sel = 4'b0000;
#10
A=1;
end
alu alu (
.clk(clk),
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));
endmodule
I believe I connected up the module to the testbench (through a wire), so why am I getting high impedance on ALU_out?
This was a tricky typo. You mistakenly used an upper-case "O" in the ALU_Out signal name. Since Verilog is case-sensitive, this is a different signal from ALU_out. It is not mandatory to declare all signals in Verilog. However, you can use the following compiler directive in your code to help catch this type of common problem:
`default_nettype none
Your simulator should generate an error.
To fix it, change:
assign ALU_Out = Result[7:0];
to:
assign ALU_out = Result[7:0];
My simulators also generated a warning message because you didn't drive the reset input of alu. Here is the fix:
alu alu (
.clk(clk),
.reset(reset), /// <------ add this
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));

How do I resolve Verilog simulation error: "Too many port connections. Expected 8, found 9" in ModelSim

I'm trying to build an 8-bit multiplier in Verilog, but I keep running in to this weird error when I go to simulate my module's test bench. It says:
Too many port connections. Expected 8, found 9
This doesn't really make any sense seeing as how both the module AND the test bench have 9 variables listed. Any help will be much appreciated!
Multiplier Module
module my8bitmultiplier (output [15:0] O, output Done, Cout, input [7:0] A, B, input Load, Clk, Reset, Cin);
reg Done;
reg [1:0] state;
reg [7:0] A_reg, B_reg;
reg [15:0] A_temp, B_temp, O_temp, O_reg;
my16bitadder Adding(O_temp, Cout,A_temp,B_temp, Cin);
always#(posedge Clk)
begin
if(Reset) assign state = {2'b00};
case(state)
0:
if(Load)
begin
A_reg = A;
B_reg = B;
O_reg = A_reg;
state = 1;
end
1:
begin
A_temp = A_reg;
B_temp = O_reg;
B_reg = B_reg - 1;
state = 2;
end
2:
begin
O_reg = O_temp;
if(B_temp)
begin
state = 1;
end
else
begin
state = 3;
Done = 1'b1;
end
end
3:
begin
Done = 1'b0;
state = 0;
end
endcase
end
endmodule
Testbench
module my8bitmultiplier_tb;
reg Load, Clk, Reset, Cin;
reg [7:0] A, B;
wire [15:0] O;
wire Done, Cout;
my8bitmultiplier dut(O, Done, Cout, A, B, Load, Clk, Reset, Cin);
always #5 Clk = ~Clk;
initial
begin
A = 8'b10;
B = 8'b10;
Load = 1;
Cin = 0;
#10 Load = 0;
#3000 A = 8'd100;
#3000 B = 8'd100;
#3000 Load = 1;
#3010 Load = 0;
#6000 A = 8'd150;
#6000 B = 8'd150;
#6000 Load = 1;
#6000 Load = 0;
begin
$display ($time,"A= %d B= %d O=%d ", A, B, O);
end
#10000 $finish;
end
endmodule
When I run you code on another simulator, I get a more helpful warning message:
reg Done;
|
xmvlog: *W,ILLPDX : Multiple declarations for a port not allowed in module with ANSI list of port declarations (port 'Done') [12.3.4(IEEE-2001)].
The warning goes away when I delete this line:
reg Done;
and change:
module my8bitmultiplier (output [15:0] O, output Done, Cout, input [7:0] A, B, input Load, Clk, Reset, Cin);
to:
module my8bitmultiplier (output [15:0] O, output reg Done, Cout, input [7:0] A, B, input Load, Clk, Reset, Cin);
Perhaps that solves your problem on modelsim. You can also try your code on different simulators on edaplayground. You will sometimes get more helpful messages.

Always loop that does not assign the outputs

I am making an average that resets every period on EDA Playground. No errors are displayed on the simulator, Icarus Verilog, but the outputs are continually unassigned (which, of course, is not what I intended).
Here is my design:
module shift
(
input [13:0] in,
input clock,
output [31:0] sum,
output [14:0] avg);
integer reset;
reg [31:0] sum_reg;
reg [14:0] avg_reg;
always #(posedge clock)
if (reset == 8) begin
avg_reg = sum_reg >> 3;
sum_reg = 0;
reset = 0;
end else begin
sum_reg = sum_reg + in;
reset = reset + 1;
end
assign sum = sum_reg;
assign avg = avg_reg;
endmodule
Here is my testbench:
module shift_tb;
reg [13:0] in;
reg clock = 1'b0;
reg reset;
wire [31:0] sum;
wire [14:0] avg;
shift s
(
.in(in),
.clock(clock),
.sum(sum),
.avg(avg));
integer f;
initial begin
for (f = 9000; f < 10000; f = f + 10) begin
in = f;
$display("in = %d, sum = %d, avg = %d", in, sum, avg);
end
end
always
#1 clock = ~clock;
endmodule
What is wrong with this code?
One problem is reset is an integer that is initially x and stays that way. You need a way of initializing it to 0.
Another problem is your testbench for-loop has no delay. You should add #(nedgedge clk)

Verilog code 2 errors i can't find: Would be grateful for an extra pair of eyes to spot a mistake i might've overlooked

I'm writing a verilog code where i'm reading two files and saving those numbers into registers. I'm then multiplying them and adding them. Pretty much a Multiplication Accumulator. However i'm having a hard frustrating time with the code that i have. It read the numbers from the files correctly and it multiples but here is the problem? When i first run it using ModelSim, I reset everything so i can clear out the accumulator. I then begin the program, but there is always this huge delay in my "macc_out" and i cannot seem to figure out why. This delay should not be there and instead it should be getting the result out A*B+MAC. Even after the delay, it's not getting the correct output. My second problem is that if i go from reset high, to low (start the program) and then back to reset high ( to reset all my values), they do not reset! This is frustrating since i've been working on this for a week and don't know/can't see a bug. Im asking for an extra set of eyes to see if you can spot my mistake. Attached is my code with the instantiations and also my ModelSim functional Wave Form. Any help is appreciated!
module FSM(clk,start,reset,done,clock_count);
input clk, start, reset;
output reg done;
output reg[10:0] clock_count;
reg [0:0] macc_clear;
reg[5:0] Aread, Bread, Cin;
wire signed [7:0] a, b;
wire signed [18:0] macc_out;
reg [3:0] i,j,m;
reg add;
reg [0:0] go;
reg[17:0] c;
parameter n = 8;
reg[1:0] state;
reg [1:0] S0 = 2'b00;
reg [1:0] S1 = 2'b01;
reg [1:0] S2 = 2'b10;
reg [1:0] S3 = 2'b11;
ram_A Aout(.clk(clk), .addr(Aread), .q(a));
ram_B Bout(.clk(clk), .addr(Bread), .q(b));
mac macout(.clk(clk), .macc_clear(macc_clear), .A(a), .B(b), .macc_out(macc_out), .add(add));
ram_C C_in(.clk(clk), .addr(Cin), .q(c));
always #(posedge clk) begin
if (reset == 1) begin
i <= 0;
add<=0;
j <= 0;
m <= 0;
clock_count <= 0;
go <= 0;
macc_clear<=1;
end
else
state<=S0;
case(state)
S0: begin
// if (reset) begin
// i <= 0;
// add<=0;
// j <= 0;
// m <= 0;
// clock_count <= 0;
// go <= 0;
// macc_clear<=1;
// state <= S0;
// end
macc_clear<=1;
done<=0;
state <= S1;
end
S1: begin
add<=1;
macc_clear<=0;
clock_count<=clock_count+1;
m<=m+1;
Aread <= 8*m + i;
Bread <= 8*j + m;
if (m==7) begin
state <= S2;
macc_clear<=1;
add<=0;
end
else
state <=S1;
end
S2: begin
add<=1;
macc_clear<=0;
m<=0;
i<=i+1;
if (i<7)
state<=S1;
else if (i==8) begin
state<=S3;
add<=0;
end
end
S3: begin
add<=1;
i<=0;
j<=j+1;
if(j<7)
state<=S1;
else begin
state<=S0;
done<=1;
add<=0;
end
end
endcase
end
always # (posedge macc_clear) begin
Cin <= 8*j + i;
c <= macc_out;
end
endmodule
module mac(clk, macc_clear, A, B, macc_out, add);
input clk, macc_clear;
input signed [7:0] A, B;
input add;
output reg signed [18:0] macc_out;
reg signed [18:0] MAC;
always #( posedge clk) begin
if (macc_clear) begin
macc_out <= MAC;
MAC<=0;
end
else if (add) begin
MAC<=(A*B)+ MAC;
macc_out<=MAC;
end
end
endmodule
module ram_A( clk, addr,q);
output reg[7:0] q;
input [5:0] addr;
input clk;
reg [7:0] mem [0:63];
initial begin
$readmemb("ram_a_init.txt", mem);
end
always #(posedge clk) begin
q <= mem[addr];
end
endmodule
module ram_C(clk,addr, q);
input [18:0] q;
input [5:0] addr;
input clk;
reg [18:0] mem [0:63];
always #(posedge clk) begin
mem[addr] <= q;
end
endmodule
ModelSim Functional Simulation Wave Form
1) Take a look at the schematic view for your MACC module - I think some of your "problems" will be obvious from that;
2) Consider using an always#(*) (Combinational) block for your FSM control signals (stuff like add or macc_clear) rather than a always#(posedge clk) (sequential) - it makes the logic to assert them easier. Right now they're registered, so you have a cycle delay. ;
3) In your MAC, you clear the MAC register on a reset, but you don't clear the macc_out register.
In short, I think you need to step back, and consider which signals are combinational logic, and which ones are sequential and need to be in registers.

Resources