Simulation behaviour, explanation requested

  • Thread starter Jyrki Takalo-Kastari
  • Start date
J

Jyrki Takalo-Kastari

Hi all,

Here is the simplified version of the code I'm having trouble to
understand why it simulates as it does. It's behavioral code and not
supposed to be synthesized.

Problematic line is the one I marked with ***. When the simulator gets to
that line for some reason the value of d is not the value of coe_imexi_d
but the previous value. Once I run through the rest of the process, the
wave window shows that the value of d is the same as value of coe_imexi_d
at that time. Am I missing something here, because I've always thought
that the signals should be the same if assigned the way I've done here? If
I use coe_imexi_d instead of d on that line it works as it should, but I'd
like to understand what is behind this behaviour.

ARCHITECTURE sim OF vb IS

SIGNAL hsync : std_logic;
SIGNAL vsync : std_logic;
SIGNAL pclk : std_logic;
SIGNAL gReset : std_logic;
SIGNAL d : std_logic_vector(11 DOWNTO 0);
SIGNAL clk : std_logic;

BEGIN -- ARCHITECTURE sim

-- These are used to rename some of the entity signals
hsync <= coe_imexi_hsync;
vsync <= coe_imexi_vsync;
pclk <= coe_imexi_pclk;
gReset <= coe_imexi_gReset;
d <= coe_imexi_d;
clk <= csi_imclk_clk;

get_data : PROCESS (pclk, clk, gReset) IS
VARIABLE pixel : IM_PIXEL_BUS := (OTHERS => '0');
VARIABLE new_pixel : boolean := FALSE;
BEGIN -- PROCESS get_data
IF gReset = '1' THEN
-- reset output registers
ELSE
IF rising_edge(pclk) THEN
IF hsync = '1' AND vsync = '1' THEN
*** pixel := d;
new_pixel := TRUE;
END IF;
END IF;

IF rising_edge(clk) THEN
-- do something else
END IF;
END IF;
END PROCESS get_data;

END ARCHITECTURE sim;
 
K

KJ

Hi all,

Here is the simplified version of the code I'm having trouble to  
understand why it simulates as it does. It's behavioral code and not  
supposed to be synthesized.

Problematic line is the one I marked with ***. When the simulator gets to  
that line for some reason the value of d is not the value of coe_imexi_d  
but the previous value. Once I run through the rest of the process, the  
wave window shows that the value of d is the same as value of coe_imexi_d  
at that time. Am I missing something here, because I've always thought  
that the signals should be the same if assigned the way I've done here? If  
I use coe_imexi_d instead of d on that line it works as it should, but I'd  
like to understand what is behind this behaviour.
   -- These are used to rename some of the entity signals
   hsync                  <= coe_imexi_hsync;
   vsync                  <= coe_imexi_vsync;
   pclk                   <= coe_imexi_pclk;
   gReset                 <= coe_imexi_gReset;
   d                      <= coe_imexi_d;
   clk                    <= csi_imclk_clk;

Each of these assignements delays the signal by one simulation delta.
Noticeably absent from the above list though is signal pclk. The
rising edge of pclk is used in the 'get_data' process. By not
delaying pclk with a similar rename that you did to all the other
signals, you've essentially given it a head start.

Some solutions:
1. Either create a new pclk_1 signal which is just a renamed pclk as
you've done with all the others (I'll add here that this creating of
new signals just to rename is a poor approach to the problem for
exactly the reasons that you're seeing here).

2. Get rid of the renaming completely and just use the entity names
that you're given (best approach, even though I gather that you don't
like the entity names).

3. Use variables with the names that you like and assign these at the
start of the process, or processes if there are more than one (roughly
equivalently as a best approach...unless you have a bunch of processes
and need to copy/paste the variable definitions and assignments)

4. Use the VHDL alias statement to create the names you like without
creating a new signal (nearly as good as best approach).

Kevin Jennings
 
J

Jyrki Takalo-Kastari

The following 'renames' are your problem.

Each of these assignements delays the signal by one simulation delta.
Noticeably absent from the above list though is signal pclk. The
rising edge of pclk is used in the 'get_data' process. By not
delaying pclk with a similar rename that you did to all the other
signals, you've essentially given it a head start.

Thanks for your reply KJ

If you look closer you see that pclk is actually on that list! Right below
vsync. I had no idea that assigning signals can cause delay so that's a
valuable information to me but still doesn't explain why this happens.
I'll change the code to use aliases (another feature I wasn't aware of),
but I'm still wondering why the simulation doesn't behave as it should. I
guess it's probably a testbench related thing? In the testbench hsync,
vsync and d change at the same time on the rising edge of pclk. I have an
rtl code which uses exactly the same renaming procedure I've used in this
example (copy/paste actually, same entity) and it works just fine using
the same testbench. I was just playing around to test if simulation time
could be shortened by removing fifo's and other extra stuff from the code.

Using those entity names makes the code a real pain to read and maintain
but SOPC builder can generate proper settings for interface if those names
are used.
 
T

Tricky

I had no idea that assigning signals can cause delay so that's a
valuable information to me but still doesn't explain why this happens.


Deltas are not real time as such, but infinitly small measures of
time. But like Jyrki said the signal asignments delay the signal by 1
delta. Try adding the line:
wait for 0 ps;

before
pixel := d;

The wait statement adds a 1 delta delay to the process.
 
M

Mike Treseler

Jyrki said:
I'm still wondering why the simulation doesn't behave as
it should. I guess it's probably a testbench related thing?

Yes. I like to use a test process with no sensitivity list
that calls a synchronous wait procedure to update signals.

procedure tic (arg : natural := 1) is
begin
for i in 1 to arg loop
wait until rising_edge(clk_s);
end loop;
end procedure tic;

http://home.comcast.net/~mike_treseler/test_uart.vhd
for details.

-- Mike Treseler
 
K

KJ

Thanks for your reply KJ

If you look closer you see that pclk is actually on that list! Right below
vsync.
You're right, my error. There is still though a basic question about
precisely when coe_imexi_pclk changes relative to each of the other
signals...more on that in a bit.
had no idea that assigning signals can cause delay so that's a valuable
information to me but still doesn't explain why this happens.

Take a look at the code that is generating the various coe_* signals, based
on your earlier post it appears that 'coe_imexi_d' must be changing one
simulation delta cycle prior to when coe_imexi_pclk changes. I base that on
your statement that the problematic line of code is 'wrong' when you use 'd'
but correct when you use 'coe_imexi_d'. Since the only difference between
these two signals is a 'time shift' of one delta cycle, then it follows that
this should be the cause of the different behavior. If you use Modelsim,
you can drag these signals into the list window and there you'll see the
time and the delta cycle that the signal changes.
I'll change the code to use aliases (another feature I wasn't aware of),
but I'm still wondering why the simulation doesn't behave as it should. I
guess it's probably a testbench related thing?
Since pclk is being delayed like all of the other signals as you pointed
out, then you'll probably have the same failure using aliases as well.
In the testbench hsync, vsync and d change at the same time on the rising
edge of pclk.
That would be bad...but you're probably saying the 'same time' without
taking into account delta delays. If a signal is being synchronously
generated it will change on the simulation delta cycle immediately after the
change in the clock...without exception and yet it appears that
'coe_imexi_d' is changing one delta cycle before....so you need to trace
back to why that would be

For example, in the following code, the signal 'a' will change at t=1 ns
delta=1 but the signal 'b' will change at t=1 delta=2 and signal 'c' will
change at t=1 delta = 3.

a <= '0', '1' after 1 ns;
b <= a;
c <= b;

The whole concept of 'delta' may seem to be a bit of some clumsy workaround
or something required 'for simulation' but that's not really the case.
Instead if you think of it as a propogation delay needed to evaluate the
line of code it should make sense. Their are no units of measure on delta,
it is simply a count, but you should consider it in your mind to be some
small fraction of time....but not precisely 0.
I have an rtl code which uses exactly the same renaming procedure I've
used in this example (copy/paste actually, same entity) and it works just
fine using the same testbench. I was just playing around to test if
simulation time could be shortened by removing fifo's and other extra
stuff from the code.
Maybe those fifo changes shifted when 'coe_imexi_d' arrives somewhat.

Kevin Jennings
 
K

KJ

Slight followup to my previous post. It's possible that 'coe_imexi_d' is
not changing on the previous simulation delta relative to 'coe_imexi_pclk'
but on the exact same simulation delta. But, depending on the order that
the simulator evaluates the assignment of 'd' relative to the process that
uses 'pclk' you could get different results when using the testbench on
different designs.

In any case, whether 'coe_imexi_d' is changing at the exact same time as
'coe_imexi_pclk' or one simulation delta before, there is a basic design
issue with the testbench it would appear since a synchronously generated
signal always changes one simulation delta after the clock that generates
it.

KJ
 
K

KJ

Follow up to the earlier post, I think you may have a misconception even
about what is the 'correct' response of your code. Any synchronous system
can tolerate a whole bunch of delay on the input signals relative to the
clock (specifically, it can tolerate a delay up to but not including one
whole clock cycle of delay) and yet your original post indicates that you're
getting the incorrect response when the inputs are delayed by one simulation
delta.

As I said in the previous post, I think you have an error in your testbench
since, based on your description, the input signal are not changing after
pclk at all and adding a simulation delta delay to an input signal changes
the output of your system. But your description that you are not getting
what you expect as output when the signals are delayed by that one
simulation delta cycle also indicates to me that you have a fundamental
misconception about when the outputs of flip flops should change in response
to the clock and that in turn has caused you to incorrectly model something
in the testbench.

Kevin Jennings
 
J

Jyrki Takalo-Kastari

Follow up to the earlier post, I think you may have a misconception even
about what is the 'correct' response of your code. Any synchronous
system
can tolerate a whole bunch of delay on the input signals relative to the
clock (specifically, it can tolerate a delay up to but not including one
whole clock cycle of delay) and yet your original post indicates that
you're
getting the incorrect response when the inputs are delayed by one
simulation
delta.

As I said in the previous post, I think you have an error in your
testbench
since, based on your description, the input signal are not changing after
pclk at all and adding a simulation delta delay to an input signal
changes
the output of your system. But your description that you are not getting
what you expect as output when the signals are delayed by that one
simulation delta cycle also indicates to me that you have a fundamental
misconception about when the outputs of flip flops should change in
response
to the clock and that in turn has caused you to incorrectly model
something
in the testbench.

Yes I believe this is correct and I figured what was wrong with the
testbench. I did something different than what I've done before with this
testbech, which was to assign the input signals hsync and vsync using wait
for commands that were relative to the pclk period (pclk and sync signals
assigned the same time and the d one delta later). Then d was assigned
after the first hsync event which created the whole scenario. I now
understant the whole delta delay concept much better thanks to you KJ. I
added one delta delay for hsync and vsync and discovered another bug in
the testbench which made the code with bad timing look like it was working
properly.

The rest of the system was working properly all along the way but the
problems were in the testbench which seems to be the case way too often
for me. Probably because of my lack of undertanding how the simulator
actually works. Thanks everybody and especially KJ!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,585
Members
45,081
Latest member
AnyaMerry

Latest Threads

Top