Differfence in the assignment of a variable to a signal with and without condition

Discussion in 'VHDL' started by filmil, May 23, 2007.

  1. filmil

    filmil Guest

    Greetings.

    I noticed a difference between the simulation results from the two
    different architectures given below. The architectures are almost the
    same, except for the lines marked with "-- XXX Difference".

    The intention of both architectures is that the signal 'output' be set
    to the value of the variable v. The signal 'output' is only read when
    rd = '1'. The first architecture sets output to an undefined value
    for other values of rd, while the second drives output irrespective of
    the value of rd. Thus, I expect the value of 'output', when rd='1' to
    be the same in both cases.

    The simulation shows results I didn't expect. In case of behavior_1,
    the signal is driven as expected. In case of behavior_2, the output
    signal has value "(others => '0')", which is not equal to the value of
    'v'.

    Why do I see different behaviors? I suspect it has to do with 'v'
    being a variable and not a signal, but I don't know why.

    FYI, this is a minimal example that shows the issue. The actual code
    I used when I found this had to do with a FIFO. In its architecture I
    used a shared variable for a memory array instead of a signal array,
    for simulation efficiency.

    f

    --- Snippet: entity driver, architectures behavior_1 and behavior_2
    library ieee;
    use ieee.STD_LOGIC_1164.all;
    use ieee.NUMERIC_STD.all;

    entity driver is
    generic( CLK_PERIOD : Time := 4 ns );
    end;
    architecture behavior_1 of driver is
    constant WIDTH : positive := 3;
    subtype t is std_logic_vector(WIDTH-1 downto 0);

    constant UNDEF : t := (others => 'X');

    signal clk, rd : std_logic;
    signal output : t;
    shared variable v : integer range 0 to (2**WIDTH-1) := 0;
    begin

    rdgen : process
    variable i : integer;
    begin
    wait for 5 * CLK_PERIOD;
    for i in 1 to 5 loop
    wait until rising_edge(clk);
    rd <= '1';
    wait until rising_edge(clk);
    rd <= '0';
    end loop;
    wait;
    end process;

    clkgen : process
    begin
    clk <= '1';
    wait for CLK_PERIOD / 2;
    clk <= '0';
    wait for CLK_PERIOD / 2;
    end process;

    sequential : process(clk)
    begin
    if rising_edge(clk) then
    v := v + 1;
    end if;
    end process;
    output <= std_logic_vector(to_unsigned(v, WIDTH)) when rd = '1' else
    UNDEF; -- XXX Difference
    end;

    architecture behavior_2 of driver is
    constant WIDTH : positive := 3;
    subtype t is std_logic_vector(WIDTH-1 downto 0);

    constant UNDEF : t := (others => 'X');

    signal clk, rd : std_logic;
    signal output : t;
    shared variable v : integer range 0 to (2**WIDTH-1) := 0;
    begin

    rdgen : process
    variable i : integer;
    begin
    wait for 5 * CLK_PERIOD;
    for i in 1 to 5 loop
    wait until rising_edge(clk);
    rd <= '1';
    wait until rising_edge(clk);
    rd <= '0';
    end loop;
    wait;
    end process;

    clkgen : process
    begin
    clk <= '1';
    wait for CLK_PERIOD / 2;
    clk <= '0';
    wait for CLK_PERIOD / 2;
    end process;

    sequential : process(clk)
    begin
    if rising_edge(clk) then
    v := v + 1;
    end if;
    end process;
    output <= std_logic_vector(to_unsigned(v, WIDTH)); -- XXX Difference
    end;
    filmil, May 23, 2007
    #1
    1. Advertising

  2. Re: Differfence in the assignment of a variable to a signal withand without condition

    filmil wrote:

    > Why do I see different behaviors? I suspect it has to do with 'v'
    > being a variable and not a signal, but I don't know why.


    Suggestion.
    Don't use shared variables.
    Declare and use regular variables inside one process.
    If you need to wire processes, use signals.
    See: http://home.comcast.net/~mike_treseler/
    for examples.

    -- Mike Treseler
    Mike Treseler, May 23, 2007
    #2
    1. Advertising

  3. Re: Differfence in the assignment of a variable to a signal withand without condition

    Mike Treseler wrote:
    > Suggestion.
    > Don't use shared variables.


    Just wondering: what is so bad about shared variables? Why are they
    there if they are not to be used?

    f
    Filip Miletic, May 23, 2007
    #3
  4. filmil

    Jim Lewis Guest

    Re: Differfence in the assignment of a variable to a signal withand without condition

    Filip,
    > Mike Treseler wrote:
    >> Suggestion.
    >> Don't use shared variables.

    >
    > Just wondering: what is so bad about shared variables? Why are they
    > there if they are not to be used?
    >
    > f

    I suspect that was the short way of telling your usage
    of shared variables was deprecated with VHDL-2000. Historically,
    they were added in VHDL-93, however, there was concern over
    concurrent access to them. As a result, in VHDL-2000 they were extended
    and are currently required to use a protected type (which is
    different from a regular type). Hence, your usage of a shared
    variable is illegal.

    BTW, personally I use shared variables for modeling in testbenches.
    A protected type is similar to a class, however, it is currently
    missing inheritance and polymorphism (which are planned to be
    added in the next revision). I find them most useful for data
    structures and such.

    Cheers,
    Jim
    SynthWorks VHDL Training
    http://www.synthworks.com
    Jim Lewis, May 23, 2007
    #4
  5. Re: Differfence in the assignment of a variable to a signal withand without condition

    Filip Miletic wrote:
    > Mike Treseler wrote:
    >> Suggestion.
    >> Don't use shared variables.

    >
    > Just wondering: what is so bad about shared variables? Why are they
    > there if they are not to be used?


    Not bad, but an advanced topic and easy to get wrong.
    In my opinion, not indicated for a simple testbench.
    And there are the complications that Jim outlined.

    They can be handy for variable length testbench data,

    http://groups.google.com/group/comp.lang.vhdl/search?q=treseler simple_ok

    but be sure to declare them in a package,
    not in an architecture (where instances collide)

    -- Mike Treseler
    Mike Treseler, May 24, 2007
    #5
  6. filmil

    Andy Guest

    On May 23, 5:29 pm, Jim Lewis <> wrote:
    > Filip,> Mike Treseler wrote:
    > >> Suggestion.
    > >> Don't use shared variables.

    >
    > > Just wondering: what is so bad about shared variables? Why are they
    > > there if they are not to be used?

    >
    > > f

    >
    > I suspect that was the short way of telling your usage
    > of shared variables was deprecated with VHDL-2000. Historically,
    > they were added in VHDL-93, however, there was concern over
    > concurrent access to them. As a result, in VHDL-2000 they were extended
    > and are currently required to use a protected type (which is
    > different from a regular type). Hence, your usage of a shared
    > variable is illegal.
    >
    > BTW, personally I use shared variables for modeling in testbenches.
    > A protected type is similar to a class, however, it is currently
    > missing inheritance and polymorphism (which are planned to be
    > added in the next revision). I find them most useful for data
    > structures and such.
    >
    > Cheers,
    > Jim
    > SynthWorks VHDL Traininghttp://www.synthworks.com


    What Jim said, plus...

    Concurrent signal assignments are implied processes with a sensitivity
    list including all signals on the right hand side of the assignment
    operator.

    The concurrent assignment to output in behavior_1 is sensitive to rd,
    so every time rd changes, it re-executes and uses the value of v at
    that time. In behavior_2, it is sensitive to nothing (no signals), so
    it only executes once, when v is 0.

    Andy
    Andy, May 24, 2007
    #6
  7. filmil

    Jim Lewis Guest

    Re: Differfence in the assignment of a variable to a signal withand without condition

    Mike,
    In VHDL-2000 shared variables were extended and
    and are currently required to use a protected type.
    Hence, your usage of a shared variable is illegal.

    The value of protected types is not readily apparent
    until you start to use them for verification data
    structures. Here is a simple example of a protected type:

    type ErrorCountProtectedType is protected
    procedure IncErrorCount ;
    impure function GetErrorCount return integer ;
    end protected ErrorCountProtectedType ;
    type ErrorCountProtectedType is protected body
    variable ErrCnt : integer := 0 ;
    procedure IncErrorCount is
    begin
    ErrCnt := ErrCnt + 1 ;
    end procedure IncErrorCount ;
    impure function GetErrorCount return integer is
    begin
    return ErrCnt ;
    end GetErrorCount ;
    end protected body ErrorCountProtectedType ;


    The following example creates a single error counter
    that can be incremented by multiple different processes
    using the method IncErrorCount.

    architecture Test of ErrorCount is
    use work.ErrorCountPkg.all ;

    shared variable ErrCnt : ErrorCountProtectedType ;
    begin
    TestProc1 : process
    begin
    for i in 1 to 10 loop
    ErrCnt.IncErrorCount ; wait for 1 ns ;
    end loop ;
    write(output, "P1 " & integer'image( ErrCnt.GetErrorCount ) & LF);
    wait ;
    end process ;

    TestProc2 : process
    begin
    for i in 1 to 10 loop
    ErrCnt.IncErrorCount ; wait for 2 ns ;
    end loop ;
    write(output, "P2 " & integer'image( ErrCnt.GetErrorCount ) & LF);
    wait ;
    end process ;
    end Test ;


    Cheers,
    Jim
    P.S.
    The verification data structures seem quite limited until
    you start to factor in the package generics that were just
    added to the language.


    > Filip Miletic wrote:
    >> Mike Treseler wrote:
    >>> Suggestion.
    >>> Don't use shared variables.

    >> Just wondering: what is so bad about shared variables? Why are they
    >> there if they are not to be used?

    >
    > Not bad, but an advanced topic and easy to get wrong.
    > In my opinion, not indicated for a simple testbench.
    > And there are the complications that Jim outlined.
    >
    > They can be handy for variable length testbench data,
    >
    > http://groups.google.com/group/comp.lang.vhdl/search?q=treseler simple_ok
    >
    > but be sure to declare them in a package,
    > not in an architecture (where instances collide)
    >
    > -- Mike Treseler
    >
    Jim Lewis, May 24, 2007
    #7
  8. Re: Differfence in the assignment of a variable to a signal withand without condition

    Jim Lewis wrote:
    > Mike,
    > In VHDL-2000 shared variables were extended and
    > and are currently required to use a protected type.
    > Hence, your usage of a shared variable is illegal.


    Please don't rat me out to the IEEE :)

    Modelsim gives now gives a warning,
    but the old code still runs.

    Thanks for the examples of protected types.
    Those are hard to find.

    -- Mike Treseler
    Mike Treseler, May 25, 2007
    #8
  9. Re: Differfence in the assignment of a variable to a signal withand without condition

    Mike Treseler wrote:

    > Thanks for the examples of protected types.
    > Those are hard to find.


    Jim's example runs fine in Modelsim
    if I put the protected types in architecture
    scope instead of a package:


    ______________________________________________
    use std.textio.all;
    entity protected_error_counter is
    end entity protected_error_counter;

    architecture sim of protected_error_counter is
    type ErrorCountProtectedType is protected
    procedure IncErrorCount;
    impure function GetErrorCount return integer;
    end protected ErrorCountProtectedType;

    type ErrorCountProtectedType is protected body
    variable ErrCnt : integer := 0;
    procedure IncErrorCount is
    begin
    ErrCnt := ErrCnt + 1;
    end procedure IncErrorCount;

    impure function GetErrorCount return integer is
    begin
    return ErrCnt;
    end GetErrorCount;
    end protected body ErrorCountProtectedType;

    shared variable ErrCnt : ErrorCountProtectedType;
    begin
    TestProc1 : process
    begin
    for i in 1 to 10 loop
    ErrCnt.IncErrorCount; wait for 1 ns;
    end loop;
    write(output, "P1 " & integer'image(ErrCnt.GetErrorCount) & LF);
    wait;
    end process;
    TestProc2 : process
    begin
    for i in 1 to 10 loop
    ErrCnt.IncErrorCount; wait for 2 ns;
    end loop;
    write(output, "P2 " & integer'image(ErrCnt.GetErrorCount) & LF);
    wait;
    end process;
    end sim;

    ___________________________

    56 Thu May 24 /evtfs/home/tres/vhdl/play>
    vsim -c protected_error_counter
    Reading /flip/usr1/modeltech/tcl/vsim/pref.tcl

    # 6.2a

    # vsim -c protected_error_counter

    # // ModelSim SE 6.2a Jun 16 2006 Linux 2.6.16.21-0.25-smp
    # Loading /flip/usr1/modeltech/linux/../std.standard
    # Loading /flip/usr1/modeltech/linux/../std.textio(body)
    # Loading work.protected_error_counter(sim)
    VSIM 1> run
    # P1 16
    # P2 20
    VSIM 2>
    Mike Treseler, May 25, 2007
    #9
  10. Paul Uiterlinden, May 25, 2007
    #10
  11. Mike Treseler wrote:

    > Jim's example runs fine in Modelsim
    > if I put the protected types in architecture
    > scope instead of a package:


    I usually do it the other way around: put everything, including the
    declaration of the protect shared variable itself (not only the type
    definition) in a package. This package is then used in all bus functional
    models I create. Also the testbench uses the package. This is a very
    convenient way to create a global error counter.

    The models then will increment this error counter every time an error is
    detected. At the end of the simulation, all the testbench has to do is read
    the error counter and write out a PASS/FAIL message, thus creating a self
    checking testbench.

    --
    Paul Uiterlinden
    www.aimvalley.nl
    e-mail addres: remove the not.
    Paul Uiterlinden, May 25, 2007
    #11
  12. Re: Differfence in the assignment of a variable to a signal withand without condition

    > Mike Treseler wrote:
    >> Jim's example runs fine in Modelsim
    >> if I put the protected types in architecture
    >> scope instead of a package:


    Paul Uiterlinden wrote:
    > I usually do it the other way around: put everything, including the
    > declaration of the protect shared variable itself (not only the type
    > definition) in a package.


    Ahh. So. Of course. I missed the package body.
    It works fine fully packaged.
    Thanks to Jim and Paul for the tutorial.

    -- Mike Treseler
    ________________________________________

    package ErrorCountPkg is
    type ErrorCountProtectedType is protected
    procedure IncErrorCount;
    impure function GetErrorCount return integer;
    end protected ErrorCountProtectedType;
    shared variable ErrCnt : ErrorCountProtectedType;
    end package ErrorCountPkg;

    package body ErrorCountPkg is
    type ErrorCountProtectedType is protected body
    variable ErrCnt : integer := 0;
    procedure IncErrorCount is
    begin
    ErrCnt := ErrCnt + 1;
    end procedure IncErrorCount;
    impure function GetErrorCount return integer is
    begin
    return ErrCnt;
    end GetErrorCount;
    end protected body ErrorCountProtectedType;
    end package body ErrorCountPkg;

    use std.textio.all;
    use work.ErrorCountPkg.all;
    entity protected_error_counter is
    end entity protected_error_counter;

    architecture sim of protected_error_counter is
    begin
    TestProc1 : process
    begin
    for i in 1 to 10 loop
    ErrCnt.IncErrorCount; wait for 1 ns;
    end loop;
    write(output, "P1 " & integer'image(ErrCnt.GetErrorCount) & LF);
    wait;
    end process;
    TestProc2 : process
    begin
    for i in 1 to 10 loop
    ErrCnt.IncErrorCount; wait for 2 ns;
    end loop;
    write(output, "P2 " & integer'image(ErrCnt.GetErrorCount) & LF);
    wait;
    end process;
    end sim;
    Mike Treseler, May 25, 2007
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. -
    Replies:
    12
    Views:
    692
    Remon van Vliet
    Jun 15, 2005
  2. Nicolas Moreau
    Replies:
    9
    Views:
    3,154
  3. dibacco73
    Replies:
    1
    Views:
    650
    joris
    Feb 12, 2009
  4. wagnerrv
    Replies:
    0
    Views:
    642
    wagnerrv
    Jul 20, 2012
  5. ramy
    Replies:
    7
    Views:
    279
Loading...

Share This Page