Split array assignment in and out of process?...

L

littlewing

Guest
I have some code that fails in the simulator but seemingly is OK when
synthesized:

entity synchronizer is
generic ( stages : positive:= 3);
port (
inval, clock: in std_logic;
outval : out std_logic
);
end entity;

architecture rtl of synchronizer is

signal shifter : std_logic_vector(0 to stages);

begin

shifter(0) <= inval; -- Assignment outside of process

process(clock)
begin
if rising_edge(clock) then
for i in 1 to stages loop
shifter(i) <= shifter(i-1); -- Assignment inside of process
end loop;
end if;
end process;

outval <= shifter(stages);
end architecture;


In the simulator (late-model Vivado default), the \"out\" signal drives to
\"X\" = illegal value, messing up my whole design.

I can fix it by moving the assignment to shifter(0) into the process and
changing the sensitivity list as follows: (only process shown)

process(clock, inval) -- \"inval\" included in sensitivity list
begin
shifter(0) <= inval; -- Assignment inside of process
if rising_edge(clock) then
for i in 1 to stages loop
shifter(i) <= shifter(i-1); -- Assignment inside of process
end loop;
end if;
end process;

Apparently the simulator thinks I am assigning two values to one
destination. I try to assign to part of \"shifter\" outside of the
process and the rest of it inside of the process. In VHDL, is the
array considered one signal, or is it a convenience to describe a
multiplicity of independent signals? Is my original code incorrect?
 
On Saturday, September 2, 2023 at 4:55:01 PM UTC-4, littlewing wrote:
I have some code that fails in the simulator but seemingly is OK when
synthesized:


Apparently the simulator thinks I am assigning two values to one
destination. I try to assign to part of \"shifter\" outside of the
process and the rest of it inside of the process. In VHDL, is the
array considered one signal, or is it a convenience to describe a
multiplicity of independent signals? Is my original code incorrect?

VHDL considers a signal to be driven if it is the target of an assignment. In this case, the signal \'shifter\' (all bits) is being driven both by your process with the sensitivity list as well as the implicit \'shifter(0) <= inval;\' process . It doesn\'t matter that the two processes assigned to non-overlapping sub-elements of the signal \'shifter\'.

The reason for the \'X\' is that while the sensitivity list process drives all the bits of \'shifter\', since there is no assignment to \'shifter(0)\' it should resolve to \'U\' for that process. When it comes to resolving the two drivers for \'shifter(0)\', the \'U\' will win over anything that the \'shifter(0) <= inval;\' process creates. Since you say that synthesis is OK, the synthesis tool is likely letting it slide for some reason. That tool then would not really be compliant even if it is doing what you want. You might also check the end results to make sure that it did actually synthesize to \'shifter(0) <= inval;\' and not something else.

Your original code is not correct and that is what the simulator is effectively telling you when you run the simulation. \'Not correct\' meaning that simulation results do not match synthesis results. It is not \'illegal\' VHDL since VHDL does allow multiple drivers to a \'resolved\' signal type such as \'std_logic/std_logic_vector\'.

However, most synthesis are for signals that are not meant to be driven by more than one driver. The better type to use for all of those signals is \'std_ulogic/std_ulogic_vector\'. If you take your original code and change the type of \'shifter\' from \'std_logic_vector\' to \'std_ulogic_vector\', Vivado should fail to compile because you have multiple drivers for \'shifter\' and it should tell you that. The nice thing is that you won\'t have to run any simulation to figure that out. Std_logic is the \'usual\' type that most folks use, but std_ulogic is the far better choice for exactly this reason. Better to find latent design errors during a compile then during a simulation run or, even worse, after deploying it into something that was synthesized. Save std_logic for cases where there actually are intended to be multiple drivers for a signal and all but one of those drivers will be driving a \'Z\' at all times.

Kevin Jennings
 
On 9/3/2023 05:16 PM, KJ wrote:
On Saturday, September 2, 2023 at 4:55:01 PM UTC-4, littlewing wrote:
I have some code that fails in the simulator but seemingly is OK when
synthesized:


Apparently the simulator thinks I am assigning two values to one
destination. I try to assign to part of \"shifter\" outside of the
process and the rest of it inside of the process. In VHDL, is the
array considered one signal, or is it a convenience to describe a
multiplicity of independent signals? Is my original code incorrect?

VHDL considers a signal to be driven if it is the target of an assignment. In this case, the signal \'shifter\' (all bits) is being driven both by your process with the sensitivity list as well as the implicit \'shifter(0) <= inval;\' process . It doesn\'t matter that the two processes assigned to non-overlapping sub-elements of the signal \'shifter\'.

The reason for the \'X\' is that while the sensitivity list process drives all the bits of \'shifter\', since there is no assignment to \'shifter(0)\' it should resolve to \'U\' for that process. When it comes to resolving the two drivers for \'shifter(0)\', the \'U\' will win over anything that the \'shifter(0) <= inval;\' process creates. Since you say that synthesis is OK, the synthesis tool is likely letting it slide for some reason. That tool then would not really be compliant even if it is doing what you want. You might also check the end results to make sure that it did actually synthesize to \'shifter(0) <= inval;\' and not something else.

Your original code is not correct and that is what the simulator is effectively telling you when you run the simulation. \'Not correct\' meaning that simulation results do not match synthesis results. It is not \'illegal\' VHDL since VHDL does allow multiple drivers to a \'resolved\' signal type such as \'std_logic/std_logic_vector\'.

However, most synthesis are for signals that are not meant to be driven by more than one driver. The better type to use for all of those signals is \'std_ulogic/std_ulogic_vector\'. If you take your original code and change the type of \'shifter\' from \'std_logic_vector\' to \'std_ulogic_vector\', Vivado should fail to compile because you have multiple drivers for \'shifter\' and it should tell you that. The nice thing is that you won\'t have to run any simulation to figure that out. Std_logic is the \'usual\' type that most folks use, but std_ulogic is the far better choice for exactly this reason. Better to find latent design errors during a compile then during a simulation run or, even worse, after deploying it into something that was synthesized. Save std_logic for cases where there actually are intended to be multiple drivers for a signal and all but one of those drivers will be driving a \'Z\' at all times.

Kevin Jennings

Thanks for your thorough answer, Kevin. FYI, the Vivado tools do pick
up multiple drivers, very late in the implementation flow.

Geno
 

Welcome to EDABoard.com

Sponsor

Back
Top