Not seeing a clock cycle delay in Vivado simulation during a register/flipflop assignment - verilog

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.

Related

EDAPlayground: Verilog code "reached maximum runtime"

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.

Fastest way to react to an external trigger signal

An external trigger signal is sent to the FPGA. The trigger signal should be accepted only if and1 and and2 are also high at the time the trigger is received. If the trigger is accepted, a 10 microsecond duration trigger out pulse should be created. The goal is to try and minimise the time that the FPGA takes to accept/reject this external trigger signal.
module trigger(
input CLK,
input trigger,
input and1,
input and2,
output triggerOut,
);
The first attempt at a solution was the following;
assign triggerOut = trigger & and1 & and2;
The reaction time is fast but I don't think this allows the 10 microsecond trigger duration to be implemented.
The current solution is the following;
always #(posedge CLK) begin
if(trigger & and1 & and2)
triggerOut <= 1;
end
This solution allows a counter to be added, which allows the 10 microsecond trigger pulse to be implemented. The caveat is that now the reaction time to the external trigger is tied to the frequency of CLK. The reaction time can be improved by increasing the CLK frequency, but there is a limit to how high CLK can be increased.
Another possible solution may be sensitivity to the changing trigger input;
always #(posedge trigger) begin
if(trigger & and1 & and2)
triggerOut <= 1;
end
I have read that this may be bad practice. It was not clear to me why using #(posedge CLK) is preferred to #(posedge trigger). What defines the reaction time of the FPGA to a sensitivity like #(posedge trigger)? I suppose this must still be somehow tied to CLK - is this approach potentially any faster?
Are there any better approaches to improve the reaction time to the trigger input?
It's difficult to reach that goal without resorting to asynchronous logic. Fortunately, recent FPGAs have level triggered latches as primitives, so incomplete combinational always blocks not always are a bad practice.
OTOH, the 10us width triggerOutput signal needs a synchronous clock to count time, but this timer will, at a first approach, be triggered by an asynchronous input. That will surely pose a problem of cross domain clocking and the trivial solution (synchronizing with two flip-flops) will introduce some latency so the 10us pulse may not start at the same time that trigger is internally accepted, and/or be exactly 10us width. To avoid the metastability issue with triggerOutput, it can be used as an asynchronous reset signal for the 1 to 10 counter.
That all said, this module is a implementation of an asynchronous approach to your trigger detector and acceptor:
module detect_trigger (
input wire clk, // let's say it's 1 MHz (period = 1us)
input wire trigger,
input wire and1,
input wire and2,
output reg triggerOut
);
reg [3:0] cnt = 4'd0;
initial triggerOut = 1'b0;
always #* begin
if (cnt >= 4'd11)
triggerOut = 1'b0;
else if (trigger && and1 && and2)
triggerOut = 1'b1;
end
always #(posedge clk or negedge triggerOut) begin
if (triggerOut == 1'b0)
cnt <= 4'd0;
else if (cnt < 4'd11)
cnt <= cnt + 4'd1;
end
endmodule
A test bench module could be as this:
module tb;
reg clk;
reg trigger;
reg and1, and2;
wire triggerOut;
detect_trigger uut (
.clk(clk),
.trigger(trigger),
.and1(and1),
.and2(and2),
.triggerOut(triggerOut)
);
initial begin
$dumpfile ("dump.vcd");
$dumpvars(1, tb);
clk = 1'b0;
and1 = 1'b0;
and2 = 1'b0;
trigger = 1'b0;
repeat (5) begin
#3023;
and1 = 1'b1;
#2419;
and2 = 1'b1;
#1865;
and1 = 1'b0;
and2 = 1'b0;
end
$finish;
end
always begin
clk = #500 ~clk;
end
always begin
trigger = 1'b0;
#1753;
trigger = 1'b1;
#2;
end
endmodule
The output of this test bench is as follows:
You can modify and run the above design with EDA Playground here:
https://www.edaplayground.com/x/3SGs

variable clock generation in verilog using task

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.

Monitor statement verilog

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)

gate control clock generation

Here is the code first...
always#(posedge clk)
begin
if(cstate==idle) rclk<=1;
else rclk<=0;
end
always#(negedge clk)
rclk<=0;
What I want to achieve is this: every time at the rising edge of clock signal, if the signal cstate equals idle(4'b0000), the the rclk goes to one, else to zero, at the same time, every time the falling edge of clk will set the rclk to zero. THIS CODE IS NOT SYNTHESIZABLE since the compiler gives the error " the rclk signal is driven by multiple drivers".
How can I achieve the same function by other techniques?
It looks like you want a clock gate cell. Based on a 1 cycle wide enable signal generate a clock pulse which has the same high time as the input clock.
A naive way of doing this might be :
assign rclk = (cstate==idle) ? clk : 1'b0 ;
Which could easily be synthesised assign rclk = (cstate==idle) & clk ;
cstate == idle is going to glitch which is why it would normally be used by a flip-flop allowing the answer to settle before being used.
Using a clock gate cell stops you from creating glitches on the (rclk) clock line. It is common to instantiate your libraries clock gate cell in the rtl for this. In RTL it might be similar to :
reg result;
always #(posedge clk or negedge rst_n) begin
if (~rst_n) begin
result <= 1'b0;
end
else begin
result <= (cstate == idle);
end
end
assign rclk = (result) ? clk : 1'b0 ;
This means result will be stable for each clock cycle, not allowing glitches through from the comparator.
Expanded answer
I have included my example again below with waveform, I have replaced your state comparison with a simple counter which overflows to reset itself. Not the comparison is matching to 2'b10; which means the clock appears on the following count (2'b11). If the clock was to appear in exactly the same time your comparison matched then you have no glitch suppression on your clock and will likely generate unreliable hardware.
reg [1:0] counter = 0;
always #(posedge clk)
counter <= counter+1;
reg result;
wire result_a = (counter == 2'b10 );
always #(posedge clk or negedge rst_n) begin
if (~rst_n) begin
result <= 1'b0;
end
else begin
result <= result_a;
end
end
assign rclk = (result) ? clk : 1'b0 ;

Resources