• Split array assignment in and out of process?

    From littlewing@21:1/5 to All on Sat Sep 2 16:54:57 2023
    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?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From KJ@21:1/5 to littlewing on Sun Sep 3 14:16:18 2023
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From littlewing@21:1/5 to All on Mon Sep 4 09:05:27 2023
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)