# Is this phase accumulator trick well-known???

Started by February 8, 2009
```hi comp.arch.fpga,
(accidentally posted to comp.lang.vhdl
a few moments ago- sorry)

The question - repeated after the explanation -
is: here's what I think is a nifty trick; has
anyone seen it, or been aware of it, before?
I can't believe it's really new.

I have been messing around with baud rate generators
and suchlike - creating a pulse that's active for
one clock period at some required repetition rate -
and wanted to try a phase accumulator technique
instead of a simple divider.  That makes it far
easier to specify the frequency - it's simply the
phase-delta input value - and easily allows for
non-integral divide ratios, at the cost of one
master clock period of jitter.

The phase-accumulator produces pulses with a
repetition rate of
Fc * M / N
where Fc is the master clock, M is the phase delta
and N is the counter's modulus.  However, to get
the huge convenience of specifying M as the required
frequency, I must make N be equal to the frequency
of Fc, and this is unlikely to be an exact power of 2.
So the phase accumulator works like this:

on every clock pulse...
if (acc < 0) then
add := acc + N;
output_pulse <= '1';
else
output_pulse <= '0';
end if;
acc := acc - M;  -- unconditionally

This is fine, but it means that on the "wrap-around"
clock cycle I must add either N-M to the accumulator;
if either M or N are variable, that costs me another
adder.

Today I came up with an intriguing (to me) alternative:
on the wrap-around cycle, add N to the accumulator;
on the immediately subsequent cycle, add (-2M); on
all other cycles, add (-M).  This is of course rather
easy to do since 2M is just a left shift.  A few
trial synthesis runs convinced me that it will give
measurably better performance than the two-adder
version.  VHDL code is appended for anyone who wants
to play.

My question is: has this trick been published anywhere?
Or is it something that "those skilled in the art"
already know about?  I haven't seen it before, but that
simply means I probably haven't looked hard enough.

Thanks!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~ rate generator using novel wrap-around technique
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity rate_gen is
-- Specify the master clock frequency as a generic.
generic ( ref_Hz: positive := 50_000_000 );
port
( clock : in  std_logic
; reset : in  std_logic  -- Synchronous reset.
; rate  : in  unsigned   -- Desired output frequency
; pulse : out std_logic  -- The output pulse train
);
end;

architecture RTL of rate_gen is
begin
process (clock)
-- variable "count" is the accumulator
variable count: integer range -2**rate'length to ref_Hz-1 := 0;
-- variable "overflow" is the output pulse and wraparound marker
variable overflow: std_logic := '0';
begin
if rising_edge(clock) then
if reset = '1' then
count := 0;
overflow := '0';
elsif count < 0 then
overflow := '1';
count := count + ref_Hz;
elsif overflow = '1' then
overflow := '0';
count := count - (to_integer(rate) * 2);
else
overflow := '0';
count := count - to_integer(rate);
end if;
pulse <= overflow;
end if;
end process;
end;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
```
```On Feb 8, 7:02=A0pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> hi comp.arch.fpga,
> (accidentally posted to comp.lang.vhdl
> a few moments ago- sorry)
>
> The question - repeated after the explanation -
> is: here's what I think is a nifty trick; has
> anyone seen it, or been aware of it, before?
> I can't believe it's really new.
>
> I have been messing around with baud rate generators
> and suchlike - creating a pulse that's active for
> one clock period at some required repetition rate -
> and wanted to try a phase accumulator technique
> instead of a simple divider. =A0That makes it far
> easier to specify the frequency - it's simply the
> phase-delta input value - and easily allows for
> non-integral divide ratios, at the cost of one
> master clock period of jitter.
>
> The phase-accumulator produces pulses with a
> repetition rate of
> =A0 Fc * M / N
> where Fc is the master clock, M is the phase delta
> and N is the counter's modulus. =A0However, to get
> the huge convenience of specifying M as the required
> frequency, I must make N be equal to the frequency
> of Fc, and this is unlikely to be an exact power of 2.
> So the phase accumulator works like this:
>
> =A0 on every clock pulse...
> =A0 =A0 if (acc < 0) then
> =A0 =A0 =A0 add :=3D acc + N;
> =A0 =A0 =A0 output_pulse <=3D '1';
> =A0 =A0 else
> =A0 =A0 =A0 output_pulse <=3D '0';
> =A0 =A0 end if;
> =A0 =A0 acc :=3D acc - M; =A0-- unconditionally
>
> This is fine, but it means that on the "wrap-around"
> clock cycle I must add either N-M to the accumulator;
> if either M or N are variable, that costs me another
> adder.
>
> Today I came up with an intriguing (to me) alternative:
> on the wrap-around cycle, add N to the accumulator;
> on the immediately subsequent cycle, add (-2M); on
> all other cycles, add (-M). =A0This is of course rather
> easy to do since 2M is just a left shift. =A0A few
> trial synthesis runs convinced me that it will give
> measurably better performance than the two-adder
> version. =A0VHDL code is appended for anyone who wants
> to play.
>
> My question is: has this trick been published anywhere?
> Or is it something that "those skilled in the art"
> already know about? =A0I haven't seen it before, but that
> simply means I probably haven't looked hard enough.
>
> Thanks!
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ~~ rate generator using novel wrap-around technique
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> library ieee;
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
>
> entity rate_gen is
> =A0 -- Specify the master clock frequency as a generic.
> =A0 generic ( ref_Hz: positive :=3D 50_000_000 );
> =A0 port
> =A0 =A0 ( clock : in =A0std_logic
> =A0 =A0 ; reset : in =A0std_logic =A0-- Synchronous reset.
> =A0 =A0 ; rate =A0: in =A0unsigned =A0 -- Desired output frequency
> =A0 =A0 ; pulse : out std_logic =A0-- The output pulse train
> =A0 =A0 );
> end;
>
> architecture RTL of rate_gen is
> begin
> =A0 process (clock)
> =A0 =A0 -- variable "count" is the accumulator
> =A0 =A0 variable count: integer range -2**rate'length to ref_Hz-1 :=3D 0;
> =A0 =A0 -- variable "overflow" is the output pulse and wraparound marker
> =A0 =A0 variable overflow: std_logic :=3D '0';
> =A0 begin
> =A0 =A0 if rising_edge(clock) then
> =A0 =A0 =A0 if reset =3D '1' then
> =A0 =A0 =A0 =A0 count :=3D 0;
> =A0 =A0 =A0 =A0 overflow :=3D '0';
> =A0 =A0 =A0 elsif count < 0 then
> =A0 =A0 =A0 =A0 overflow :=3D '1';
> =A0 =A0 =A0 =A0 count :=3D count + ref_Hz;
> =A0 =A0 =A0 elsif overflow =3D '1' then
> =A0 =A0 =A0 =A0 overflow :=3D '0';
> =A0 =A0 =A0 =A0 count :=3D count - (to_integer(rate) * 2);
> =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 overflow :=3D '0';
> =A0 =A0 =A0 =A0 count :=3D count - to_integer(rate);
> =A0 =A0 =A0 end if;
> =A0 =A0 =A0 pulse <=3D overflow;
> =A0 =A0 end if;
> =A0 end process;
> end;
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> --
> Jonathan Bromley, Consultant
>
> DOULOS - Developing Design Know-how
> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> The contents of this message may contain personal views which
> are not the views of Doulos Ltd., unless specifically stated.
> --
> Jonathan Bromley, Consultant
>
> DOULOS - Developing Design Know-how
> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> The contents of this message may contain personal views which
> are not the views of Doulos Ltd., unless specifically stated.

Dear Jonathan

you wrote that you have made a few trial synthesis runs with the code
you appended.
can you tell what synthesis tool did you use?

How many LUT/ FF did you get for say Xilinx S-3 family as target
device?

I tried Xilinx XST and I have to admit I do not know how to make your
unmodified code to pass Xilinx synthesis without errors.
Maybe everybody else can do that, of course this is possible too - but
I prefer to use VHDL that is KNOWN for ME that
it passes synthesis for multiply FPGA vendor toolchains. If your code
is actually able to pass synthesis then it is not
yet known to me HOW.

Xilinx claims to dominate the FPGA market with 50% gloval share, so if
some VHDL is not working with Xilinx tools,
then the use of it already limited to < 50% (at least if we as per
Xilinx saying..)

Antti

```
```On Feb 8, 8:12=A0pm, Antti <Antti.Luk...@googlemail.com> wrote:
> On Feb 8, 7:02=A0pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
> wrote:
>
>
>
> > hi comp.arch.fpga,
> > (accidentally posted to comp.lang.vhdl
> > a few moments ago- sorry)
>
> > The question - repeated after the explanation -
> > is: here's what I think is a nifty trick; has
> > anyone seen it, or been aware of it, before?
> > I can't believe it's really new.
>
> > I have been messing around with baud rate generators
> > and suchlike - creating a pulse that's active for
> > one clock period at some required repetition rate -
> > and wanted to try a phase accumulator technique
> > instead of a simple divider. =A0That makes it far
> > easier to specify the frequency - it's simply the
> > phase-delta input value - and easily allows for
> > non-integral divide ratios, at the cost of one
> > master clock period of jitter.
>
> > The phase-accumulator produces pulses with a
> > repetition rate of
> > =A0 Fc * M / N
> > where Fc is the master clock, M is the phase delta
> > and N is the counter's modulus. =A0However, to get
> > the huge convenience of specifying M as the required
> > frequency, I must make N be equal to the frequency
> > of Fc, and this is unlikely to be an exact power of 2.
> > So the phase accumulator works like this:
>
> > =A0 on every clock pulse...
> > =A0 =A0 if (acc < 0) then
> > =A0 =A0 =A0 add :=3D acc + N;
> > =A0 =A0 =A0 output_pulse <=3D '1';
> > =A0 =A0 else
> > =A0 =A0 =A0 output_pulse <=3D '0';
> > =A0 =A0 end if;
> > =A0 =A0 acc :=3D acc - M; =A0-- unconditionally
>
> > This is fine, but it means that on the "wrap-around"
> > clock cycle I must add either N-M to the accumulator;
> > if either M or N are variable, that costs me another
> > adder.
>
> > Today I came up with an intriguing (to me) alternative:
> > on the wrap-around cycle, add N to the accumulator;
> > on the immediately subsequent cycle, add (-2M); on
> > all other cycles, add (-M). =A0This is of course rather
> > easy to do since 2M is just a left shift. =A0A few
> > trial synthesis runs convinced me that it will give
> > measurably better performance than the two-adder
> > version. =A0VHDL code is appended for anyone who wants
> > to play.
>
> > My question is: has this trick been published anywhere?
> > Or is it something that "those skilled in the art"
> > already know about? =A0I haven't seen it before, but that
> > simply means I probably haven't looked hard enough.
>
> > Thanks!
>
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > ~~ rate generator using novel wrap-around technique
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > library ieee;
> > use ieee.std_logic_1164.all;
> > use ieee.numeric_std.all;
>
> > entity rate_gen is
> > =A0 -- Specify the master clock frequency as a generic.
> > =A0 generic ( ref_Hz: positive :=3D 50_000_000 );
> > =A0 port
> > =A0 =A0 ( clock : in =A0std_logic
> > =A0 =A0 ; reset : in =A0std_logic =A0-- Synchronous reset.
> > =A0 =A0 ; rate =A0: in =A0unsigned =A0 -- Desired output frequency
> > =A0 =A0 ; pulse : out std_logic =A0-- The output pulse train
> > =A0 =A0 );
> > end;
>
> > architecture RTL of rate_gen is
> > begin
> > =A0 process (clock)
> > =A0 =A0 -- variable "count" is the accumulator
> > =A0 =A0 variable count: integer range -2**rate'length to ref_Hz-1 :=3D =
0;
> > =A0 =A0 -- variable "overflow" is the output pulse and wraparound marke=
r
> > =A0 =A0 variable overflow: std_logic :=3D '0';
> > =A0 begin
> > =A0 =A0 if rising_edge(clock) then
> > =A0 =A0 =A0 if reset =3D '1' then
> > =A0 =A0 =A0 =A0 count :=3D 0;
> > =A0 =A0 =A0 =A0 overflow :=3D '0';
> > =A0 =A0 =A0 elsif count < 0 then
> > =A0 =A0 =A0 =A0 overflow :=3D '1';
> > =A0 =A0 =A0 =A0 count :=3D count + ref_Hz;
> > =A0 =A0 =A0 elsif overflow =3D '1' then
> > =A0 =A0 =A0 =A0 overflow :=3D '0';
> > =A0 =A0 =A0 =A0 count :=3D count - (to_integer(rate) * 2);
> > =A0 =A0 =A0 else
> > =A0 =A0 =A0 =A0 overflow :=3D '0';
> > =A0 =A0 =A0 =A0 count :=3D count - to_integer(rate);
> > =A0 =A0 =A0 end if;
> > =A0 =A0 =A0 pulse <=3D overflow;
> > =A0 =A0 end if;
> > =A0 end process;
> > end;
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> > --
> > Jonathan Bromley, Consultant
>
> > DOULOS - Developing Design Know-how
> > VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> > Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> > jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> > The contents of this message may contain personal views which
> > are not the views of Doulos Ltd., unless specifically stated.
> > --
> > Jonathan Bromley, Consultant
>
> > DOULOS - Developing Design Know-how
> > VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> > Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> > jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> > The contents of this message may contain personal views which
> > are not the views of Doulos Ltd., unless specifically stated.
>
> Dear Jonathan
>
> you wrote that you have made a few trial synthesis runs with the code
> you appended.
> can you tell what synthesis tool did you use?
>
> How many LUT/ FF did you get for say Xilinx S-3 family as target
> device?
>
> I tried Xilinx XST and I have to admit I do not know how to make your
> unmodified code to pass Xilinx synthesis without errors.
> Maybe everybody else can do that, of course this is possible too - but
> I prefer to use VHDL that is KNOWN for ME that
> it passes synthesis for multiply FPGA vendor toolchains. If your code
> is actually able to pass synthesis then it is not
> yet known to me HOW.
>
> Xilinx claims to dominate the FPGA market with 50% gloval share, so if
> some VHDL is not working with Xilinx tools,
> then the use of it already limited to < 50% (at least if we as per
> Xilinx saying..)
>
> Antti

ok, now i KNOW too

xilinx synthesis: 50mhz ref 9600 baud (fixed not variable), s3
FF:18
LUT 17
used Jons unmodifed code :)

Antti

```
```On Feb 8, 8:27=A0pm, Antti <Antti.Luk...@googlemail.com> wrote:
> On Feb 8, 8:12=A0pm, Antti <Antti.Luk...@googlemail.com> wrote:
>
>
>
> > On Feb 8, 7:02=A0pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
> > wrote:
>
> > > hi comp.arch.fpga,
> > > (accidentally posted to comp.lang.vhdl
> > > a few moments ago- sorry)
>
> > > The question - repeated after the explanation -
> > > is: here's what I think is a nifty trick; has
> > > anyone seen it, or been aware of it, before?
> > > I can't believe it's really new.
>
> > > I have been messing around with baud rate generators
> > > and suchlike - creating a pulse that's active for
> > > one clock period at some required repetition rate -
> > > and wanted to try a phase accumulator technique
> > > instead of a simple divider. =A0That makes it far
> > > easier to specify the frequency - it's simply the
> > > phase-delta input value - and easily allows for
> > > non-integral divide ratios, at the cost of one
> > > master clock period of jitter.
>
> > > The phase-accumulator produces pulses with a
> > > repetition rate of
> > > =A0 Fc * M / N
> > > where Fc is the master clock, M is the phase delta
> > > and N is the counter's modulus. =A0However, to get
> > > the huge convenience of specifying M as the required
> > > frequency, I must make N be equal to the frequency
> > > of Fc, and this is unlikely to be an exact power of 2.
> > > So the phase accumulator works like this:
>
> > > =A0 on every clock pulse...
> > > =A0 =A0 if (acc < 0) then
> > > =A0 =A0 =A0 add :=3D acc + N;
> > > =A0 =A0 =A0 output_pulse <=3D '1';
> > > =A0 =A0 else
> > > =A0 =A0 =A0 output_pulse <=3D '0';
> > > =A0 =A0 end if;
> > > =A0 =A0 acc :=3D acc - M; =A0-- unconditionally
>
> > > This is fine, but it means that on the "wrap-around"
> > > clock cycle I must add either N-M to the accumulator;
> > > if either M or N are variable, that costs me another
> > > adder.
>
> > > Today I came up with an intriguing (to me) alternative:
> > > on the wrap-around cycle, add N to the accumulator;
> > > on the immediately subsequent cycle, add (-2M); on
> > > all other cycles, add (-M). =A0This is of course rather
> > > easy to do since 2M is just a left shift. =A0A few
> > > trial synthesis runs convinced me that it will give
> > > measurably better performance than the two-adder
> > > version. =A0VHDL code is appended for anyone who wants
> > > to play.
>
> > > My question is: has this trick been published anywhere?
> > > Or is it something that "those skilled in the art"
> > > already know about? =A0I haven't seen it before, but that
> > > simply means I probably haven't looked hard enough.
>
> > > Thanks!
>
> > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ~~ rate generator using novel wrap-around technique
> > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > library ieee;
> > > use ieee.std_logic_1164.all;
> > > use ieee.numeric_std.all;
>
> > > entity rate_gen is
> > > =A0 -- Specify the master clock frequency as a generic.
> > > =A0 generic ( ref_Hz: positive :=3D 50_000_000 );
> > > =A0 port
> > > =A0 =A0 ( clock : in =A0std_logic
> > > =A0 =A0 ; reset : in =A0std_logic =A0-- Synchronous reset.
> > > =A0 =A0 ; rate =A0: in =A0unsigned =A0 -- Desired output frequency
> > > =A0 =A0 ; pulse : out std_logic =A0-- The output pulse train
> > > =A0 =A0 );
> > > end;
>
> > > architecture RTL of rate_gen is
> > > begin
> > > =A0 process (clock)
> > > =A0 =A0 -- variable "count" is the accumulator
> > > =A0 =A0 variable count: integer range -2**rate'length to ref_Hz-1 :=
=3D 0;
> > > =A0 =A0 -- variable "overflow" is the output pulse and wraparound mar=
ker
> > > =A0 =A0 variable overflow: std_logic :=3D '0';
> > > =A0 begin
> > > =A0 =A0 if rising_edge(clock) then
> > > =A0 =A0 =A0 if reset =3D '1' then
> > > =A0 =A0 =A0 =A0 count :=3D 0;
> > > =A0 =A0 =A0 =A0 overflow :=3D '0';
> > > =A0 =A0 =A0 elsif count < 0 then
> > > =A0 =A0 =A0 =A0 overflow :=3D '1';
> > > =A0 =A0 =A0 =A0 count :=3D count + ref_Hz;
> > > =A0 =A0 =A0 elsif overflow =3D '1' then
> > > =A0 =A0 =A0 =A0 overflow :=3D '0';
> > > =A0 =A0 =A0 =A0 count :=3D count - (to_integer(rate) * 2);
> > > =A0 =A0 =A0 else
> > > =A0 =A0 =A0 =A0 overflow :=3D '0';
> > > =A0 =A0 =A0 =A0 count :=3D count - to_integer(rate);
> > > =A0 =A0 =A0 end if;
> > > =A0 =A0 =A0 pulse <=3D overflow;
> > > =A0 =A0 end if;
> > > =A0 end process;
> > > end;
> > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> > > --
> > > Jonathan Bromley, Consultant
>
> > > DOULOS - Developing Design Know-how
> > > VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> > > Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> > > jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> > > The contents of this message may contain personal views which
> > > are not the views of Doulos Ltd., unless specifically stated.
> > > --
> > > Jonathan Bromley, Consultant
>
> > > DOULOS - Developing Design Know-how
> > > VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> > > Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> > > jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> > > The contents of this message may contain personal views which
> > > are not the views of Doulos Ltd., unless specifically stated.
>
> > Dear Jonathan
>
> > you wrote that you have made a few trial synthesis runs with the code
> > you appended.
> > can you tell what synthesis tool did you use?
>
> > How many LUT/ FF did you get for say Xilinx S-3 family as target
> > device?
>
> > I tried Xilinx XST and I have to admit I do not know how to make your
> > unmodified code to pass Xilinx synthesis without errors.
> > Maybe everybody else can do that, of course this is possible too - but
> > I prefer to use VHDL that is KNOWN for ME that
> > it passes synthesis for multiply FPGA vendor toolchains. If your code
> > is actually able to pass synthesis then it is not
> > yet known to me HOW.
>
> > Xilinx claims to dominate the FPGA market with 50% gloval share, so if
> > some VHDL is not working with Xilinx tools,
> > then the use of it already limited to < 50% (at least if we as per
> > Xilinx saying..)
>
> > Antti
>
> ok, now i KNOW too
>
> xilinx synthesis: 50mhz ref 9600 baud (fixed not variable), s3
> FF:18
> LUT 17
> used Jons unmodifed code :)
>
> Antti

when found that the unmodifed code CAN pass synthesis well felt
stupid.
but it doesnt pass hdl compile for Xilinx ISIM simulator, or at least
i have
not found that trick yet. maybe the compile for sim trick is also
simple.
(for Jons unmodifed code)

so, my first remark ramains, i prefer write VHDL that does pass
synthesis/implementation + sim for multiply FPGA vendor tools.

Antti

```
```Antti wrote:
> On Feb 8, 8:27 pm, Antti <Antti.Luk...@googlemail.com> wrote:
>> On Feb 8, 8:12 pm, Antti <Antti.Luk...@googlemail.com> wrote:
>>
>>
>>
>>> On Feb 8, 7:02 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
>>> wrote:
>>>> hi comp.arch.fpga,
>>>> (accidentally posted to comp.lang.vhdl
>>>> a few moments ago- sorry)
>>>> The question - repeated after the explanation -
>>>> is: here's what I think is a nifty trick; has
>>>> anyone seen it, or been aware of it, before?
>>>> I can't believe it's really new.
>>>> I have been messing around with baud rate generators
>>>> and suchlike - creating a pulse that's active for
>>>> one clock period at some required repetition rate -
>>>> and wanted to try a phase accumulator technique
>>>> instead of a simple divider.  That makes it far
>>>> easier to specify the frequency - it's simply the
>>>> phase-delta input value - and easily allows for
>>>> non-integral divide ratios, at the cost of one
>>>> master clock period of jitter.
>>>> The phase-accumulator produces pulses with a
>>>> repetition rate of
>>>>   Fc * M / N
>>>> where Fc is the master clock, M is the phase delta
>>>> and N is the counter's modulus.  However, to get
>>>> the huge convenience of specifying M as the required
>>>> frequency, I must make N be equal to the frequency
>>>> of Fc, and this is unlikely to be an exact power of 2.
>>>> So the phase accumulator works like this:
>>>>   on every clock pulse...
>>>>     if (acc < 0) then
>>>>       add := acc + N;
>>>>       output_pulse <= '1';
>>>>     else
>>>>       output_pulse <= '0';
>>>>     end if;
>>>>     acc := acc - M;  -- unconditionally
>>>> This is fine, but it means that on the "wrap-around"
>>>> clock cycle I must add either N-M to the accumulator;
>>>> if either M or N are variable, that costs me another
>>>> adder.
>>>> Today I came up with an intriguing (to me) alternative:
>>>> on the wrap-around cycle, add N to the accumulator;
>>>> on the immediately subsequent cycle, add (-2M); on
>>>> all other cycles, add (-M).  This is of course rather
>>>> easy to do since 2M is just a left shift.  A few
>>>> trial synthesis runs convinced me that it will give
>>>> measurably better performance than the two-adder
>>>> version.  VHDL code is appended for anyone who wants
>>>> to play.
>>>> My question is: has this trick been published anywhere?
>>>> Or is it something that "those skilled in the art"
>>>> already know about?  I haven't seen it before, but that
>>>> simply means I probably haven't looked hard enough.
>>>> Thanks!
>>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> ~~ rate generator using novel wrap-around technique
>>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> library ieee;
>>>> use ieee.std_logic_1164.all;
>>>> use ieee.numeric_std.all;
>>>> entity rate_gen is
>>>>   -- Specify the master clock frequency as a generic.
>>>>   generic ( ref_Hz: positive := 50_000_000 );
>>>>   port
>>>>     ( clock : in  std_logic
>>>>     ; reset : in  std_logic  -- Synchronous reset.
>>>>     ; rate  : in  unsigned   -- Desired output frequency
>>>>     ; pulse : out std_logic  -- The output pulse train
>>>>     );
>>>> end;
>>>> architecture RTL of rate_gen is
>>>> begin
>>>>   process (clock)
>>>>     -- variable "count" is the accumulator
>>>>     variable count: integer range -2**rate'length to ref_Hz-1 := 0;
>>>>     -- variable "overflow" is the output pulse and wraparound marker
>>>>     variable overflow: std_logic := '0';
>>>>   begin
>>>>     if rising_edge(clock) then
>>>>       if reset = '1' then
>>>>         count := 0;
>>>>         overflow := '0';
>>>>       elsif count < 0 then
>>>>         overflow := '1';
>>>>         count := count + ref_Hz;
>>>>       elsif overflow = '1' then
>>>>         overflow := '0';
>>>>         count := count - (to_integer(rate) * 2);
>>>>       else
>>>>         overflow := '0';
>>>>         count := count - to_integer(rate);
>>>>       end if;
>>>>       pulse <= overflow;
>>>>     end if;
>>>>   end process;
>>>> end;
>>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> --
>>>> Jonathan Bromley, Consultant
>>>> DOULOS - Developing Design Know-how
>>>> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>>>> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
>>>> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>>>> The contents of this message may contain personal views which
>>>> are not the views of Doulos Ltd., unless specifically stated.
>>>> --
>>>> Jonathan Bromley, Consultant
>>>> DOULOS - Developing Design Know-how
>>>> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>>>> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
>>>> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>>>> The contents of this message may contain personal views which
>>>> are not the views of Doulos Ltd., unless specifically stated.
>>> Dear Jonathan
>>> you wrote that you have made a few trial synthesis runs with the code
>>> you appended.
>>> can you tell what synthesis tool did you use?
>>> How many LUT/ FF did you get for say Xilinx S-3 family as target
>>> device?
>>> I tried Xilinx XST and I have to admit I do not know how to make your
>>> unmodified code to pass Xilinx synthesis without errors.
>>> Maybe everybody else can do that, of course this is possible too - but
>>> I prefer to use VHDL that is KNOWN for ME that
>>> it passes synthesis for multiply FPGA vendor toolchains. If your code
>>> is actually able to pass synthesis then it is not
>>> yet known to me HOW.
>>> Xilinx claims to dominate the FPGA market with 50% gloval share, so if
>>> some VHDL is not working with Xilinx tools,
>>> then the use of it already limited to < 50% (at least if we as per
>>> Xilinx saying..)
>>> Antti
>> ok, now i KNOW too
>>
>> xilinx synthesis: 50mhz ref 9600 baud (fixed not variable), s3
>> FF:18
>> LUT 17
>> used Jons unmodifed code :)
>>
>> Antti
>
> when found that the unmodifed code CAN pass synthesis well felt
> stupid.
> but it doesnt pass hdl compile for Xilinx ISIM simulator, or at least
> i have
> not found that trick yet. maybe the compile for sim trick is also
> simple.
> (for Jons unmodifed code)
>
> so, my first remark ramains, i prefer write VHDL that does pass
> synthesis/implementation + sim for multiply FPGA vendor tools.
>
> Antti
>
>
>
>

Hi Antti,
I'm reasonably convinced that Jonathan has written good code (I should
state that I'm a colleague of his, so I'm biased!)

Over the last 6 months I have reported bugs in both Modelsim and
Active-HDL - both of which are more mature than isim. I would suggest
you just report a bug.

regards
Alan

P.S. To my great pleasure, both Mentor and Aldec were efficient in
fixing the bugs.

--
Alan Fitch
apfitch at ieee
dot org
```
```Hi Jonathan,

I can't quite get your idea (You may have mistyped M,N)

This is what I do for phase accummulator(modulus not power of 2),
e.g. modulus = 1600, increment = 869
------------------------------
if(modulo_adder < 1600)then
modulo_adder <= modulo_adder + 869;
overflow <= '0';
else
modulo_adder <= modulo_adder + 869 - 1600;
overflow <= '1';
end if;
-------------------------------

Can you please express your idea in a numerical example. Sounds
interesting

kadhiem

```
```On Feb 8, 11:16=A0pm, Alan Fitch <apfi...@invalid.invalid> wrote:
> Antti wrote:
> > On Feb 8, 8:27 pm, Antti <Antti.Luk...@googlemail.com> wrote:
> >> On Feb 8, 8:12 pm, Antti <Antti.Luk...@googlemail.com> wrote:
>
> >>> On Feb 8, 7:02 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
> >>> wrote:
> >>>> hi comp.arch.fpga,
> >>>> (accidentally posted to comp.lang.vhdl
> >>>> a few moments ago- sorry)
> >>>> The question - repeated after the explanation -
> >>>> is: here's what I think is a nifty trick; has
> >>>> anyone seen it, or been aware of it, before?
> >>>> I can't believe it's really new.
> >>>> I have been messing around with baud rate generators
> >>>> and suchlike - creating a pulse that's active for
> >>>> one clock period at some required repetition rate -
> >>>> and wanted to try a phase accumulator technique
> >>>> instead of a simple divider. =A0That makes it far
> >>>> easier to specify the frequency - it's simply the
> >>>> phase-delta input value - and easily allows for
> >>>> non-integral divide ratios, at the cost of one
> >>>> master clock period of jitter.
> >>>> The phase-accumulator produces pulses with a
> >>>> repetition rate of
> >>>> =A0 Fc * M / N
> >>>> where Fc is the master clock, M is the phase delta
> >>>> and N is the counter's modulus. =A0However, to get
> >>>> the huge convenience of specifying M as the required
> >>>> frequency, I must make N be equal to the frequency
> >>>> of Fc, and this is unlikely to be an exact power of 2.
> >>>> So the phase accumulator works like this:
> >>>> =A0 on every clock pulse...
> >>>> =A0 =A0 if (acc < 0) then
> >>>> =A0 =A0 =A0 add :=3D acc + N;
> >>>> =A0 =A0 =A0 output_pulse <=3D '1';
> >>>> =A0 =A0 else
> >>>> =A0 =A0 =A0 output_pulse <=3D '0';
> >>>> =A0 =A0 end if;
> >>>> =A0 =A0 acc :=3D acc - M; =A0-- unconditionally
> >>>> This is fine, but it means that on the "wrap-around"
> >>>> clock cycle I must add either N-M to the accumulator;
> >>>> if either M or N are variable, that costs me another
> >>>> adder.
> >>>> Today I came up with an intriguing (to me) alternative:
> >>>> on the wrap-around cycle, add N to the accumulator;
> >>>> on the immediately subsequent cycle, add (-2M); on
> >>>> all other cycles, add (-M). =A0This is of course rather
> >>>> easy to do since 2M is just a left shift. =A0A few
> >>>> trial synthesis runs convinced me that it will give
> >>>> measurably better performance than the two-adder
> >>>> version. =A0VHDL code is appended for anyone who wants
> >>>> to play.
> >>>> My question is: has this trick been published anywhere?
> >>>> Or is it something that "those skilled in the art"
> >>>> already know about? =A0I haven't seen it before, but that
> >>>> simply means I probably haven't looked hard enough.
> >>>> Thanks!
> >>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >>>> ~~ rate generator using novel wrap-around technique
> >>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >>>> library ieee;
> >>>> use ieee.std_logic_1164.all;
> >>>> use ieee.numeric_std.all;
> >>>> entity rate_gen is
> >>>> =A0 -- Specify the master clock frequency as a generic.
> >>>> =A0 generic ( ref_Hz: positive :=3D 50_000_000 );
> >>>> =A0 port
> >>>> =A0 =A0 ( clock : in =A0std_logic
> >>>> =A0 =A0 ; reset : in =A0std_logic =A0-- Synchronous reset.
> >>>> =A0 =A0 ; rate =A0: in =A0unsigned =A0 -- Desired output frequency
> >>>> =A0 =A0 ; pulse : out std_logic =A0-- The output pulse train
> >>>> =A0 =A0 );
> >>>> end;
> >>>> architecture RTL of rate_gen is
> >>>> begin
> >>>> =A0 process (clock)
> >>>> =A0 =A0 -- variable "count" is the accumulator
> >>>> =A0 =A0 variable count: integer range -2**rate'length to ref_Hz-1 :=
=3D 0;
> >>>> =A0 =A0 -- variable "overflow" is the output pulse and wraparound ma=
rker
> >>>> =A0 =A0 variable overflow: std_logic :=3D '0';
> >>>> =A0 begin
> >>>> =A0 =A0 if rising_edge(clock) then
> >>>> =A0 =A0 =A0 if reset =3D '1' then
> >>>> =A0 =A0 =A0 =A0 count :=3D 0;
> >>>> =A0 =A0 =A0 =A0 overflow :=3D '0';
> >>>> =A0 =A0 =A0 elsif count < 0 then
> >>>> =A0 =A0 =A0 =A0 overflow :=3D '1';
> >>>> =A0 =A0 =A0 =A0 count :=3D count + ref_Hz;
> >>>> =A0 =A0 =A0 elsif overflow =3D '1' then
> >>>> =A0 =A0 =A0 =A0 overflow :=3D '0';
> >>>> =A0 =A0 =A0 =A0 count :=3D count - (to_integer(rate) * 2);
> >>>> =A0 =A0 =A0 else
> >>>> =A0 =A0 =A0 =A0 overflow :=3D '0';
> >>>> =A0 =A0 =A0 =A0 count :=3D count - to_integer(rate);
> >>>> =A0 =A0 =A0 end if;
> >>>> =A0 =A0 =A0 pulse <=3D overflow;
> >>>> =A0 =A0 end if;
> >>>> =A0 end process;
> >>>> end;
> >>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >>>> --
> >>>> Jonathan Bromley, Consultant
> >>>> DOULOS - Developing Design Know-how
> >>>> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
> >>>> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> >>>> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
> >>>> The contents of this message may contain personal views which
> >>>> are not the views of Doulos Ltd., unless specifically stated.
> >>>> --
> >>>> Jonathan Bromley, Consultant
> >>>> DOULOS - Developing Design Know-how
> >>>> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
> >>>> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> >>>> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
> >>>> The contents of this message may contain personal views which
> >>>> are not the views of Doulos Ltd., unless specifically stated.
> >>> Dear Jonathan
> >>> you wrote that you have made a few trial synthesis runs with the code
> >>> you appended.
> >>> can you tell what synthesis tool did you use?
> >>> How many LUT/ FF did you get for say Xilinx S-3 family as target
> >>> device?
> >>> I tried Xilinx XST and I have to admit I do not know how to make your
> >>> unmodified code to pass Xilinx synthesis without errors.
> >>> Maybe everybody else can do that, of course this is possible too - bu=
t
> >>> I prefer to use VHDL that is KNOWN for ME that
> >>> it passes synthesis for multiply FPGA vendor toolchains. If your code
> >>> is actually able to pass synthesis then it is not
> >>> yet known to me HOW.
> >>> Xilinx claims to dominate the FPGA market with 50% gloval share, so i=
f
> >>> some VHDL is not working with Xilinx tools,
> >>> then the use of it already limited to < 50% (at least if we as per
> >>> Xilinx saying..)
> >>> Antti
> >> ok, now i KNOW too
>
> >> xilinx synthesis: 50mhz ref 9600 baud (fixed not variable), s3
> >> FF:18
> >> LUT 17
> >> used Jons unmodifed code :)
>
> >> Antti
>
> > when found that the unmodifed code CAN pass synthesis well felt
> > stupid.
> > but it doesnt pass hdl compile for Xilinx ISIM simulator, or at least
> > i have
> > not found that trick yet. maybe the compile for sim trick is also
> > simple.
> > (for Jons unmodifed code)
>
> > so, my first remark ramains, i prefer write VHDL that does pass
> > synthesis/implementation + sim for multiply FPGA vendor tools.
>
> > Antti
>
> Hi Antti,
> =A0 I'm reasonably convinced that Jonathan has written good code (I shoul=
d
> state that I'm a colleague of his, so I'm biased!)
>
> Over the last 6 months I have reported bugs in both Modelsim and
> Active-HDL - both of which are more mature than isim. I would suggest
> you just report a bug.
>
> regards
> Alan
>
> P.S. To my great pleasure, both Mentor and Aldec were efficient in
> fixing the bugs.
>
> --
> Alan Fitch
> apfitch at ieee
> dot org

Those who work with REAL FPGA's and tools from FPGA vendors sometimes
can not wait until the FGPA vendors fix their bugs.
i agree ISIM is not a much of a thing.

but still i try to write code that passes with most tools from the
FPGA vendors, in their current state.
not after they fix the bugs i report.

i dont argue that Jonathan writes CORRECT code as per LRM.
that doesnt make the code to pass FPGA vendors toolchains.
its unfortunate of course.

Antti

```
```On Sun, 8 Feb 2009 10:27:08 -0800 (PST), Antti wrote:

>ok, now i KNOW too

Aw, shucks, you found me out.  Sitting in my futuristic
bunker in a hollowed-out volcano, stroking my fluffy
white cat and letting out the occasional megalomaniac
cackle, I was thinking: BWAH HAH HAH At last I have
created something that could confuse even the great
Antti.  But it was not to be so :-)

>xilinx synthesis: 50mhz ref 9600 baud (fixed not variable), s3
>FF:18
>LUT 17

Yup.  With a constant rate input, XST does The Right Thing and
collapses all the constants.  With a variable input, you get
approximately 2X LUT-to-FF ratio because you can't fit a
3-input MUX and an adder bit into a single LUT (at least,
not in Spartan-3... maybe when we have LUT6??? .....)

>used Jons unmodifed code :)

It simulates correctly too, although of course it needs to
be wrapped in something that provides a signal to connect
to its unconstrained input port.  I haven't tried it with
ISIM just yet, but I believe the code is strictly VHDL-93
compliant and therefore it is NOT MY FAULT if some simulator
cannot handle it.  By contrast, if you can find a synthesis
tool that can't handle it then I'd be glad to know, because
my intent was to create portable synthesisable code.

Thanks
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
```
```On Sun, 08 Feb 2009 15:19:47 -0600, "kadhiem_ayob" wrote:

>This is what I do for phase accummulator(modulus not power of 2),
>e.g. modulus = 1600, increment = 869
>------------------------------
>if(modulo_adder < 1600)then
>     modulo_adder <= modulo_adder + 869;
>     overflow <= '0';
>else
>     modulo_adder <= modulo_adder + 869 - 1600;
>     overflow <= '1';
>end if;

Yes, exactly.  But if "869" is a variable (from an
input port) so that the rate is configurable, then
you have

if (...overflow...) then
modulo_adder <= modulo_adder + N;
else
modulo_adder <= modulo_adder + N - 1600;

The last line requires TWO adders, in addition to the
multiplexer created by the IF.  This causes a significant
performance hit.  That's what I was trying to fix.  I did
it by saying...

if (...overflow...) then
adder <= adder + N;
else
adder <= adder - 1600;  --oops, need to add extra N

So we modify the code like this:

if (...overflow...) then
adder <= adder + N;
elsif (...there was an overflow on the previous clock...)
adder <= adder + 2*N;  -- make up for the lost N
else
adder <= adder - 1600;

By the way, your code also implies a magnitude comparator,
whereas the less-than-zero test in my code can be done
merely by looking at the most significant bit of the
accumulator.  This saves both gates and levels of logic,
and is well worth the small additional trouble of
allowing for signed arithmetic.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
```
```On Feb 8, 11:32=A0pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Sun, 8 Feb 2009 10:27:08 -0800 (PST), Antti wrote:
> >ok, now i KNOW too
>
> Aw, shucks, you found me out. =A0Sitting in my futuristic
> bunker in a hollowed-out volcano, stroking my fluffy
> white cat and letting out the occasional megalomaniac
> cackle, I was thinking: BWAH HAH HAH At last I have
> created something that could confuse even the great
> Antti. =A0But it was not to be so :-)
>
> >xilinx synthesis: 50mhz ref 9600 baud (fixed not variable), s3
> >FF:18
> >LUT 17
>
> Yup. =A0With a constant rate input, XST does The Right Thing and
> collapses all the constants. =A0With a variable input, you get
> approximately 2X LUT-to-FF ratio because you can't fit a
> 3-input MUX and an adder bit into a single LUT (at least,
> not in Spartan-3... maybe when we have LUT6??? .....)
>
> >used Jons unmodifed code :)
>
> It simulates correctly too, although of course it needs to
> be wrapped in something that provides a signal to connect
> to its unconstrained input port. =A0I haven't tried it with
> ISIM just yet, but I believe the code is strictly VHDL-93
> compliant and therefore it is NOT MY FAULT if some simulator
> cannot handle it. =A0By contrast, if you can find a synthesis
> tool that can't handle it then I'd be glad to know, because
> my intent was to create portable synthesisable code.
>
> Thanks
> --
> Jonathan Bromley, Consultant
>
> DOULOS - Developing Design Know-how
> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> The contents of this message may contain personal views which
> are not the views of Doulos Ltd., unless specifically stated.

ah forget ISIM not need make it pass that...

yes the code is most likely full vhdl-93 whatever and it passes
xilinx synthesis.. i may try Actel i am doing something where
the code be handy.

Ah, BTW, if you create hdl template from the unit with xilinx
it converts the unsigned to std_logic
so that has to be manually patched..
so this small code actually did trap 2 xilinx tool bugs...

i would possible not have posted my first response
but i was fighting a small stupid problem what happened
to be a really stupid issue.

an USB bootloader did not seem to work after small
change of code.

[3 days later]

i had all the time used file blinky.bin
from folder that contained blinky.c
assuming it to be my blink led binary (knwon good one)
but as i finally found out, my script converted
blinky.hex to BLINKER.BIN
and blinky.bin was 0 bytes long.

so when i did read back the flash after update
it looked like the update failed, nothing written.

actually it worked, but the update was 0 byte long.

good night everyone !

Antti

```