Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

calculate 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?

Thanks

9 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored 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 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);
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

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

    How could i resolve?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored 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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

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

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored 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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored 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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored 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)