Is this phase accumulator trick well-known???

Started by Jonathan Bromley 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