labor-mst/src/feedback_loop.vhd
Greek 89182e8060 * Route sclk for ADC/DAC through controller entity itself
* Remove ADC/DAC input/outputs constraints
* Fix PMOD-AS1 Controller
	- Invert SCLK
2020-04-29 14:01:01 +02:00

305 lines
10 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.typedef_package.all;
-- Architecture
-- --- ---------- ------ ------- ---
--->|ADC|--->|Delay Line|--->|Scaler|--->|ADD/SUB|--->|DAC|--->
-- --- ---------- ------ ------- ---
-- ^
-- --- ----- --- |
--->|ADC|-------------------->|Latch|->| | |
-- --- ----- |MUX|--
-- GND--->| |
-- ---
-- Feedback Loop
-- This entity implements the feedback loop as defined above.
-- In addition to that, this entity latches and provides various max values that can be used for debug
-- purposes.
entity feedback_loop is
port (
clk : in std_logic;
reset : in std_logic;
adc_data_in1 : in std_logic; -- PMOD-AD1
adc_data_in2 : in std_logic; -- PMOD-AD1
adc_cs_n : out std_logic; -- PMOD-AD1
adc_sclk : out std_logic; -- PMOD-AD1
dac_data_out : out std_logic; -- PMOD-DA3
dac_cs_n : out std_logic; -- PMOD-DA3
dac_ldac : out std_logic; -- PMOD-DA3
dac_sclk : out std_logic; -- PMOD-DA3
-- DYNAMIC CONFIGURATION
addsub_mode : in std_logic; -- (1=ADD, 0=SUB)
add_input_mux : in std_logic; -- (1=ADC Input 2, 0=GND)
delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); -- unsigned delay clock count
factor : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- 1Q3 Fixed Point
-- DEBUG
reset_debug : in std_logic;
adc_data1_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
adc_data2_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
scaler_max : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
dac_max : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0)
);
end entity;
architecture arch of feedback_loop is
--*****SIGNAL DECLARATION*****
signal adc_data1, adc_data2 : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
signal adc_done : std_logic := '0';
--*****COMPONENT DECLARATION*****
component pmod_ad1_ctrl is
generic(
TRANSFER_CLK_COUNT : integer := 16;
DELAY_CLK_CNT : integer := 2;
DATA_WIDTH : integer := 12
);
port (
clk : in std_logic;
reset : in std_logic;
enable : in std_logic;
sdata1 : in std_logic; -- PMOD-AD1
sdata2 : in std_logic; -- PMOD-AD1
sclk : out std_logic;-- PMOD-AD1
cs_n : out std_logic;-- PMOD-AD1
data1 : out std_logic_vector(DATA_WIDTH-1 downto 0);
data2 : out std_logic_vector(DATA_WIDTH-1 downto 0);
done : out std_logic
);
end component;
component pmod_da3_ctrl is
generic(
TRANSFER_CLK_COUNT : integer := 16;
DATA_WIDTH : integer := 16
);
port (
clk : in std_logic;
reset : in std_logic;
start : in std_logic;
data : in std_logic_vector(DATA_WIDTH-1 downto 0);
cs_n : out std_logic;-- PMOD-DA3
sdata : out std_logic;-- PMOD-DA3
ldac : out std_logic;-- PMOD-DA3
sclk : out std_logic;-- PMOD-DA3
done : out std_logic
);
end component;
component scaler is
generic (
DATA_WIDTH : integer := 12;
FACTOR_WIDTH : integer := 4;
PIPELINE_STAGES : integer := 1
);
port (
clk : in std_logic;
data_in : in std_logic_vector(DATA_WIDTH-1 downto 0);
factor : in std_logic_vector(FACTOR_WIDTH-1 downto 0);
data_out : out std_logic_vector(DATA_WIDTH+FACTOR_WIDTH-1 downto 0)
);
end component;
component addsub is
generic (
PIPELINE_STAGES : integer := 1;
DATA_WIDTH : integer := 16
);
port (
clk : in std_logic;
reset : in std_logic;
mode : in std_logic;
cap : in std_logic;
A : in std_logic_vector(DATA_WIDTH-1 downto 0);
B : in std_logic_vector(DATA_WIDTH-1 downto 0);
RES : out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end component;
component delay_line is
generic (
DATA_WIDTH : integer := 12;
DELAY_WIDTH : integer := 8;
MAX_DELAY : integer := 200
);
port (
clk : in std_logic;
reset : in std_logic;
delay : in std_logic_vector(DELAY_WIDTH-1 downto 0);
data_in : in std_logic_vector(DATA_WIDTH-1 downto 0);
data_out : out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end component;
--*****SIGNAL DECLARATION*****
signal delay_out : std_logic_vector(ADC_DATA_WIDTH downto 0) := (others => '0');
signal latch_out : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
signal scaler_out, addsub_out, inputA : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
signal scaler_done, addsub_done : std_logic := '0';
begin
--*****STAGE I*****
adc_inst : pmod_ad1_ctrl
generic map(
TRANSFER_CLK_COUNT => ADC_TRANSFER_CLK_COUNT,
DELAY_CLK_CNT => ADC_DELAY_CLK_CNT,
DATA_WIDTH => ADC_DATA_WIDTH
)
port map(
clk => clk,
reset => reset,
enable => '1',
sdata1 => adc_data_in1,
sdata2 => adc_data_in2,
sclk => adc_sclk,
cs_n => adc_cs_n,
data1 => adc_data1,
data2 => adc_data2,
done => adc_done
);
--*****STAGE II*****
delay_line_inst : delay_line
generic map(
DATA_WIDTH => ADC_DATA_WIDTH+1,
DELAY_WIDTH => DELAY_WIDTH,
MAX_DELAY => MAX_DELAY
)
port map(
clk => clk,
reset => reset,
delay => delay,
data_in => (adc_done & adc_data1),
data_out => delay_out
);
--*****STAGE III*****
scaler_inst : scaler
generic map(
DATA_WIDTH => ADC_DATA_WIDTH,
FACTOR_WIDTH => FACTOR_WIDTH,
PIPELINE_STAGES => 1
)
port map(
clk => clk,
data_in => delay_out(ADC_DATA_WIDTH-1 downto 0),
factor => factor,
data_out => scaler_out
);
process(clk)
begin
if (rising_edge(clk)) then
if (reset = '1') then
scaler_done <= '0';
else
scaler_done <= delay_out(ADC_DATA_WIDTH);
end if;
end if;
end process;
latch : process(clk)
begin
if (rising_edge(clk)) then
if (reset = '1') then
latch_out <= (others => '0');
elsif (adc_done) then
latch_out <= adc_data2;
end if;
end if;
end process;
--*****STAGE IV*****
mux: process(all)
begin
if (add_input_mux = '1') then
inputA <= latch_out & "0000";
else
inputA <= (others => '0');
end if;
end process;
addsub_inst : addsub
generic map(
PIPELINE_STAGES => 1,
DATA_WIDTH => DAC_DATA_WIDTH
)
port map(
clk => clk,
reset => reset,
mode => addsub_mode,
cap => add_input_mux,
A => inputA,
B => scaler_out,
RES => addsub_out
);
process(clk)
begin
if (rising_edge(clk)) then
if (reset = '1') then
addsub_done <= '0';
else
addsub_done <= scaler_done;
end if;
end if;
end process;
--*****STAGE V*****
dac_inst : pmod_da3_ctrl
generic map(
TRANSFER_CLK_COUNT => DAC_TRANSFER_CLK_COUNT,
DATA_WIDTH => DAC_DATA_WIDTH
)
port map(
clk => clk,
reset => reset,
start => addsub_done,
data => addsub_out,
cs_n => dac_cs_n,
sdata => dac_data_out,
ldac => dac_ldac,
sclk => dac_sclk,
done => open
);
--*****DEBUG*****
process(clk)
begin
if (rising_edge(clk)) then
if (reset = '1' or reset_debug = '1') then
adc_data1_max <= (others => '0');
adc_data2_max <= (others => '0');
dac_max <= (others => '0');
scaler_max <= (others => '0');
-- ADC MAX VALUES
elsif (adc_done = '1') then
if (to_integer(unsigned(adc_data1)) >= to_integer(unsigned(adc_data1_max))) then
adc_data1_max <= adc_data1;
elsif (to_integer(unsigned(adc_data2)) >= to_integer(unsigned(adc_data2_max))) then
adc_data2_max <= adc_data2;
end if;
-- DAC MAX VALUES
elsif (addsub_done = '1') then
if (to_integer(unsigned(addsub_out)) >= to_integer(unsigned(dac_max))) then
dac_max <= addsub_out;
end if;
-- SCALER MAX VALUES
elsif (scaler_done = '1') then
if (to_integer(unsigned(scaler_out)) >= to_integer(unsigned(scaler_max))) then
scaler_max <= scaler_out;
end if;
end if;
end if;
end process;
end architecture;