another counter question

M

martstev

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
 
D

David Ashley

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;
 
P

Peter

(e-mail address removed) 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...
 
P

Peter

(e-mail address removed) 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...
 
A

alessandro basili

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
 
J

jens

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.
 
D

David Ashley

jens said:
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
 
P

Peter

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
 
A

alessandro basili

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
 
K

KJ

alessandro basili said:
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
 
A

alessandro basili

KJ said:
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
 
K

KJ

alessandro said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top