assign not updating result value in testbench in EDA playground - verilog

I am using EDA Playground with Aldec Riviera simulator, and I have this module here:
module alu(input logic [31:0] a, b,
input logic [2:0] alucontrol,
output logic [31:0] result,
output logic zero);
logic [31:0] condinvb, sum;
assign condinvb = alucontrol[2] ? ~b : b;
assign sum = a + condinvb + alucontrol[2];
always_comb
case (alucontrol[1:0])
2'b00: result = a & b;
2'b01: result = a | b;
2'b10: result = sum;
2'b11: result = sum[31];
endcase
assign zero = (result == 32'b0);
endmodule
and my testbench is here:
module alu_testbench();
logic [31:0] a,b;
logic [2:0] alucontrol;
logic [31:0] result;
logic zero, clk;
alu test_alu(a,b,alucontrol);
initial begin
$dumpfile("dump.vcd"); $dumpvars(1);
clk = 0;
a = 'hdead0000; b = 'h0000beef; alucontrol = 'b010; #1;
a = 'hc0debabe; b = 'h0000ffff; alucontrol = 'b000; #1;
a = 'hc0de0000; b = 'h0000babe; alucontrol = 'b001; #1;
a = 'hc0debabe; b = 'h0000babe; alucontrol = 'b100; #1;
end
always begin
#1; clk = ~clk;
end
endmodule
When I run the testbench and look at the generated waveform, I do not see result being updated. Instead, it stays as XXXX_XXXX. What am I doing wrong in the testbench?

In the testbench, you declared the result signal, but it is not connected to anything. You probably intended it to be driven by the alu output of the same name. In that case, you should connect it to the instance:
Change:
alu test_alu(a,b,alucontrol);
to:
alu test_alu(a,b,alucontrol,result,zero);
Try your code on other simulators on edaplayground; you should get warnings about unconnected ports.
With your code, if you looked inside the alu instance, the result signal would not be X.
Another equivalent way to code the instance is to use connections by name:
alu test_alu (
.a (a),
.b (b),
.alucontrol (alucontrol),
.result (result),
.zero (zero)
);
This makes it easier to avoid common connection errors.

Related

Verilog Adder/Subtractor [duplicate]

This question already has answers here:
How do I use flip flop output as input for reset signal
(1 answer)
Why is my counter out value producing StX?
(2 answers)
Closed 2 months ago.
Trying to make a Binary adder and Subtractor in Verilog Output keeps coming out as X I don't think it is the testbench I believe is something wrong with the wires for the output F. The Flip Flops and the Multiplexer should be correct but I have no way of knowing for sure I do not get any error messages when I run this
module Subtractor(A, B, Bin, Bout , Sub); //Variables for subtractor
// 1-bit full binary subtractor.
input A;//Input variable
input B;//Input variable
input Bin;//Input variable
output Bout;
output Sub;
assign Bout=((~A)&(B))|((~A)&(Bin))|((B)&(Bin));
assign Sub=(A^B^Bin);
endmodule
module Adder(A, B, Cin, Cout, Sum);
// 1- bit full binary adder
input A, B, Cin;
output Cout, Sum;
assign Cout = ((A)&(Cin))|((B)&(Cin))|((A)&(B));
assign Sum = (A^B^Cin);
endmodule
module CarryFLIPFLOP(CLK,RESET,D,Q);
//Flip flop for carry value
input CLK,RESET,D;
output reg Q;
always #(posedge CLK)
begin
if(RESET)
Q<=0;
else
Q<=D;
end
endmodule
module BorrowFLIPFLOP(CLK,RESET,D,Q);
// 1- bit full binary adder
input CLK,RESET,D;
output reg Q;
//reg Q;
always #(posedge CLK)
begin
if(RESET)
Q<=0;
else
Q<=D;
end
endmodule
module Fplexer(Sum, Sub, S, F, clk);
input Sum, Sub, S, clk;
output reg F;
always#(posedge clk) begin
if(S==1) begin
F <= Sum;
end else begin
F <= Sub;
end
end
endmodule
module z_flag(clk,F,R,Z);
input clk,F,R;
output reg Z=1;
always#(posedge clk)begin
Z=R|(Z&~F);
end
endmodule
module top(A,B,S,R,clk,F,Z,N,V);
input A, B, S, R, clk;
output F, Z, N, V;
wire w0,w1,w2,w3,w4,w5,w6,w7,w8;
assign w7 = A;
assign w8 = B;
Subtractor S0(.A(w7), .B(w8), .Bin(w3), .Bout(w4), .Sub(w5));
BorrowFLIPFLOP Borrow(.CLK(clk), .RESET(R), .D(w2), .Q(w3));
Adder A0(.A(w7), .B(w8), .Cin(w0), .Cout(w1), .Sum(w2));
CarryFLIPFLOP Carry(.CLK(clk), .RESET(R), .D(w2), .Q(w0));
Fplexer multi(.Sum(w2), .Sub(w5), .S(S), .F(w6), .clk(clk));
assign V=(w0 & w1);
assign F = w6;
assign N = w6;
z_flag Zflag(.clk(clk), .F(w6), .R(R), .Z(Z));
endmodule
module testbench;
reg clk;
reg R;
reg A;
reg B;
reg S = 0;
wire F;
//intitialize clock/top
top UUT(A,B,S,R,clk,F,Z,N,V);
always
#5 clk = ~clk;
initial begin
$display("Testing +- Machine");
$monitor("%d - %d Is %d",A, B, F);
A = 0; B = 1; S = 0; R=0; #10;
clk = 1; #1;
clk = 0; #1;
clk = 1; #1;
A = 1; B = 1; #10;
clk = 1; #1;
clk = 0; #1;
clk = 1; #1;
A = 1; B = 0; #10;
clk = 1; #1;
clk = 0; #1;
clk = 1; #1;
end
endmodule
Your design has a reset signal and you never used it.
Your FLIPFLOP code does not have RESET in the sensitivity list.
You are making assignments to clk in an always block and in the initial block. Pick one place.
Learn how to save waveforms to see internal signals, not just the top level output.

I am unable to understand the error in this code that is preventing an output to be displayed

module Calculator(out,a,b,op);
input [3:0] a,b;
input [1:0] op;
output [4:0] out;
reg [32:0] out;
initial
begin
case(op)
2'b00: out <= a+b;
2'b01: out <= a-b;
2'b10: out <= a*b;
2'b11: out <= a/b;
endcase
out = a+b;
end
endmodule
module test_Calci;
reg [3:0]a,b;
reg [1:0] op;
wire [32:0] out;
Calculator ca1 (out,a,b,op);
initial
begin
#40 a=32'b1; b=32'b1; op = 2'b00;
end
endmodule
The code is successfully compiling, but the expected output is not being displayed.
The initial block inside the Calculator module only executes once at time 0. At that time, the last statement which is executed (out = a+b) assigns out to the value X because a and b are X. out never gets assigned again.
You want out to be assigned every time any of the inputs change value. To do that, use an always block:
module Calculator(out,a,b,op);
input [3:0] a,b;
input [1:0] op;
output reg [32:0] out;
always #* begin
case(op)
2'b00: out = a+b;
2'b01: out = a-b;
2'b10: out = a*b;
2'b11: out = a/b;
endcase
end
endmodule
I made other changes to your code as well. For combinational logic, it is a good practice to use blocking assignments (=) instead of nonblocking (<=).
You should not have the assignment to out outside of the case statement since it will override the value assigned in the case.
You declare out with 2 different bit widths (5 and 33), which is a little strange. I merged them into one declaration.

4-bit adder subtractor Verilog code errors

I am trying to do a 4-bit adder subtractor in Verilog code, but there is some kind of problem in my code that I couldn't figure out. I'm not sure if the testbench or the Verilog is wrong. Can someone please help me with it? Also, when I try to simulate it, it gives Loading Errors.
My Verilog code:
module addsubparameter (A, B, OP, C_out, Sum);
input A,B;
input OP;
output C_out;
output Sum;
wire C_out, Sum;
reg assigning;
always#(OP)
begin
if (OP == 0)
assigning = A + B + OP;
else
assigning = A + (~B + 1) + OP;
end
assign {C_out, Sum} = assigning;
endmodule
module adder (a, b, op, cout, sum);
parameter size = 4 ;
input [3:0] a, b;
output [3:0] sum;
input op;
output cout;
wire [2:0] c;
genvar i;
generate
for (i = 0; i < size; i = i + 1) begin: adder
if (i == 0)
addsubparameter (a[i], b[i], op, sum[i], c[i]);
else if (i == 3)
addsubparameter (a[i], b[i], c[i-1], cout, sum[i]);
else
addsubparameter (a[i], b[i], c[i-1], sum[i], c[i]);
end
endgenerate
endmodule
And this is my testbench:
module addsub_tb();
reg [3:0] a;
reg [3:0] b;
reg op;
wire [3:0] sum;
wire cout;
adder DUT (a,b,op,sum,cout);
initial begin
a = 4'b1010; b = 4'b1100; op = 1'b0; #100;
a = 4'b1111; b = 4'b1011; op = 1'b1; #100;
a = 4'b1010; b = 4'b1010; op = 1'b0; #100;
end
endmodule
Your simulator should generate error and/or warning messages because you have syntax errors. If it does not, sign up for a free account on edaplayground, where you will have access to multiple simulators which will produce helpful messages.
You need to add instance names. For example, I added i0 in the line below:
addsubparameter i0 (a[i], b[i], op, sum[i], c[i]);
You have port connection width mismatches, and these indicate connection errors. This is a common type of error when you use connections by position. You mistakenly connected the sum signal to the cout port, and vice versa. You should use connections by name instead. For example, change:
adder DUT (a,b,op,sum,cout);
to:
adder dut (
.a (a),
.b (b),
.op (op),
.cout (cout),
.sum (sum)
);
Use this coding style for all your instances.
You won't get a simulation warning, but you might get a synthesis warnings about an incomplete sensitivity list. Change:
always#(OP)
to:
always #*

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.

Resources