Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
21615 Discussions

VHDL Math Real & Quartus

Altera_Forum
Honored Contributor II
4,711 Views

I've been using the VHDL package ieee.math_real to declare parameters, the idea being to condense as much information in a design file as possible. in particular, for fixed point operations in feedback controls systems, it helps to see the scaling of the parameters directly in the design file. For example, the code below does synthesize correctly in Quartus: 

 

constant RecipSqrt3 : signed(N-1 downto 0) := to_signed(integer(real(ROUND((2.0**15)*(0.577350269189626)))),16); 

 

However, the code below does not:  

 

variable RecipFactor : real := ROUND((2.0**15)*(1.0/(SQRT(3.0))));  

 

Quartus gives a message about this; upon further checking the / operator is not defined for A/B where both A and B are real. It is defined, however, for the complex numbers in the complex package of math_real.  

 

I like the notation of 1.0/SQRT(3.0) better than 0.577350269189626 for example.  

 

Has anyone had success with the / operator for complex numbers or real numbers? Thanks in advance. James
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
3,185 Views

I remember having that divide problem once also, but I forgot when ... I don't divide many 'real's though, but recently I did this: 

ARCZ => integer( ( real(PI_TIMES_TWO) * ARCTAN( 2.0 ** (-(i))) / MATH_2_PI)) , 

This is in Quartus II 11.1sp1. 

 

I tried your code variable RecipFactor : real := ROUND((2.0**15)*(1.0/(SQRT(3.0)))); and got no other warning than: 

--- Quote Start ---  

Warning (10542): VHDL Variable Declaration warning at math_real.vhd(2373): used initial value expression for variable "RECIPROCAL" because variable was never assigned a value 

 

--- Quote End ---  

but that is a long time annoyance ...
0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

I don't understand what you are trying to achieve. A "variable" to be used for compile time calculations can be defined as a constant.

0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

What I am / was trying to achieve is completely parameterized code; with no errors or warning messages . . . James

0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

 

--- Quote Start ---  

What I am / was trying to achieve is completely parameterized code; with no errors or warning messages . . . James 

--- Quote End ---  

Right, that was what FVM was getting at. You can clear that particular error by using 'constant RecipFactor' instead of 'variable RecipFactor'. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

 

--- Quote Start ---  

Right, that was what FVM was getting at. You can clear that particular error by using 'constant RecipFactor' instead of 'variable RecipFactor'. 

 

Cheers, 

Dave 

--- Quote End ---  

 

 

James' question was why he got an error for the 'variable' construct not whether his code was any good. He specifically wanted to show the '1/sqrt(3)' in his equation instead of an obscure 0.577350269, which is a sound idea. There are workarounds where he wouldn't have to use a division ( pow(sqrt(3.0), -1.0) , but again that would be not pure ... 

Of course Frank's remark stays valid. 

But judging by his silence James has found what he was looking for?
0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

Thanks for the feedback everyone . . . However, the RecipFactor if made a constant still gives a message, when synthesizing the VHDL module shown below:  

 

Warning (10542): VHDL Variable Declaration warning at math_real.vhd(2373): used initial value expression for variable "RECIPROCAL" because variable was never assigned a value 

 

As mentioned, this is what I was trying to avoid. In the code below, the constant RecipSqrt3 is clean; no messages are reported by Quartus at compile time. 

 

Best, 

 

James 

 

 

 

 

--- Quote Start ---  

library ieee; 

use ieee.std_logic_1164.all; 

use ieee.numeric_std.all; 

use ieee.math_real.all; 

 

entity IFBscale is 

port( 

MCLK : in std_logic; 

HRST : in std_logic; 

START : in std_logic; 

 

IA : in std_logic_vector(15 downto 0); 

IB : in std_logic_vector(15 downto 0); 

 

ALPHA : out std_logic_vector(15 downto 0); 

BETA : out std_logic_vector(15 downto 0); 

 

ScaleFactor : in std_logic_vector(15 downto 0); 

 

DONE : out std_logic 

 

); 

end IFBscale; 

 

architecture RTL of IFBscale is 

 

constant N : integer := 16; 

constant N2 : integer := 32; 

signal factor : real; 

constant RecipFactor : real := ROUND((2.0**15)*(1.0/SQRT(3.0))); 

constant RecipSqrt3 : std_logic_vector(N-1 downto 0) := std_logic_vector(to_signed(integer(real(ROUND((2.0**15)*(0.577350269189626)))),16)); 

 

signal betax : std_logic_vector(2*N-1 downto 0); 

 

type baseDataType is record 

x : signed(N-1 downto 0); 

done : std_logic; 

slv : std_logic_vector(N*2-1 downto 0); 

slvN : std_logic_vector(N-1 downto 0); 

end record; 

 

signal ias,ibs,sum : baseDataType; 

 

signal donex : std_logic; 

signal betay : signed(N-1 downto 0); 

 

begin 

 

/*---------------------------- 

Register Outputs 

----------------------------*/  

oReg: process(all) begin 

if HRST then 

ALPHA <= (others => '0'); 

BETA <= (others => '0'); 

DONE <= '0'; 

elsif rising_edge(MCLK) then  

ALPHA <= std_logic_vector(ias.x); 

if donex then 

BETA <= std_logic_vector(betax(N2-2 downto N-1)); 

DONE <= '1'; 

else 

DONE <= '0'; 

end if; 

end if; 

end process oReg; 

 

/*---------------------------- 

Scale IA 

----------------------------*/ 

Umult1 : entity work.signed_mult2(rtl) 

generic map(arg_size => N) 

port map( 

CLK => MCLK, 

HRST => HRST, 

START => START, 

DONE => ias.done, 

a => IA, 

b => ScaleFactor, 

result => ias.slv 

); 

/*---------------------------- 

Scale IB 

----------------------------*/ 

Umult2: entity work.signed_mult2(rtl) 

generic map(arg_size => N) 

port map( 

CLK => MCLK, 

HRST => HRST, 

START => START, 

a => IB, 

b => ScaleFactor, 

result => ibs.slv 

); 

 

ias.x <= signed(ias.slv(N2-3 downto N-2)); 

ibs.x <= signed(ibs.slv(N2-3 downto N-2)); 

 

process(all) begin 

if HRST then 

sum.x <= (others => '0'); 

sum.done <= '0'; 

elsif rising_edge(MCLK) then 

if ias.done then 

sum.x <= X"0000" - ias.x - shift_left(ibs.x,1); 

sum.done <= '1'; 

else 

sum.done <= '0'; 

end if; 

end if; 

end process;  

 

sum.slvN <= std_logic_vector(sum.x); 

/*---------------------------- 

Scale Ibeta by1/sqrt(3)  

----------------------------*/ 

Umult3: entity work.signed_mult2(rtl) 

generic map(arg_size => N) 

port map( 

CLK => MCLK, 

HRST => HRST, 

START => sum.done, 

DONE => donex, 

a => sum.slvN, 

b => RecipSqrt3, 

result => betax 

); 

 

 

end RTL; 

 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

This issue with ieee.math_real makes me what to add the guidelines for declaring constants as part of my internal VHDL style guide; suited for synthesis with Quartus. I've haven't seen this type of detailed exposition in books, references, etc. James

0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

 

--- Quote Start ---  

 

Warning (10542): VHDL Variable Declaration warning at math_real.vhd(2373): used initial value expression for variable "RECIPROCAL" because variable was never assigned a value 

 

--- Quote End ---  

 

 

The reason for the warning is lines like this in math_real-body.vhdl (downloadable from the IEEE web site): 

 

 

--- Quote Start ---  

 

variable RECIPROCAL: BOOLEAN := X < 0.0;-- Check sign of argument 

 

--- Quote End ---  

 

 

This should be 'constant'. 

 

Given that this is in the IEEE library code, I don't think you can really do much about it. You might be able to recompile the IEEE libraries to over-ride whatever Quartus uses internally. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

Thanks for clarifying the problem with IEEE library code. I was in fact assuming that the variable declaration in your code causes the warning. 

 

The problem is sligthly different and hasn't to do with constant versus variable. It's quite normal, that variables inside library functions are involved when calculating constants. The warning is due to the fact, that the initial value expression in variable declaration isn't understood by Quartus as an actual assignment. You may consider this as a minor Quartus bug. 

 

P.S.: The message directive -- altera meassage_off xxxxx isn't supported for packages, so the issue has to be resolved by Altera.
0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

FvM & Dave, 

 

Thanks for the feedback, and I would agree that this is a minor Quartus bug. My main approach will be to not use reciprocal factors when declaring these types of constants.  

 

Best, James
0 Kudos
Altera_Forum
Honored Contributor II
3,185 Views

The same warning is caused by a number of other frequently used ieee.math_real, e.g. trigonometric functions.

0 Kudos
Reply