Go Back   Velocity Reviews > Newsgroups > VHDL
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

VHDL - Static functions for synthesis

 
Thread Tools Search this Thread
Old 02-23-2004, 06:45 PM   #1
Default Static functions for synthesis


Hi all,

I'd like to bring a more delicate issue to your attention, regarding a synthesis limitation in VHDL,
or in my tool. Maybe I'm lucky and I can even get some help from the VHDL gurus around.

I am trying to develop a number of parametrizable models for various DSP algorithms, including FFT
and CORDIC. The implementations of these algorithms require some look-up tables, for instance an
arctan table for CORDIC and a sine table for the tweedle factors of the FFT.

In order for the design to be generic, the look-up tables will have to be parametrizable, depending
on the generic parameters of the design, like datapath bitwidth or FFT size. The standard solution
to this problem is to write a script which generates a parametrized configuration file. Whenever you
want to change one of the parameters a new has to be generated. This can hardly be called a generic
solution.

The ideal scenario is to let the synthesis tool build these tables, based on the parameters you
supply. This is possible in VHDL using the so called constant functions. As far as I know, Verilog
tools do not support them yet, although they have been added in the Verilog 2001 standard.

Basically, constant functions are functions called when defining a constant, like in the example
below, for a pipeline stage of the CORDIC algorithm. However, since we need to work with real
numbers to compute the arctangent, the synthesis tool (Synopsys DC) will complain about that. This
should not happen, since the real numbers are not used in a synthesizable context. This is where my
knowledge of VHDL stops. Is there any workaround possible? If I don't use real types, everything
goes well and I can assign the value returned by the function to my constant.

--------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.cordic_pack.all;

entity cordic_pipestage is
generic(
INDEX : integer -- index of the pipeline stage
);
port(
clk : in std_logic;
rst : in std_logic;
en : in std_logic;

-- COORD_BITS and ANGLE_BITS are defined in cordic_pack
x_in : in signed(COORD_BITS-1 downto 0);
y_in : in signed(COORD_BITS-1 downto 0);
z_in : in signed(ANGLE_BITS-1 downto 0);

x_out : out signed(COORD_BITS-1 downto 0);
y_out : out signed(COORD_BITS-1 downto 0);
z_out : out signed(ANGLE_BITS-1 downto 0)
);
end entity;

architecture rtl of cordic_pipestage is

-- This function returns atan(1/2^n) values on a specified number of bits
function get_arctan(num_bits : natural; index : natural) return signed is
variable atan_int : integer;
variable result : signed(num_bits-1 downto 0);
begin
atan_int := integer(ROUND(ATAN(1.0/(2**real(index)))*(2**real(num_bits-1))));
result := TO_SIGNED(atan_int, num_bits);
return result;
end function;

-- the arctangent associated with the current index
-- here is where we call the constant function
constant atan : signed(ANGLE_BITS-1 downto 0) := get_arctan(ANGLE_BITS, INDEX);

begin
-- Architecture body goes here

end architecture;

--------------------------------------------------------------------------------------


I would also appreciate any comments on the topic of generic/reusable constant/table generation.

Regards,

Acciduzzu



Acciduzzu
  Reply With Quote
Old 02-23-2004, 08:26 PM   #2
Ray Andraka
 
Posts: n/a
Default Re: Static functions for synthesis
Our CORDIC macro uses a constant table with arctangents expressed as std_logic vectors. A VHDL
function rounds them to the appropriate number of bits at the point of use. Alternatively, you could
express the table as integers. We chose std_logic_vector to permit more than 31 bits of precision. The
table was generated by either Excel or a C program (I don't recall now which), and is stored in a
separate package file so it can be easily picked up and reused.

Acciduzzu wrote:

> Hi all,
>
> I'd like to bring a more delicate issue to your attention, regarding a synthesis limitation in VHDL,
> or in my tool. Maybe I'm lucky and I can even get some help from the VHDL gurus around.
>
> I am trying to develop a number of parametrizable models for various DSP algorithms, including FFT
> and CORDIC. The implementations of these algorithms require some look-up tables, for instance an
> arctan table for CORDIC and a sine table for the tweedle factors of the FFT.
>
> In order for the design to be generic, the look-up tables will have to be parametrizable, depending
> on the generic parameters of the design, like datapath bitwidth or FFT size. The standard solution
> to this problem is to write a script which generates a parametrized configuration file. Whenever you
> want to change one of the parameters a new has to be generated. This can hardly be called a generic
> solution.
>
> The ideal scenario is to let the synthesis tool build these tables, based on the parameters you
> supply. This is possible in VHDL using the so called constant functions. As far as I know, Verilog
> tools do not support them yet, although they have been added in the Verilog 2001 standard.
>
> Basically, constant functions are functions called when defining a constant, like in the example
> below, for a pipeline stage of the CORDIC algorithm. However, since we need to work with real
> numbers to compute the arctangent, the synthesis tool (Synopsys DC) will complain about that. This
> should not happen, since the real numbers are not used in a synthesizable context. This is where my
> knowledge of VHDL stops. Is there any workaround possible? If I don't use real types, everything
> goes well and I can assign the value returned by the function to my constant.
>
> --------------------------------------------------------------------------------------
> library ieee;
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
> use ieee.math_real.all;
> use work.cordic_pack.all;
>
> entity cordic_pipestage is
> generic(
> INDEX : integer -- index of the pipeline stage
> );
> port(
> clk : in std_logic;
> rst : in std_logic;
> en : in std_logic;
>
> -- COORD_BITS and ANGLE_BITS are defined in cordic_pack
> x_in : in signed(COORD_BITS-1 downto 0);
> y_in : in signed(COORD_BITS-1 downto 0);
> z_in : in signed(ANGLE_BITS-1 downto 0);
>
> x_out : out signed(COORD_BITS-1 downto 0);
> y_out : out signed(COORD_BITS-1 downto 0);
> z_out : out signed(ANGLE_BITS-1 downto 0)
> );
> end entity;
>
> architecture rtl of cordic_pipestage is
>
> -- This function returns atan(1/2^n) values on a specified number of bits
> function get_arctan(num_bits : natural; index : natural) return signed is
> variable atan_int : integer;
> variable result : signed(num_bits-1 downto 0);
> begin
> atan_int := integer(ROUND(ATAN(1.0/(2**real(index)))*(2**real(num_bits-1))));
> result := TO_SIGNED(atan_int, num_bits);
> return result;
> end function;
>
> -- the arctangent associated with the current index
> -- here is where we call the constant function
> constant atan : signed(ANGLE_BITS-1 downto 0) := get_arctan(ANGLE_BITS, INDEX);
>
> begin
> -- Architecture body goes here
>
> end architecture;
>
> --------------------------------------------------------------------------------------
>
> I would also appreciate any comments on the topic of generic/reusable constant/table generation.
>
> Regards,
>
> Acciduzzu


--
--Ray Andraka, P.E.
President, the Andraka Consulting Group, Inc.
401/884-7930 Fax 401/884-7950
email
http://www.andraka.com

"They that give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety."
-Benjamin Franklin, 1759




Ray Andraka
  Reply With Quote
Old 02-23-2004, 08:35 PM   #3
fabbl
 
Posts: n/a
Default Re: Static functions for synthesis
Hi,
The problem you have is that synthesis tools will only build what they
are told by the VHDL at compile time. VHDL is a description language, it
describes a circuit for a synthesizer. Parametric features are soley to
allow flexibility in the description. Once a parameter is set, it is
implemented by the synthesizer as if it were fixed code. If you have say, a
counter component with a variable width parameter and set that parameter to
say 4 when instantated in higher level code, then a 4 bit counter (based on
the supporting code) is created for that process. It can't be changed once
implemented past the synthesis output.

As for your other issue with wave tables, I strongly suggest you have a
block RAM or supporting memory requirement. Hard wiring function values
(depending on the sample frequency) may be wasteful depending on the target.

Handling real numbers is done in one of several ways. There are floating
point IP's (Xilinx comes to mind) you can use as well. The case your
describing may be best served by a DSP core.


"Acciduzzu" <> wrote in message
news:c1dhnk$kkc$...
> Hi all,
>
> I'd like to bring a more delicate issue to your attention, regarding a

synthesis limitation in VHDL,
> or in my tool. Maybe I'm lucky and I can even get some help from the VHDL

gurus around.
>
> I am trying to develop a number of parametrizable models for various DSP

algorithms, including FFT
> and CORDIC. The implementations of these algorithms require some look-up

tables, for instance an
> arctan table for CORDIC and a sine table for the tweedle factors of the

FFT.
>
> In order for the design to be generic, the look-up tables will have to be

parametrizable, depending
> on the generic parameters of the design, like datapath bitwidth or FFT

size. The standard solution
> to this problem is to write a script which generates a parametrized

configuration file. Whenever you
> want to change one of the parameters a new has to be generated. This can

hardly be called a generic
> solution.
>
> The ideal scenario is to let the synthesis tool build these tables, based

on the parameters you
> supply. This is possible in VHDL using the so called constant functions.

As far as I know, Verilog
> tools do not support them yet, although they have been added in the

Verilog 2001 standard.
>
> Basically, constant functions are functions called when defining a

constant, like in the example
> below, for a pipeline stage of the CORDIC algorithm. However, since we

need to work with real
> numbers to compute the arctangent, the synthesis tool (Synopsys DC) will

complain about that. This
> should not happen, since the real numbers are not used in a synthesizable

context. This is where my
> knowledge of VHDL stops. Is there any workaround possible? If I don't use

real types, everything
> goes well and I can assign the value returned by the function to my

constant.
>
> --------------------------------------------------------------------------

------------
> library ieee;
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
> use ieee.math_real.all;
> use work.cordic_pack.all;
>
> entity cordic_pipestage is
> generic(
> INDEX : integer -- index of the pipeline stage
> );
> port(
> clk : in std_logic;
> rst : in std_logic;
> en : in std_logic;
>
> -- COORD_BITS and ANGLE_BITS are defined in cordic_pack
> x_in : in signed(COORD_BITS-1 downto 0);
> y_in : in signed(COORD_BITS-1 downto 0);
> z_in : in signed(ANGLE_BITS-1 downto 0);
>
> x_out : out signed(COORD_BITS-1 downto 0);
> y_out : out signed(COORD_BITS-1 downto 0);
> z_out : out signed(ANGLE_BITS-1 downto 0)
> );
> end entity;
>
> architecture rtl of cordic_pipestage is
>
> -- This function returns atan(1/2^n) values on a specified number of

bits
> function get_arctan(num_bits : natural; index : natural) return

signed is
> variable atan_int : integer;
> variable result : signed(num_bits-1 downto 0);
> begin
> atan_int :=

integer(ROUND(ATAN(1.0/(2**real(index)))*(2**real(num_bits-1))));
> result := TO_SIGNED(atan_int, num_bits);
> return result;
> end function;
>
> -- the arctangent associated with the current index
> -- here is where we call the constant function
> constant atan : signed(ANGLE_BITS-1 downto 0) :=

get_arctan(ANGLE_BITS, INDEX);
>
> begin
> -- Architecture body goes here
>
> end architecture;
>
> --------------------------------------------------------------------------

------------
>
>
> I would also appreciate any comments on the topic of generic/reusable

constant/table generation.
>
> Regards,
>
> Acciduzzu
>





fabbl
  Reply With Quote
Old 02-24-2004, 08:32 AM   #4
Acciduzzu
 
Posts: n/a
Default Using reals to compute synthesizable constants
Hi,

Thanks for your answers. Yet, a DSP solution is out of question in my implementation.
Another point of the post was how to compute synthesizable constants (integer, sdt_logic_vector)
based on intermediate floating point values. For example, when implementing an asynchronous
protocol, the timings are controlled by counters which are preloaded with constant values.
The size of the counters and their preload values depend on the operating frequency and the time
resolution required.
It would be nice to give the clock frequency in MHz as a parameter and then compute the preload
values in VHDL, but this involves the use of intermediat real values, which are not supported for
synthesis although the real values themselves are not used for implementing hardware. Is this a
frequent limitation of the synthesis tools or only affects Synopsys DC?

constant pulse_width : real := 100; -- in ns
constant clk_freq : real := 80; -- in MHz
constant clk_period : real := 1000/clk_freq; -- in ns
constant preload_value : integer := integer(round(pulse_width/clk_period));

Only preload_value will be used in an assignment, yet DC complains about using reals



Acciduzzu
  Reply With Quote
Old 02-24-2004, 02:28 PM   #5
Ray Andraka
 
Posts: n/a
Default Re: Using reals to compute synthesizable constants
There are a number of synthesis tools that do not support reals in constant functions. You can
either restrict yourself to a tool that does allow it, or you can work with integers only. .

In your case a simple algebraic manipulation should fix it:

constant pulse_width: integer := 100; in ns;
constant clk_freq: integer:= 80; in MHz
constant preload: integer:= (pulse_width*clock_freq+500)/1000;

If you need fractional resolution on the clock freq or pulse width, use smaller units and change the
preload divisor appropriately:

constant pulse_width: integer := 1000; in ns/10;
constant clk_freq: integer:= 80000; in KHz
constant preload: integer:= (pulse_width*clock_freq+500)/10000000;


Acciduzzu wrote:

> Hi,
>
> Thanks for your answers. Yet, a DSP solution is out of question in my implementation.
> Another point of the post was how to compute synthesizable constants (integer, sdt_logic_vector)
> based on intermediate floating point values. For example, when implementing an asynchronous
> protocol, the timings are controlled by counters which are preloaded with constant values.
> The size of the counters and their preload values depend on the operating frequency and the time
> resolution required.
> It would be nice to give the clock frequency in MHz as a parameter and then compute the preload
> values in VHDL, but this involves the use of intermediat real values, which are not supported for
> synthesis although the real values themselves are not used for implementing hardware. Is this a
> frequent limitation of the synthesis tools or only affects Synopsys DC?
>
> constant pulse_width : real := 100; -- in ns
> constant clk_freq : real := 80; -- in MHz
> constant clk_period : real := 1000/clk_freq; -- in ns
> constant preload_value : integer := integer(round(pulse_width/clk_period));
>
> Only preload_value will be used in an assignment, yet DC complains about using reals


--
--Ray Andraka, P.E.
President, the Andraka Consulting Group, Inc.
401/884-7930 Fax 401/884-7950
email
http://www.andraka.com

"They that give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety."
-Benjamin Franklin, 1759




Ray Andraka
  Reply With Quote
Old 02-24-2004, 03:59 PM   #6
aser
 
Posts: n/a
Default Re: Using reals to compute synthesizable constants


Acciduzzu wrote:

>
> It would be nice to give the clock frequency in MHz as a parameter and then compute the preload
> values in VHDL, but this involves the use of intermediat real values, which are not supported for
> synthesis although the real values themselves are not used for implementing hardware. Is this a
> frequent limitation of the synthesis tools or only affects Synopsys DC?
>
> constant pulse_width : real := 100; -- in ns
> constant clk_freq : real := 80; -- in MHz
> constant clk_period : real := 1000/clk_freq; -- in ns
> constant preload_value : integer := integer(round(pulse_width/clk_period));
>
> Only preload_value will be used in an assignment, yet DC complains about using reals


Ideally any synthesizer has to operate with reals when constant calculating.
Then the type transfer function is obligatory needed to
get the resulting integer or bit vector constant.
May be some synthesizers do it.
It would be better to prove them.
But I know that synthesizers do not understand the IEEE.MATH_REAL package ,
which is useful to generate Sine constants.
In this situation I used the way
when the VHDL file with constants is generated by
another VHDL file when simulating.

But time values are not considered by synthesizers at all (neither real nor integer, nor time).
To put the delay value it can be implemented by proper automata
( in Virtex it can be SRL16 unit),
or using the customer attributes
to made the place and route tool
to keep the wire delay in the range given by your generics.
These attributes are usually different to different technology or synthesizer.

Regards,
A.Ser.



aser
  Reply With Quote
Old 02-24-2004, 04:59 PM   #7
Acciduzzu
 
Posts: n/a
Default Re: Using reals to compute synthesizable constants
Thanks again for answers. If even the VHDL tools are so picky about
synthesizable constructs, I wonder what the Verilog guys must go through if they
need to write some decent reusable modules
I hope the future has something better in stock for us.

Regards,

Acciduzzu



Acciduzzu
  Reply With Quote
Old 02-24-2004, 05:42 PM   #8
Jonathan Bromley
 
Posts: n/a
Default Re: Using reals to compute synthesizable constants
"Acciduzzu" <> wrote in message
news:c1fvti$atu$...

> If even the VHDL tools are so picky about
> synthesizable constructs, I wonder what the
> Verilog guys must go through if they
> need to write some decent reusable modules


[RantMode = ON]
VHDL has, for nearly twenty years, had the facilities
to do the simple and sensible stuff you are asking for.
Verilog hasn't. But most of the synth tools are
obsessively Verilog-centric, and can't or won't do
anything in VHDL unless it has an equivalent in Verilog.
That, surely, is:
- the only possible explanation why one well-known
synth tool processes VHDL default values on input
ports, but then sets them to zero whatever the
default you've specified;
- the only possible explanation why one well-known
synth tool can't handle VHDL entities with unconstrained
array ports;
- the only possible explanation why it took so long for
synth tools to learn about multi-dimensional arrays on
ports and nets;
[RantMode = OFF]
.... I could go on, but I'll spare y'all. And I promise
I'll give up language-ranting for Lent.

--

Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail:
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

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





Jonathan Bromley
  Reply With Quote
Old 02-24-2004, 05:47 PM   #9
Mike Treseler
 
Posts: n/a
Default Re: Using reals to compute synthesizable constants
Acciduzzu wrote:

> Thanks for your answers. Yet, a DSP solution is out of question in my
> implementation. Another point of the post was how to compute synthesizable
> constants (integer, std_logic_vector) based on intermediate floating point
> values.


Leonardo can handle real declarations
and conversions to create integer or vector
values for synthesis. See below:

-- Mike Treseler

---------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
USE IEEE.MATH_REAL.all;

-- . . .

constant pi : real := 3.141592 ;
constant sin_pi_over_8 : integer :=
integer(round( (2.0)**16 * sin(2.0*pi/16.0)));


Mike Treseler
  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Cisco 2620 static natting help biomed32uk Hardware 1 10-22-2009 03:25 PM
please help: simple java coding error 'cannot be referenced from a static context' clm90 General Help Related Topics 0 10-17-2009 06:49 AM
Give you enough string functions in Java web reporting tool freezea Software 0 10-08-2009 09:03 AM
Shag Floor danger? Dave Hardenbrook A+ Certification 3 02-28-2008 05:13 AM
Re: Anti Static Mats David Hough A+ Certification 3 05-08-2004 03:46 PM




SEO by vBSEO 3.3.2 ©2009, Crawlability, Inc.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46