EDAboard.com | EDAboard.eu | EDAboard.de | EDAboard.co.uk | RTV forum PL | NewsGroups PL

Strange signal non-assignment

elektroda.net NewsGroups Forum Index - VHDL Language - Strange signal non-assignment

Andy Peters
Guest

Tue Mar 02, 2010 3:07 am   



Here's an odd one. Following is a stripped-down test entity which has
two shift registers, one "good" and one "bad." I ginned this up
because a colleague wrote some code that uses the latter and it showed
a strange simulation result.

---- code here:
library ieee;
use ieee.std_logic_1164.all;

entity shift_test is
end entity shift_test;

architecture test of shift_test is

signal gSysClk : std_logic := '1'; -- the clock
signal aReset : std_logic := '1'; -- async reset
signal sReset : std_logic; -- sync reset

signal srStart : std_logic := '0'; -- start shift
signal srStop : std_logic := '0';

signal goodSR : std_logic_vector(7 downto 0);
signal badSR : std_logic_vector(7 downto 0);

begin -- architecture test

bit0 : process (gSysClk) is
begin -- process bit0
if rising_edge(gSysClk) then
if gReset = '1' then
goodSR(0) <= '0';
badSR(0) <= '0';
elsif srStart = '1' then
goodSR(0) <= '1';
badSR(0) <= '1';
elsif srStop = '1' then
goodSR(0) <= '0';
badSR(0) <= '0';
end if;
end if;
end process bit0;

shifters : process (gSysClk) is
begin -- process shifters
if rising_edge(gSysClk) then
goodSR(goodSR'high downto 1) <= goodSR(goodSR'high - 1
downto 0);

badshiftloop : for i in 1 to badSR'high loop
badSR(i) <= badSR(i-1);
end loop badshiftloop;
end if;
end process shifters;

-- toggle the start and stop.
MainTest : process is
begin -- process MainTest
wait until sReset = '0';
wait for 500 NS;
wait until rising_edge(gSysClk);
srStart <= '1';
wait until rising_edge(gSysClk);
srStart <= '0';
wait for 500 NS;
wait until rising_edge(gSysClk);
srStop <= '1';
wait until rising_edge(gSysClk);
srStop <= '0';
wait until rising_edge(gSysClk);
wait;
end process MainTest;

-- clock:
gSysClk <= not gSysClk after 100 NS;
aReset <= '0' after 666 NS;

SyncReset : process (gSysClk) is
begin -- process SyncReset
if rising_edge(gSysClk) then
sReset <= aReset;
end if;
end process SyncReset;

end architecture test;
------- end code

Basically, we want to expressly set or clear the input to the shift
register. This is done in the bit0 process, depending on the state of
srStart and srStop.

The shifters process never explicitly assigns bit 0 as that is
ostensibly handled in bit0. The goodSR shift register functions as one
expects: goodSR(0) is set one clock after srStart and remains true
until srStop, and the bits shift through properly.

However, in the badSR, none of the bits are ever assigned ... the
shift register remains "UUUUUUUU". Looking at the drivers on this
signal, bit0 is actually assigned a '1' in the bit0 process at the
correct time, but it also has a driver shown for the shifters process,
and this driver's value is 'U'. The bit0 process creates a driver for
goodSR(0) but there is no driver in the shifters process like there is
for badSR(0). So it's the extra driver in shifters on badSR(0) that is
overriding the bit0 assignment (one delta cycle later).

But why is this the case? Why the second driver on the loop but not on
the simpler assignment? I don't see how the simulator infers a driver
in shifters on badSR(0) but not goodSR(0) when in neither case is an
explicit assignment made to either.

FWIW, I get the same results in ModelSim and in Active-HDL.

-a

HT-Lab
Guest

Tue Mar 02, 2010 9:28 am   



Google for longest static prefix,

Also see a simpler example here : http://www.ht-lab.com/question.jpg

Hans
www.ht-lab.com


"Andy Peters" <google_at_latke.net> wrote in message
news:159aea8a-8be9-4688-b5af-00f40a896ee2_at_t31g2000prh.googlegroups.com...
Quote:
Here's an odd one. Following is a stripped-down test entity which has
two shift registers, one "good" and one "bad." I ginned this up
because a colleague wrote some code that uses the latter and it showed
a strange simulation result.

---- code here:
library ieee;
use ieee.std_logic_1164.all;

entity shift_test is
end entity shift_test;

architecture test of shift_test is

signal gSysClk : std_logic := '1'; -- the clock
signal aReset : std_logic := '1'; -- async reset
signal sReset : std_logic; -- sync reset

signal srStart : std_logic := '0'; -- start shift
signal srStop : std_logic := '0';

signal goodSR : std_logic_vector(7 downto 0);
signal badSR : std_logic_vector(7 downto 0);

begin -- architecture test

bit0 : process (gSysClk) is
begin -- process bit0
if rising_edge(gSysClk) then
if gReset = '1' then
goodSR(0) <= '0';
badSR(0) <= '0';
elsif srStart = '1' then
goodSR(0) <= '1';
badSR(0) <= '1';
elsif srStop = '1' then
goodSR(0) <= '0';
badSR(0) <= '0';
end if;
end if;
end process bit0;

shifters : process (gSysClk) is
begin -- process shifters
if rising_edge(gSysClk) then
goodSR(goodSR'high downto 1) <= goodSR(goodSR'high - 1
downto 0);

badshiftloop : for i in 1 to badSR'high loop
badSR(i) <= badSR(i-1);
end loop badshiftloop;
end if;
end process shifters;

-- toggle the start and stop.
MainTest : process is
begin -- process MainTest
wait until sReset = '0';
wait for 500 NS;
wait until rising_edge(gSysClk);
srStart <= '1';
wait until rising_edge(gSysClk);
srStart <= '0';
wait for 500 NS;
wait until rising_edge(gSysClk);
srStop <= '1';
wait until rising_edge(gSysClk);
srStop <= '0';
wait until rising_edge(gSysClk);
wait;
end process MainTest;

-- clock:
gSysClk <= not gSysClk after 100 NS;
aReset <= '0' after 666 NS;

SyncReset : process (gSysClk) is
begin -- process SyncReset
if rising_edge(gSysClk) then
sReset <= aReset;
end if;
end process SyncReset;

end architecture test;
------- end code

Basically, we want to expressly set or clear the input to the shift
register. This is done in the bit0 process, depending on the state of
srStart and srStop.

The shifters process never explicitly assigns bit 0 as that is
ostensibly handled in bit0. The goodSR shift register functions as one
expects: goodSR(0) is set one clock after srStart and remains true
until srStop, and the bits shift through properly.

However, in the badSR, none of the bits are ever assigned ... the
shift register remains "UUUUUUUU". Looking at the drivers on this
signal, bit0 is actually assigned a '1' in the bit0 process at the
correct time, but it also has a driver shown for the shifters process,
and this driver's value is 'U'. The bit0 process creates a driver for
goodSR(0) but there is no driver in the shifters process like there is
for badSR(0). So it's the extra driver in shifters on badSR(0) that is
overriding the bit0 assignment (one delta cycle later).

But why is this the case? Why the second driver on the loop but not on
the simpler assignment? I don't see how the simulator infers a driver
in shifters on badSR(0) but not goodSR(0) when in neither case is an
explicit assignment made to either.

FWIW, I get the same results in ModelSim and in Active-HDL.

-a


Magne Munkejord
Guest

Tue Mar 02, 2010 11:19 am   



HT-Lab wrote:
Quote:
Google for longest static prefix,

Also see a simpler example here : http://www.ht-lab.com/question.jpg

Hans
www.ht-lab.com


Well,
I googled it and tried to understand;
- Longest static prefix of goodSR in process shifters is 7 downto 1
since it is defined explicitly, hence no driver for goodSR(0) in that
process.
- L.S.P. of badSR is all elements of badSR since it is indexed by
variable (not static) and therefore all elements gets assigned a driver
in that process.

Then we have 2 drivers on badSR(0) of type std_logic. Since process
shifters does not explicitly assign any value to badSR(0) it will drive
it with the value it had at the delta time the process is executed.
Since the signal is initialized with 'U', and 'U' will always win the
resolution, process bit0 will never be able to force any other value on
the signal.

Does that make sense? Hopefully, I got it right and learned something
new today!

Paul Uiterlinden
Guest

Tue Mar 02, 2010 1:28 pm   



Magne Munkejord wrote:

Quote:
HT-Lab wrote:
Google for longest static prefix,

Also see a simpler example here : http://www.ht-lab.com/question.jpg

Hans
www.ht-lab.com


Well,
I googled it and tried to understand;
- Longest static prefix of goodSR in process shifters is 7 downto 1
since it is defined explicitly, hence no driver for goodSR(0) in that
process.
- L.S.P. of badSR is all elements of badSR since it is indexed by
variable (not static) and therefore all elements gets assigned a driver
in that process.

Then we have 2 drivers on badSR(0) of type std_logic. Since process
shifters does not explicitly assign any value to badSR(0) it will drive
it with the value it had at the delta time the process is executed.

I think this sentence is not correct, or at least I do not understand it
completely.

The thing is: if a process creates a driver for a signal, the initial value
of the driver is 'U' for a std_logic (or in general: the left-most value of
the type). This is so from time zero and delta zero, and it remains so to
the end of the simulation if there is not a signal assignment. This happens
with badSR(0) in process shifters.

A driver is a permanent thing. It is not only active at the moment a value
is assigned to a signal. The assignment just changes the value of the
driver.

The actual value of a signal with a resolved type (here: std_logic) is
determined by the resolution function of std_logic. That function receives
the value of all drivers and returns the resulting value. In case of
std_logic, 'U' wins over any other value. So badSR(0) wil remain 'U' for
ever.

Quote:
Since the signal is initialized with 'U', and 'U' will always win the
resolution, process bit0 will never be able to force any other value on
the signal.

Does that make sense?

Yes, absolutely.

Quote:
Hopefully, I got it right and learned something new today!

What I would like to add: I do not see any reason to have two processes in
the example of the OP. It has been said in this news group before (and
rightfully so): limit the number of processes. Having multiple processes
makes debugging harder. This is my experience as well.

--
Paul Uiterlinden
www.aimvalley.nl
e-mail addres: remove the not.

rickman
Guest

Tue Mar 02, 2010 2:53 pm   



On Mar 2, 7:28 am, Paul Uiterlinden <puit...@notaimvalley.nl> wrote:
Quote:

What I would like to add: I do not see any reason to have two processes in
the example of the OP. It has been said in this news group before (and
rightfully so): limit the number of processes. Having multiple processes
makes debugging harder. This is my experience as well.

That makes sense to me. At least, I would not put the assignment of
bit 0 in a separate process. Instead I might separately define the
input to bit 0. That could be done either in a process or a
concurrent assignment. I often do that when the logic expressed in an
if-then tree would cloud the rest of the structure of the register
process.

Rick

Magne Munkejord
Guest

Tue Mar 02, 2010 5:46 pm   



Paul Uiterlinden wrote:
Quote:
Magne Munkejord wrote:

HT-Lab wrote:
Google for longest static prefix,

Also see a simpler example here : http://www.ht-lab.com/question.jpg

Hans
www.ht-lab.com

Well,
I googled it and tried to understand;
- Longest static prefix of goodSR in process shifters is 7 downto 1
since it is defined explicitly, hence no driver for goodSR(0) in that
process.
- L.S.P. of badSR is all elements of badSR since it is indexed by
variable (not static) and therefore all elements gets assigned a driver
in that process.

Then we have 2 drivers on badSR(0) of type std_logic. Since process
shifters does not explicitly assign any value to badSR(0) it will drive
it with the value it had at the delta time the process is executed.

I think this sentence is not correct, or at least I do not understand it
completely.
Yes, it was badly written and not very accurate, in some way incorrect.

What I meant to say is that VHDL will explicitly assign a value to a
signal it has a driver for, even if no such signal assignment exists in
the code or are not executed due to conditional constructs. In this case
badSR(0) was initialized to 'U' (the default) so it is equivalent to
badSR(0) <= 'U' until the process assigns another value to it (which it
doesn't).
If badSR(0) was initialized to 'Z', the signal would resolve to the
value driven by process bit0. But the driver for process shifter would
still be 'Z'.

Quote:

The thing is: if a process creates a driver for a signal, the initial value
of the driver is 'U' for a std_logic (or in general: the left-most value of
the type). This is so from time zero and delta zero, and it remains so to
the end of the simulation if there is not a signal assignment. This happens
with badSR(0) in process shifters.

I am sure you know, but it can be initialized to another value when the
signal is declared. If
signal badSR : std_logic_vector(7 downto 0) := (others => '1');
then I assume all drivers for the signal(s) will be initialized to '1'?

Quote:

A driver is a permanent thing. It is not only active at the moment a value
is assigned to a signal. The assignment just changes the value of the
driver.

The actual value of a signal with a resolved type (here: std_logic) is
determined by the resolution function of std_logic. That function receives
the value of all drivers and returns the resulting value. In case of
std_logic, 'U' wins over any other value. So badSR(0) wil remain 'U' for
ever.

Since the signal is initialized with 'U', and 'U' will always win the
resolution, process bit0 will never be able to force any other value on
the signal.

Does that make sense?

Yes, absolutely.

Hopefully, I got it right and learned something new today!

What I would like to add: I do not see any reason to have two processes in
the example of the OP. It has been said in this news group before (and
rightfully so): limit the number of processes. Having multiple processes
makes debugging harder. This is my experience as well.


Andy Peters
Guest

Tue Mar 02, 2010 6:37 pm   



On Mar 2, 3:19 am, Magne Munkejord <magnem...@yahoo.no> wrote:
Quote:
HT-Lab wrote:
Google for longest static prefix,

Also see a simpler example here :http://www.ht-lab.com/question.jpg

Hans
www.ht-lab.com

Well,
I googled it and tried to understand;

- L.S.P. of badSR is all elements of badSR since it is indexed by
variable (not static) and therefore all elements gets assigned a driver
in that process.

Ahhhh, got it.

Quote:
Then we have 2 drivers on badSR(0) of type std_logic. Since process
shifters does not explicitly assign any value to badSR(0) it will drive
it with the value it had at the delta time the process is executed.
Since the signal is initialized with 'U', and 'U' will always win the
resolution, process bit0 will never be able to force any other value on
the signal.

Yes, this seems like it's exactly the problem. I've never run into
this because I always use the non-loop construct for the shift
register, and I would have put the bit 0 assignment in the same
process.

File this under "really dusty corners of VHDL."

-a

Andy
Guest

Tue Mar 02, 2010 9:06 pm   



On Mar 2, 6:53 am, rickman <gnu...@gmail.com> wrote:
Quote:
On Mar 2, 7:28 am, Paul Uiterlinden <puit...@notaimvalley.nl> wrote:



What I would like to add: I do not see any reason to have two processes in
the example of the OP. It has been said in this news group before (and
rightfully so): limit the number of processes. Having multiple processes
makes debugging harder. This is my experience as well.

That makes sense to me.  At least, I would not put the assignment of
bit 0 in a separate process.  Instead I might separately define the
input to bit 0.  That could be done either in a process or a
concurrent assignment.  I often do that when the logic expressed in an
if-then tree would cloud the rest of the structure of the register
process.

Rick

I agree. This is one of those cases where using a variable to capture
combinatorial logic in a clocked process makes particularly good
sense. You get the separation of a separate process or concurrent
assignment, with the simulation efficiency and scope control of a
single process.

Andy

Paul Uiterlinden
Guest

Wed Mar 10, 2010 7:09 pm   



Magne Munkejord wrote:

Quote:
Paul Uiterlinden wrote:
Magne Munkejord wrote:

HT-Lab wrote:
Google for longest static prefix,

Also see a simpler example here : http://www.ht-lab.com/question.jpg

Hans
www.ht-lab.com

Well,
I googled it and tried to understand;
- Longest static prefix of goodSR in process shifters is 7 downto 1
since it is defined explicitly, hence no driver for goodSR(0) in that
process.
- L.S.P. of badSR is all elements of badSR since it is indexed by
variable (not static) and therefore all elements gets assigned a driver
in that process.

Then we have 2 drivers on badSR(0) of type std_logic. Since process
shifters does not explicitly assign any value to badSR(0) it will drive
it with the value it had at the delta time the process is executed.

I think this sentence is not correct, or at least I do not understand it
completely.
Yes, it was badly written and not very accurate, in some way incorrect.
What I meant to say is that VHDL will explicitly assign a value to a
signal it has a driver for, even if no such signal assignment exists in
the code or are not executed due to conditional constructs. In this case
badSR(0) was initialized to 'U' (the default) so it is equivalent to
badSR(0) <= 'U' until the process assigns another value to it (which it
doesn't).
If badSR(0) was initialized to 'Z', the signal would resolve to the
value driven by process bit0. But the driver for process shifter would
still be 'Z'.


The thing is: if a process creates a driver for a signal, the initial
value of the driver is 'U' for a std_logic (or in general: the left-most
value of the type). This is so from time zero and delta zero, and it
remains so to the end of the simulation if there is not a signal
assignment. This happens with badSR(0) in process shifters.

I am sure you know, but it can be initialized to another value when the
signal is declared. If
signal badSR : std_logic_vector(7 downto 0) := (others => '1');
then I assume all drivers for the signal(s) will be initialized to '1'?

Good question (sorry for the late answer).

My initial though was: yes.
Then I started thinking and doubt set in.
So time for a little experiment:

ENTITY sig_init_val IS
END ENTITY sig_init_val;

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ARCHITECTURE arch OF sig_init_val IS
SIGNAL s : std_logic := '1';
BEGIN
driver1: PROCESS IS
BEGIN
WAIT FOR 1 ns;
s <= '0';
WAIT;
END PROCESS driver1;

driver2: PROCESS IS
BEGIN
WAIT FOR 2 ns;
s <= '0';
WAIT;
END PROCESS driver2;

mon_s: PROCESS(s) IS
BEGIN
REPORT "s = " & std_logic'IMAGE(s) & ".";
END PROCESS mon_s;
END ARCHITECTURE arch;


The outcome of this is:

# ** Note: s = '1'.
# Time: 0 ps Iteration: 0 Instance: /sig_init_val
# ** Note: s = 'X'.
# Time: 1 ns Iteration: 1 Instance: /sig_init_val
# ** Note: s = '0'.
# Time: 2 ns Iteration: 1 Instance: /sig_init_val

So the signal starts at '1' at time=0 ns, delta=0. Then it goes to 'X' at
time=1 ns, delta=1. Finally it goes to '1' at time=2 ns, delta=1.

Perhaps the surprising part is the transition at 1 ns to 'X'. So driving a
value in the future (1 ns later) has an effect now (at 1 ns).

The explanation of course is that both processes create a driver for signal
s. The initial value of both drivers is '1', as you already suspected.

At 1 ns driver1 changes value to '0', while driver2 stay unchanged at '1'.
Hence the resulting 'X'

At 2 ns driver2 changes value to '0', so now both driving values are '0'.
Hence the transition to '0'.

Ahh, I love it when theory and practice coincide. ;-)

--
Paul Uiterlinden
www.aimvalley.nl
e-mail addres: remove the not.

elektroda.net NewsGroups Forum Index - VHDL Language - Strange signal non-assignment

Arabic versionBulgarian versionCatalan versionCzech versionDanish versionGerman versionGreek versionEnglish versionSpanish versionFinnish versionFrench versionHindi versionCroatian versionIndonesian versionItalian versionHebrew versionJapanese versionKorean versionLithuanian versionLatvian versionDutch versionNorwegian versionPolish versionPortuguese versionRomanian versionRussian versionSlovak versionSlovenian versionSerbian versionSwedish versionTagalog versionUkrainian versionVietnamese versionChinese version
RTV map EDAboard.com map News map EDAboard.eu map EDAboard.de map EDAboard.co.uk map Opony