Modulo Counter in XST Synthesis?

B

Brandon

Guest
I'm receiving a synthesis error from XST for my modulo up counter.

ERROR:Xst:1775 - Unsupported modulo value 3 found in expression at line
304. The modulo should be a power of 2.

I found this, but it doesn't specifiy what the modulus may be.

http://toolbox.xilinx.com/docsan/xilinx7/books/data/docs/xst/xst0018_5.html

Here is my code:

cnt_seq_proc: process(clk, rst_n_a)
begin
if (rst_n_a = '0') then
-- active low asynchronous reset
cnt <= 0;
elsif (rising_edge(clk) ) then
if cnt_en = '1' then
cnt <= (cnt+1) mod modfactor_g;
else
cnt <= cnt;
end if; -- if cnt_en = '1' then
end if; -- if (rst_n_a = '0') then
end process cnt_seq_proc;

Is there an easy way to do this with a generic that is synthesizeable?

Thanks,
-B
 
Brandon wrote:
I'm receiving a synthesis error from XST for my modulo up counter.

ERROR:Xst:1775 - Unsupported modulo value 3 found in expression at line
304. The modulo should be a power of 2.

I found this, but it doesn't specifiy what the modulus may be.

http://toolbox.xilinx.com/docsan/xilinx7/books/data/docs/xst/xst0018_5.html

Here is my code:

cnt_seq_proc: process(clk, rst_n_a)
begin
if (rst_n_a = '0') then
-- active low asynchronous reset
cnt <= 0;
elsif (rising_edge(clk) ) then
if cnt_en = '1' then
cnt <= (cnt+1) mod modfactor_g;
else
cnt <= cnt;
end if; -- if cnt_en = '1' then
end if; -- if (rst_n_a = '0') then
end process cnt_seq_proc;

Is there an easy way to do this with a generic that is synthesizeable?
That's kinda bizarre ... I've done counters with non-power-of-two
moduluses without synthesis issues, but I don't think I've done one
with XST. I assume modfactor_g is a constant (generic or otherwise)
and not a variable?

-a
 
Brandon a écrit:
I'm receiving a synthesis error from XST for my modulo up counter.
ERROR:Xst:1775 - Unsupported modulo value 3 found in expression at line
304. The modulo should be a power of 2.
Hi
Division is always tricky in VHDL.
The best way (IMO) to do what you want is:

process (clk, rst) is
begin
if rst = '1' then
cnt <= 0;
elsif rising_edge(clk) then
if cnt_en = '1' then
if cnt = (modfactor_g - 1) then
cnt <= 0;
else
cnt <= cnt + 1;
end if;
end if;
end if;
end process;

You don't need an unconditionnal 'else'.

Nicolas
 
Andy Peters wrote:

That's kinda bizarre ... I've done counters with non-power-of-two
moduluses without synthesis issues,
Yes, mod 3 is fine on quartus.
Nicola's code works fine too.
http://home.comcast.net/~mike_treseler/roll.pdf
http://home.comcast.net/~mike_treseler/roll.vhd

-- Mike Treseler
 
I've used non-power-of-2 modulos with both arguments being static
before, but never when the left hand argument was a variable/signal.

Does that work for any operation, or only on counters (incr/decr by
one)? That would be pretty easy to do in HW. I don't use
Quartus/Altera, else I'd try it myself.

How about "a <= (a + b) mod 3" where a & b are dynamic?

If you can live with a decrementing count sequence, a more efficient
implementation (using integers only, not slv or numeric_std) that does
not require a wide AND tree would be:

signal a : natural range 0 to modfactor_g - 1;
....
if a - 1 < 0 then -- check the sign bit of the result first
a <= modfactor_g - 1;
else
a <= a - 1; -- share decrementer with comparison above
end if;

Andy
 
Andy wrote:
I've used non-power-of-2 modulos with both arguments being static
before, but never when the left hand argument was a variable/signal.
Shouldn't matter.
Both args are right of the assignment
so this is a "static" sample of the
value of the whole expression.

How about "a <= (a + b) mod 3" where a & b are dynamic?
Sure. You're just sampling the value
of the right expression and scheduling
that *value* to be put in the "a" box.

If you can live with a decrementing count sequence, a more efficient
implementation (using integers only, not slv or numeric_std) that does
not require a wide AND tree would be:
signal a : natural range 0 to modfactor_g - 1;
...
if a - 1 < 0 then -- check the sign bit of the result first
a <= modfactor_g - 1;
else
a <= a - 1; -- share decrementer with comparison above
end if;
Thanks for the tip.

-- Mike Treseler
 
What I meant was that static expressions are computed during synthesis,
and only the resulting value is plugged into the synthesis; gates don't
have to do the computation. With dynamic values, the gates have to do
the computation, and the synthesis tool has to figure out how to do it.


A true, non-power-of-two modulo requires a division-like circuit, which
is very expensive in terms of gates required. However, when combined
with another operation such as addition or subtraction, where the
previous value is assumed to be within the modulo range, it can be
simplified to a test and a subtract, which is much cheaper, and more
likely to be supported by synthesis than an arbitrary modulo, such as a
<= b mod c, with b and c being arbitrary dynamic values.

Have you tried mod in applications not involving addition/subtraction,
or where the previous value cannot be assumed to be in range?

Just curious, but if quartus does this, I'd like some ammo to fire at
Synplicity!

Thanks,

Andy
 
Andy wrote:
as a <= b mod c, with b and c being arbitrary dynamic values.
OK. I get it.
It works at least for some widths.
Here you go:
http://home.comcast.net/~mike_treseler/andy.pdf

see new case andy in:
http://home.comcast.net/~mike_treseler/roll.vhd

when andy =>
c_v := to_unsigned(to_integer(a) mod to_integer(b),c'length);

-- Mike Treseler
 
Andy Peters wrote:

That's kinda bizarre ... I've done counters with non-power-of-two
moduluses without synthesis issues,


Yes, mod 3 is fine on quartus.
Nicola's code works fine too.
http://home.comcast.net/~mike_treseler/roll.pdf
http://home.comcast.net/~mike_treseler/roll.vhd

-- Mike Treseler
The trick is the Brandon's signal cnt has to have type unsigned instead
of integer. (See ISE\vhdl\src\ieee\numeric_std.vhd )
Then Brandon's code is fine in XST (ISE 7.1)

Mike's code is also fine in XST (ISE 7.1)
=========================================================================
* HDL Analysis *
=========================================================================
Analyzing Entity <roll> (Architecture <synth>).
WARNING:Xst:1960 - "roll.vhd" line 45: Potential simulation mismatch,
variable <cnt_v> declared in block <cnt_seq_proc> is assigned in block
<init>.
Entity <roll> analyzed. Unit <roll> generated.


=========================================================================
* HDL Synthesis *
=========================================================================

Synthesizing Unit <roll>.
Related source file is "/../../../../../../../Downloads/roll.vhd".
Found 2-bit modulo-3 up counter for signal <cnt_v>.
Summary:
inferred 1 Counter(s).
Unit <roll> synthesized.
 
xipn wrote:

The trick is the Brandon's signal cnt has to have type unsigned instead
of integer. (See ISE\vhdl\src\ieee\numeric_std.vhd )
Then Brandon's code is fine in XST (ISE 7.1)
Mike's code is also fine in XST (ISE 7.1)

Analyzing Entity <roll> (Architecture <synth>).
WARNING:Xst:1960 - "roll.vhd" line 45: Potential simulation mismatch,
variable <cnt_v> declared in block <cnt_seq_proc> is assigned in block
init>.
Entity <roll> analyzed. Unit <roll> generated.
Thanks for running XST.

That's a curious warning that c_v init and
assign are in different blocks when no
block statement is used and the
design consists of a single process.

-- Mike Treseler
 

Welcome to EDABoard.com

Sponsor

Back
Top