UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Scholar ronnywebers
Scholar
6,793 Views
Registered: ‎10-10-2014

Strange simulation result when stimuli 'coincide' with active clock edges

I'm working on a custom IP that receives an incoming axi stream, delays it with a single pipeline register, and then outputs the stream. 

 

the pipeline register looks like this :

  

	process(clock)
	begin
	   if rising_edge(clock) then
	       if s00_axis_tvalid = '1' then
                reg_data_buffer <= s00_axis_tdata;
           else
                reg_data_buffer <= reg_data_buffer;
          end if;
	   end if;
	end process;

 

 I've experienced a strange simulation issue. This first made me think of a HDL issue, but later I discovered it's actually an issue with how I generated the stimuli in the testbench. Now to explain my issue, I will work backward and start with the 'good stimuli', so my solution. After that I explain the 'wrong stimuli' causing the strange simulation results.

 

I first start with the stimuli that produce the expected result :

 

To test this IP I generate stimuli that simulate the incoming axis stream. The stimuli look like :

  

         -- transmit 70 words (simple counter values)
         wait until rising_edge(AXI_ACLK);    -- synchronize to the clock
         wait for 2ns;                        -- insert a bit more delay to avoid sim issues
         for i in 0 to 69 loop
             s_snapctrl_tvalid <= '1';                      
            s_snapctrl_tdata <= std_logic_vector(to_unsigned(i, 32));
            wait for AXI_ACLK_period;
         end loop;                        
         s_snapctrl_tvalid <= '0';
         s_snapctrl_tdata <= (others => '0');        
               
         -- wait a clock cycle
         wait for AXI_ACLK_period * 1;

  

the resulting waveform looks like this - (both ok for behavioral and post synthesis simulation) - you can clearly see the 1 clock cycle delay in the pipeline.

Notice also that the data and tvalid line changes 2ns after the rising edge of the clock, as specified by the first 2 lines in the stimuli :

 

pipeline - behav - correct with 2ns delay.png

 

So first 2 lines in the stimuli allign the values 2ns after the rising edge of the clock, these actually were needed to solve my problem.

 

Stimuli without the 2ns delay

So now to demonstrate my problem, I'll comment out the 2ns delay (but leave the wait until rising_edge) :

 

 

         -- transmit 70 words (simple counter values)
         wait until rising_edge(AXI_ACLK);    -- synchronize to the clock
--         wait for 2ns;                        -- insert a bit more delay to avoid sim issues
         for i in 0 to 69 loop
             s_snapctrl_tvalid <= '1';                      
            s_snapctrl_tdata <= std_logic_vector(to_unsigned(i, 32));
            wait for AXI_ACLK_period;
         end loop;                        
         s_snapctrl_tvalid <= '0';
         s_snapctrl_tdata <= (others => '0');        
               
         -- wait a clock cycle
         wait for AXI_ACLK_period * 1;

 

 

these stimuli produce the following sim result :

 

pipeline - behav - error without the 2ns delay.png

 

so in the simulation it looks like the pipeline register no longer functions correctly. However both behavioral and post synthesis simulation showed the same 'eroneous' behavior.

 

now with my very first stimuli

 

now even worse, my very first stimuli were like this :

 

 

         -- transmit 70 words (simple counter values)
         for i in 0 to 69 loop
            wait until rising_edge(AXI_ACLK);       -- properly synchronize with the clock to avoid strange results
            s_snapctrl_tvalid <= '1';                      
            s_snapctrl_tdata <= std_logic_vector(to_unsigned(i, 32));
         end loop;
         wait until rising_edge(AXI_ACLK);                           
         s_snapctrl_tvalid <= '0';
         s_snapctrl_tdata <= (others => '0');        
               
         -- wait a clock cycle
         wait for AXI_ACLK_period * 1;

the behavioral simulation showed exactly what I expected : the 1 pipeline register working ok

 

 

pipeline - behav - ok with data aligned to clock edges.png

 

however the post synthesis functional simulation showed a different result

 

pipeline - post synt - error when data aligned to clock edges.png

 

so for quiet a while I was doubting about my HDL code, something that after synthesis was optimized away. But that wasn't the case, it was caused by wrong usage of stimuli.

 

Questions

 

So a long story to explain that these 'minor' differences in stimuli produce very confusing simulation results. I guess the simulator does it's job properly, however I think I don't know the proper way to generate this kind of stimuli, and align it properly to the clock. If they 'coincide' with the clock edge, simulation results can look very strange.

 

The correct version at the beginning does work for me, however, it inserts the 2ns offset in my larger chian of stimuli, so I'm wondering how other people would create this kind of stimuli.  How do you allign these stimuli properly to the clock to avoid these issues?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
6 Replies
Instructor
Instructor
6,760 Views
Registered: ‎08-14-2007

Re: Strange simulation result when stimuli 'coincide' with active clock edges

This requires some understanding of how simulation works.  In a behavioral simulation, the clock and signal appear to change at the same instant in time.  However internal to the simulator there is a concept of a "delta" delay, which has no real time delay.  The delta simply indicates when in the order of processing the signal is recognized as changing state.

 

When your test bench uses just time (nanoseconds or picoseconds) to generate both a signal and a clock, the two can change at the same time, and if so will also change at the same "delta" time.  Whether the simulation "sees" the clock edge or the signal change first is dependent only on the order in which it handles the processes involved.  Changing the order of your processes in the source code, which should have no effect in real hardware, could then change the outcome of the simulation.  This is called a race condition, or in lay terms "strange simulation result when stimuli coincide with active clock edges." ;-)

 

In behavioral simulation, when the test bench waits for a clock edge to change a stimulus, the change in that stimulus happens one "delta" delay after the clock edge.  That is enough to ensure that all processes see the new value of the stimulus on the next clock edge.  The stimulus appears to change at the clock edge when you view the waveform, but under the hood it happens after the clock edge.

 

In real hardware, a signal will take time to switch after a clock edge.  Also in real hardware, a signal needs to meet setup and hold timing at the next sampling flop.  Therefore when designing a test bench for post translate simulation, it makes sense to add a real time delay rather than just depending on the delta delay.  Otherwise you could fail to meet hold time.  In post-translate simulation without timing (as opposed to post-route timing simulation) you might only need to add a picosecond to meet hold requirements.

-- Gabor
Teacher muzaffer
Teacher
6,751 Views
Registered: ‎03-31-2012

Re: Strange simulation result when stimuli 'coincide' with active clock edges

The simple solution is to produce all stimuli using clocked processes using only one clock for all the system, no waits etc.
The problem originates from the design of the simulation languages which allow, for efficiency purposes, reordering of any event which don't need to be strictly ordered. Using a single clock & clocked processes to generate and consume all events make them strictly ordered but it makes writing test-benches more difficult.
SystemVerilog has different sequencing constructs (like program in addition to module concept) which make life easier for the verification engineer. I am not familiar enough with VHDL if there are similar constructs in that language.
- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
Explorer
Explorer
6,747 Views
Registered: ‎09-07-2011

Re: Strange simulation result when stimuli 'coincide' with active clock edges

Sometime you'll see  testbench stimulus and capture on opposite clock edge of the DUT to avoid this kind of stuff.   Basically same ideas as your 2ns delay.

 

There are some "delta delay" gotchas - some can depend on how the clocks are assigned in the testbench and BFMs.  I'm sure if you google "vhdl clock delta delays" you might get some good info.

 

 

Scholar ronnywebers
Scholar
6,740 Views
Registered: ‎10-10-2014

Re: Strange simulation result when stimuli 'coincide' with active clock edges

thanks all for the ideas. I think I like the idea of a separate clocked process the most, as it does not 'disturb' my main stimuli process.

 

so I could for example I put this axi stream stimuli in a separate, clocked process (using a single system clock), and add an enable (boolean) to trigger the sequence ? the boolean will be set to true in my main sequence at the appropriate time, so the stimuli kicks off?

 

then I'm still puzzled how I could launch this sequence multiple times ... a function or a procedure is not a solution I guess, because they don't seem to run 'in parallel'? Only processes allow for this ? So should I set the boolean to true, wait let's say 2 clock cycles, and turn it back to false. So I can re-use the same process?

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Scholar ronnywebers
Scholar
6,659 Views
Registered: ‎10-10-2014

Re: Strange simulation result when stimuli 'coincide' with active clock edges

thanks @gszakacs, you wrote :

 

"In behavioral simulation, when the test bench waits for a clock edge to change a stimulus, the change in that stimulus happens one "delta" delay after the clock edge.  That is enough to ensure that all processes see the new value of the stimulus on the next clock edge.  The stimulus appears to change at the clock edge when you view the waveform, but under the hood it happens after the clock edge."

 

I'd like to continu on this phrase : I have a simulation which behaves different during 'behavioral' and 'post synthesis functional' simulation (thus not timing simulation, just synthesiszed & run 'post synthesis behavioral').

 

The difference that I see is a matter of data appearing 1 clock cycle 'earlier' in the post synthesis, compared to the behavioral. To the behavioral is as I expect it to work, and also as it works on hardware. So I'm dealing with a simulation issue here, probably the 'order' of interpretation is different in the post synthesis functional vs behavioral.

 

So here is my question : you wrote "In behavioral simulation, when the test bench waits for a clock edge to change a stimulus, the change in that stimulus happens one "delta" delay after the clock edge. "

 

So is the same true for 'post synthesis functional sim'? Or in other words, why would I see a different result in behavioral vs post synthesis functional sim.

 

Behavioral almost always simulates as I 'expect' it, but post-synthesis I sometimes get strange results. Then first I start doubting about my code, but most of the times (if not all) it's just my testbench not 'working' as it should... :-( Not real decent example found on the web, showing such a race condition issue and providing a good solution for it.

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Instructor
Instructor
6,476 Views
Registered: ‎08-14-2007

Re: Strange simulation result when stimuli 'coincide' with active clock edges

In post-synthesis simulation, the main difference is that everything synthesized uses the models from the Xilinx primitives libraries whether the primitives were instantiated or inferred.  There are elements in these libraries that include clock buffering that can cause issues with "hold time" even though you're not running a timing simulation.  Many of the models include small time delays on clock to output (like 1 ps) to avoid hold time issues, but of course your test bench wouldn't have similar delays unless you explicitly put them in the RTL because the test bench is never synthesized.  I often put timed delays on test bench stimulus, not only to handle the imperfect models in the primitives libraries, but also to allow the test bench to be used in a timing simulation if required.

-- Gabor