------------------------------------------------------------------------------- -- Company: -- Engineer: Jason M. Blevins -- -- Create Date: 19:38:12 11/10/2016 -- Design Name: -- Module Name: dds_pulse_gen - behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Revision 0.02 - Added Sweep Functionality 10-17-2017 -- Additional Comments: -- * All information is proprietary/confidential * -- -- A 256-bit control word (32x8 right shifted in) is read from an external FIFO. -- The control word contains all information needed to create a pulse -- -- RESERVED = fifo_data_r(255 downto 241) -- 15-bits -- SWAP IQ CHANELS = fifo_data_r(240) -- 1-bit set to '1' for negative frequencies -- SCALE FACTOR TO SCALE OUTPUT AMPLITUDE = fifo_data_r(239 downto 224) -- 16-bits, (0,1], full-scale = 1.000000000000000 -- DDS PHASE OFFSET = fifo_data_r(223 downto 192) -- 32-bits, reserved, set to 0x0000_0000 -- DDS PHASE INCREMENT = fifo_data_r(191 downto 160) -- 32-bits -- # DDS SAMPLES = fifo_data_r(159 downto 128) -- 32-bits -- # MIDPOINT SAMPLES PRIOR TO PULSE = fifo_data_r(127 downto 96) -- 32-bits -- RESERVED = fifo_data_r(95 downto 88) -- 8-bit -- DDS PHASE INCREMENT STEP = fifo_data_r(87 downto 64) -- 24-bits (2's complement SIGNED !!) -- RESERVED = fifo_data_r(63 downto 48) -- 16-bits -- DDS PHASE INCREMENT DWELL = fifo_data_r(47 downto 32) -- 16-bits -- RESERVED = fifo_data_r(31 downto 0) -- 32-bits -- ------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; --Library UNIMACRO; --use UNIMACRO.vcomponents.all; USE IEEE.NUMERIC_STD.ALL; entity dds_pulse_gen is port( clk_in : in std_logic; rst_in : in std_logic; fifo_data_in : in std_logic_vector(31 downto 0); fifo_dval_in : in std_logic; fifo_empty_in : in std_logic; fifo_rden_out : out std_logic; holdoff_in : in std_logic; data_out : out std_logic_vector(31 downto 0); dval_out : out std_logic ); end entity; architecture mixed of dds_pulse_gen is component mult_16signed_x_16unsigned_latency3 port( clk : in std_logic; a : in std_logic_vector(15 downto 0); b : in std_logic_vector(15 downto 0); ce : in std_logic; sclr : in std_logic; p : out std_logic_vector(15 downto 0) ); end component; component dds_latency10 port( -- ce : in std_logic; -- clk : in std_logic; -- sclr : in std_logic; -- pinc_in : in std_logic_vector(31 downto 0); -- poff_in : in std_logic_vector(31 downto 0); -- rdy : out std_logic; -- cosine : out std_logic_vector(15 downto 0); -- sine : out std_logic_vector(15 downto 0) aclk : IN STD_LOGIC; aclken : IN STD_LOGIC; aresetn : IN STD_LOGIC; s_axis_phase_tvalid : IN STD_LOGIC; s_axis_phase_tdata : IN STD_LOGIC_VECTOR(31 DOWNTO 0); m_axis_data_tvalid : OUT STD_LOGIC; m_axis_data_tdata : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) ); end component; component addsub port ( a : in std_logic_vector(31 downto 0); -- unsigned b : in std_logic_vector(23 downto 0); -- signed --clk : in std_logic; s : out std_logic_vector(31 downto 0) -- latency=0 ?? Not practical in HW, design should be updated to allow for latency. ); end component; constant MIDPOINT : std_logic_vector(31 downto 0) := x"00000000"; type state_type is (s0, s0a, s0b, s0c, s1, s2, s3); signal state : state_type; signal state_r : state_type; signal rst_r : std_logic := '1'; signal rstn_r : std_logic := '0'; signal cnt1_r : unsigned(3 downto 0) := "0000"; signal cnt1 : unsigned(3 downto 0); signal cnt2_r : unsigned(2 downto 0) := "000"; signal cnt2 : unsigned(2 downto 0); signal cnt3_r : unsigned(31 downto 0) := x"00000000"; signal cnt3 : unsigned(31 downto 0); signal cnt4_r : unsigned(31 downto 0) := x"00000000"; signal cnt4 : unsigned(31 downto 0); signal cnt5_r : unsigned(3 downto 0) := "0000"; signal cnt5 : unsigned(3 downto 0); signal fifo_data_ce : std_logic; signal fifo_data_r : std_logic_vector(255 downto 0); signal fifo_rden : std_logic; --signal fifo_rden_r : std_logic := '0'; signal dval_r : std_logic := '0'; signal dval : std_logic; signal dds_data : std_logic_vector(31 downto 0); signal data : std_logic_vector(31 downto 0); signal data_r : std_logic_vector(31 downto 0); signal idle_sample_cnt_r : unsigned(31 downto 0); signal idle_sample_cnt_r1 : unsigned(31 downto 0); signal dds_sample_cnt_r : unsigned(31 downto 0); signal dds_sample_cnt_r1 : unsigned(31 downto 0); signal phase_inc_init_r : std_logic_vector(31 downto 0); signal phase_offset_r : std_logic_vector(31 downto 0); signal swap_r : std_logic := '0'; signal scale_r : std_logic_vector(15 downto 0); signal mult_dval_r : std_logic := '0'; signal data_swap_scaled : std_logic_vector(31 downto 0); signal data_scaled : std_logic_vector(31 downto 0); signal dds_ce : std_logic; signal dds_rst : std_logic; signal dds_rdy : std_logic; signal mult_ce : std_logic; signal mult_ce_pipe_r : std_logic_vector(1 downto 0) := "00"; signal holdoff_r : std_logic; --signal phase_inc_mux_sel : std_logic; signal phase_inc_update_en : std_logic; --signal phase_inc_mux : std_logic_vector(31 downto 0); signal phase_inc : std_logic_vector(31 downto 0); signal phase_inc_r : std_logic_vector(31 downto 0); signal phase_inc_r1 : std_logic_vector(31 downto 0); signal phase_inc_step_r : std_logic_vector(23 downto 0) := (others => '0'); signal phase_inc_dwell_r : unsigned(15 downto 0) := x"0000"; signal phase_inc_dwell_cnt_r : unsigned(15 downto 0) := x"0000"; signal phase_inc_dwell_cnt : unsigned(15 downto 0); signal phase_inc_addsub : std_logic_vector(31 downto 0); signal rstn : std_logic; begin i_addsub : addsub port map( a => phase_inc_r, b => phase_inc_step_r, --clk => clk_in, s => phase_inc_addsub ); fifo_rden_out <= fifo_rden;--fifo_rden_r; data_out <= data_r; dval_out <= dval_r; process(clk_in) begin if(rising_edge(clk_in))then if(rst_r = '1')then state_r <= s0; cnt1_r <= (others => '0'); cnt2_r <= (others => '0'); cnt3_r <= (others => '0'); cnt4_r <= (others => '0'); cnt5_r <= (others => '0'); phase_inc_dwell_cnt_r <= (others => '0'); else state_r <= state; cnt1_r <= cnt1; cnt2_r <= cnt2; cnt3_r <= cnt3; cnt4_r <= cnt4; cnt5_r <= cnt5; phase_inc_dwell_cnt_r <= phase_inc_dwell_cnt; end if; if(fifo_data_ce = '1')then fifo_data_r <= fifo_data_in & fifo_data_r(255 downto 32);--fifo_data_r(223 downto 0) & fifo_data_in; end if; rst_r <= rst_in; rstn_r <= not(rst_in); dval_r <= dval; phase_offset_r <= fifo_data_r(223 downto 192); -- phase_inc_init_r <= fifo_data_r(191 downto 160); dds_sample_cnt_r <= unsigned(fifo_data_r(159 downto 128)); dds_sample_cnt_r1 <= dds_sample_cnt_r; swap_r <= fifo_data_r(240); scale_r <= fifo_data_r(239 downto 224); idle_sample_cnt_r <= unsigned(fifo_data_r(127 downto 96)); idle_sample_cnt_r1 <= idle_sample_cnt_r; phase_inc_step_r <= fifo_data_r(87 downto 64); phase_inc_dwell_r <= unsigned(fifo_data_r(47 downto 32)); data_r <= data; holdoff_r <= holdoff_in; phase_inc_r <= phase_inc; if(phase_inc_update_en = '1')then phase_inc_r1 <= phase_inc_r; end if; end if; end process; phase_inc_init_r <= fifo_data_r(191 downto 160); -- FSM next-state & output process process(state_r, cnt1_r, cnt2_r, cnt3_r, cnt4_r, cnt5_r, holdoff_r, fifo_empty_in, fifo_dval_in, phase_inc_init_r, phase_inc_r, mult_dval_r, data_swap_scaled, idle_sample_cnt_r1, dds_sample_cnt_r1, phase_inc_dwell_r, phase_inc_dwell_cnt_r, phase_inc_addsub) begin --defaults fifo_rden <= '0'; cnt1 <= cnt1_r; cnt2 <= cnt2_r; cnt3 <= cnt3_r; cnt4 <= cnt4_r; cnt5 <= cnt5_r; state <= state_r; dds_ce <= '0'; dds_rst <= '1'; dval <= mult_dval_r; data <= data_swap_scaled; fifo_data_ce <= '0'; phase_inc_dwell_cnt <= phase_inc_dwell_cnt_r; phase_inc <= phase_inc_r; phase_inc_update_en <= '0'; case state_r is when s0 => phase_inc_dwell_cnt <= (others => '0'); if(fifo_empty_in = '0' and cnt1_r < 8)then fifo_rden <= '1'; cnt1 <= cnt1_r +1; end if; if(fifo_dval_in = '1')then fifo_data_ce <= '1'; if(cnt2_r < 7)then cnt2 <= cnt2_r +1; else cnt2 <= (others => '0'); cnt1 <= (others => '0'); state <= s0a; end if; end if; -- This state is needed to clock the input shift reg data into next set of regs. -- Possibly can be removed to decrease pulse param processing cycles. when s0a => state <= s0b;--s1; phase_inc <= phase_inc_init_r; -- This state is needed to clock the input shift reg data into next set of regs. -- Possibly can be removed to decrease pulse param processing cycles. when s0b => state <= s1; phase_inc_update_en <= '1'; phase_inc <= phase_inc_addsub;--phase_inc_r + phase_inc_step_r; -- This state is needed to clock the input shift reg data into next set of regs. -- Possibly can be removed to decrease pulse param processing cycles. -- when s0c => -- state <= s1; -- phase_inc_update_en <= '1'; -- phase_inc <= phase_inc_addsub;--phase_inc_r + phase_inc_step_r; -- Insert midpoint (idle) samples that preceed the pulse. when s1 => data <= MIDPOINT; if(cnt3_r < idle_sample_cnt_r1)then if(holdoff_r = '0')then cnt3 <= cnt3_r +1; dval <= '1'; end if; else cnt3 <= (others => '0'); if(dds_sample_cnt_r1 > 0)then state <= s2; else state <= s0; end if; end if; -- Turn on DDS for requested number of samples. when s2 => dds_rst <= '0'; if(holdoff_r = '0')then if(phase_inc_dwell_cnt_r < phase_inc_dwell_r)then phase_inc_dwell_cnt <= phase_inc_dwell_cnt_r +1; else phase_inc_dwell_cnt <= (others => '0'); phase_inc_update_en <= '1'; phase_inc <= phase_inc_addsub;--phase_inc_r + phase_inc_step_r; end if; end if; if(holdoff_r = '0')then dds_ce <= '1'; if(cnt4_r < dds_sample_cnt_r1)then cnt4 <= cnt4_r +1; else cnt4 <= (others => '0'); state <= s3; end if; end if; -- phase_inc_mux_sel <= '1'; -- --phase_inc_en <= not(holdoff_r); -- dds_rst <= '0'; -- if(cnt4_r < dds_sample_cnt_r1)then -- if(holdoff_r = '0')then -- dds_ce <= '1'; -- cnt4 <= cnt4_r +1; -- if(phase_inc_dwell_cnt_r < phase_inc_dwell_r)then -- phase_inc_dwell_cnt <= phase_inc_dwell_cnt_r +1; -- else -- phase_inc_dwell_cnt <= x"00000"; -- phase_inc_en <= '1'; -- end if; -- end if; -- else -- if(holdoff_r = '0')then -- dds_ce <= '1'; -- cnt4 <= (others => '0'); -- state <= s3; -- end if; -- end if; -- Keep DDS enabled to overcome the latency of the core (i.e. wait for our samples to pop out). when s3 => dds_rst <= '0'; if(cnt5_r < 9)then if(holdoff_r = '0')then dds_ce <= '1'; cnt5 <= cnt5_r +1; end if; else cnt5 <= (others => '0'); state <= s0; end if; when others => end case; end process; process(clk_in) begin if(rising_edge(clk_in))then mult_dval_r <= mult_ce_pipe_r(1); mult_ce_pipe_r(1 downto 0) <= mult_ce_pipe_r(0) & (dds_rdy and dds_ce); end if; end process; data_swap_scaled <= data_scaled when swap_r = '0' else data_scaled(15 downto 0) & data_scaled(31 downto 16); mult_ce <= mult_ce_pipe_r(1) or mult_ce_pipe_r(0) or (dds_rdy and dds_ce); i_dds : dds_latency10 port map( -- ce => dds_ce, -- clk => clk_in, -- sclr => dds_rst, -- pinc_in => phase_inc_r1, -- poff_in => phase_offset_r, -- rdy => dds_rdy, -- cosine => dds_data(15 downto 0), -- sine => dds_data(31 downto 16) aclk => clk_in, aclken => dds_ce, aresetn => rstn_r, s_axis_phase_tvalid => dds_ce, s_axis_phase_tdata => phase_inc_r1, m_axis_data_tvalid => dds_rdy, m_axis_data_tdata => dds_data(31 downto 0) ); i_mult1 : mult_16signed_x_16unsigned_latency3 port map( clk => clk_in, a => dds_data(15 downto 0), b => scale_r, ce => mult_ce, sclr => '0', p => data_scaled(15 downto 0) ); i_mult2 : mult_16signed_x_16unsigned_latency3 port map( clk => clk_in, a => dds_data(31 downto 16), b => scale_r, ce => mult_ce, sclr => '0', p => data_scaled(31 downto 16) ); end mixed;