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$
2
  • $\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$ Commented Apr 30, 2019 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$ Commented Apr 30, 2019 at 20:12

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.