diff --git a/lib/radio/ddc/src/syn_ddc.vhd b/lib/radio/ddc/src/syn_ddc.vhd index 914639a..751ca44 100644 --- a/lib/radio/ddc/src/syn_ddc.vhd +++ b/lib/radio/ddc/src/syn_ddc.vhd @@ -20,6 +20,9 @@ library ieee_proposed; use ieee_proposed.math_utility_pkg.all; use ieee_proposed.fixed_pkg.all; +library altera; +use altera.altera_syn_attributes.all; + library work; use work.fixed_util_pkg.all; @@ -30,26 +33,51 @@ use work.fixed_util_pkg.all; nbits_in_frac : integer := 14; nbits_out : integer := 32; nbits_out_frac : integer := 30; - lo_nbits_phase : integer := 20; - lo_nbits_freq : integer := 20; + lo_nbits_phase : integer := 24; + lo_nbits_freq : integer := 24; cic_nstages : integer := 5; cic_ratio : integer := 25; cic_scale_nbits : integer := 22 ); PORT ( - rst : in std_logic; - clk : in std_logic; - lo_nco_rst : in std_logic; - lo_nco_en : in std_logic; - lo_freq_in : in unsigned(lo_nbits_freq-1 downto 0); - lo_phase_in : in unsigned(lo_nbits_phase-1 downto 0); - din_i : in signed(nbits_in-1 downto 0); - din_q : in signed(nbits_in-1 downto 0); - dout_i : out signed(nbits_out-1 downto 0); - dout_q : out signed(nbits_out-1 downto 0); - din_vld : in std_logic; - dout_vld : out std_logic + rst : in std_logic; + + adc_clk : in std_logic; + adc_da : in signed(15 downto 0); + adc_ofa : in std_logic; + adc_rand : out std_logic; + adc_pga : out std_logic; + adc_dith : out std_logic; + adc_shdn : out std_logic; + + usb_usbclk : in std_logic; + usb_ifclk : in std_logic; + usb_fd : out signed(15 downto 0); + usb_pktend : out std_logic; + usb_fifoadr : out unsigned(1 downto 0); + usb_slcs_n : out std_logic; + usb_slwr_n : out std_logic; + usb_slrd_n : out std_logic; + usb_sloe : out std_logic; + usb_flaga : in std_logic; + usb_flagb : in std_logic; + usb_flagc : in std_logic; + + cl_clk_out : out std_logic; + cl_dout : out unsigned(23 downto 0); + cl_pat_sel : out std_logic; + cl_prbs_en : out std_logic; + cl_ds_opt : out std_logic; + cl_bal : out std_logic; + cl_pd_n : out std_logic; + cl_tsen : in std_logic; + + reg_aen : in std_logic; + reg_dio : inout unsigned(7 downto 0); + reg_oe : in std_logic; + reg_we : in std_logic + ); END syn_ddc; @@ -99,6 +127,45 @@ ARCHITECTURE behavior OF syn_ddc IS SIGNAL ddc_dec_i : sfixed(shi(nbits_out, nbits_out_frac) downto slo(nbits_out, nbits_out_frac)); SIGNAL ddc_dec_q : sfixed(shi(nbits_out, nbits_out_frac) downto slo(nbits_out, nbits_out_frac)); + + SIGNAL reg_lo_nco_rst : std_logic; + SIGNAL reg_lo_nco_en : std_logic; + SIGNAL reg_lo_freq_in : unsigned(31 downto 0); + SIGNAL reg_lo_phase_in : unsigned(31 downto 0); + + SIGNAL reg_en_addr : std_logic; + SIGNAL reg_en_data : std_logic; + SIGNAL reg_addr_last : std_logic; + SIGNAL reg_data_last : std_logic; + SIGNAL reg_addr_async : unsigned (7 downto 0); + SIGNAL reg_data_async : unsigned (7 downto 0); + SIGNAL reg_addr : unsigned (7 downto 0); + SIGNAL reg_data : unsigned (7 downto 0); + + SIGNAL fifo_usb_we : std_logic; + SIGNAL fifo_usb_re : std_logic; + SIGNAL fifo_usb_ff : std_logic; + SIGNAL fifo_usb_ef : std_logic; + SIGNAL fifo_usb_aff : std_logic; + SIGNAL fifo_usb_aef : std_logic; + + type fifo_usb_array_t is array (0 to 3) of unsigned (15 downto 0); + SIGNAL fifo_usb_in : fifo_usb_array_t; + SIGNAL fifo_usb_out : unsigned (15 downto 0); + + SIGNAL fifo_usb_we_pipe : unsigned(3 downto 0); + SIGNAL enable : std_logic; + SIGNAL ddc_din_vld : std_logic; + SIGNAL ddc_dout_vld : std_logic; + + SIGNAL cl_we_pipe : unsigned(1 downto 0); + type cl_data_array_t is array (0 to 1) of unsigned (31 downto 0); + SIGNAL cl_sd_data : cl_data_array_t; + + SIGNAL cl_dout_L : std_logic_vector(24 downto 0); + SIGNAL cl_dout_H : std_logic_vector(24 downto 0); + SIGNAL cl_dout_clk : std_logic_vector(24 downto 0); + BEGIN -- Instantiate the Unit Under Test (UUT) @@ -118,26 +185,235 @@ BEGIN PORT MAP ( rst => rst, - clk => clk, - lo_nco_rst => lo_nco_rst, - lo_nco_en => lo_nco_en, - lo_freq_in => lo_freq_in, - lo_phase_in => lo_phase_in, - din_vld => din_vld, + clk => adc_clk, + lo_nco_rst => reg_lo_nco_rst, + lo_nco_en => reg_lo_nco_en, + lo_freq_in => reg_lo_freq_in(lo_nbits_freq-1 downto 0), + lo_phase_in => reg_lo_phase_in(lo_nbits_phase-1 downto 0), + din_vld => ddc_din_vld, din_i => ddc_din_i, din_q => ddc_din_q, dec_vld => dec_vld, dec_i => ddc_dec_i, dec_q => ddc_dec_q, - dout_vld => dout_vld, + dout_vld => ddc_dout_vld, dout_i => ddc_dout_i, dout_q => ddc_dout_q ); + +reg_dio <= reg_addr when reg_oe = '1' else (others => 'Z'); + +---------------------------------------------------------- +-- Register control +---------------------------------------------------------- +proc_reg_da_async: + process(reg_we) + begin + if rising_edge(reg_we) then + if reg_aen = '1' then + reg_addr_async <= reg_dio; + else + reg_data_async <= reg_dio; + end if; + end if; + end process; - ddc_din_i <= sfixed(din_i); - ddc_din_q <= sfixed(din_q); +proc_reg_da_sync: + process(adc_clk) +-- process(usb_usbclk) + begin + if rising_edge(adc_clk) then +-- if rising_edge(usb_usbclk) then + if rst = '1' then + reg_en_addr <= '0'; + reg_en_data <= '0'; + reg_addr_last <= '0'; + reg_data_last <= '0'; + elsif reg_we = '1' then + reg_en_addr <= reg_aen and not reg_addr_last; + reg_en_data <= not (reg_aen or reg_data_last); + reg_addr_last <= reg_aen; + reg_data_last <= not reg_aen; + else + reg_addr_last <= '0'; + reg_data_last <= '0'; + end if; + reg_data <= reg_data_async; + reg_addr <= reg_addr_async; + end if; + end process; + + -- Registers +proc_register_write: + process(adc_clk) +-- process(usb_usbclk) + begin + if rising_edge(adc_clk) then +-- if rising_edge(usb_usbclk) then + if rst = '1' then + reg_lo_nco_rst <= '0'; + reg_lo_nco_en <= '0'; + elsif reg_en_data = '1' then + case reg_addr is + when X"00" => -- Control + reg_lo_nco_rst <= reg_data(0); + reg_lo_nco_en <= reg_data(1); + + when X"10" => -- freqency + reg_lo_freq_in(7 downto 0) <= reg_data; + + when X"11" => -- freqency + reg_lo_freq_in(15 downto 8) <= reg_data; + + when X"12" => -- freqency + reg_lo_freq_in(23 downto 16) <= reg_data; + + when X"13" => -- freqency + reg_lo_freq_in(31 downto 24) <= reg_data; + + when X"20" => -- phase + reg_lo_phase_in(7 downto 0) <= reg_data; + + when X"21" => -- phase + reg_lo_phase_in(15 downto 8) <= reg_data; + + when X"22" => -- phase + reg_lo_phase_in(23 downto 16) <= reg_data; + + when X"23" => -- phase + reg_lo_phase_in(31 downto 24) <= reg_data; + + when others => null; + end case; + end if; + end if; + end process; + +---------------------------------------------------------- +-- DDC input +---------------------------------------------------------- +proc_adc_input_register: + process(adc_clk) + begin + if rising_edge(adc_clk) then + ddc_din_vld <= enable; + if enable = '1' then + ddc_din_i <= sfixed(resize(adc_da, nbits_in)); + end if; + end if; + end process; + + ddc_din_q <= to_sfixed(0.0, shi(nbits_in, nbits_in_frac), slo(nbits_in, nbits_in_frac)); - dout_i <= signed(ddc_dout_i); - dout_q <= signed(ddc_dout_q); + enable <= '1'; + adc_rand <= '0'; + adc_pga <= '0'; + adc_dith <= '0'; + adc_shdn <= not enable; + +---------------------------------------------------------- +-- USB FIFO output +---------------------------------------------------------- +proc_usb_interleave_iq: + process(adc_clk) + variable i, q : unsigned(31 downto 0); + begin + if rising_edge(adc_clk) then + if rst = '1' then + fifo_usb_we_pipe <= (others => '0'); + elsif ddc_dout_vld = '1' then + fifo_usb_we_pipe <= (others => '1'); + i := unsigned(ddc_dout_i); + q := unsigned(ddc_dout_q); + fifo_usb_in(0) <= i(15 downto 0); + fifo_usb_in(1) <= i(31 downto 16); + fifo_usb_in(2) <= q(15 downto 0); + fifo_usb_in(3) <= q(31 downto 16); + elsif fifo_usb_ff = '0' then + fifo_usb_we_pipe <= fifo_usb_we_pipe(fifo_usb_we_pipe'left-1 downto 0) & '0'; + fifo_usb_in(0) <= fifo_usb_in(1); + fifo_usb_in(1) <= fifo_usb_in(2); + fifo_usb_in(2) <= fifo_usb_in(3); + end if; + end if; + end process; + +inst_usbfifo: entity work.fifo_async + GENERIC MAP + ( + addr_width => 7, + data_width => 16, + almost_full_thresh => 96, + almost_empty_thresh => 32 + ) + PORT MAP + ( + rst => rst, + clk_w => adc_clk, + clk_r => usb_ifclk, + we => fifo_usb_we, + re => fifo_usb_re, + data_w => fifo_usb_in(0), + data_r => fifo_usb_out, + fifo_full => fifo_usb_ff, + fifo_empty => fifo_usb_ef, + fifo_afull => fifo_usb_aff, + fifo_aempty => fifo_usb_aef + + ); + + fifo_usb_we <= fifo_usb_we_pipe(fifo_usb_we_pipe'left); + usb_fd <= signed(fifo_usb_out); + fifo_usb_re <= usb_flaga; + usb_slcs_n <= '0'; + usb_slwr_n <= not usb_flaga; + usb_slrd_n <= '1'; + usb_sloe <= '0'; + + +---------------------------------------------------------- +-- Channel-Link DDR output +---------------------------------------------------------- +proc_cl_interleave_iq: + process(adc_clk) + variable i, q : unsigned(31 downto 0); + begin + if rising_edge(adc_clk) then + if rst = '1' then + cl_we_pipe <= (others => '0'); + elsif ddc_dout_vld = '1' then + cl_we_pipe <= (others => '1'); + i := unsigned(ddc_dout_i); + q := unsigned(ddc_dout_q); + cl_sd_data(0) <= i; + cl_sd_data(1) <= q; + else + cl_we_pipe <= cl_we_pipe(cl_we_pipe'left-1 downto 0) & '0'; + cl_sd_data(0) <= cl_sd_data(1); + end if; + end if; + end process; +inst_cl_ddr_out: entity work.cl_ddr_out + PORT MAP + ( + aclr => rst, + datain_h => cl_dout_H, + datain_l => cl_dout_L, + outclock => adc_clk, + outclocken => '1', + dataout => cl_dout_clk + ); + + cl_dout_H <= '0' & cl_we_pipe(cl_we_pipe'left) & "0000000" & std_logic_vector(cl_sd_data(0)(31 downto 16)); + cl_dout_L <= '1' & cl_we_pipe(cl_we_pipe'left) & "0000000" & std_logic_vector(cl_sd_data(0)(15 downto 0)); + cl_dout <= unsigned(cl_dout_clk(23 downto 0)); + cl_clk_out <= cl_dout_clk(24); + cl_pat_sel <= '0'; + cl_prbs_en <= '0'; + cl_ds_opt <= '0'; + cl_bal <= '0'; + cl_pd_n <= '1'; + +---------------------------------------------------------- END; diff --git a/lib/radio/ddc/src/tb_ddc.vhd b/lib/radio/ddc/src/tb_ddc.vhd index 37d6fca..fa3a61e 100644 --- a/lib/radio/ddc/src/tb_ddc.vhd +++ b/lib/radio/ddc/src/tb_ddc.vhd @@ -33,13 +33,13 @@ ENTITY tb_ddc IS nbits_in_frac : integer := 14; nbits_out : integer := 32; nbits_out_frac : integer := 30; - lo_nbits_phase : integer := 20; - lo_nbits_freq : integer := 20; + lo_nbits_phase : integer := 24; + lo_nbits_freq : integer := 24; cic_nstages : integer := 5; cic_ratio : integer := 25; cic_scale_nbits : integer := 22; - rfgen_nbits_phase : integer := 20; - rfgen_nbits_freq : integer := 20 + rfgen_nbits_phase : integer := 32; + rfgen_nbits_freq : integer := 32 ); END tb_ddc; @@ -108,7 +108,7 @@ ARCHITECTURE behavior OF tb_ddc IS END COMPONENT; --Constants - constant fa : REAL := 100.0E6; + constant fa : REAL := 2.0**27; constant frf1 : REAL := 33.99E6; constant frf2 : REAL := 2.1E6; constant frf3 : REAL := 19.01E6; @@ -352,6 +352,7 @@ BEGIN tb_param : PROCESS file RESULT_R: text open write_mode is "ratio.txt"; file RESULT_N: text open write_mode is "nstages.txt"; + file FSAMPLE: text open write_mode is "fa.txt"; variable L: line; BEGIN @@ -360,6 +361,7 @@ BEGIN wait until rising_edge(clk) and rst = '0'; fprint(RESULT_R, L,"%s\n", natural'image(cic_ratio)); fprint(RESULT_N, L,"%s\n", natural'image(cic_nstages)); + fprint(FSAMPLE, L,"%s\n", real'image(fa)); wait; END PROCESS;