Forum Discussion
Altera_Forum
Honored Contributor
12 years agocalculate 64 bit unsigned
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? Thanks9 Replies
- Altera_Forum
Honored Contributor
--- 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 libraryfunction 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); - Altera_Forum
Honored Contributor
the problem arises when N is 64 as a integer is not enough to represent it.
How could i resolve? - Altera_Forum
Honored Contributor
--- 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; - Altera_Forum
Honored Contributor
actually you need to go lower than 2^32 as temp1,temp2 exceed 2^32, try 2^16
- Altera_Forum
Honored Contributor
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 - Altera_Forum
Honored Contributor
looks like this will work (not a function)
then choose 64 bits of phaseconstant 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; - Altera_Forum
Honored Contributor
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 - Altera_Forum
Honored Contributor
--- 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) - Altera_Forum
Honored Contributor
It works thanks