Problem with starting value during simulation


A

Andreas Wallner

Hi,

I have a problem with a piece of code I'm simulating using modelsim.
The piece of code should allow sending a strobe from one clock domain
to another.

-- snip --
library ieee;
use ieee.std_logic_1164.all;

entity strobe_handshake is
port (
-- clk domain A
clka : in std_ulogic;
reqa : in std_ulogic;
siga : out std_ulogic;

-- clk domain B
clkb : in std_ulogic;
reqb : in std_ulogic;
sigb : out std_ulogic
);
end entity;

library ieee;
use ieee.std_logic_1164.all;

architecture rtl of strobe_handshake is
signal muxa : std_ulogic := '0';
signal muxb : std_ulogic := '0';
signal togglea : std_ulogic := '0';
signal toggleb : std_ulogic := '0';
signal synca : std_ulogic_vector(2 downto 0) := "000";
signal syncb : std_ulogic_vector(2 downto 0) := "000";
begin
muxa <= togglea when reqa = '0' else not togglea;
siga <= synca(2) xor synca(1);
process(clka)
begin
if clka'event and clka = '1' then
togglea <= muxa;

syncb <= syncb(1 downto 0) & toggleb;
end if;
end process;

muxb <= toggleb when reqb = '0' else not toggleb;
sigb <= syncb(2) xor syncb(1);
process(clkb)
begin
if clkb'event and clkb = '1' then
toggleb <= muxb;

synca <= synca(1 downto 0) & togglea;
end if;
end process;
end architecture;
-- snip --

ATM I just stimulate the DUT with this:

-- snip --
dut: entity work.strobe_handshake(rtl)
port map (
clka => clk1,
reqa => req1,
siga => ack1,
clkb => clk2,
reqb => req2,
sigb => ack2
);

clock_1: process
begin
clk1 <= not clk1;
wait for (1.0/55000000.0) * 1 sec;
end process;

clock_2: process
begin
clk2 <= not clk2;
wait for (1.0/100000000.0) * 1 sec;
end process;
-- snip --

The problem is: I would expect that the does not output a pulse (sig*)
line, until I input a strobe on the req* line. If the clocks in the
stimulus start with a high->low transition (@ 0 ps) everything works
as I expect it, if the stimulus starts low->high it outputs a pulse,
because the mux* line starts off high, although the start value is
defined as '0'.

Any ideas why this is?

Regards,
Andreas
 
Ad

Advertisements

M

Mike Treseler

Andreas said:
The problem is: I would expect that the does not output a pulse (sig*)
line, until I input a strobe on the req* line. If the clocks in the
stimulus start with a high->low transition (@ 0 ps) everything works
as I expect it, if the stimulus starts low->high it outputs a pulse,
because the mux* line starts off high, although the start value is
defined as '0'.

Any ideas why this is?

muxa <= togglea when reqa = '0' else not togglea;

-- applies for all times other than 0, as it is not inside the process.
-- Mike Treseler
 
A

Andreas Wallner

Any ideas why this is?
  muxa <= togglea when reqa = '0' else not togglea;

-- applies for all times other than 0, as it is not inside the process.

Thank you, I didn't know that those statements didn't apply @ time 0.
But shouldn't the initial value of the signal take care of that?
And more important: What about the hardware synthesized from that
code? I'll later try to synthesize it and take a look at the
schematics, but will that also exhibit this behaviour?
How to take care of that problem?

Regards,
Andreas
 
J

Jonathan Bromley

muxa <= togglea when reqa = '0' else not togglea;

-- applies for all times other than 0, as it is not inside the process.

I haven't looked carefully at the OP's code yet,
but I'm afraid this is probably a red herring.

Concurrent signal assignments (the kind that
stand alone, outside any process) are nothing
special in VHDL - they are just a shorthand
way to write a process. So that line of
code actually turns into, and is EXACTLY
equivalent to:

process (togglea, reqa) begin
if reqa = '0' then
muxa <= togglea;
else
muxa <= not togglea;
end if;
end process;

Like any other VHDL process this starts
executing at time zero, does its code, and then
sits around waiting for its sensitivity list
to trip. So I'm afraid I don't agree with
Mike's diagnosis; that statement *will* take
effect at time zero, correctly processing
all the signals' initial values; and it
*will* respect any changes on its inputs,
both at time (zero + delta) and at all
future times.

I would take a closer look at the behaviour
of reqa and reqb in the testbench. Are they
initialized at declaration? If not, they'll
start life at 'U' as usual - and that would
cause the observed behaviour, because the
process
muxa <= togglea when reqa = '0' else not togglea;
will give "muxa <= not togglea" if reqa='U'.

Generally, providing active clock edges exactly
at time zero is a scary thing to do in a testbench.
Does it really make any sense? Is it essential
to do that? If not, I strongly suggest you
allow the clock to idle awhile after the start
of simulation. It'll make things much easier
to diagnose, at the very least.
 
K

KJ

And more important: What about the hardware synthesized from that
code? I'll later try to synthesize it and take a look at the
schematics, but will that also exhibit this behaviour?
How to take care of that problem?

Lesson 1: Get rid of your signal initializations, if something needs
resetting, then use a reset signal. Even if your tool and target
device support VHDL initializations, ask yourself what happens if that
very first clock rising edge that occurs causes a setup time violation
with any of the design inputs? Hint: The answer is that the design
may not work as designed.

The way to "take care of that problem" is to use a properly
synchronized reset signal.

Lesson 2: If you think you don't need to synchronize your reset
signal because reset will be there for a 'long' time then ask yourself
what happens when the reset signals de-asserts within the setup time
of the clock? Hint: The answer is that the design may not work as
designed.

If you're concerned that some output signals "aren't right" prior to
that first clock cycle after reset then ask yourself if that is really
a concern or not? What are the actual consequences?

Lesson 3: Every part is connected to something else. Analyze the
design to see if it really matters whether a particular output is in
the 'wrong' state for one clock cycle. Many times it does not.

Kevin Jennings
 
Ad

Advertisements

A

Andreas Wallner

Lesson 1:  Get rid of your signal initializations, if something needs
resetting, then use a reset signal.  Even if your tool and target
device support VHDL initializations, ask yourself what happens if that
very first clock rising edge that occurs causes a setup time violation
with any of the design inputs?  Hint:  The answer is that the design
may not work as designed.

The way to "take care of that problem" is to use a properly
synchronized reset signal.

Lesson 2:  If you think you don't need to synchronize your reset
signal because reset will be there for a 'long' time then ask yourself
what happens when the reset signals de-asserts within the setup time
of the clock?  Hint:  The answer is that the design may not work as
designed.

If you're concerned that some output signals "aren't right" prior to
that first clock cycle after reset then ask yourself if that is really
a concern or not?  What are the actual consequences?

Lesson 3:  Every part is connected to something else.  Analyze the
design to see if it really matters whether a particular output is in
the 'wrong' state for one clock cycle.  Many times it does not.

Kevin Jennings

I normally do exactly that, but in this case I thought it would be
easier to try to write the code without a reset signal because of the
two clock domains. I edited the part, and now reset all important
registers with the reset signal from the corresponding clock domain.
Thank you
 
Ad

Advertisements


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

Top