Why is the simulation stuck in Vivado - verilog

I tried to develop a spare memory code, but the simulation got stuck in vivado. I cannot exactly say whether it is stuck or not, but the simulation is not running. I've attached the image for the problem I'm unable to clearly express. The test bench of the code goes here. While trying to get a simulated waveform, vivado is not giving a simulation whereas it is fully working in Icarus Verilog, and the simulation waveforms are clear in GTK wave.
module trial_tb;
reg clk;
reg rst_n;
reg bist_enable;
reg we;
reg [5:0] wraddr;
reg data_in;
reg re;
reg [5:0] rdaddr;
wire data_out;
wire repair_fail;
wire repair_finish;
integer m;
integer idx;
SRAM_repair uut (clk, rst_n, bist_enable, we, wraddr, data_in, re, rdaddr, data_out, repair_fail, repair_finish);
initial
begin
clk = 0;
rst_n <= 0;
bist_enable <= 0;
rdaddr <= 'b0;
wraddr <= 'b0;
we <= 1'b0;
re <= 1'b0;
data_in <= 1'b0;
#5.0 rst_n <= 1;
#5.0 bist_enable <= 1;
#52.9 bist_enable <= 1'b0;
we <= 1'b1;
data_in <= 1'b0;
for ( m=0 ; m<=32; m=m+1) begin
wraddr <= m;
#0.2;
end
data_in <= 1'b1;
for ( m=33 ; m<=63; m=m+1) begin
wraddr <= m;
#0.2;
end
#0.2;
we <= 1'b0;
re <= 1'b1;
for ( m=0 ; m<64; m= m+1) begin
rdaddr <= m;
#0.2;
end
end
initial
begin
$dumpfile ("SRAM_repair.vcd");
$dumpvars( 0, trial_tb);
// $dumpvars( 0, trial_tb.uut.i_bisr_controller.fcr\[0\]);
// $dumpvars( 0, trial_tb.uut.i_bisr_controller.fcr\[1\]);
// $dumpvars( 0, trial_tb.uut.i_bisr_controller.fcr\[2\]);
// $dumpvars( 0, trial_tb.uut.i_bisr_controller.fcr\[3\]);
// $dumpvars( 0, trial_tb.uut.i_bisr_controller.fcr\[4\]);
// $dumpvars( 0, trial_tb.uut.i_bisr_controller.fcr\[5\]);
#90 $finish;
end
always #0.1 clk = ~clk;
endmodule

I suspect you did not use a proper timescale for the delays in your testbench. From IEEE Std 1800-2017, section 22.7 `timescale:
If there is no `timescale specified or it has been reset by a
`resetall directive, the default time unit and precision are
tool-specific.
When not specified, my simulator defaults to:
`timescale 1ns/1ns
I see the simulation hang at time 0, as I think you do. Since the time precision is the same as the time unit (both are 1ns for me), the 0.1 delay for clk is rounded down to 0, causing an infinite loop in the clk always block.
I fixed this by adding this explicit timescale before the module:
`timescale 1ns/100ps
This sets the precision less than the unit, allowing the clk to toggle properly.
The discrepancy you see between Vivado and Icarus is likely a result of different timescales being used. To see what timescale is in effect, add this code to your testbench:
initial $printtimescale;

Related

No response from uut in testbench

I am not getting any response from the uut in the testbench. The module exp2_up_down_counter works ok without testbench, but gives output as xxxx when instantiated in the testbench.
Here is the main module of the up-down counter:
`timescale 1ns/1ps
module exp2_up_down_counter (input clk, reset, mode, output reg [3:0] count);
always #(posedge clk)
if (reset == 1)
count <= 0; // reset the counter if reset is high
else if (mode == 1)
count <= count + 1; // works as up counter if mode pin is high
else
count <= count - 1; // works as down counter if mode pin is low
endmodule
Simulation without testbench:
Testbench for up-down counter
`timescale 1ns/1ps
module exp2_up_down_counter_tb;
reg clk, reset, mode;
wire [3:0] count;
exp2_up_down_counter uut(.clk(clk), .reset(reset), .mode(mode), .count(count));
initial begin
clk = 1'b0;
end
always #(*) #5 clk <= ~clk;
initial begin
// initializing the inputs
reset = 1;
mode = 0;
#5;
reset = 0;
#10
mode = 1;
#5000 $finish;
end
endmodule
Simulation with testbench:
In exp2_up_down_counter, count is declared as a reg. This means that its default value is X at time 0. Since the reset signal is synchronous to the clock, you need to wait for the 1st posedge of clock before you release the reset. Currently, the reset is released at the 1st posedge of clock in the testbench, which is a race condition. Therefore, count does not get assigned the value of 0, and it retains the value of X for the whole simulation.
You need to delay the reset release. For example, change:
#5;
reset = 0;
to:
#15;
reset = 0;
However, it is better to drive your synchronous inputs in the testbench the same way you drive your signals in the design: using #(posedge clk) and using nonblocking assignments (<=):
initial begin
reset = 1;
mode = 0;
repeat (2) #(posedge clk);
reset <= 0;
repeat (1) #(posedge clk);
mode <= 1;
#5000 $finish;
end
Also, this is a more standard way to drive the clock in the testbench:
always #5 clk = ~clk;

RTL if statements not matching with simulation

I am struggling to understand why the output flickers between 0 and 1, when the output should constantly remain 0 since the reduction OR gate of 000 is 0 not 1.
When I tried a different bit width, the problem suddenly disappeared. However, I would like to know what is going on rather than relying on randomness for correctness.
project_test .sv
`timescale 1ns/1ns
module project_test
( input logic clk, rst,
input logic in,
output logic [2:0] c
);
logic [2:0] out;
always#(posedge clk or posedge rst) begin
if(rst)
out <= 'b0;
else if(in) begin
if(|out)
out <= 'b0;
end
else
out <= out + 1'b1;
end
assign c = out;
endmodule: project_test
testbench.sv
`timescale 1ns/1ns
module testbench;
logic clk, rst;
logic in;
logic [2:0] c;
project_test project_test(
.clk(clk),
.rst(rst),
.in(in),
.c(c)
);
initial begin
clk = 0;
rst = 1;
in = 0 ;
#30
rst = 0;
#20;
in = 1;
#500;
rst=1;
#100ns;
$stop();
end
always#(clk) begin
#10ns clk <= !clk;
end
endmodule
Simulation output:
RTL viewer:
That is an improper way to generate a clock signal in the testbench. You should not have the clk signal in the sensitivity list because it keeps re-triggerring the always block. Your clock generator potentially adds events to the Verilog event queue, which can cause odd behavior. In fact, when I ran your code on the Cadence simulator, I did not see the clock toggling at all.
This is a more standard way to generate a clock:
always begin
#10ns clk = !clk;
end
You are using a very verbose implementation. Why can't you do something like below.
always#(posedge clk or posedge rst)
begin
if(rst)
out <= 'd0;
else
out <= (in) ? 'd0 : (out + 1'b1);
end

Verilog: one clock cycle delay using register

I'm trying to delay two signals. I wrote a register to do that and instantiated it but a strange thing happens. Delaying "state" signal seems to work, but delaying "nb_bits" signal doesn't.
Here's my code for the register:
`timescale 1ns / 1ps
module register(
input CLK,
input clr,
input en,
input [7:0] in,
output [7:0] out
);
reg [7:0] temp;
always # (posedge CLK or posedge clr) begin
if (clr) begin
temp <= 8'b00010000;
end
else if (en) begin
temp <= in;
end
else begin
temp <= temp;
end
end
assign out = temp;
endmodule
And that's ma instantiation:
wire [3:0] nbb;
nb_bits_register nb_bits_reg(
.CLK(CLK),
.clr(clr),
.en(en),
.in(nb_bits),
.out(nbb)
);
wire [7:0] stt;
register state_reg(
.CLK(CLK),
.clr(clr),
.en(en),
.in(state),
.out(stt)
);
nb_bits_register module is analogical; I didn't want to parametrize before solving this problem.
`timescale 1ns / 1ps
module nb_bits_register(
input CLK,
input clr,
input en,
input [3:0] in,
output [3:0] out
);
reg [3:0] temp;
always # (posedge CLK or posedge clr) begin
if (clr) begin
temp <= 4'b0000;
end
else if (en) begin
temp <= in;
end
else begin
temp <= temp;
end
end
assign out = temp;
endmodule
And here's a simulation:
enter image description here
And testbench:
`timescale 1ns / 1ps
module state_machine_tb();
reg CLK, clr, en;
reg [7:0] symbol;
reg [3:0] nb_bits;
wire [7:0] state;
initial begin
CLK <= 1;
clr <= 0;
en <= 0;
symbol <= 8'b00110010;
nb_bits <= 1;
#10
clr <= 1;
en <= 1;
#10
clr <= 0;
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110010;
nb_bits <= 2;
#10
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110000;
nb_bits <= 3;
#10
$finish;
end
always begin
#5 CLK <= ~CLK;
end
state_machine state_machine_inst(
.CLK(CLK),
.clr(clr),
.en(en),
.symbol(symbol),
.nb_bits(nb_bits),
.state(state)
);
endmodule
It does seem like a rase condition in the scheduler. By definition from the Verilog LRM, the order of evaluating procedural blocks (always blocks and initial blocks) is indeterminate. You might notice a pattern with a particular simulator and version, but that patter can change when changing the simulator or changing the version of the same simulator.
Use blocking assignment with your clock (ex: always #5 CLK = ~CLK;). With will guarantee the CLK will be updated before other stimulus.
In the test bench, change all the #10 to #(posedge CLK). The timing will be the same, however it guarantees CLK was updated before evaluating the new values symbol and other stimulus.
FYI: If you change output [7:0] out to output reg [7:0] out you can assign out directly in your always block, removing the need for temp. This doesn't change anything functionally; just fewer variables and lines of code.
It seems like a race condition: your changes of nb_bits coincide with positive edges of CLK, so there's an ambiguity resolved by the simulator in this way:
change nb_bits (from 1 to 2, etc.)
change CLK from 0 to 1
execute in nb_bits_register: if (en) temp <= in; ... assign out = temp;
As the result, out = in in nb_bits_register.
A solution is to avoid this coincidence, e.g. by changing the first #10 in the testbench to #11.

6-bit binary counter with LED output

I'm really new to verilog world and i can't understand why my program return nothing. I'm trying to make simple 6-bit up counter that counts on button press. The code is
module top (CLK, BTN_RST, LED, BTN_C);
input CLK, BTN_RST, BTN_C; //
output [5:0]LED;
reg [5:0]LED;
always #(posedge CLK or posedge BTN_RST) begin
if (BTN_RST) begin
LED <= 6'b000000;
end
else begin: COUNT
while (BTN_C) begin
LED <= LED + 1'b1;
disable COUNT;
end
end
end
endmodule
And the test bench is
module top_test;
reg CLK;
reg BTN_RST;
reg BTN_C;
reg [5:0]LED;
initial begin
CLK = 0;
BTN_RST = 0;
BTN_C = 0;
#1 BTN_RST = 1;
#5 BTN_RST = 0;
#10 BTN_C = 1;
#50;
end
always
begin
#5 CLK=~CLK;
end
This code compiles and runs (as i can see on iSim), but LED output gives me XXXXXX. I think I'm not only got some mistakes here, but also can't understand how test bench works and how to make right assignments on input and output. Can anyone please help me?
You need to add an instance of your design in your testbench. Now, LED is no longer X; I see it counting up from 0.
module top_test;
reg CLK;
reg BTN_RST;
reg BTN_C;
wire [5:0]LED;
initial begin
CLK = 0;
BTN_RST = 0;
BTN_C = 0;
#1 BTN_RST = 1;
#5 BTN_RST = 0;
#10 BTN_C = 1;
#50;
end
always
begin
#5 CLK=~CLK;
end
top dut (
// Inputs:
.BTN_C (BTN_C),
.BTN_RST (BTN_RST),
.CLK (CLK),
// Outputs:
.LED (LED)
);
endmodule
I changed reg to wire for LED in top_test. I see LED increasing from 0 when I use VCS as a simulator. But, when I switch to Incisive, LED stays at 0.
I think your while/disable code is causing a problem. I have recoded it to look a little more standard:
module top (CLK, BTN_RST, LED, BTN_C);
input CLK, BTN_RST, BTN_C; //
output [5:0]LED;
reg [5:0]LED;
always #(posedge CLK or posedge BTN_RST) begin
if (BTN_RST) begin
LED <= 6'b000000;
end else if (BTN_C) begin
LED <= LED + 1'b1;
end
end
endmodule

Parse error when I try to use Verilog; testbenching an LFSR doesn't work

I am currently working on random number generation using Verilog. Sources have indicated that using Linear Feedback Shift Registers are one of the best ways to randomize MSBs. So I decided to code and testbench an LFSR. Snippet is below:
module lfsr_counter(clk, reset, ce, lfsr_done);
input clk, reset, ce;
output lfsr_done;
reg lfsr_done;
reg [10:0] lfsr;
initial lfsr_done = 0;
wire d0,lfsr_equal;
xnor(d0,lfsr[10],lfsr[8]);
assign lfsr_equal = (lfsr == 11'h359);
always #(posedge clk,posedge reset) begin
if(reset) begin
lfsr <= 0;
lfsr_done <= 0;
end
else begin
if(ce)
lfsr <= lfsr_equal ? 11'h0 : {lfsr[9:0],d0};
lfsr_done <= lfsr_equal;
end
end
endmodule
module testbench();
reg clk, reset, ce;
wire lfsr_done;
lfsr_counter dut(clk, reset, ce, lfsr_done); // Design Under Test
initial
begin
reset = 0;
clk = 1;
ce = 0;
#100
ce = 1;
#200 $finish;
end
//Generate Clock
always #10 clk = !clk;
endmodule
But I keep getting these parse errors:
I don't really get it. I'm using Verilogger Pro btw
I think always block terms are separated by or, not a comma.
always #(posedge clk or posedge reset) begin

Resources