another counter question

Discussion in 'VHDL' started by martstev@gmail.com, Sep 16, 2006.

  1. Guest

    I am trying to use Altera 9000 part to run at 16.66MHz clock...

    I had several counters..and I have something close to this

    signal counter: integer range 0 to 4194303;

    process (clk,reset)

    if (CLK='1' and CLK'event) then
    count <= count + 1;
    end if;

    if (count <= 120 ) then
    PW <= '0' ;
    else if (count <= 178) then
    PW <= '1';
    else if (count <= 183) then
    PW <= '0';
    end if;

    if (count <= 48000 ) then
    PW_2 <= '1' ;
    else if (count <= 48825) then
    PW_2 <= '0';
    else if (count <= 4182300) then
    PW_2 <= '1';
    end if;

    end if;

    end process;



    I have a counter defined as integer range. and my code complies and
    simulates.

    What I noticed is that the counter was violating the setup and hold
    time (gettting timing error and counter won't reset to 0) in Max Plus 2
    simulation as well on the board, since I have a high integer value. So
    I divided the clock by 2 and use 8.33MHz clock but now I can't get the
    1020ns resolution for PW. (1020/120 = 8.5) so I need to go back to
    16.67MHz clock (one of the PW is 1020ns active low)

    I looked at somet Max Plus 2 primitives for counter but not sure how to
    use them or is there a better way to define counter in Max Plus 2?? Any
    tips?? Also, I didn't have any luck using Hex Value or Std_logic_vector
    (coundn't do arithmetics in Max Plus 2 with Std_logic_vector)..does any
    one know about this as well?

    Thanks,
    Martin
    , Sep 16, 2006
    #1
    1. Advertising

  2. David Ashley Guest

    wrote:
    > I am trying to use Altera 9000 part to run at 16.66MHz clock...
    >
    > I had several counters..and I have something close to this
    >
    > signal counter: integer range 0 to 4194303;
    >
    > process (clk,reset)
    >
    > if (CLK='1' and CLK'event) then
    > count <= count + 1;
    > end if;
    >
    > if (count <= 120 ) then
    > PW <= '0' ;
    > else if (count <= 178) then
    > PW <= '1';
    > else if (count <= 183) then
    > PW <= '0';
    > end if;
    >
    > if (count <= 48000 ) then
    > PW_2 <= '1' ;
    > else if (count <= 48825) then
    > PW_2 <= '0';
    > else if (count <= 4182300) then
    > PW_2 <= '1';
    > end if;
    >
    > end if;
    >
    > end process;
    >
    >
    >
    > I have a counter defined as integer range. and my code complies and
    > simulates.
    >
    > What I noticed is that the counter was violating the setup and hold
    > time (gettting timing error and counter won't reset to 0) in Max Plus 2
    > simulation as well on the board, since I have a high integer value. So
    > I divided the clock by 2 and use 8.33MHz clock but now I can't get the
    > 1020ns resolution for PW. (1020/120 = 8.5) so I need to go back to
    > 16.67MHz clock (one of the PW is 1020ns active low)
    >
    > I looked at somet Max Plus 2 primitives for counter but not sure how to
    > use them or is there a better way to define counter in Max Plus 2?? Any
    > tips?? Also, I didn't have any luck using Hex Value or Std_logic_vector
    > (coundn't do arithmetics in Max Plus 2 with Std_logic_vector)..does any
    > one know about this as well?
    >
    > Thanks,
    > Martin
    >


    Your definitions of PW and PW2 don't cover all cases so there
    is an inferred latch, which is taboo. Note they're not clocked
    in your implementation, so I didn't either in mine but I made
    them concurrent statements.

    I used unsigned instead of integer -- who knows what the
    synthesizer is going to choose for integer. Probably it's 32
    bits, so wouldn't wrap when you want it. The range checking
    is only done during simulation I suspect, and I seem to recall
    wrapping behaviour is not guaranteed. Use one of the bit
    based types so you know what you're getting.

    Hope this is useful.

    -Dave


    library ieee;
    use ieee.std_logic_1164.all;
    use numeric_std.all;

    -- standard wrapping omitted
    signal counter : unsigned (22 downto 0) := (others => '0'); -- 4194303
    = X"3fffff"
    begin
    process(clk)
    begin
    if clk'event and clk = '1' then
    counter <= counter + 1;
    end if;
    end process;

    PW <= '0' when count < 120 else
    '1' when count <= 178 else
    '0';

    PW2 <= '1' when count < 48000 else
    '0' when count < 48825 else
    '1';

    end architecture;


    --
    David Ashley http://www.xdr.com/dash
    Embedded linux, device drivers, system architecture
    David Ashley, Sep 16, 2006
    #2
    1. Advertising

  3. Peter Guest

    skrev:

    > signal counter: integer range 0 to 4194303;
    >
    > process (clk,reset)
    >
    > if (CLK='1' and CLK'event) then
    > count <= count + 1;
    > end if;
    >
    > if (count <= 120 ) then
    > PW <= '0' ;
    > else if (count <= 178) then
    > PW <= '1';


    Hi,

    Why not compare inside the clocked region? You can set PW when you
    reach 120 and clear it at 178. "Equal" comparators consumes less
    resources than "less or equal" comparators. Putting them inside the
    clocked region makes the signal start at the output of a flip-flop so
    you dont start with a deep combinatorial net.

    /Peter

    PS The process is triggered by reset, but its not used to reset count...
    Peter, Sep 18, 2006
    #3
  4. Peter Guest

    skrev:

    > signal counter: integer range 0 to 4194303;
    >
    > process (clk,reset)
    >
    > if (CLK='1' and CLK'event) then
    > count <= count + 1;
    > end if;
    >
    > if (count <= 120 ) then
    > PW <= '0' ;
    > else if (count <= 178) then
    > PW <= '1';


    Hi,

    Why not compare inside the clocked region? You can set PW when you
    reach 120 and clear it at 178. "Equal" comparators consumes less
    resources than "less or equal" comparators. Putting them inside the
    clocked region makes the signal start at the output of a flip-flop so
    you dont start with a deep combinatorial net.

    /Peter

    PS The process is triggered by reset, but its not used to reset count...
    Peter, Sep 18, 2006
    #4
  5. I agree with the "equal" comparators issue suggested by Peter, but I
    don't think is the point. I think the best way to implement a big
    counter is divided in two and use the Carry out signal to start the
    second counter.
    The carry-out counter divides in pieces the combinational logic chain
    and reduces the propagation delay in your logic.
    Try this out.
    Regards

    Alessandro

    Peter wrote:
    > skrev:
    >
    >
    >>signal counter: integer range 0 to 4194303;
    >>
    >>process (clk,reset)
    >>
    >>if (CLK='1' and CLK'event) then
    >> count <= count + 1;
    >>end if;
    >>
    >>if (count <= 120 ) then
    >> PW <= '0' ;
    >>else if (count <= 178) then
    >> PW <= '1';

    >
    >
    > Hi,
    >
    > Why not compare inside the clocked region? You can set PW when you
    > reach 120 and clear it at 178. "Equal" comparators consumes less
    > resources than "less or equal" comparators. Putting them inside the
    > clocked region makes the signal start at the output of a flip-flop so
    > you dont start with a deep combinatorial net.
    >
    > /Peter
    >
    > PS The process is triggered by reset, but its not used to reset count...
    >
    alessandro basili, Sep 18, 2006
    #5
  6. jens Guest

    If you really want to make a fast counter, look no further than a LFSR.
    As an example, you can design a 31-bit counter (with 2,147,483,647
    valid states) with 31 flip-flops and one XOR (or XNOR) gate.

    On another note, beware of the logic hazards on the PW and PW2 outputs-
    only use them as inputs in the same clk domain, or register the outputs.
    jens, Sep 18, 2006
    #6
  7. David Ashley Guest

    jens wrote:
    > If you really want to make a fast counter, look no further than a LFSR.
    > As an example, you can design a 31-bit counter (with 2,147,483,647
    > valid states) with 31 flip-flops and one XOR (or XNOR) gate.
    >
    > On another note, beware of the logic hazards on the PW and PW2 outputs-
    > only use them as inputs in the same clk domain, or register the outputs.
    >


    That's an interesting approach, all you'd need to do is know a good
    starting state (such as '1') and figure out what the value would be
    X states later and compare against that.

    The code would be cryptic but comments would help.

    You wouldn't be able to do comparisons on intermediate values and
    have them make any sense, as the output isn't increasing monotically.
    But I'm sure there are a lot of cases where this would be a perfect low
    resource solution.

    -Dave

    --
    David Ashley http://www.xdr.com/dash
    Embedded linux, device drivers, system architecture
    David Ashley, Sep 18, 2006
    #7
  8. Peter Guest

    alessandro basili skrev:

    > I agree with the "equal" comparators issue suggested by Peter, but I
    > don't think is the point. I think the best way to implement a big
    > counter is divided in two and use the Carry out signal to start the
    > second counter.
    > The carry-out counter divides in pieces the combinational logic chain
    > and reduces the propagation delay in your logic.
    > Try this out.
    > Regards
    >


    Thats a good idea. Using a pipelined carry chain I have run a 32-bit
    counter at over 30 MHz in an old 5V process FPGA. A guess this
    particular chip is rather old? But there shall be no problems to reach
    16 MHz with a 22-bit counter.

    /Peter
    Peter, Sep 19, 2006
    #8
  9. I think this is a very unfeasible counter to Martin's problem. As far as
    I understood he really needs to have PW and PW_2 active in some values
    range. I really don't see how would you implement such a signal,
    checking the state that you can really do not foresee (unless you want
    to layout a sequence of a 31-bit LFSR).
    I think LFSR are good for RAM addressing as reported here:

    http://www.opencores.org/forums/cores/2003/11/00044

    Maybe I missed the point, but I really cannot see it usefull in this case.

    Alessandro

    David Ashley wrote:
    > jens wrote:
    >
    >>If you really want to make a fast counter, look no further than a LFSR.
    >> As an example, you can design a 31-bit counter (with 2,147,483,647
    >>valid states) with 31 flip-flops and one XOR (or XNOR) gate.
    >>
    >>On another note, beware of the logic hazards on the PW and PW2 outputs-
    >>only use them as inputs in the same clk domain, or register the outputs.
    >>

    >
    >
    > That's an interesting approach, all you'd need to do is know a good
    > starting state (such as '1') and figure out what the value would be
    > X states later and compare against that.
    >
    > The code would be cryptic but comments would help.
    >
    > You wouldn't be able to do comparisons on intermediate values and
    > have them make any sense, as the output isn't increasing monotically.
    > But I'm sure there are a lot of cases where this would be a perfect low
    > resource solution.
    >
    > -Dave
    >
    alessandro basili, Sep 19, 2006
    #9
  10. KJ Guest

    "alessandro basili" <> wrote in message
    news:eeo4sf$fsk$...
    >I think this is a very unfeasible counter to Martin's problem. As far as I
    >understood he really needs to have PW and PW_2 active in some values range.
    >I really don't see how would you implement such a signal, checking the
    >state that you can really do not foresee (unless you want to layout a
    >sequence of a 31-bit LFSR).
    > I think LFSR are good for RAM addressing as reported here:
    >
    > http://www.opencores.org/forums/cores/2003/11/00044
    >
    > Maybe I missed the point, but I really cannot see it usefull in this case.
    >
    > Alessandro


    Actually using an LFSR to implement a counter where you set flags at hard
    coded constants is quite feasible and useful and will result in just about
    the smallest, fastest counter possible. The original post had a simple
    counter that counts up and sets some outputs when that count was less than
    or greater than a series of hard coded constants. This can easily be
    transformed into one that sets/resets flip flops when particular counts get
    reached and remain in their current state otherwise.

    Here's another hint: All of the states of an LFSR can be precomputed
    constants so comparing 'count=178' can be done just as easily with
    'count=Lfsr_Count(178)' where I've taken some liberties but the idea is
    that the 178th step of an LFSR can be pre-computed in a VHDL function (in
    this case 'Lfsr_Count') that can then be used to set a constant that will be
    used to trigger the flags.

    KJ
    KJ, Sep 19, 2006
    #10
  11. KJ wrote:
    > "alessandro basili" <> wrote in message
    > news:eeo4sf$fsk$...
    >
    >>I think this is a very unfeasible counter to Martin's problem. As far as I
    >>understood he really needs to have PW and PW_2 active in some values range.
    >>I really don't see how would you implement such a signal, checking the
    >>state that you can really do not foresee (unless you want to layout a
    >>sequence of a 31-bit LFSR).
    >>I think LFSR are good for RAM addressing as reported here:
    >>
    >>http://www.opencores.org/forums/cores/2003/11/00044
    >>
    >>Maybe I missed the point, but I really cannot see it usefull in this case.
    >>
    >>Alessandro

    >
    >
    > Actually using an LFSR to implement a counter where you set flags at hard
    > coded constants is quite feasible and useful and will result in just about
    > the smallest, fastest counter possible. The original post had a simple
    > counter that counts up and sets some outputs when that count was less than
    > or greater than a series of hard coded constants. This can easily be
    > transformed into one that sets/resets flip flops when particular counts get
    > reached and remain in their current state otherwise.
    >
    > Here's another hint: All of the states of an LFSR can be precomputed
    > constants so comparing 'count=178' can be done just as easily with
    > 'count=Lfsr_Count(178)' where I've taken some liberties but the idea is
    > that the 178th step of an LFSR can be pre-computed in a VHDL function (in
    > this case 'Lfsr_Count') that can then be used to set a constant that will be
    > used to trigger the flags.
    >
    > KJ
    >
    >

    I completely agree with you, just in the case this "lfsr_count" function
    already exists. Otherwise how could you tell what will be the count
    value on its 178th step? Can you calculate it to write something like:

    if count = magic_val1 then
    pw <= '1';
    elsif count = magic_val2 then
    pw <= '0';

    Don't you think is easier to have a simple counter with a carry-chain?
    Sorry but I cannot see the point to use an over-killing lfsr.

    Al
    alessandro basili, Sep 19, 2006
    #11
  12. KJ Guest

    alessandro basili wrote:
    > KJ wrote:
    > > "alessandro basili" <> wrote in message
    > > news:eeo4sf$fsk$...
    > >
    > >>I think this is a very unfeasible counter to Martin's problem. As far as I
    > >>understood he really needs to have PW and PW_2 active in some values range.
    > >>I really don't see how would you implement such a signal, checking the
    > >>state that you can really do not foresee (unless you want to layout a
    > >>sequence of a 31-bit LFSR).
    > >>I think LFSR are good for RAM addressing as reported here:
    > >>
    > >>http://www.opencores.org/forums/cores/2003/11/00044
    > >>
    > >>Maybe I missed the point, but I really cannot see it usefull in this case.
    > >>
    > >>Alessandro

    > >
    > >
    > > Actually using an LFSR to implement a counter where you set flags at hard
    > > coded constants is quite feasible and useful and will result in just about
    > > the smallest, fastest counter possible. The original post had a simple
    > > counter that counts up and sets some outputs when that count was less than
    > > or greater than a series of hard coded constants. This can easily be
    > > transformed into one that sets/resets flip flops when particular counts get
    > > reached and remain in their current state otherwise.
    > >
    > > Here's another hint: All of the states of an LFSR can be precomputed
    > > constants so comparing 'count=178' can be done just as easily with
    > > 'count=Lfsr_Count(178)' where I've taken some liberties but the idea is
    > > that the 178th step of an LFSR can be pre-computed in a VHDL function (in
    > > this case 'Lfsr_Count') that can then be used to set a constant that will be
    > > used to trigger the flags.
    > >
    > > KJ
    > >
    > >

    > I completely agree with you, just in the case this "lfsr_count" function
    > already exists.

    If it doesn't exist you can write the function yourself. Xilinx has an
    app note XAPP052 (I think), google for 'LFSR Xilinx' and you should be
    able to find it. In there you'll find the tap points needed for any
    size LFSR up to 168 bits. Given those magic numbers you can code up
    the function that computes the LFSR state for any point in the sequence
    for any size LFSR up to 168 bits in length. The function prototype for
    mine is...

    function Lfsr_Increment(A: unsigned; B: natural := 1) return unsigned;

    Where 'A' is the LFSR state that you're starting at, 'B' is the number
    of steps you want to advance and the return value is an unsigned of the
    same size as 'A' that represents the answer. Although maybe not
    immediately, you'll probably find that you will want to have the
    complementary Lfsr_Decrement function that backs you from an initial
    state to something 'earlier'.

    > Otherwise how could you tell what will be the count
    > value on its 178th step?

    See above

    > Can you calculate it to write something like:
    >
    > if count = magic_val1 then
    > pw <= '1';
    > elsif count = magic_val2 then
    > pw <= '0';
    >

    Below shows a typical usage to implement a a 4 bit up/down counter that
    sets a flag when 3/4 of the way and another one when all of the way
    through the sequence. Once you have all of the various 'Lfsr'
    functions written and tested, they slip right into your typical counter
    templates quite easily. Adapting this to set and hold the flag instead
    of just flagging it for one cycle is straightforward.

    signal Lfsr: unsigned(3 downto 0);
    process(clock)
    constant INIT_COUNT_VALUE: unsigned(Lfsr'range) :=
    Lfsr_Initialize(Lfsr);
    constant NEARLY_DONE_VALUE: unsigned(Lfsr'range) :=
    Lfsr_Get_Value(Lfsr, 0.75);
    constant COMPLETELY_DONE_VALUE: unsigned(Lfsr'range) :=
    Lfsr_Get_Value(Lfsr, 1.0);
    begin
    if rising_edge(Clock) then
    if (Reset = '1') then
    Lfsr <= Lfsr_Initialize(Lfsr);
    elsif (Increment_The_Counter = '1') then
    Lfsr <= Lfsr_Increment(Lfsr);
    elsif (Decrement_The_Counter = '1') then
    Lfsr <= Lfsr_Decrement(Lfsr);
    end if;
    end if;
    if (Lfsr = NEARLY_DONE_VALUE) then
    Nearly_Done <= '1';
    else
    Nearly_Done <= '0';
    end if;
    if (Lfsr = COMPLETELY_DONE_VALUE) then
    Done <= '1';
    else
    Done <= '0';
    end if;
    end process;

    > Don't you think is easier to have a simple counter with a carry-chain?

    No, it's simpler to just say x <= x+1; and not try to think that you
    can outengineer the synthesis folks who live, breathe and eat these
    optomizations.

    > Sorry but I cannot see the point to use an over-killing lfsr.

    For the original poster I agree it might be overkill....unless you
    already have those Lfsr functions written and ready to use in which
    case I think my example of how to use them would say that it's really
    not much different.

    When you're squeezed for space or clock cycle performance though, LFSRs
    are a handy thing to have ready to slip in to replace standard
    counters. Another good usage would be when writing the code to infer a
    fifo. In that application the write address pointer, the read address
    pointer and the fifo depth counter itself can all be LFSR based in many
    cases.

    KJ
    KJ, Sep 19, 2006
    #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. Rafa

    counter question

    Rafa, Feb 4, 2004, in forum: VHDL
    Replies:
    1
    Views:
    498
    ALuPin
    Feb 5, 2004
  2. The Eeediot
    Replies:
    3
    Views:
    2,217
    =?Utf-8?B?UnVsaW4gSG9uZw==?=
    Dec 22, 2004
  3. tonyfai
    Replies:
    0
    Views:
    817
    tonyfai
    Sep 13, 2007
  4. George2
    Replies:
    1
    Views:
    784
    Alf P. Steinbach
    Jan 31, 2008
  5. aardvarkman
    Replies:
    1
    Views:
    72
    aardvarkman
    Oct 19, 2007
Loading...

Share This Page