inferred latch when modelling combinational logic

  • Thread starter Florian Schlembach
  • Start date
F

Florian Schlembach

Guest
Hi there,

I am trying to model a simple combinational logic using an always block (rdy and chan_out are 1-bit signals):

----
always @(rdy or chan_out) begin
if(rdy && !chan_out) begin
$strobe("time %d: chan_out=%b, CHAN 0",$time,chan_out);
end
end
----

In my HDL simulator both rdy and chan_out show a rising edge at a certain time snapshot, lets say 405ns, but the strobe message is printed out anyway. Hence, chan_out is 0. See this screenshot: http://www.upload-pictures.de/bild.php/20602,screenshotT91CS.png

Is there a latch inferred? Actually it shouldn't, because both rdy and chan_out are in the sensitivity list? How can I overcome it?

Cheers! Flo
 
Florian Schlembach wrote:
Hi there,

I am trying to model a simple combinational logic using an always block (rdy and chan_out are 1-bit signals):

----
always @(rdy or chan_out) begin
if(rdy && !chan_out) begin
$strobe("time %d: chan_out=%b, CHAN 0",$time,chan_out);
end
end
----

In my HDL simulator both rdy and chan_out show a rising edge at a certain time snapshot, lets say 405ns, but the strobe message is printed out anyway. Hence, chan_out is 0. See this screenshot: http://www.upload-pictures.de/bild.php/20602,screenshotT91CS.png

Is there a latch inferred? Actually it shouldn't, because both rdy and chan_out are in the sensitivity list? How can I overcome it?

Cheers! Flo
For simulation, if rdy and chan_out don't actually have rising edges
within the same delta cycle, then you can in effect have a zero-width
"glitch" on (rdy && !chan_out). You could verify this by adding a
wire like:

wire rdy_and_not_chan_out = rdy && !chan_out;

and add this to the waveform view. You should see a spike in the
waveform at the time your $strobe statement fires. You could filter
out this condition in your always block by adding any delay before
the if statement, for example if your `timescale is 1 ns / 1 ps then

always @(rdy or chan_out) begin
#0.001 ; // Wait one timing resolution unit
if(rdy && !chan_out) begin
$strobe("time %d: chan_out=%b, CHAN 0",$time,chan_out);
end
end

should filter out the zero-width glitch case bacause it only looks at
the combined signals after 1 ps has elapsed.

-- Gabor
 
Thanks, Gabor! *Without any delay* I cannot see any spikes in the simulator (ISim):

http://www.upload-pictures.de/bild.php/20631,screenshotT17QQ.png

Adding another if assignment with (rdy && !chan_out) like this:
---
always @(rdy or chan_out) begin
if(rdy && !chan_out) begin
$strobe("time %d: chan_out=%b, CHAN 0",$time,chan_out);
end
else if(rdy && chan_out) begin
$strobe("time %d: chan_out=%b, CHAN 1",$time,chan_out);
end
end
---

ends up two printouts at time instant 405ns:
time 405: chan_out=1, CHAN 0
time 405: chan_out=1, CHAN 1

thats weird!

Anyway, adding the delay before the if-assignment works! But how does this issue behave after synthesis? I know that delays are ignored by the synthesizer but in practice should be also such non-optimal trigger events?
 
Florian Schlembach wrote:
Thanks, Gabor! *Without any delay* I cannot see any spikes in the simulator (ISim):

http://www.upload-pictures.de/bild.php/20631,screenshotT17QQ.png

Adding another if assignment with (rdy && !chan_out) like this:
---
always @(rdy or chan_out) begin
if(rdy && !chan_out) begin
$strobe("time %d: chan_out=%b, CHAN 0",$time,chan_out);
end
else if(rdy && chan_out) begin
$strobe("time %d: chan_out=%b, CHAN 1",$time,chan_out);
end
end
---

ends up two printouts at time instant 405ns:
time 405: chan_out=1, CHAN 0
time 405: chan_out=1, CHAN 1

thats weird!

Anyway, adding the delay before the if-assignment works! But how does this issue behave after synthesis? I know that delays are ignored by the synthesizer but in practice should be also such non-optimal trigger events?
Synthesis will take (rdy && !chan_out) and make an AND gate with one
inverted input, or the equivalent circuit for the technology you're
designing with. In an FPGA this would end up in a LUT. What happens
when two inputs of a gate toggle simultaneously depends on the actual
hardware implementation. In an FPGA, for example the routing delays
on the two input nets would probably have a significant difference
that could cause a glitch on the output of the LUT. Your code was
obviously not written for synthesis, as it only has system calls and
makes no signal assignments. So if this is inside a synthesizable
module, the whole process would be ignored by the synthesizer.

-- Gabor

PS - when replying to a thread in Google Groups, reply to the
group - not the post author. The new Groups default seems to
reply to both.
 
Indeed, I am implementing the algorithm on a FPGA (Xilinx Spartan-3A) which is also based on a 4-input LUT.
The issue before was for a testbench that validates the proper functionality of my module. The simulation works quite well but I have problems in getting it run on hardware. I expect a similar glitches, e.g. for this combinational part of my module:

---
//filter input
always @(rfd or ce or chan_in) begin
if(rfd && ce) begin
if(!chan_in) begin
din = input_i;
nd = 1'b1;
end else if(chan_in) begin
din = input_q;
nd = 1'b1;
end
end
if(!rfd) nd = 1'b0;
end
---

ce is only set at the initial start to 1 and then kept activated. I suppose there is some sort of a glitch for the two cases (rdy && !chan_in) and (rdy && chan_in).

As I said, simulation works fine in this case, even without any delay assignments.
How can I work around this issue when implementing this code in hardware?
 
On 12/6/2012 8:14 AM, Gabor wrote:

For simulation, if rdy and chan_out don't actually have rising edges
within the same delta cycle, then you can in effect have a zero-width
"glitch" on (rdy && !chan_out). You could verify this by adding a
wire like:

wire rdy_and_not_chan_out = rdy && !chan_out;

and add this to the waveform view. You should see a spike in the
waveform at the time your $strobe statement fires.

Actually, I think the simulator should not display a zero width glitch
in the waveform output. All dumpers I have seen display in the monitor
phase of the simulation time step, just like $strobe and $monitor, and
this is well after the glitch has occurred. If you want to observe the
state of the variables during a delta cycle (when the code is executed)
you need to use $display which should execute immediately.

Cary
 
Am Montag, 10. Dezember 2012 20:00:15 UTC+1 schrieb Cary R.:
On 12/6/2012 8:14 AM, Gabor wrote:



For simulation, if rdy and chan_out don't actually have rising edges

within the same delta cycle, then you can in effect have a zero-width

"glitch" on (rdy && !chan_out). You could verify this by adding a

wire like:



wire rdy_and_not_chan_out = rdy && !chan_out;



and add this to the waveform view. You should see a spike in the

waveform at the time your $strobe statement fires.





Actually, I think the simulator should not display a zero width glitch

in the waveform output. All dumpers I have seen display in the monitor

phase of the simulation time step, just like $strobe and $monitor, and

this is well after the glitch has occurred. If you want to observe the

state of the variables during a delta cycle (when the code is executed)

you need to use $display which should execute immediately.



Cary

thanks, Cary! You are right, $display shows the actual value. In what order everything is being processed is defined by the "Stratified Event Queue", nicely described in this article:

http://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CDMQFjAA&url=http%3A%2F%2Fsunburst-design.com%2Fpapers%2FCummingsSNUG2002Boston_NBAwithDelays.pdf&ei=d3_QULWOMMbAtAbo9oH4Bw&usg=AFQjCNHz7LwVcH1BZlQPGv1_opUWO2RS3A

I am really wondering how I can overcome this discrepancies in time when I implement the verilog code in hardware? How can I go for sure that a certain value is being asserted to a certain point of time?
 
On 12/18/2012 6:41 AM, Florian Schlembach wrote:

I am really wondering how I can overcome this discrepancies in time
when I implement the verilog code in hardware? How can I go for sure
that a certain value is being asserted to a certain point of time?
In general you do not have to worry about glitches in combinational
logic unless the combinational logic is driving a clock or the glitches
have not stabilized when the active clock edge occurs. Well there's also
asynchronous logic design, but that requires a whole different set of
skills. Another thing to consider is that real logic has some intrinsic
delay and most of this delay is inertial so some glitch filter is built
into the real logic.

If you do not want this signal to glitch then you need to enforce some
order in how the signals transition. You cannot count on them
transitioning at the exact same time because in general they are
probably independent signals with individual delay paths. If I
understood more of what you were trying to do I may have other
suggestions/comments.

Given your original code I would assume this is a monitor routine that
is independent of the synthesized code. If that is the case then this
routine will fail when you have real logic with real delays. One way
around this is if you can constrain the delay to 0.1 time units or some
other fixed delay you can do something like the following:

wire rdy_and_not_chan_out;

// Set the delay as needed (inertial delay).
assign #0.1 rdy_and_not_chan_out = rdy & ~chan_out;

always @(rdy_and_not_chan_out) begin
// Subtract the delay here, but this is still printed in the future!
if (rdy_and_not_chan_out) $display("time: %d: chan_out=%b, CHAN 0",
$time-0.1, chan_out);
end

You will need an appropriate `timescale directive somewhere for the 0.1
delay to do something productive (e.g. `timescale 1ns/100ps would ignore
glitches less than 100ps). If all the signals change on whole time unit
delays this output will still be grouped correctly since it is displayed
before the next full time step.

Cary
 
thanks, Cary! You are right in the fact that this was just some sort of a monitoring procedure. At the end, all should be synthesized and in hardware everything reacts with a certain delay. Basically, I tried to synthesize a similar example as a above, the $display functions replaced with something reasonable for the real case. However, I did not get the desired result. In simulation it worked out well, but it hardware it didn't.
I assume this is related to the delays with whose I didn't really consider.

You cannot count on them
transitioning at the exact same time because in general they are
probably independent signals with individual delay paths."
Thats the point I should start to work on. I am not yet so much into HDL programming to get the right feeling of how hardware behaves on synthesized code. Probably, I should try to delay everything by one cycle (using the nonblocking assignment where all the LHS variables are updated at the end of the time step) and give the registers some time to settle. Does anybody has some nice must-have-read articles on this issue?
 

Welcome to EDABoard.com

Sponsor

Back
Top