Using integers for counters in synthesis

  • Thread starter Benjamin Couillard
  • Start date
B

Benjamin Couillard

Guest
Hi everyone,

I have a simple question. Assuming we have this process :


MY_PROCESS : process(CLK)
variable cnt : natural range 0 to 255;
begin
if rising_edge(CLK) then
output_signal <= '0';
if (srst = '1') then
cnt := 0;
else
if (cnt = 100) then
output_signal <= '1';
end if;
cnt := cnt + 1;
end if;
end if;
end process;

In simulation, I will get an error at the rising edge of CLK when cnt
is 255. However, what happens in synthesis? Will the synthesizer add
logic to prevent cnt from wrapping aroung ? Or will it simply
implement the "usual" wraparound behavior? Is it synthesizer
specific?

Best regards.

Benjamin
 
On Dec 8, 1:25 am, Benjamin Couillard <benjamin.couill...@gmail.com>
wrote:
Hi everyone,

I have a simple question. Assuming we have this process :

MY_PROCESS : process(CLK)
variable cnt : natural range 0 to 255;
begin
   if rising_edge(CLK) then
    output_signal <= '0';
    if (srst = '1') then
      cnt := 0;
   else
    if (cnt = 100) then
       output_signal <= '1';
   end if;
   cnt := cnt + 1;
   end if;
  end if;
end process;

In simulation, I will get an error at the rising edge of CLK when cnt
is 255. However, what happens in synthesis? Will the synthesizer add
logic to prevent cnt from wrapping aroung ? Or will it simply
implement the "usual" wraparound behavior? Is it synthesizer
specific?

Best regards.

Benjamin
From my experience, counters like this will just wrap in synthesis.
The error you get is more to do with the VHDL type system rather than
how it works on hardware. It is one danger of the VHDL types, but it
might just be safer to stick with an Unsigned type in your code.

Personally, If I want wrapping behaviour I use and unsigned, but if I
always reset at a specific number, Ill use an integer.
 
Benjamin Couillard <benjamin.couillard@gmail.com> writes:

Hi everyone,

I have a simple question. Assuming we have this process :


MY_PROCESS : process(CLK)
variable cnt : natural range 0 to 255;
begin
if rising_edge(CLK) then
output_signal <= '0';
if (srst = '1') then
cnt := 0;
else
if (cnt = 100) then
output_signal <= '1';
end if;
cnt := cnt + 1;
end if;
end if;
end process;

In simulation, I will get an error at the rising edge of CLK when cnt
is 255.
Quite right too, you're trying to push 256 into that variable and
you've said "it can't happen" when you defined the range.

However, what happens in synthesis? Will the synthesizer add
logic to prevent cnt from wrapping aroung ? Or will it simply
implement the "usual" wraparound behavior? Is it synthesizer
specific?
In theory it's completely undefined - you've told the synthesiser that
that variable can't be bigger than 255, so if you try and make it so,
the synthesiser is probably within its rights to generate logic that
shorts the power supplies and makes magic smoke issue forth from your
FPGA :)

In reality, no synthesiser I know of would implement this as anything
other than an 8 bit counter which wraps around.

HOWEVER... in order to keep your simulation matching your synthesis
(which IMHO you must do), you should either:

1) Use an unsigned vector, for which wraparound behaviour is the
defined behaviour on overflow.

2) Put some explicit code in to handle the overflow - the synthesiser
will spot that it is unneeded in your case, and implement the same as
it would've before.

As an aside - if you find yourself using a different maximum for cnt
(say 200 for example), and you don't do option 2) you'll likely find the
synthesiser generating an 8 bit wraparound counter which will still
count up to 255, making your sim and synth completely different...

Cheers,
Martin

--
martin.j.thompson@trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.co.uk/capabilities/39-electronic-hardware
 
Martin Thompson wrote:
Benjamin Couillard <benjamin.couillard@gmail.com> writes:

Hi everyone,

I have a simple question. Assuming we have this process :


MY_PROCESS : process(CLK)
variable cnt : natural range 0 to 255;
begin
if rising_edge(CLK) then
output_signal <= '0';
if (srst = '1') then
cnt := 0;
else
if (cnt = 100) then
output_signal <= '1';
end if;
cnt := cnt + 1;
end if;
end if;
end process;

In simulation, I will get an error at the rising edge of CLK when cnt
is 255.

Quite right too, you're trying to push 256 into that variable and
you've said "it can't happen" when you defined the range.

However, what happens in synthesis? Will the synthesizer add
logic to prevent cnt from wrapping aroung ? Or will it simply
implement the "usual" wraparound behavior? Is it synthesizer
specific?

In theory it's completely undefined - you've told the synthesiser that
that variable can't be bigger than 255, so if you try and make it so,
the synthesiser is probably within its rights to generate logic that
shorts the power supplies and makes magic smoke issue forth from your
FPGA :)

In reality, no synthesiser I know of would implement this as anything
other than an 8 bit counter which wraps around.

HOWEVER... in order to keep your simulation matching your synthesis
(which IMHO you must do), you should either:

1) Use an unsigned vector, for which wraparound behaviour is the
defined behaviour on overflow.

2) Put some explicit code in to handle the overflow - the synthesiser
will spot that it is unneeded in your case, and implement the same as
it would've before.
I agree that you have to fix your code like that, but not for any
synthesis-related reason - simply because it is wrong. The run-time
bound error proves that your there is a mismatch between the model
and the design intent. You would have to fix the code regardless
of whether the code is synthesisable or not.


As an aside - if you find yourself using a different maximum for cnt
(say 200 for example), and you don't do option 2) you'll likely find the
synthesiser generating an 8 bit wraparound counter which will still
count up to 255, making your sim and synth completely different...
Again, I find this a very dangerous way of putting it. Now newbies
may think that they should avoid integers because of sim/synth
mismatches, which simply do not exist. It is meaningless to talk
about mismatches beyond a simulation error.

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Python as a HDL: http://www.myhdl.org
VHDL development, the modern way: http://www.sigasi.com
Analog design automation: http://www.mephisto-da.com
World-class digital design: http://www.easics.com
 
On Dec 7, 6:25 pm, Benjamin Couillard <benjamin.couill...@gmail.com>
wrote:
Hi everyone,

I have a simple question. Assuming we have this process :

MY_PROCESS : process(CLK)
variable cnt : natural range 0 to 255;
begin
   if rising_edge(CLK) then
    output_signal <= '0';
    if (srst = '1') then
      cnt := 0;
   else
    if (cnt = 100) then
       output_signal <= '1';
   end if;
   cnt := cnt + 1;
   end if;
  end if;
end process;

In simulation, I will get an error at the rising edge of CLK when cnt
is 255. However, what happens in synthesis? Will the synthesizer add
logic to prevent cnt from wrapping aroung ? Or will it simply
implement the "usual" wraparound behavior? Is it synthesizer
specific?

Best regards.

Benjamin
Put a modulo 256 on the counter:

count : process (clk) is
variable cnt : natural range 0 to 255;
begin
if (srst = '1') then
cnt := 0;
outreg <= '0';
elsif rising_edge(clk) then
if (cnt = 100) then
outreg <= '1';
else
outreg <= '0';
end if;

cnt := (cnt + 1) mod 256;
end if;
end process count;

The synthesis tool will recognize that the modulo is just there to
prevent overflow in simulation and it gets optimized away in the
hardware.

-a
 
On Dec 8, 8:28 am, Martin Thompson <martin.j.thomp...@trw.com> wrote:
2) Put some explicit code in to handle the overflow - the synthesiser
will spot that it is unneeded in your case, and implement the same as
it would've before.
That depends on what code you put in there to "handle the overflow"...

If your resulting code will not allow an overflow of the assignment,
then you are removing the ambiguity caused by the illegal condition of
an overflow. Absent the ambiguity, the synthesis tool will then be
bound to replicate the resulting behavior, which may or may not be the
same as before.

A minor point: "the overflow" occurs only upon the assignment, not on
the increment. It is perfectly legal to add 1 to cnt when cnt is 255
(the result is 256). What is not legal is to take that result and try
to store it back into cnt! For example, (cnt + 1 > 255) is perfectly
legal and meaningful with cnt: natural range 0 to 255. With cnt:
unsigned (7 downto 0), it is also legal, but meaningless and will
always evaluate as false. Using (cnt + 1 > 255) or (cnt - 1 < 0) as a
conditional is an excellent way to efficiently detect a roll-over (by
accessing the carry/borrow bit), but it only works for integer
subtypes, not signed/unsigned.

Andy
 
Jan Decaluwe <jan@jandecaluwe.com> writes:

Martin Thompson wrote:
HOWEVER... in order to keep your simulation matching your synthesis
(which IMHO you must do), you should either:

1) Use an unsigned vector, for which wraparound behaviour is the
defined behaviour on overflow.

2) Put some explicit code in to handle the overflow - the synthesiser
will spot that it is unneeded in your case, and implement the same as
it would've before.

I agree that you have to fix your code like that, but not for any
synthesis-related reason - simply because it is wrong. The run-time
bound error proves that your there is a mismatch between the model
and the design intent.
Yes - I didn't mean to imply it was for a synthesis-related issue.

The question asked what would happen - I answered. Then followed up
with:

HOWEVER... in order to keep your simulation matching your synthesis
(which IMHO you must do), you should either:
the implication of "you must do" was intended to be "it's wrong
without it" - but I can see it might not be strong enough. Or maybe I
should've written "to keep your simulation matching your design intent".

You would have to fix the code regardless
of whether the code is synthesisable or not.
Well, yes, if the simulation is dying like that, something is wrong.

I read the question (accurately or not!) to be more "it'll die in
sim, but I reckon it'll be alright in the real hardware, do I need to
bother with it?" - to which I was trying to say "YES!"

As an aside - if you find yourself using a different maximum for cnt
(say 200 for example), and you don't do option 2) you'll likely find the
synthesiser generating an 8 bit wraparound counter which will still
count up to 255, making your sim and synth completely different...

Again, I find this a very dangerous way of putting it. Now newbies
may think that they should avoid integers because of sim/synth
mismatches, which simply do not exist.
Well, that certainly wasn't my intent, sorry!

It is meaningless to talk about mismatches beyond a simulation
error.
Yes - assuming your simulation is good enough to show the error.

Cheers,
Martin

--
martin.j.thompson@trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.co.uk/capabilities/39-electronic-hardware
 
Andy <jonesandy@comcast.net> writes:

On Dec 8, 8:28 am, Martin Thompson <martin.j.thomp...@trw.com> wrote:
2) Put some explicit code in to handle the overflow - the synthesiser
will spot that it is unneeded in your case, and implement the same as
it would've before.

That depends on what code you put in there to "handle the overflow"...
OK, yes - assuming the code you put in there makes it wrap around to
zero (which is what I meant by "in your case")

If your resulting code will not allow an overflow of the assignment,
then you are removing the ambiguity caused by the illegal condition of
an overflow. Absent the ambiguity, the synthesis tool will then be
bound to replicate the resulting behavior, which may or may not be the
same as before.
Yes, if you make it saturate for example, the synthesiser (of course)
will add logic to replicate your saturation requirement.

<snip>

Cheers,
Martin

--
martin.j.thompson@trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.co.uk/capabilities/39-electronic-hardware
 
On Tue, 7 Dec 2010 17:25:40 -0800 (PST), Benjamin Couillard
<benjamin.couillard@gmail.com> wrote:

Hi everyone,

I have a simple question. Assuming we have this process :


MY_PROCESS : process(CLK)
variable cnt : natural range 0 to 255;
begin
if rising_edge(CLK) then
output_signal <= '0';
if (srst = '1') then
cnt := 0;
else
if (cnt = 100) then
output_signal <= '1';
end if;
cnt := cnt + 1;
end if;
end if;
end process;

In simulation, I will get an error at the rising edge of CLK when cnt
is 255.
As you should. Wrapping round is always an error in integer arithmetic.
(Relying on that error is ... IMO, not best practice)

If you want wrapround from 255 to 0, you want a modular type - as others point
out, numeric_std.unsigned meets your needs.

Or you could make the wrapround explicit using the "mod" operator.
This is more flexible since the "mod" value can be something other than 256.

However, what happens in synthesis?
Anything at all, since you have presumably fixed the error during simulation ;-)

Conventionally, synthesis tools will treat the error condition as a "don't care"
and implement the smallest (or fastest) logic they can ... which may even be
exactly what you wanted. Or not...

- Brian
 
On Dec 8, 9:28 am, Martin Thompson <martin.j.thomp...@trw.com> wrote:
Benjamin Couillard <benjamin.couill...@gmail.com> writes:
Hi everyone,

I have a simple question. Assuming we have this process :

MY_PROCESS : process(CLK)
variable cnt : natural range 0 to 255;
begin
   if rising_edge(CLK) then
    output_signal <= '0';
    if (srst = '1') then
      cnt := 0;
   else
    if (cnt = 100) then
       output_signal <= '1';
   end if;
   cnt := cnt + 1;
   end if;
  end if;
end process;

In simulation, I will get an error at the rising edge of CLK when cnt
is 255.

Quite right too, you're trying to push 256 into that variable and
you've said "it can't happen" when you defined the range.  

However, what happens in synthesis? Will the synthesizer add
logic to prevent cnt from wrapping aroung ? Or will it simply
implement the "usual" wraparound behavior? Is it synthesizer
specific?

In theory it's completely undefined - you've told the synthesiser that
that variable can't be bigger than 255, so if you try and make it so,
the synthesiser is probably within its rights to generate logic that
shorts the power supplies and makes magic smoke issue forth from your
FPGA :)

In reality, no synthesiser I know of would implement this as anything
other than an 8 bit counter which wraps around.

HOWEVER... in order to keep your simulation matching your synthesis
(which IMHO you must do), you should either:

1) Use an unsigned vector, for which wraparound behaviour is the
defined behaviour on overflow.

2) Put some explicit code in to handle the overflow - the synthesiser
will spot that it is unneeded in your case, and implement the same as
it would've before.

As an aside - if you find yourself using a different maximum for cnt
(say 200 for example), and you don't do option 2) you'll likely find the
synthesiser generating an 8 bit wraparound counter which will still
count up to 255, making your sim and synth completely different...
How exactly would my simulation be different from synthesis if I used
a max of 200 for a counter? If my simulation tries to increment the
counter past 200 it stops! That would not be an issue of different
results, that would be my simulation failing to complete! If my usage
of the counter never pushes it past 200, then the simulation and synth
match.

I think people are making far too big of an issue about this. An HDL
is supposed to be describing hardware, hence the name HDL. If you
take the position that the simulation and synthesis should always
match 10% you can never design anything real. If I have a counter
that is only needed for values of 200 or less and I don't care what
happens when the value is over 200, then case 2 is perfectly ok.

The OP has not responded, but I think he is just asking what the
synthesizer does. I don't think his issue is about what the "correct"
thing to do is.

Rick
 
rickman <gnuarm@gmail.com> writes:

How exactly would my simulation be different from synthesis if I used
a max of 200 for a counter? If my simulation tries to increment the
counter past 200 it stops! That would not be an issue of different
results, that would be my simulation failing to complete! If my usage
of the counter never pushes it past 200, then the simulation and synth
match.
OK, yes, I think I expressed myself badly :)

I was trying to talk about unexpected behaviour, and confused the
issue by talking about mismatches. As I said to Jan, if the
simulation doesn't test far enough, one might get different behaviour
to what one (might) expect (however innaccurate that expectation may be).

I think people are making far too big of an issue about this. An HDL
is supposed to be describing hardware, hence the name HDL. If you
take the position that the simulation and synthesis should always
match 10% you can never design anything real.
^^^
I assume you mean 100% there?

If I have a counter that is only needed for values of 200 or less
and I don't care what happens when the value is over 200, then case
2 is perfectly ok.
Quite so, I never intended to say anything other.

The OP has not responded, but I think he is just asking what the
synthesizer does. I don't think his issue is about what the "correct"
thing to do is.
On re-reading the OP with that in mind, I agree.

Sorry for any confusion caused!

Cheers,
Martin

--
martin.j.thompson@trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.co.uk/capabilities/39-electronic-hardware
 
On Dec 11, 10:21 am, Brian Drummond <brian_drumm...@btconnect.com>
wrote:
If you want wrapround from 255 to 0, you want a modular type - as others point
out, numeric_std.unsigned meets your needs.

Or you could make the wrapround explicit using the "mod" operator.
This is more flexible since the "mod" value can be something other than 256.
Most synthesis tools will not accept a modulo or divide operation by a
non-integer power of two. For other values, you have to use a
conditional to test for the pending overflow and take appropriate
actions to prevent it.

Andy
 
On 13 déc, 10:23, Martin Thompson <martin.j.thomp...@trw.com> wrote:
rickman <gnu...@gmail.com> writes:
How exactly would my simulation be different from synthesis if I used
a max of 200 for a counter?  If my simulation tries to increment the
counter past 200 it stops!  That would not be an issue of different
results, that would be my simulation failing to complete!  If my usage
of the counter never pushes it past 200, then the simulation and synth
match.

OK, yes, I think I expressed myself badly :)

I was trying to talk about unexpected behaviour, and confused the
issue by talking about mismatches.  As I said to Jan, if the
simulation doesn't test far enough, one might get different behaviour
to what one (might) expect (however innaccurate that expectation may be).

I think people are making far too big of an issue about this.  An HDL
is supposed to be describing hardware, hence the name HDL.  If you
take the position that the simulation and synthesis should always
match 10% you can never design anything real.  

        ^^^
I assume you mean 100% there?

If I have a counter that is only needed for values of 200 or less
and I don't care what happens when the value is over 200, then case
2 is perfectly ok.

Quite so, I never intended to say anything other.



The OP has not responded, but I think he is just asking what the
synthesizer does.  I don't think his issue is about what the "correct"
thing to do is.

On re-reading the OP with that in mind, I agree.

Sorry for any confusion caused!

Cheers,
Martin

--
martin.j.thomp...@trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technologyhttp://www.conekt.co.uk/capabilities/39-electronic-hardware
Thnaks for the answers. My question was mostly out of curiosity, I
tried it with ISE and I got a regular 8-bit wrapround counter.
 

Welcome to EDABoard.com

Sponsor

Back
Top