![]() |
|
|
|||||||
![]() |
VHDL - Static functions for synthesis |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
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 |
|
|
|
|
#2 |
|
Posts: n/a
|
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 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 |
|
|
|
#3 |
|
Posts: n/a
|
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 |
|
|
|
#4 |
|
Posts: n/a
|
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 |
|
|
|
#5 |
|
Posts: n/a
|
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 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 |
|
|
|
#6 |
|
Posts: n/a
|
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 |
|
|
|
#7 |
|
Posts: n/a
|
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 |
|
|
|
#8 |
|
Posts: n/a
|
"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 |
|
|
|
#9 |
|
Posts: n/a
|
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 |
|
![]() |
| Thread Tools | Search this Thread |
|
|
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 |