* Add diagram * Modify counters of PMOD-AD1 and PMOD-DA3 controllers to use less bits * Increase factor width to 5 bits - Highest bit is truncated * Add download directory to git repo
306 lines
10 KiB
VHDL
306 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(DAC_DATA_WIDTH) => open, --Truncate result
|
|
data_out(DAC_DATA_WIDTH-1 downto 0) => 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; |