Why usign a Variable here won't work ?

Discussion in 'VHDL' started by LC, Nov 12, 2009.

  1. LC

    LC Guest

    Hi,

    I'm puzzled...

    This code in (1) works great (function kind of obvious, to generate one
    clock-width pulse every rise transition of a trigger signal).

    while the code in (2) does not work. No errors/warnings
    only fails to produce logic that works as expected.
    (I originally thought of using this version (2) since
    "tv_sr" is absolutely local to this process... but
    stepped into this strange issue)(or pure ignorance !!!)

    Anyone take out of the dark, please ??
    Thanks.

    (I'm using QuartusII-8.1)


    Luis C.



    (1)
    ....etc...
    SIGNAL tv_sr: STD_LOGIC_VECTOR (1 downto 0);
    ....etc...
    sample_trigger: PROCESS(clock)
    BEGIN
    IF (clock='1' AND clock'EVENT)
    THEN
    tv_sr(0) <= trig_in;
    tv_sr(1) <= tv_sr(0);

    IF (tv_sr="01") THEN trig_smp <='1';
    ELSE trig_smp <='0';
    END IF;
    END IF;
    END PROCESS sample_trigger;


    (2)
    ....etc...
    sample_trigger: PROCESS(clock)
    VARIABLE tv_sr: STD_LOGIC_VECTOR (1 downto 0);
    BEGIN
    IF (clock='1' AND clock'EVENT)
    THEN
    tv_sr(0) := trig_in;
    tv_sr(1) := tv_sr(0);

    IF (tv_sr="01") THEN trig_smp <='1';
    ELSE trig_smp <='0';
    END IF;
    END IF;
    END PROCESS sample_trigger;
     
    LC, Nov 12, 2009
    #1
    1. Advertising

  2. LC

    Dave Guest

    On Nov 11, 9:01 pm, LC <> wrote:
    > Hi,
    >
    > I'm puzzled...
    >
    > This code in (1) works great (function kind of obvious, to generate one
    > clock-width pulse every rise transition of a trigger signal).
    >
    > while the code in (2) does not work. No errors/warnings
    > only fails to produce logic that works as expected.
    > (I originally thought of using this version (2) since
    > "tv_sr" is absolutely local to this process... but
    > stepped into this strange issue)(or pure ignorance !!!)
    >
    > Anyone take out of the dark, please ??
    > Thanks.
    >
    > (I'm using QuartusII-8.1)
    >
    > Luis C.
    >
    > (1)
    > ...etc...
    > SIGNAL  tv_sr:  STD_LOGIC_VECTOR (1 downto 0);
    > ...etc...
    > sample_trigger: PROCESS(clock)
    > BEGIN
    >         IF (clock='1' AND clock'EVENT)
    >         THEN
    >                 tv_sr(0) <= trig_in;
    >                 tv_sr(1) <= tv_sr(0);
    >
    >                 IF (tv_sr="01")       THEN    trig_smp <='1';
    >                                 ELSE    trig_smp <='0';
    >                 END IF;                                
    >         END IF;
    > END PROCESS sample_trigger;
    >
    > (2)
    > ...etc...
    > sample_trigger: PROCESS(clock)
    > VARIABLE tv_sr: STD_LOGIC_VECTOR (1 downto 0);
    > BEGIN
    >         IF (clock='1' AND clock'EVENT)
    >         THEN
    >                 tv_sr(0) := trig_in;
    >                 tv_sr(1) := tv_sr(0);
    >
    >                 IF (tv_sr="01")       THEN    trig_smp <='1';
    >                                 ELSE    trig_smp <='0';
    >                 END IF;                                
    >         END IF;
    > END PROCESS sample_trigger;


    Variables and signals behave in fundamentally different ways.
    Basically, a signal assignment does not update the signal's value
    immediately, but instead delays the update until the end of the
    process. A variable assignment updates the variable's value
    immediately. This difference means that a variable does not always
    imply a register, though it may be in a clocked process.
     
    Dave, Nov 12, 2009
    #2
    1. Advertising

  3. LC wrote:

    > while the code in (2) does not work. No errors/warnings
    > only fails to produce logic that works as expected.


    It works like I would expect.
    Try tracing code.

    > IF (clock='1' AND clock'EVENT)
    > THEN
    > tv_sr(0) := trig_in;


    -- tv_sr(0) has value trig_in

    > tv_sr(1) := tv_sr(0);


    -- tv_sr(0) has value trig_in so "00" or "11"
    >
    > IF (tv_sr="01") THEN


    -- can't happen


    -- Mike Treseler
     
    Mike Treseler, Nov 12, 2009
    #3
  4. LC

    Chris Abele Guest

    Dave wrote:
    > On Nov 11, 9:01 pm, LC <> wrote:
    >> Hi,
    >>
    >> I'm puzzled...
    >>
    >> This code in (1) works great (function kind of obvious, to generate one
    >> clock-width pulse every rise transition of a trigger signal).
    >>
    >> while the code in (2) does not work. No errors/warnings
    >> only fails to produce logic that works as expected.
    >> (I originally thought of using this version (2) since
    >> "tv_sr" is absolutely local to this process... but
    >> stepped into this strange issue)(or pure ignorance !!!)
    >>
    >> Anyone take out of the dark, please ??
    >> Thanks.
    >>
    >> (I'm using QuartusII-8.1)
    >>
    >> Luis C.
    >>
    >> (1)
    >> ...etc...
    >> SIGNAL tv_sr: STD_LOGIC_VECTOR (1 downto 0);
    >> ...etc...
    >> sample_trigger: PROCESS(clock)
    >> BEGIN
    >> IF (clock='1' AND clock'EVENT)
    >> THEN
    >> tv_sr(0) <= trig_in;
    >> tv_sr(1) <= tv_sr(0);
    >>
    >> IF (tv_sr="01") THEN trig_smp <='1';
    >> ELSE trig_smp <='0';
    >> END IF;
    >> END IF;
    >> END PROCESS sample_trigger;
    >>
    >> (2)
    >> ...etc...
    >> sample_trigger: PROCESS(clock)
    >> VARIABLE tv_sr: STD_LOGIC_VECTOR (1 downto 0);
    >> BEGIN
    >> IF (clock='1' AND clock'EVENT)
    >> THEN
    >> tv_sr(0) := trig_in;
    >> tv_sr(1) := tv_sr(0);
    >>
    >> IF (tv_sr="01") THEN trig_smp <='1';
    >> ELSE trig_smp <='0';
    >> END IF;
    >> END IF;
    >> END PROCESS sample_trigger;

    >
    > Variables and signals behave in fundamentally different ways.
    > Basically, a signal assignment does not update the signal's value
    > immediately, but instead delays the update until the end of the
    > process. A variable assignment updates the variable's value
    > immediately. This difference means that a variable does not always
    > imply a register, though it may be in a clocked process.


    As Dave says a variable is updated immediately, so the sequence
    [tv_sr(0) := trig_in;] followed by [tv_sr(1) := tv_sr(0);] means that
    tv_sr(0) and tv_sr(1) are both set to trig_in. Consequently the test
    [IF (tv_sr="01")] can never be true, and you'll never get an output pulse.

    I think that if you swap the order of the assignment statements this
    might work, but the output pulse will occur one time step sooner than it
    will in your example (1).

    That's my best guess, anyway.

    Chris
     
    Chris Abele, Nov 12, 2009
    #4
  5. LC

    LC Guest

    Thanks for your help.

    Following your valuable help I thought it should
    be also possible using variables and I tried as
    follows:

    tv_sr := tv_sr(0)&trig_in;

    and it works fine.

    --

    Is it bad practice to write things this
    way or the other way (with signals) ? or is irrelevant ?

    (I'm trying to build a more solid way of
    thinking about VHDL code writing
    in the hope of having less and less issues)

    Again, Many thanks.

    Luis C.
     
    LC, Nov 12, 2009
    #5
  6. LC

    KJ Guest

    On Nov 12, 7:31 am, LC <> wrote:

    >
    > Is it bad practice to write things this
    > way or the other way (with signals) ? or is irrelevant ?
    >


    As a general statement, it is not relevant whether you use variables
    or signals. Your goals should be:
    1. The code functionally performs what it is expected to perform.
    This rule must always be met, no exceptions.
    2. Is easy to understand. If variables happen to make it easier in a
    particular case, use variables. If signals make it easier, use
    signals.

    Since it appears that the whole reason you ran into this is because
    you were trying to make a signal more 'local' to the only place in the
    architecture where it is intended to be used, let me point out two
    other places where signals can be declared that localizes there usage
    in the same fashion that variable are local to a process. VHDL has
    'generate' and 'block' statements within which a signal can be
    declared which is visible only within the block or generate in the
    same way that a variable is visible only within a process. The syntax
    for how you declare signals within a generate or block is shown
    below. As you can see, the effort is really no different than it is
    for a variable. Bottom line is that whether you use a signal or a
    variable should depend on rule #2 above and not on limiting the scope
    or visibility of the signal/variable.

    SOME_BLOCK : block
    signal My_Local_Signal: std_ulogic;
    begin
    -- Put all your code here, concurrent statements or processes
    -- Try it out by putting all of the code for the entire arch-
    -- itecture inside a block
    end SOME_BLOCK;

    SOME_GENERATE : if (1=1) generate
    signal My_Local_Signal: std_ulogic;
    begin
    -- Put all your code here, concurrent statements or processes
    -- Try it out by putting all of the code for the entire arch-
    -- itecture inside a block

    -- Note: Generate statements can also be of the form
    -- "for i in 1 to 4 generate" as well as the "if" conditional
    -- form shown above.
    end SOME_GENERATE;


    > (I'm trying to build a more solid way of
    > thinking about VHDL code writing
    > in the hope of having less and less issues)


    You violated rule #1 by not verifying that form (2) was equivalent to
    (1) by using a simulator. The best way to get "a more solid way of
    thinking about VHDL code writing" is by writing code and using a
    simulator to verify that the design functions as intended. It is far
    quicker than debugging on any form of live hardware. Having said that
    though, posting questions here can also lead to learning new
    techniques and best practices of those who've already climbed the
    learning curve...not to mention finding out about the best prices on
    Nike shoes and Gucci bags.

    Kevin Jennings
     
    KJ, Nov 12, 2009
    #6
  7. LC

    LC Guest

    Kevin, Very valuable tips many tks.

    > You violated rule #1 by not verifying that form (2) was equivalent to
    > (1) by using a simulator.


    yep.. Guilty I admit (I'm an hardware guy)
    Naturally the carpenter first attempt uses wood... only
    after some failures he considers iron as a solution ;-)

    lc.



    KJ wrote:
    > On Nov 12, 7:31 am, LC <> wrote:
    >
    >> Is it bad practice to write things this
    >> way or the other way (with signals) ? or is irrelevant ?
    >>

    >
    > As a general statement, it is not relevant whether you use variables
    > or signals. Your goals should be:
    > 1. The code functionally performs what it is expected to perform.
    > This rule must always be met, no exceptions.
    > 2. Is easy to understand. If variables happen to make it easier in a
    > particular case, use variables. If signals make it easier, use
    > signals.
    >
    > Since it appears that the whole reason you ran into this is because
    > you were trying to make a signal more 'local' to the only place in the
    > architecture where it is intended to be used, let me point out two
    > other places where signals can be declared that localizes there usage
    > in the same fashion that variable are local to a process. VHDL has
    > 'generate' and 'block' statements within which a signal can be
    > declared which is visible only within the block or generate in the
    > same way that a variable is visible only within a process. The syntax
    > for how you declare signals within a generate or block is shown
    > below. As you can see, the effort is really no different than it is
    > for a variable. Bottom line is that whether you use a signal or a
    > variable should depend on rule #2 above and not on limiting the scope
    > or visibility of the signal/variable.
    >
    > SOME_BLOCK : block
    > signal My_Local_Signal: std_ulogic;
    > begin
    > -- Put all your code here, concurrent statements or processes
    > -- Try it out by putting all of the code for the entire arch-
    > -- itecture inside a block
    > end SOME_BLOCK;
    >
    > SOME_GENERATE : if (1=1) generate
    > signal My_Local_Signal: std_ulogic;
    > begin
    > -- Put all your code here, concurrent statements or processes
    > -- Try it out by putting all of the code for the entire arch-
    > -- itecture inside a block
    >
    > -- Note: Generate statements can also be of the form
    > -- "for i in 1 to 4 generate" as well as the "if" conditional
    > -- form shown above.
    > end SOME_GENERATE;
    >
    >
    >> (I'm trying to build a more solid way of
    >> thinking about VHDL code writing
    >> in the hope of having less and less issues)

    >
    > You violated rule #1 by not verifying that form (2) was equivalent to
    > (1) by using a simulator. The best way to get "a more solid way of
    > thinking about VHDL code writing" is by writing code and using a
    > simulator to verify that the design functions as intended. It is far
    > quicker than debugging on any form of live hardware. Having said that
    > though, posting questions here can also lead to learning new
    > techniques and best practices of those who've already climbed the
    > learning curve...not to mention finding out about the best prices on
    > Nike shoes and Gucci bags.
    >
    > Kevin Jennings
     
    LC, Nov 12, 2009
    #7
  8. LC a écrit :
    > Kevin, Very valuable tips many tks.
    >
    > > You violated rule #1 by not verifying that form (2) was equivalent to
    > > (1) by using a simulator.

    >
    > yep.. Guilty I admit (I'm an hardware guy)
    > Naturally the carpenter first attempt uses wood... only
    > after some failures he considers iron as a solution ;-)
    >

    Well I think most of the people in this newsgroup consider themselves as
    harware guys, and we certainly all use a simulator :)

    Nicolas
     
    Nicolas Matringe, Nov 12, 2009
    #8
  9. Brian Drummond wrote:

    > Which means that to achieve the desired semantics (use the previous value, then
    > update the variable), you have to describe the task backwards...


    I might say, "describe the task from the top down" ;)


    >> IF (tv_sr="01") THEN trig_smp <='1';
    >> ELSE trig_smp <='0';
    >> END IF;

    >
    > tv_sr(1) := tv_sr(0);
    >
    > tv_sr(0) := trig_in;


    I like to combine lines when possible to
    simplify assignment ordering.
    In this case, something like

    rise_v := bool2bit(tv_sr_v = "01");
    tv_sr_v := tv_sr_v(0) & trig;

    -- Mike Treseler
     
    Mike Treseler, Nov 12, 2009
    #9
  10. LC wrote:

    > I thought it should
    > be also possible using variables and I tried as
    > follows:
    >
    > tv_sr := tv_sr(0)&trig_in;
    >
    > and it works fine.


    Well done.
    I did the same thing.

    > Is it bad practice to write things this
    > way or the other way (with signals) ? or is irrelevant ?


    Mostly irrelevant.
    It depends how much interest I have in the craft of
    vhdl simulation and synthesis.
    If I found that a nuisance, I might stick
    with structural code and just power through it.
    If I found it fun, I might gild the lilly a bit.


    > (I'm trying to build a more solid way of
    > thinking about VHDL code writing
    > in the hope of having less and less issues)


    Sounds like you're on your way.
    Good luck.

    -- Mike Treseler



    _____________________________________________
    library ieee;
    use ieee.std_logic_1164.all;
    entity rise is

    port (reset,clock : in std_ulogic;
    trig : in std_ulogic;
    rise : out std_ulogic
    );
    end entity rise;

    -- Thu Nov 12 12:39:15 2009 M.Treseler
    architecture synth of rise is
    begin
    sample_trigger : process(reset, clock) is

    function bool2bit (arg : boolean) return std_ulogic
    is variable ret_v : std_ulogic;
    begin
    case arg is
    when true => ret_v := '1';
    when others => ret_v := '0';
    end case;
    return ret_v;
    end function bool2bit;

    variable tv_sr_v : std_logic_vector (1 downto 0);
    variable rise_v : std_ulogic;
    begin
    if reset = '1' then
    -- reset variables here
    tv_sr_v := (others => '0');
    rise_v := '0';
    elsif rising_edge(clock) then
    -- update output regs here
    rise_v := bool2bit(tv_sr_v = "01");
    -- update input regs here
    tv_sr_v := tv_sr_v(0) & trig;
    end if;
    rise <= rise_v; -- update ports here for free reset wiring
    end process sample_trigger;
    end architecture synth;
     
    Mike Treseler, Nov 12, 2009
    #10
    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. Jerry Camel

    Usign an OCX in an ASP .NET page

    Jerry Camel, Sep 14, 2005, in forum: ASP .Net
    Replies:
    5
    Views:
    6,511
    ankit
    Oct 17, 2008
  2. Neil Daniell
    Replies:
    0
    Views:
    571
    Neil Daniell
    Jan 4, 2005
  3. Replies:
    0
    Views:
    790
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,236
    Smokey Grindel
    Dec 2, 2006
  5. perien

    why won't atof work here?

    perien, Jun 12, 2010, in forum: C Programming
    Replies:
    0
    Views:
    491
    perien
    Jun 12, 2010
Loading...

Share This Page