I have a problem in the test bench code, and I am not getting correct waveforms. Even the clock does not trigger.
CODE for D Flipflop:
module D_FF(o,D,clk);
output reg o;
input D,clk;
always # (posedge clk)
begin
if(D==1'b1)begin
o=1'b1;
end
else begin
o=1'b0;
end
end
endmodule
Code for TestBench:
module DD_flipflop_tb();
reg clk,D;
wire o;
D_FF i1(o,D,clk);
initial begin
clk=1'b0;
D=1'b0;
end
always begin
#20 clk=~clk;
#35 D=~D;
#5000 $finish;
end
endmodule
Here is what happens in the always block in your testbench.
At time 0, clk and D are 0.
At time 20, you invert clk, which becomes 1.
At time 55, you invert D, which becomes 1.
At time 5055, you call $finish which terminates the simulation. The statements in the block only execute once, which is why your inputs never change more than once.
In your testbench, initialize them as 0 in an initial block, then separate the clock generation from the data signal.
initial begin
clk = 0;
forever #20 clk=~clk;
end
initial begin
D=0;
forever #35 D=~D;
end
initial #5000 $finish;
You might want to assign separately the clock and the stimulus in the testbench:
initial begin
clk = 0;
D = 0;
#5000 $finish;
end
//..clock
always
#20 clk = ~clk;
//..stimulus
always
#35 D = ~D;
Related
Do RHS signals in an assignment ,inside always block will be added to senstivity list ? if that is true, may i know, why the following code is not working ?
`timescale 1ns/1ps
module tb();
reg clk=0;
initial begin
#10 clk = 1;
#1000;
$finish();
end
always#(*)begin
#10 clk=!clk;
end
initial begin
$recordfile("wave.trn");
$recordvars();
end
endmodule
Your code does not working for a different reason:
An always block is not sensitive to signal changes until all actions have finished.
Thus after your clock has toggled, the always block waits for a new clock event, which is not forthcoming.
To generate a clock you should use something like:
initial
begin
clk = 1'b0;
forever
#(CLK_PERIOD/2) clk = ~clk;
end
I am working with a system of two d_flipflops (DFFs) connected to each other (with output,q, of first DFF connected to input,d, of second flipflops. I created sub-modules of DFFs and embedded them into a top module. I then created a test bench. However the problem is that the simulation doesn't progress beyond the initial state irrespective of the time-delays I provide. It says simulation is finished at t=0. while there is no error in compilation, I dont understand whats wrong with my code. I also tried providing absolute time values as delays in test bench (e.g #50ns instead of #50) but of no use. I tried simulating this in iverilog and also tried different compilers from EDAplayground. It would be of great help to me if someone could provide insights to my problem.
Thank you!
module d_ff(d, clk, reset, q, q_not);
input d, clk, reset;
output q, q_not;
reg q, q_not;
always # (reset or posedge clk)
begin
if (reset == 0)
begin
q<=d;
q_not <= ~d;
end
else
begin
q<=1'b0;
q_not <= 1'b1;
end
end
endmodule
module main(d, clk, reset, q2, q2_not, q1_not);
input d, clk, reset;
output q2, q2_not, q1_not;
wire d2;
d_ff dup(.d(d), .clk(clk), .reset(reset), .q(d2), .q_not(q1_not));
d_ff dup2(.d(d2), .clk(clk), .reset(reset), .q(q2), .q_not(q2_not));
initial
begin
$display("end of main module");
$finish;
end
endmodule
Here is the testbench:
// Code your testbench here
// or browse Examples
`timescale 1 ns / 100 ps /// 100ps
module main_tb;
reg d, clk, reset;
wire q2, q2_not, q1_not;
main UUT(.d(d), .clk(clk), .reset(reset), .q2(q2), .q2_not(q2_not), .q1_not(q1_not));
initial
begin
clk = 0;
d=1'b0;
reset=1'b1;
#500ns reset=1'b0;
end
always begin
#50ns clk = !clk;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
initial
begin
$monitor("clk = %b, d=%b, reset=%b, q=%b, q_not=%b, d2_not=%b", clk,d,reset, q2,q2_not, q1_not);
#500 reset =1'b1;
#500 d=1'b1;
#500 reset =1'b0;
#500 d=1'b0;
#500 reset = 1'b0;
#500 d=1'b0;
#500 reset = 1'b0;
#500 d=1'b0;
#500 d=1'b1;
#100 reset =1'b1;
#500 d = 1'b1;
#50000ns $finish;
end
endmodule
This:
initial
begin
$display("end of main module");
$finish;
end
Is killing your simulation as all initial statements are run in parallel. Remove it and put a $finish or $stop at the end of the main initial.
Also better to move all clk assignment into the clk block, the same with reset and b:
initial
begin
clk = 1'b0;
forever
#50ns clk = !clk;
end
initial
begin
$monitor("clk = %b, d=%b, reset=%b, q=%b, q_not=%b, d2_not=%b", clk,d,reset, q2,q2_not, q1_not);
d=1'b0;
reset=1'b1;
#500ns reset=1'b0;
#500 reset =1'b1;
#500 d=1'b1;
#500 reset =1'b0;
#500 d=1'b0;
...
$finish; // $stop;
end
I've encountered a test bench which can essentially be boiled down to the below example: clock and signals are changed in the in the same timestep with blocking assignments. I believe this causes a race condition between the clock and the two ctrlX signals, but I was unable to prove in the EDA playground (I understand it's beyond my control). Am I correct that there is a race condition?
(EDA Playground link: https://www.edaplayground.com/x/5yDX#&togetherjs=gkG5xewfNN)
module tb_example;
reg clk = 1;
reg [3:0] dff1,dff2;
reg [3:0] ctrl1 = 'd0;
reg [3:0] ctrl2 = 'd0;
initial begin
#10 ctrl1 = 'd1;
#20 ctrl1 = 'd2;
#10 ctrl1 = 'd3;
#100 $finish;
end
always begin
#5 clk = !clk;
end
initial begin
$dumpfile("dump.vcd");
$dumpvars(0,tb_example);
end
initial begin
#10 ctrl2 = 'd1;
#20 ctrl2 = 'd2;
#10 ctrl2 = 'd3;
#100 $finish;
end
always # (posedge(clk)) begin
dff1 <= ctrl1;
end
always # (posedge(clk)) begin
dff2 <= ctrl2;
end
endmodule
Yes, this is a race condition because you are using blocking assignments for ctrlx and they are changing at the same time as posedge clk. So, the values assigned to dffx are indeterminate and can vary from simulator to simulator.
One way to avoid this is to change ctrlx on the negedge of clk:
reg clk = 0;
i am unable to get correct output in a text file however simulation in modelsim is quite ok.. but while writing it to text file im getting XX for every input. may be there is some syntax error or some other. if any can help plz write down test bench for writing dout (output )of a flipflop (as an example) with every dout(output) showing in a new line in a text file.
Code:
module LFSR( clk,reset,out);
parameter width =4;
input clk,reset;
output [width-1:0] out ;
reg [width-1:0] lfsr;
integer r;
wire feedback = lfsr[width-1]^lfsr[width-2];
always #(posedge clk)
if (reset)
begin
lfsr <= 4'b1000;
end
else
begin
lfsr[0] <= feedback;
for(r=1;r<width;r=r+1)
lfsr[r]<=lfsr[r-1];
end
assign out=lfsr;
endmodule
Testbench:
module aaatest();
parameter width =4;
reg clk,reset;
wire [width-1:0] out;
reg [width-1:0] lfsr[13:0];
integer f,i;
initial
begin
f = $fopen("output.txt","w");
end
LFSR patt (clk,reset,out);
always #5 clk=~clk;
initial begin
clk=1; reset=1;
#10 reset=0;
# 140 $stop;
end
initial
begin
clk=1;
for (i = 0; i<14; i=i+1)
#(posedge clk)
lfsr[i]<= out;
end
initial begin
for (i = 0; i<14; i=i+1)
$fwrite(f,"%b\n",lfsr[i]);
end
initial begin
$display("clk out");
$monitor("%b,%b", clk, out);
end
initial
begin
$fclose(f);
end
endmodule
I would like you to think about these sections of code:
initial begin
f = $fopen("output.txt","w");
end
initial begin
for (i = 0; i<14; i=i+1)
$fwrite(f,"%b\n",lfsr[i]);
end
initial begin
$fclose(f);
end
When describing hardware we have a massively parallel simulation. All initials are meant to start at the same time, time 0.
If this works at all, as there is no guarantee that the file will be opened before you write to it, you are writing the file at time zero before you have even reset the logic your simulating.
Something like below might be more appropriate:
initial begin
f = $fopen("output.txt","w");
#(negedge reset); //Wait for reset to be released
#(posedge clk); //Wait for fisrt clock out of reset
for (i = 0; i<14; i=i+1) begin
$fwrite(f,"%b\n",lfsr[i]);
end
$fclose(f);
end
To follow up on Gregs suggestions the reset being released too early consider something similar to:
initial begin
clk=0; reset=1; //Clock low at time zero
#(posedge clk);
#(posedge clk);
reset=0;
# 140 $stop;
end
Which keep reset asserted for 2 clock rising edges.
Update with working example
There are a few odd things happening, you call $stop (Not $finish) after #140 but also try to loop 14 times, the $stop means only 4 loops are executed.
Your test program is made up of 2 initial begins working in parallel rather than one program that is sequentially executed. You had no delay in writing out your text file and you wrote the buffered version of the lfsr rather than the lfsr output directly.
The following example simulates correctly and writes the text file your looking for:
module aaatest();
parameter width =4;
reg clk,reset;
wire [width-1:0] out;
reg [width-1:0] lfsr[13:0];
integer f,i;
LFSR patt (clk,reset,out);
always #5 clk=~clk;
//Clock and reset release
initial begin
clk=0; reset=1; //Clock low at time zero
#(posedge clk);
#(posedge clk);
reset=0;
end
initial begin
f = $fopen("output.txt","w");
#(negedge reset); //Wait for reset to be released
#(posedge clk); //Wait for fisrt clock out of reset
for (i = 0; i<14; i=i+1) begin
#(posedge clk);
lfsr[i] <= out;
$display("LFSR %b", out);
$fwrite(f,"%b\n", out);
end
$fclose(f);
$finish;
end
endmodule
I have following codes with blocking (code 1) and nonblocking (code 2) assignment in always block.
But output is different in both cases. Why?
Event queue I know, but probably I am not able to understand where "always # (clk)" statement will be placed in event queue.
// Code 1
module osc2 (clk, d);
output clk;
reg clk;
input d;
initial
begin
#10 clk = 0;
$monitor ("%d %b", $time, clk);
end
initial #100 $finish;
always # (clk) #10 clk = ~clk;
endmodule
// Output of Code 1
10 0
20 1
// Code 2
module osc2 (clk, d);
output clk;
reg clk;
input d;
initial
begin
#10 clk = 0;
$monitor ("%d %b", $time, clk);
end
initial #100 $finish;
always # (clk) #10 clk <= ~clk;
endmodule
// Output of Code 2
10 0
20 1
30 0 (goes on upto 90)
90 0
For explanatory purposes, I unraveled the content of the first two loops and expanded components for break down. The below code will simulate.
always # (clk) #10 clk = ~clk;
initial while (1) // to see the loop, functionally equivalent to 'always'
begin // procedural block
begin : loop0_unraveled
#(clk); // suspend continuation of loop until change in clk
#10; // suspend continuation of loop 10 time units
clk = ~clk; /* eval '~clk' now
* update clk now
*/
end
begin : loop1_unraveled
begin // this block is functionally equivalent to '#(clk)'
reg smpl_clk; // local variable
smpl_clk = clk; // sample
$display("%t::Pre-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
wait(clk != smpl_clk); // suspend continuation of loop until
/* 1. no other blocking statements can execute, go to next region
* 2. All other regions are empty
* 3. Remaining events are block
* 4. Nothing left to do, exit simulation
*/
$display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
end
#10; // unreachable
clk = ~clk;
end
end
always # (clk) #10 clk <= ~clk;
initial while (1) // to see the loop, functionally equivalent to 'always'
begin // procedural block
begin : loop0_unraveled
#(clk); // suspend continuation of loop until change in clk
#10; // suspend continuation of loop 10 time units
clk <= ~clk; /* eval '~clk' now,
* update clk after all blocking statements are suspended
*/
end
begin : loop1_unraveled
begin // this block is functionally equivalent to '#(clk)'
reg smpl_clk; // local variable
smpl_clk = clk; // sample
$display("%t::Pre-Suspend : smpl_clk=%b clk=%b",$time, smpl_clk, clk);
wait(clk != smpl_clk); // suspend continuation of loop until true
/* 1. no other blocking statements can execute, go to next region
* 2. In NBA region update clk
* 3. Go back to active region
* 4. Eval true, continue
*/
$display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
end
#10; // reached
clk <= ~clk;
end
end // Go to top of the loop
As I already mentioned here, self triggering blocks are not very common in practice. Clock generator are usually implanted something similar to:
initial begin
#10 clk = 0;
forever #10 clk = ~clk;
end
Or
always #10 clk = (clk===1'b0);