302 lines
7.7 KiB
VHDL
302 lines
7.7 KiB
VHDL
----------------------------------------------------------------------------------
|
|
-- 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_CYCLES_PRE_DONE : integer);
|
|
Port ( CLK : in STD_LOGIC;
|
|
RESET : in STD_LOGIC;
|
|
ADC_PRESCALER : in STD_LOGIC_VECTOR(7 downto 0);
|
|
PHASEINC : in STD_LOGIC_VECTOR(11 downto 0);
|
|
PORT1 : in STD_LOGIC_VECTOR (17 downto 0);
|
|
PORT2 : in STD_LOGIC_VECTOR (17 downto 0);
|
|
REF : in STD_LOGIC_VECTOR (17 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 (12 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 DSP_SLICE
|
|
PORT (
|
|
clk : IN STD_LOGIC;
|
|
ce : IN STD_LOGIC;
|
|
sel : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
|
|
a : IN STD_LOGIC_VECTOR(17 DOWNTO 0);
|
|
b : IN STD_LOGIC_VECTOR(17 DOWNTO 0);
|
|
c : IN STD_LOGIC_VECTOR(47 DOWNTO 0);
|
|
p : OUT STD_LOGIC_VECTOR(47 DOWNTO 0)
|
|
);
|
|
END COMPONENT;
|
|
COMPONENT window
|
|
PORT(
|
|
CLK : IN std_logic;
|
|
INDEX : IN std_logic_vector(6 downto 0);
|
|
WINDOW_TYPE : IN std_logic_vector(1 downto 0);
|
|
VALUE : OUT std_logic_vector(15 downto 0)
|
|
);
|
|
END COMPONENT;
|
|
|
|
signal p1_I : std_logic_vector(47 downto 0);
|
|
signal p1_Q : std_logic_vector(47 downto 0);
|
|
signal p2_I : std_logic_vector(47 downto 0);
|
|
signal p2_Q : std_logic_vector(47 downto 0);
|
|
signal r_I : std_logic_vector(47 downto 0);
|
|
signal r_Q : std_logic_vector(47 downto 0);
|
|
signal clk_cnt : integer range 0 to 255;
|
|
signal sample_cnt : integer range 0 to 131071;
|
|
signal samples_to_take : integer range 0 to 131071;
|
|
|
|
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 mult_a : std_logic_vector(17 downto 0);
|
|
signal mult_b : std_logic_vector(17 downto 0);
|
|
signal mult_c : std_logic_vector(47 downto 0);
|
|
signal mult_p : std_logic_vector(47 downto 0);
|
|
|
|
signal mult_enable : std_logic;
|
|
signal mult_accumulate : std_logic_vector(0 downto 0);
|
|
|
|
type States is (Idle, Sampling, P1Q, P2I, P2Q, RI, RQ, SaveP1Q, SaveP2I, SaveP2Q, SaveRI, SaveRQ, 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
|
|
);
|
|
|
|
Mult : DSP_SLICE
|
|
PORT MAP (
|
|
clk => CLK,
|
|
ce => mult_enable,
|
|
sel => mult_accumulate,
|
|
a => mult_a,
|
|
b => mult_b,
|
|
c => mult_c,
|
|
p => mult_p
|
|
);
|
|
|
|
-- sign extend b input of multiplier (sin/cos)
|
|
mult_b(17 downto 16) <= mult_b(15) & mult_b(15);
|
|
|
|
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');
|
|
mult_enable <= '0';
|
|
mult_accumulate <= "0";
|
|
else
|
|
-- when not idle, generate pulses for ADCs
|
|
if state /= Idle then
|
|
if clk_cnt = unsigned(ADC_PRESCALER) - 1 then
|
|
if sample_cnt < samples_to_take then
|
|
ADC_START <= '1';
|
|
end if;
|
|
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');
|
|
mult_enable <= '0';
|
|
mult_accumulate <= "0";
|
|
if START = '1' then
|
|
state <= Sampling;
|
|
samples_to_take <= to_integer(unsigned(SAMPLES & "0000"));
|
|
end if;
|
|
when Sampling =>
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
ACTIVE <= '1';
|
|
mult_enable <= '0';
|
|
if NEW_SAMPLE = '1' then
|
|
sample_cnt <= sample_cnt + 1;
|
|
mult_enable <= '1';
|
|
mult_a <= PORT1;
|
|
mult_b(15 downto 0) <= cosine;
|
|
mult_c <= p1_I;
|
|
state <= P1Q;
|
|
end if;
|
|
when P1Q =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
mult_a <= PORT1;
|
|
mult_b(15 downto 0) <= sine;
|
|
mult_c <= p1_Q;
|
|
state <= P2I;
|
|
when P2I =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
mult_a <= PORT2;
|
|
mult_b(15 downto 0) <= cosine;
|
|
mult_c <= p2_I;
|
|
state <= P2Q;
|
|
when P2Q =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
mult_a <= PORT2;
|
|
mult_b(15 downto 0) <= sine;
|
|
mult_c <= p2_Q;
|
|
state <= RI;
|
|
when RI =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
mult_a <= REF;
|
|
mult_b(15 downto 0) <= cosine;
|
|
mult_c <= r_I;
|
|
state <= RQ;
|
|
when RQ =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
mult_a <= REF;
|
|
mult_b(15 downto 0) <= sine;
|
|
mult_c <= r_Q;
|
|
-- first result is available
|
|
p1_I <= mult_p;
|
|
state <= SaveP1Q;
|
|
when SaveP1Q =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
p1_Q <= mult_p;
|
|
state <= SaveP2I;
|
|
when SaveP2I =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
p2_I <= mult_p;
|
|
state <= SaveP2Q;
|
|
when SaveP2Q =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
p2_Q <= mult_p;
|
|
state <= SaveRI;
|
|
when SaveRI =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '1';
|
|
r_I <= mult_p;
|
|
state <= SaveRQ;
|
|
when SaveRQ =>
|
|
ACTIVE <= '1';
|
|
DONE <= '0';
|
|
PRE_DONE <= '0';
|
|
mult_enable <= '0';
|
|
r_Q <= mult_p;
|
|
-- from now on accumulate results
|
|
mult_accumulate <= "1";
|
|
phase <= std_logic_vector(unsigned(phase) + unsigned(PHASEINC));
|
|
if sample_cnt < samples_to_take then
|
|
state <= Sampling;
|
|
else
|
|
state <= Ready;
|
|
end if;
|
|
when Ready =>
|
|
ACTIVE <= '1';
|
|
DONE <= '1';
|
|
PRE_DONE <= '1';
|
|
mult_enable <= '0';
|
|
PORT1_I <= p1_I;
|
|
PORT1_Q <= p1_Q;
|
|
PORT2_I <= p2_I;
|
|
PORT2_Q <= p2_Q;
|
|
REF_I <= r_I;
|
|
REF_Q <= r_Q;
|
|
state <= Idle;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
end Behavioral;
|
|
|