Strange testbench behavior in gtkwave - verilog

I'm trying to design an elevator controller in SystemVerilog. The code compiles well but the testbench is completely different when I put it in gtkwave.
The controller receives 3 different inputs (one for each of the 3 floors, like buttons of a proper elevator) and passes its output to the elevator engine, which can stay on the same floor, go up or go down by one or two floors.
This is the code for the module:
enum logic [4:0] {fermo, sale, sale2, scende, scende2} motore;
module ascx (input logic x0, x1, x2, clk, reset,
output logic [4:0] y);
enum logic [1:0] {pianoterra, primopiano, secondopiano} piani;
logic [1:0] pianoatt, pianoprox;
always_ff#(posedge clk, posedge reset)
if(reset) pianoatt <= pianoterra;
else pianoatt <= pianoprox;
always_comb begin
if(x1) pianoprox = primopiano;
else if(x0) pianoprox = pianoterra;
else if(x2) pianoprox = secondopiano;
end
always #(*) begin
case(pianoatt)
pianoterra: begin
if(x0) assign y = fermo; /*assign y = 5'b00001;*/
if(x1) assign y = sale; /*assign y = 5'b00010;*/
if(x2) assign y = sale2; /*assign y = 5'b00100;*/
end
primopiano: begin
if(x0) assign y = scende; /*assign y = 5'b01000;*/
if(x1) assign y = fermo; /*assign y = 5'b00001;*/
if(x2) assign y = sale; /*assign y = 5'b00010;*/
end
secondopiano: begin
if(x0) assign y = scende2; /*assign y = 5'b10000;*/
if(x1) assign y = scende; /*assign y = 5'b01000;*/
if(x2) assign y = fermo; /*assign y = 5'b00001;*/
end
default assign y = fermo;
endcase
end
endmodule
Here's the testbench:
module tst_ascx();
logic clk, reset, x0, x1, x2;
logic [4:0] y;
ascx dut(clk, reset, x0, x1, x2, y);
always begin
clk=0; #10;
clk=1; #10;
end
initial begin
$dumpfile("ascx.vcd");
$dumpvars;
reset=1; x0=0; x1=0; x2=0; #10;
reset=0; x0=1; x1=0; x2=0; #10;
x0=0; x1=1; #10;
x1=0; x2=1; #10;
x0=1; x2=0; #10;
x0=0; x2=1; #10;
x1=1; x2=0; #10;
x0=1; x0=0; #10;
end
endmodule
And here the gtkwave display:
The clock, as shown in the image, is not correct.
The input x0 should not be periodic, it simply represents a button being pressed at some time.
I can't say if for the rest the module is working properly, because of these two problems.

You connected signals to your dut incorrectly. The 1st signal in the dut instance (clk) is connected to the 1st port in the module declaration (x0), etc.
To avoid this type of common mistake, use connection-by-name instead of connection-by-position. Refer to IEEE Std 1800-2017, section 23.3.2.2 Connecting module instance ports by name.
Change:
ascx dut(clk, reset, x0, x1, x2, y);
to:
ascx dut (
.clk (clk),
.reset (reset),
.x0 (x0),
.x1 (x1),
.x2 (x2),
.y (y)
);
Unrelated to your problem: you should not use the assign keyword in the always block. Refer to this explanation of a procedural continuous assignment

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.

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.

Systemverilog recursion update value for next stage

I am trying to create a recursive logic in Systemverilog but I seem to be missing the right logic to carry the output of one iteration to the next.
Here is an example of the problem:
parameter WIDTH=4;
module test_ckt #(parameter WIDTH = 4)(CK, K, Z);
input CK;
input [WIDTH-1:0] K;
output reg Z;
wire [WIDTH/2-1:0] tt;
wire [WIDTH-1:0] tempin;
assign tempin = K;
genvar i,j;
generate
for (j=$clog2(WIDTH); j>0; j=j-1)
begin: outer
wire [(2**(j-1))-1:0] tt;
for (i=(2**j)-1; i>0; i=i-2)
begin
glitchy_ckt #(.WIDTH(1)) gckt (tempin[i:i], tempin[(i-1):i-1], tt[((i+1)/2)-1]);
end
// How do I save the value for the next iteration?
wire [(2**(j-1))-1:0] tempin;
assign outer[j].tempin = outer[j].tt;
end
endgenerate
always #(posedge CK)
begin
// How do I use the final output here?
Z <= tt[0];
end
endmodule
module glitchy_ckt #(parameter WIDTH = 1)(A1, B1, Z1);
input [WIDTH-1:0] A1,B1;
output Z1;
assign Z1 = ~A1[0] ^ B1[0];
endmodule
Expected topology:
S1 S2
K3--<inv>--|==
|XOR]---<inv>----|
K2---------|== |
|==
<--gckt---> |XOR]
|==
K1--<inv>--|== |
|XOR]------------|
K0---------|== <-----gckt---->
Example input and expected outputs:
Expected output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 1 <- j=1 and i=1.
Actual output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 0 <- j=1 and i=1. Here, because tempin is not updated, inputs are same as (j=2 & i=1).
Test-bench:
`timescale 1 ps / 1 ps
`include "test_ckt.v"
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
#0 CK = 0;
A = 4'b1010;
#500 $finish;
end
initial begin
//dump waveform
$dumpfile("test_ckt.vcd");
$dumpvars(0,dut);
end
endmodule
How do I make sure that tempin and tt get updated as I go from one stage to the next.
Your code does not have any recursion in it. You were trying to solve it using loops, but generate blocks are very limited constructs and, for example, you cannot access parameters defined in other generate iterations (but you can access variables or module instances).
So, the idea is to use a real recursive instantiation of the module. In the following implementation the module rec is the one which is instantiated recursively. It actually builds the hierarchy from your example (I hope correctly).
Since you tagged it as system verilog, I used the system verilog syntax.
module rec#(WIDTH=1) (input logic [WIDTH-1:0]source, output logic result);
if (WIDTH <= 2) begin
always_comb
result = source; // << generating the result and exiting recursion.
end
else begin:blk
localparam REC_WDT = WIDTH / 2;
logic [REC_WDT-1:0] newSource;
always_comb // << calculation of your expression
for (int i = 0; i < REC_WDT; i++)
newSource[i] = source[i*2] ^ ~source[(i*2)+1];
rec #(REC_WDT) rec(newSource, result); // << recursive instantiation with WIDTH/2
end // else: !if(WIDTH <= 2)
initial $display("%m: W=%0d", WIDTH); // just my testing leftover
endmodule
The module is instantiated first time from the test_ckt:
module test_ckt #(parameter WIDTH = 4)(input logic CK, input logic [WIDTH-1:0] K, output logic Z);
logic result;
rec#(WIDTH) rec(K, result); // instantiate first time )(top)
always_ff #(posedge CK)
Z <= result; // assign the results
endmodule // test_ckt
And your testbench, a bit changed:
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
CK = 0;
A = 4'b1010;
#500
A = 4'b1000;
#500 $finish;
end
initial begin
$monitor("Z=%b", Z);
end
endmodule // mytb
Use of $display/$monitor is more convenient than dumping traces for such small examples.
I did not do much testing of what I created, so there could be issues, but you can get basic ideas from it in any case. I assume it should work with any WIDTH which is power of 2.

Why this output get out with one delay?

I made 4_to_1 MUX with 2_to_1 MUX. I used always syntax. The output is delayed one time unit, but I don't know why.
When I change the always condition of 4_to_1 MUX's module sel to *, it works well. Why is this working?
module MUX_2_to_1 (
a0,a1,sel,out);
input [3:0]a0;
input [3:0]a1;
input sel;
output reg [3:0]out;
always #(sel)
begin
if (sel == 0)
out <= a0;
else if (sel == 1)
out <= a1;
end
endmodule
*
module MUX_4_to_1(
x0,x1,x2,x3,sel,out);
input [3:0]x0;
input [3:0]x1;
input [3:0]x2;
input [3:0]x3;
input [1:0]sel;
output reg [3:0]out;
wire [3:0]w0;
wire [3:0]w1;
MUX_2_to_1 m0 (x0,x1,sel[0],w0);
MUX_2_to_1 m1 (x2,x3,sel[0],w1);
always #(sel)
begin
if(sel[1] == 0)
out <= w0;
else if (sel[1] == 1)
out <= w1;
end
endmodule
*
`timescale 100ps/1ps
module Testbench_Mux;
reg [3:0]x0;
reg [3:0]x1;
reg [3:0]x2;
reg [3:0]x3;
reg [1:0]sel;
wire [3:0]out;
MUX_4_to_1 m0 (x0,x1,x2,x3,sel,out);
initial
begin
x0 = 4'b0001; x1 = 4'b0010; x2 = 4'b0100; x3 = 4'b1000;
#0 sel = 2'b00;
#5 sel = 2'b01;
#5 sel = 2'b10;
#5 sel = 2'b11;
#5 $stop;
end
endmodule
You are not using recommended Verilog coding practices for combinational logic. One problem is that you used an incomplete sensitivity list:
always #(sel)
Since there are 2 other signals, w0 and w1, which are read in the always block, they must also be in the sensitivity list. The verbose way to do this is:
always #(sel or w0 or w1)
The preferred way to do this is to use the compact * syntax:
always #(*)
This assures that the always block will be triggered when any change occurs to any signal read in the block.
Another issue is that you should always use blocking assignments for combinational logic. There is ample documentation out there as to the reason.
Change <= to =:
always #(*)
begin
if(sel[1] == 0)
out = w0;
else if (sel[1] == 1)
out = w1;
end
If you don't follow these recommendations, you get undesired simulation results.
You should change your MUX_2_to_1 module as well.

Can't get my head around testbenches

I am having trouble making testbenches. It is far into the quarter in my school but I feel like I am missing out on some fundamentals.
Here I am trying to make a 2 by 4 decoder, but I want to simulate it inside verilog.
module decoder2to4(x, enable, y);
input [1:0] x; //this is my decoder input
input enable;
output [3:0] y;
reg [3:0] y;
always #(x, enable ) //
begin
if(enable==0) //if enable isn't on, all outputs WON'T OUTPUT correct and give us 1111
y = 4'b1111;
else //if enable is high...
if (x == 2'b00) //...then we check our inputs and give corresponding outputs
y = 4'b0001;
if (x == 2'b01)
y = 4'b0010;
if (x == 2'b10)
y = 4'b0100;
if (x == 2'b11);
y = 4'b1000;
end
endmodule
This is my simulation file ~ did i write it correctly ?
module testbench_2to4decoder;
reg [1:0] x; //use reg not wire to assign values
wire [3:0] y; //for the outputs
2to4Decoder uut(x,y);
initial begin
x = 2'b00;
enable = 1'b0; //keep it off
#10 //wait some time
enable = 1'b1; //turn enable on
#10; //wait some time
x = 2'b01; //input 01
#10; //wait some time
x = 2'b10; //input 10
#10; //then
x = 2'b11; //input 11
#10;
enable = 1'b0; //turn it off
#10;
end
endmodule
You are not instantiating the design properly. Firstly, enable is not connected. enable is not even declared in testbench.
Also, the module name is wrong. Instead of following:
2to4Decoder uut(x,y);
You must have:
decoder2to4 uut(x,enable, y);
Using a reset logic is encouraged to have default values of output. But since this is a combinational circuit, it is not mandatory here.
The inputs can be provided by using a for or repeat loop and increment variable x in it. But this is just for coding efficiency.
Rest of the things seems to be fine. Refer Module instantiation link.

Resources