All my testbench is trying to do is verify whether or not the LED signal went high, but on Modelsim when I try and simulate it, the clock doesn't even start, but it initializes to zero. I can also step through my design so I don't appear to have an infinite loop or anything like that. Is there anything obviously wrong here, especially with regards to clock initialization and generation?
`timescale 1ns/100ps
module fir_filter_tb();
reg clk, reset_n;
reg led;
top top_level (
.clk(clk),
.reset_n(reset_n),
.led(led)
);
initial
begin
$display($time, " << Starting the Simulation >>");
clk = 1'b0; // at time 0
reset_n = 0; // reset is active
led = 0; // output is low
#10 reset_n = 1'b1; // at time 20 release reset
end
always #10 clk = ~clk;
always
begin
if (led == 1'b1) begin
$write($time, "Filter Successful");
end else begin
$write($time, "bleh you suck");
end
end
endmodule : fir_filter_tb
The problem is with the always block with led in it. Since there is no timing control, it prevents time from advancing (time remains stuck at 0). It creates an infinite zero-time loop.
One way to fix it is to use:
always #*
This will only trigger the block when led changes.
Related
I am trying to generate a pulse from a signal ext_sample_clk. My design currently has 2 clock signals, clk and ext_sample_clk, which I am generating through a testbench. The following is my simplified code. Besides this, I also have the clk and reset generation logic, which I have not shown for simplicity. I can share those if needed.
module tb;
reg clk;
reg rst;
reg ext_sample_clk;
reg ext_sample_clk_r1;
wire ext_sample_pulse_orig;
//clock gen logic
always
begin
clk = 1'b1;
#5; // 10 ns
clk = 1'b0;
#5;
end
// reset gen logic
initial
begin
rst = 1;
#(100);
rst = 0;
end
// ext_sample_clk logic
always
begin
ext_sample_clk = 1'b1;
#50;
ext_sample_clk = 1'b0;
#50;
end
// register the ext_sample_clk logic, should infer a flip flop
always #(posedge clk) begin
if (rst)
ext_sample_clk_r1 <= 0;
else
ext_sample_clk_r1 <= ext_sample_clk; // lhs doesn't appear to be delayed by 1 clock cycle wrt to rhs
end
assign ext_sample_pulse_orig = ext_sample_clk && !ext_sample_clk_r1;
endmodule
I am expecting to see ext_sample_clk_r1 delayed by one clock pulse compared to ext_sample_clk. But the following is what I observe when I run a simulation on Vivado.
Can anyone explain why I am not seeing a clock cycle delay in ext_sample_clk_r1 with reference to ext_sample_clk. Am I missing something ?
Since you want ext_sample_clk_r1 and ext_sample_clk to be synchronous to the same clock (clk), you need to drive them both off of posedge clk, using nonblocking assignments (<=):
initial begin
ext_sample_clk = 1'b1;
forever begin
repeat (10) #(posedge clk);
ext_sample_clk <= ~ext_sample_clk;
end
end
Here is a running example on edaplayground.
The most probably way of getting the results you see is by using a blocking assignment to ext_sample_clk instead of a non-blocking assignment. Your testbench needs to follow the same rules as if it were part of the design to avoid race conditions. Use a non-blocking assignment or have your testbench apply signals on the opposite edge.
I have a simple Verilog code for a sequential logic network. It consists of a design and a testbench file; it compiles, but it runs for too long. I'm not sure why; apart from the clk, I didn't put any loops in it. Maybe I have some syntax mistakes using the binary numbers. I ran it using the online EDA Playground software; I didn't try it on Xilinx.
Simulator: Icarus Verilog 0.9.7, compile options: -Wall. "Execution
interrupted or reached maximum runtime."
This is what the log wrote.
Design file:
module hazimodul(
input clk,
input rst,
input ce,
input x,
output z
);
reg[1:0] all;
reg[3:0] y;
reg[0:0] zout;
always#(posedge clk)
begin
if(rst)
begin
zout <= 1'b0;
all <= 2'b00;
y <= 4'b0111;
end
else if(ce)
begin
if(all == 2'b00)
begin
if(x== 1'b0)
zout<=1'b0;
else
all <=2'b01;
end
if(all==2'b01)
begin
zout <= y[3:3];
y <= {y[2:0],y[3:3]};
if (y == 4'b0111)
all <= 2'b10;
end
if(all==2'b10)
begin
if(x == 1'b0)
all <= 2'b00;
end
end
end
assign z = zout;
endmodule
Test file:
module test;
reg clk;
reg rst;
reg x;
reg ce;
// Outputs
wire z;
// Instantiate the Unit Under Test (UUT)
hazimodul uut (
.clk(clk),
.rst(rst),
.x(x),
.ce(ce),
.z(z)
);
initial begin
// Initialize Inputs
clk = 0;
rst = 0;
x=0;
ce=0;
#10;
rst<=1;
#20;
rst<=0;
#30
ce<=1;
#40
x<=1;
#80
x<=0;
#90
x<=1;
end
always #5
clk <=~clk;
endmodule
You need to tell the simulator when to stop running. One way is to use the $finish system task, which you can add to your testbench:
initial #1000 $finish;
Now, the simulation finishes on edaplayground. You can change the #1000 delay to something more meaningful to your design.
Here is an explanation of why your code continues to run. Your testbench has 2 parallel threads: one initial block and one always block. In both threads, you add events to the Verilog event queue. The initial block ends after the last assignment to x.
However, the always block continues to add events to the event queue, so the simulation never ends.
Adding the second initial block with the $finish forces the simulation to end, regardless of the infinite always block.
So I have my counter in verilog which is 4 bits and I want it to stay on max value, 1111, until I give it a signal to start counting from 0000 again.
Here's what I've been able to come up with so far:
module contadorAscMax
(
input iClk,
input iRst,
output oQ,
input iCE,
input iSignal,
output [3:0] orCnt
);
reg[3:0] rvCnt_d;
reg[3:0] rvCnt_q;
assign orCnt = rvCnt_q;
always #(posedge iClk or posedge iRst)
begin
if(iRst)
begin
rvCnt_q<=4'b0;
end
else
begin
if(iCE)
begin
rvCnt_q<=rvCnt_d;
end
else
begin
rvCnt_q<=rvCnt_q;
end
end
end
always #*
begin
rvCnt_d=rvCnt_q+4'b1;
if(rvCnt_d == 4'b1111)
begin
rvCnt_d = rvCnt_d;
end
else if(rvCnt_d == 4'b1111 & iSignal)
begin
rvCnt_d = 4'b0;
end
end
endmodule
But it just won't wait for the signal. I am very new to verilog so my code probable doesn't make much sense to a hardware guy, since I am a software engineer so sorry if there are some rookie mistakes here.
As for the testbench, here is what I have:
`timescale 1ns / 1ps
module vtfContMax;
// Inputs
reg iClk;
reg iRst;
reg iCE;
reg iSignal;
// Outputs
wire oQ;
wire [3:0] orCnt;
// Instantiate the Unit Under Test (UUT)
contadorAscMax uut (
.iClk(iClk),
.iRst(iRst),
.oQ(oQ),
.iCE(iCE),
.iSignal(iSignal),
.orCnt(orCnt)
);
initial begin
// Initialize Inputs
iClk = 1;
iRst = 1;
iCE = 1;
iSignal = 0;
// Wait 100 ns for global reset to finish
#10;
iRst = 0;
repeat(10)
begin
repeat(10)
begin
wait(iClk);
wait(!iClk);
end
end
$stop();
// Add stimulus here
end
always
begin
#5;
iClk = ~iClk;
#10
iSignal = ~iSignal;
end
endmodule
Thanks for any help :)
You have split the code in a register and combinatorial section. Although that is a good idea for complex logic, for a simple 4 bit counter it is a bit over the top.
For solving your problem you are close. The trick with code like this, is to make the definition using 'programming' language. Then the code flows from that.
I want to have a counter which goes from 1111 to 0000 when a signal is present, else I want it to count up.
This then leads to:
always #(clk or posedge reset)
begin
if (reset)
count <= 4'b1111;
else
begin
if (count==4'b1111 && start_signal)
count <= 4'b0000;
else
count <= count + 4'b0001
end
end
What you don't mention, but what I see from your code you also have an enable (iCE) and an unused output oQ. The total then becomes:
module contadorAscMax
(
input iClk,
input iRst,
// output oQ,
input iCE,
input iSignal,
output reg [3:0] orCnt
);
always #(iClk or posedge iRst)
begin
if (iRst)
orCnt <= 4'b0000; // or should that be 4'b1111
// Is this really what you want?
// It will start counting after a reset!
else
begin
if (iCE)
begin
if (orCnt==4'b1111 && iSignal)
orCnt <= 4'b0000;
else
orCnt <= orCnt+ 4'b0001;
end
end
end
endmodule
Some more remarks:
Your reset condition looks flawed to me but you have to solve that.
Give the counter enable signal a decent name: 'count_enable' not 'signal'.
Last: I would not use all the 'i's and 'o's. The 'o' signals from one module will be the 'i' of another. Thus you have to change the signal names somewhere. It is better to have a defined signal in your system. If only so you can find in the timing report or gates after synthesis.
I have used following code to generate clock (whichever value I pass through task it will create that frequency), but the code only works if I use CLKSEL_global = clksel_local (i.e. blocking assignment) but that creates delta delay.
How do I generate variable clock without introducing delta delay? Is their another way of using a task. I am using task so that I can pass real values
`timescale 1ns/1ps
module tb();
real CLKSEL_global;
reg CLK7;
new dut(clk,clk_out);
task task_CLOCK;
input real clksel_local;
begin
CLKSEL_global = clksel_local;
end
endtask
initial begin
CLK7 = 0;
forever begin
#(500.0/CLKSEL_global) CLK7 = 1;
#(500.0/CLKSEL_global) CLK7 = 0;
end
end
initial begin
task_CLOCK(340.0);
end
initial begin
#100 $finish ;
end
endmodule
This solution feels like a nasty hack but I think achieves the requirement. When changing the Clock frequency it will change on the next edge, but allows #(posedge clk) to be used for the edge you want to change it on. The change is actually 1ns after the positive edge.
Normally the you would set the frequency and allow it to take effect on the edge giving a full cycle of setup.
module tb();
real CLKSEL_global = 500;
reg clk;
task task_CLOCK;
input real clksel_local;
begin
CLKSEL_global <= clksel_local;
end
endtask
initial begin
#1ns;
clk = 1'b0;
forever begin
#((500.0ns/CLKSEL_global) -1ns) clk = ~clk;
end
end
initial begin
$dumpfile("dump.vcd"); $dumpvars;
task_CLOCK(1);
repeat(2)
#(posedge clk);
task_CLOCK(2);
repeat(2)
#(posedge clk);
$finish ;
end
endmodule
Working copy of above on EDA Playground.
Removing #2 reset after monitor statement makes the code not to work.The output just stands at 0 x. Whereas including it works fine. Why?
module counter(out,clock,reset);
input clock,reset;
wire clock,reset;
output [3:0]out;
reg [3:0]out;
always #(posedge clock or negedge clock)
begin
if(reset)
out<=1'b0;
else
out<=out+1;
end
endmodule
module tb();
reg clock,reset;
output [3:0]out;
counter c(out,clock,reset);
initial
begin
clock=0;
reset=1;
end
initial
begin
$monitor("%d %d",$time,out);
#2 reset=0;
end
always
#1 clock=~clock;
initial
#100 $finish;
endmodule
By removing the #2 you create a race condition on reset:
initial reset = 1;
initial reset = 0;
Simulators will often have the the final value of reset the last assignment read in the compiling order. Try merging you initial blocks:
initial
begin
$monitor("%d %d",$time,out);
clock=0;
reset=1;
#2 // <-- optional (and still recommened) if you make the below change
// #(clk) //<-- if you truely want a dual edge triggered flip-flop with synchronous reset
reset=0;
end
Dual edge triggered flip-flop are very uncommon and many synthesizers and FPGAs do not support them. I'm guessing you are intending to have an negative edge triggered flip-flop with an active high asynchronous reset. In this case replace:
always #(posedge clock or negedge clock)
with:
always #(negedge clock or posedge reset)