0
$\begingroup$

I have to write code on DDS using DITHERING technique, in which i have to generate a PSUEDO RANDOM SEQUENCE and add that sequence after LUT/before LUT so that spurs are avoided.

I have the PRN generator code but I am confused about how to add this prn in coding. Please clarify.

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use ieee.math_real.all;

entity ddssine1 is
port(
    i_clk          : in  std_logic;
    i_rstb         : in  std_logic;
    i_sync_reset   : in  std_logic;
    i_fcw          : in  std_logic_vector(31 downto 0);
    i_start_phase  : in  std_logic_vector(31 downto 0);
    o_sine         : out std_logic_vector(13 downto 0));
end ddssine1;
architecture Behavioral of ddssine1 is

constant C_LUT_DEPTH    : integer := 2**13;  -- 8Kword
constant C_LUT_BIT      : integer := 14;     -- 14 bit LUT
type t_lut_sin is array(0 to C_LUT_DEPTH-1) of std_logic_vector(C_LUT_BIT-1 downto 0);

-- quantize a real value as signed 
function quantization_sgn(nbit : integer; max_abs : real; dval : real) return std_logic_vector is
variable temp    : std_logic_vector(nbit-1 downto 0):=(others=>'0');
constant scale   : real :=(2.0**(real(nbit-1)))/max_abs;
constant minq    : integer := -(2**(nbit-1));
constant maxq    : integer := +(2**(nbit-1))-1;
variable itemp   : integer := 0;
begin
  if(nbit>0) then
    if (dval>=0.0) then 
      itemp := +(integer(+dval*scale+0.49));
    else 
      itemp := -(integer(-dval*scale+0.49));
    end if;
    if(itemp<minq) then itemp := minq; end if;
    if(itemp>maxq) then itemp := maxq; end if;
  end if;
  temp := std_logic_vector(to_signed(itemp,nbit));
  return temp;
end quantization_sgn;
-- generate the sine values for a LUT of depth "LUT_DEPTH" and quantization of "LUT_BIT"
function init_lut_sin return t_lut_sin is
variable ret           : t_lut_sin:=(others=>(others=>'0'));  -- LUT generated
variable v_tstep       : real:=0.0;
variable v_qsine_sgn   : std_logic_vector(C_LUT_BIT-1 downto 0):=(others=>'0');
constant step          : real := 1.00/real(C_LUT_DEPTH);
begin
    for count in 0 to C_LUT_DEPTH-1 loop
        v_qsine_sgn := quantization_sgn(C_LUT_BIT, 1.0,sin(MATH_2_PI*v_tstep));
        ret(count)  := v_qsine_sgn;
        v_tstep := v_tstep + step;
     end loop;
     return ret;
end function init_lut_sin;

-- initialize LUT with sine samples
constant C_LUT_SIN                 : t_lut_sin := init_lut_sin;
signal r_sync_reset                : std_logic;
signal r_start_phase               : unsigned(31 downto 0);
signal r_fcw                       : unsigned(31 downto 0);
signal r_nco                       : unsigned(31 downto 0);
signal lut_addr                    : std_logic_vector(12 downto 0);
signal lut_value                   : std_logic_vector(13 downto 0);
signal  tmp                        : std_logic_vector (0 to 17); 
signal  feedback                   : std_logic;
 signal  count                     : std_logic_vector (0 to 17);
begin
p_nco : process(i_clk)
begin
    if(i_rstb='0') then
        r_sync_reset      <= '1';
        r_start_phase     <= (others=>'0');
        r_fcw             <= (others=>'0');
        r_nco             <= (others=>'0');
    elsif(rising_edge(i_clk)) then
        r_sync_reset      <= i_sync_reset   ;
        r_start_phase     <= unsigned(i_start_phase);
        r_fcw             <= unsigned(i_fcw);
        if(r_sync_reset='1') then
            r_nco             <= r_start_phase;
        else
            r_nco             <= r_nco + r_fcw;
        end if;
    end if;
end process p_nco;

p_rom : process(i_clk)
begin
    if(rising_edge(i_clk)) then
        lut_addr   <= std_logic_vector(r_nco(31 downto 19));
        lut_value  <= C_LUT_SIN(to_integer(unsigned(lut_addr)));
    end if;
end process p_rom;

p_sine : process(i_clk)
begin
    if(i_rstb='0') then
        o_sine     <= (others=>'0');
    elsif(rising_edge(i_clk)) then
        o_sine     <= lut_value;
    end if;
end process p_sine;
 p_dither:process(i_clk)     
begin
   feedback <= not(tmp(16) xor tmp(17));
       if (i_rstb = '1') then
      tmp <= (others=>'0');
      elsif (rising_edge(i_clk)) then
      tmp <=  feedback & tmp(0 to 16) ;
      end if;
  count <= tmp;
  end process p_dither;
end Behavioral;
testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ddssinetb1 is
end ddssinetb1;

architecture Behavioral of ddssinetb1 is

component  ddssine1
port (
    i_clk          : in  std_logic;
    i_rstb         : in  std_logic;
    i_sync_reset   : in  std_logic;
    i_fcw          : in  std_logic_vector(31 downto 0);
    i_start_phase  : in  std_logic_vector(31 downto 0);
    o_sine         : out std_logic_vector(13 downto 0));
end component;

signal i_clk                       : std_logic:='0';
signal i_rstb                      : std_logic;
signal i_sync_reset                : std_logic;
signal i_start_phase               : std_logic_vector(31 downto 0):=X"00000000";
signal i_fcw                       : std_logic_vector(31 downto 0):=X"40000000";  
signal o_sine                      : std_logic_vector(13 downto 0);


begin

i_clk  <= not i_clk  after 5 ns;
i_rstb <= '0', '1' after 163 ns;
i_sync_reset <= '1', '0' after 200 ns;
u1:ddssine1
port map(
    i_clk                       => i_clk                      ,
    i_rstb                      => i_rstb                     ,
    i_sync_reset                => i_sync_reset               ,
    i_start_phase               => i_start_phase             ,
    i_fcw                       => i_fcw                      ,
    o_sine                      => o_sine    

           );

figure enter image description here ways to add prn sequence

$\endgroup$
  • $\begingroup$ As a helpful hint since no one answered yet, I suspect that your question is much too broad and there is more information here (including your code) than anyone would likely have the time to go through. I have this post in case it helps on implementing PRN generators dsp.stackexchange.com/questions/37875/… or perhaps you could post some more concise (brief) questions with regards to implementation. $\endgroup$ – Dan Boschen Apr 30 '19 at 20:09
  • $\begingroup$ This link also details PRN generation since GPS Gold Codes are formed from the sum of two PRN generators. dsp.stackexchange.com/questions/52810/… For dithering the PRN is simply added to the least significant bits to add randomization (whitening) to the signal. $\endgroup$ – Dan Boschen Apr 30 '19 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.