controller: done, untested

parent 8b4fd4d7
......@@ -62,9 +62,11 @@ entity tdc is
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0)
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- Debug interface.
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic
-- TODO
);
end entity;
......@@ -91,6 +93,8 @@ signal oc_ready : std_logic;
signal oc_freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal oc_store : std_logic;
signal oc_sfreq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal freeze_ack : std_logic;
begin
cmp_channelbank: tdc_channelbank
generic map(
......@@ -172,6 +176,10 @@ begin
oc_ready_i => oc_ready,
oc_freq_i => oc_freq,
oc_store_o => oc_store,
oc_sfreq_i => oc_sfreq
oc_sfreq_i => oc_sfreq,
freeze_req_i => freeze_req_i,
freeze_ack_o => freeze_ack
);
freeze_ack_o <= freeze_ack;
end architecture;
......@@ -54,7 +54,10 @@ entity tdc_controller is
oc_ready_i : in std_logic;
oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_o : out std_logic;
oc_sfreq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
oc_sfreq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic
);
end entity;
......@@ -73,11 +76,25 @@ signal ha_inc : std_logic;
signal ha_last : std_logic;
signal ha_sel : std_logic;
signal acc : std_logic_vector(g_FP_COUNT-1 downto 0);
signal acc_reset : std_logic;
signal acc_en : std_logic;
signal mul : std_logic_vector(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto 0);
signal mul_d1 : std_logic_vector(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto 0);
signal div_start : std_logic;
signal div_ready : std_logic;
signal div_quotient : std_logic_vector(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto 0);
signal div_qsat : std_logic_vector(g_FP_COUNT-1 downto 0);
type t_state is (
-- startup calibration
SC_NEWCHANNEL, SC_CLEARHIST, SC_READ, SC_UPDATE, SC_STOREF0,
-- online calibration
OC_STARTM, OC_WAITM, OC_NEXTCHANNEL
OC_STARTM, OC_WAITM, OC_WAITMUL1, OC_WAITMUL2, OC_STARTDIV, OC_WAITDIV, OC_WRITELUT, OC_NEXTCHANNEL,
-- freeze state (transfer control to debug interface)
FREEZE
);
signal state: t_state;
......@@ -125,6 +142,61 @@ begin
his_d_o <= (his_d_o'range => '0') when (ha_sel = '1')
else std_logic_vector(unsigned(his_d_i) + 1);
-- accumulator
process(clk_i)
begin
if rising_edge(clk_i) then
if acc_reset = '1' then
acc <= (acc'range => '0');
elsif acc_en = '1' then
acc <= std_logic_vector(unsigned(acc) + unsigned(his_d_i));
end if;
end if;
end process;
-- multiplier
process(clk_i)
begin
if rising_edge(clk_i) then
mul <= std_logic_vector(unsigned(acc) * unsigned(oc_sfreq_i));
mul_d1 <= mul;
end if;
end process;
-- divider
cmp_divider: tdc_divider
generic map(
g_WIDTH => g_FP_COUNT+g_FCOUNTER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
start_i => div_start,
dividend_i => mul_d1,
divisor_i(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto g_FCOUNTER_WIDTH)
=> (others => '0'),
divisor_i(g_FCOUNTER_WIDTH-1 downto 0)
=> oc_freq_i,
ready_o => div_ready,
quotient_o => div_quotient,
remainder_o => open
);
process(div_quotient)
begin
if div_quotient(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto g_FP_COUNT)
= (g_FCOUNTER_WIDTH-1 downto 0 => '0') then
div_qsat <= div_quotient(g_FP_COUNT-1 downto 0);
else -- saturate
div_qsat <= (div_qsat'range => '1');
end if;
end process;
-- generate LUT address and write data
lut_a_o <= std_logic_vector(unsigned(ha_count) + 1);
lut_d_o <= div_qsat;
-- main FSM
process(clk_i)
begin
......@@ -162,10 +234,35 @@ begin
state <= OC_WAITM;
when OC_WAITM =>
if oc_ready_i = '1' then
state <= OC_WAITMUL1;
end if;
when OC_WAITMUL1 =>
state <= OC_WAITMUL2;
when OC_WAITMUL2 =>
state <= OC_STARTDIV;
when OC_STARTDIV =>
state <= OC_WAITDIV;
when OC_WAITDIV =>
if div_ready = '1' then
state <= OC_WRITELUT;
end if;
when OC_WRITELUT =>
if ha_last = '1' then
state <= OC_NEXTCHANNEL;
else
state <= OC_WAITMUL1;
end if;
when OC_NEXTCHANNEL =>
if freeze_req_i = '1' then
state <= FREEZE;
else
state <= OC_STARTM;
end if;
when FREEZE =>
if freeze_req_i = '0' then
state <= OC_STARTM;
end if;
end case;
end if;
end if;
......@@ -182,18 +279,25 @@ begin
ha_inc <= '0';
ha_sel <= '0';
acc_reset <= '0';
acc_en <= '0';
div_start <= '0';
next_o <= '0';
calib_sel_o <= '0';
lut_we_o <= '0';
his_we_o <= '0';
oc_start_o <= '0';
oc_store_o <= '0';
freeze_ack_o <= '0';
case state is
when SC_NEWCHANNEL =>
hc_reset <= '1';
ha_reset <= '1';
when SC_CLEARHIST =>
calib_sel_o <= '1';
ha_inc <= '1';
ha_sel <= '1';
his_we_o <= '1';
......@@ -214,13 +318,30 @@ begin
when OC_STARTM =>
oc_start_o <= '1';
ha_reset <= '1';
acc_reset <= '1';
when OC_WAITM =>
null;
when OC_WAITMUL1 =>
null;
when OC_WAITMUL2 =>
null;
when OC_STARTDIV =>
div_start <= '1';
when OC_WAITDIV =>
null;
when OC_WRITELUT =>
lut_we_o <= '1';
acc_en <= '1';
ha_inc <= '1';
when OC_NEXTCHANNEL =>
next_o <= '1';
if last_i = '1' then
ready_p <= '1';
end if;
when FREEZE =>
freeze_ack_o <= '1';
end case;
end process;
end architecture;
......@@ -52,7 +52,10 @@ component tdc_controller is
oc_ready_i : in std_logic;
oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_o : out std_logic;
oc_sfreq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
oc_sfreq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic
);
end component;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment