---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 17:27:54 05/05/2020 -- Design Name: -- Module Name: Sampling - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity Sampling is Generic(CLK_DIV : integer; CLK_FREQ : integer; IF_FREQ : integer; CLK_CYCLES_PRE_DONE : integer); Port ( CLK : in STD_LOGIC; RESET : in STD_LOGIC; PORT1 : in STD_LOGIC_VECTOR (15 downto 0); PORT2 : in STD_LOGIC_VECTOR (15 downto 0); REF : in STD_LOGIC_VECTOR (15 downto 0); ADC_START : out STD_LOGIC; NEW_SAMPLE : in STD_LOGIC; DONE : out STD_LOGIC; PRE_DONE : out STD_LOGIC; START : in STD_LOGIC; SAMPLES : in STD_LOGIC_VECTOR (9 downto 0); PORT1_I : out STD_LOGIC_VECTOR (47 downto 0); PORT1_Q : out STD_LOGIC_VECTOR (47 downto 0); PORT2_I : out STD_LOGIC_VECTOR (47 downto 0); PORT2_Q : out STD_LOGIC_VECTOR (47 downto 0); REF_I : out STD_LOGIC_VECTOR (47 downto 0); REF_Q : out STD_LOGIC_VECTOR (47 downto 0); ACTIVE : out STD_LOGIC); end Sampling; architecture Behavioral of Sampling is COMPONENT SinCos PORT ( clk : IN STD_LOGIC; phase_in : IN STD_LOGIC_VECTOR(11 DOWNTO 0); cosine : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); sine : OUT STD_LOGIC_VECTOR(15 DOWNTO 0) ); END COMPONENT; COMPONENT SinCosMult PORT ( clk : IN STD_LOGIC; a : IN STD_LOGIC_VECTOR(15 DOWNTO 0); b : IN STD_LOGIC_VECTOR(15 DOWNTO 0); p : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) ); END COMPONENT; signal p1_I : signed(47 downto 0); signal p1_Q : signed(47 downto 0); signal p2_I : signed(47 downto 0); signal p2_Q : signed(47 downto 0); signal r_I : signed(47 downto 0); signal r_Q : signed(47 downto 0); signal clk_cnt : integer range 0 to CLK_DIV - 1; signal sample_cnt : integer range 0 to 131071; signal samples_to_take : integer range 0 to 131071; constant phase_inc : integer := IF_FREQ * 4096 * CLK_DIV / CLK_FREQ; signal phase : std_logic_vector(11 downto 0); signal sine : std_logic_vector(15 downto 0); signal cosine : std_logic_vector(15 downto 0); signal mult1_I : std_logic_vector(31 downto 0); signal mult1_Q : std_logic_vector(31 downto 0); signal mult2_I : std_logic_vector(31 downto 0); signal mult2_Q : std_logic_vector(31 downto 0); signal multR_I : std_logic_vector(31 downto 0); signal multR_Q : std_logic_vector(31 downto 0); type States is (Idle, Sampling, WaitForMult, Accumulating, Ready); signal state : States; begin -- Always fails for simulation, comment out -- assert (phase_inc * CLK_FREQ / (4096*CLK_DIV) = IF_FREQ) -- report "Phase increment not exact" -- severity FAILURE; LookupTable : SinCos PORT MAP ( clk => CLK, phase_in => phase, cosine => cosine, sine => sine ); Port1_I_Mult : SinCosMult PORT MAP ( clk => CLK, a => PORT1, b => cosine, p => mult1_I ); Port1_Q_Mult : SinCosMult PORT MAP ( clk => CLK, a => PORT1, b => sine, p => mult1_Q ); Port2_I_Mult : SinCosMult PORT MAP ( clk => CLK, a => PORT2, b => cosine, p => mult2_I ); Port2_Q_Mult : SinCosMult PORT MAP ( clk => CLK, a => PORT2, b => sine, p => mult2_Q ); Ref_I_Mult : SinCosMult PORT MAP ( clk => CLK, a => REF, b => cosine, p => multR_I ); Ref_Q_Mult : SinCosMult PORT MAP ( clk => CLK, a => REF, b => sine, p => multR_Q ); process(CLK, RESET) begin if rising_edge(CLK) then if RESET = '1' then state <= Idle; ADC_START <= '0'; DONE <= '0'; PRE_DONE <= '0'; ACTIVE <= '0'; clk_cnt <= 0; sample_cnt <= 0; phase <= (others => '0'); else -- when not idle, generate pulses for ADCs if state /= Idle then if clk_cnt = CLK_DIV - 1 then ADC_START <= '1'; clk_cnt <= 0; else clk_cnt <= clk_cnt + 1; ADC_START <= '0'; end if; else ADC_START <= '0'; end if; -- handle state transitions case state is when Idle => sample_cnt <= 0; DONE <= '0'; PRE_DONE <= '0'; ACTIVE <= '0'; clk_cnt <= 0; phase <= (others => '0'); p1_I <= (others => '0'); p1_Q <= (others => '0'); p2_I <= (others => '0'); p2_Q <= (others => '0'); r_I <= (others => '0'); r_Q <= (others => '0'); phase <= (others => '0'); if START = '1' then state <= Sampling; samples_to_take <= to_integer(unsigned(SAMPLES & "0000000")); end if; when Sampling => DONE <= '0'; PRE_DONE <= '0'; ACTIVE <= '1'; if NEW_SAMPLE = '1' then state <= WaitForMult; end if; when WaitForMult => DONE <= '0'; PRE_DONE <= '0'; ACTIVE <= '1'; state <= Accumulating; when Accumulating => -- multipliers are finished with the sample p1_I <= p1_I + signed(mult1_I); p1_Q <= p1_Q + signed(mult1_Q); p2_I <= p2_I + signed(mult2_I); p2_Q <= p2_Q + signed(mult2_Q); r_I <= r_I + signed(multR_I); r_Q <= r_Q + signed(multR_Q); -- advance phase ACTIVE <= '1'; DONE <= '0'; PRE_DONE <= '0'; phase <= std_logic_vector(unsigned(phase) + phase_inc); if sample_cnt < samples_to_take then sample_cnt <= sample_cnt + 1; state <= Sampling; else state <= Ready; end if; when Ready => ACTIVE <= '1'; DONE <= '1'; PRE_DONE <= '1'; PORT1_I <= std_logic_vector(p1_I); PORT1_Q <= std_logic_vector(p1_Q); PORT2_I <= std_logic_vector(p2_I); PORT2_Q <= std_logic_vector(p2_Q); REF_I <= std_logic_vector(r_I); REF_Q <= std_logic_vector(r_Q); state <= Idle; end case; end if; end if; end process; end Behavioral;