Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20688 Discussions

calculate 64 bit unsigned

Altera_Forum
Honored Contributor II
1,253 Views

hi, 

i've implemented a nco megafunction with a 64 bit phase accumulator in order to obtain very high precision output frequencies. 

Now to be able to program externally (by microcontroller for example) the phase increment value and also to make my nco fully programmable, i need to write vhdl code for this function: 

 

Phase_Inc = Fout*2^N/F_clk. 

 

The parameters for the fuction should be Fout, F_clk and N (number of bits). The output should be a std_logic_vector(63 downto 0) in my case. 

 

Could you help me? 

Thanks
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
457 Views

 

--- Quote Start ---  

hi, 

i've implemented a nco megafunction with a 64 bit phase accumulator in order to obtain very high precision output frequencies. 

Now to be able to program externally (by microcontroller for example) the phase increment value and also to make my nco fully programmable, i need to write vhdl code for this function: 

 

Phase_Inc = Fout*2^N/F_clk. 

 

The parameters for the fuction should be Fout, F_clk and N (number of bits). The output should be a std_logic_vector(63 downto 0) in my case. 

 

Could you help me? 

Thanks 

--- Quote End ---  

 

 

try this. you need numeric_std library 

 

function get_phase_inc(Fout,clk,N : natural) return std_logic_vector is variable phase : integer; begin phase := Fout*2**N/clk; return std_logic_vector(to_unsigned(phase,N)); end function; signal test : std_logic_vector(7 downto 0); ... test <= get_phase_inc(10,100,8);
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

the problem arises when N is 64 as a integer is not enough to represent it. 

How could i resolve?
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

 

--- Quote Start ---  

the problem arises when N is 64 as a integer is not enough to represent it. 

How could i resolve? 

--- Quote End ---  

 

 

Indeed.. 

 

try this since Fo*2^64/clk = Fo*2^32/clk * 2*32/clk. 

 

function phase_inc(Fout,clk, N : natural) return std_logic_vector is variable phase : integer; variable temp1,temp2:unsigned(N/2-1 downto 0); begin phase := Fout*(2**N/2)/clk; temp1 := to_unsigned(phase,32); phase := (2**N/2)/clk; temp2 := to_unsigned(phase,32); return std_logic_vector(temp1*temp2); end function;
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

actually you need to go lower than 2^32 as temp1,temp2 exceed 2^32, try 2^16

0 Kudos
Altera_Forum
Honored Contributor II
457 Views

I finally see no way to get value without losing resolution as there is no support for 64 bits range 

anyway 64 bits phase accum is too drastic, 24 bits is ok generally
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

looks like this will work (not a function) 

 

 

constant fo:unsigned(31 downto 0) := x"11110000"; constant fclk : unsigned(31 downto 0) := x"ffff0000"; constant temp: unsigned(95 downto 0) := fo & x"0000000000000000"; constant phase : unsigned(95 downto 0) := temp/fclk;  

 

then choose 64 bits of phase
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

ok I'll try this way then I'll let you know... 

 

i don't understand the constant temp.... 

 

So if my numbers is: 

Fo=4050Hz 

Fclk=250Khz 

N=64 

 

how could i put them in your code? 

Thanks
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

 

--- Quote Start ---  

ok I'll try this way then I'll let you know... 

 

i don't understand the constant temp.... 

 

So if my numbers is: 

Fo=4050Hz 

Fclk=250Khz 

N=64 

 

how could i put them in your code? 

Thanks 

--- Quote End ---  

 

 

just insert the binary value(in hex) of 4050 for Fo and 250000 for Fclk. Keep everything else same (2**64 is implied by the zeros on temp)
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

It works thanks

0 Kudos
Reply