controller: done, untested

parent 8b4fd4d7
...@@ -62,9 +62,11 @@ entity tdc is ...@@ -62,9 +62,11 @@ entity tdc is
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0); detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_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); 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. -- Debug interface.
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic
-- TODO -- TODO
); );
end entity; end entity;
...@@ -91,6 +93,8 @@ signal oc_ready : std_logic; ...@@ -91,6 +93,8 @@ signal oc_ready : std_logic;
signal oc_freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0); signal oc_freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal oc_store : std_logic; signal oc_store : std_logic;
signal oc_sfreq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0); signal oc_sfreq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal freeze_ack : std_logic;
begin begin
cmp_channelbank: tdc_channelbank cmp_channelbank: tdc_channelbank
generic map( generic map(
...@@ -172,6 +176,10 @@ begin ...@@ -172,6 +176,10 @@ begin
oc_ready_i => oc_ready, oc_ready_i => oc_ready,
oc_freq_i => oc_freq, oc_freq_i => oc_freq,
oc_store_o => oc_store, 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; end architecture;
...@@ -54,7 +54,10 @@ entity tdc_controller is ...@@ -54,7 +54,10 @@ entity tdc_controller is
oc_ready_i : in std_logic; oc_ready_i : in std_logic;
oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0); oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_o : out std_logic; 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; end entity;
...@@ -73,11 +76,25 @@ signal ha_inc : std_logic; ...@@ -73,11 +76,25 @@ signal ha_inc : std_logic;
signal ha_last : std_logic; signal ha_last : std_logic;
signal ha_sel : 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 ( type t_state is (
-- startup calibration -- startup calibration
SC_NEWCHANNEL, SC_CLEARHIST, SC_READ, SC_UPDATE, SC_STOREF0, SC_NEWCHANNEL, SC_CLEARHIST, SC_READ, SC_UPDATE, SC_STOREF0,
-- online calibration -- 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; signal state: t_state;
...@@ -125,6 +142,61 @@ begin ...@@ -125,6 +142,61 @@ begin
his_d_o <= (his_d_o'range => '0') when (ha_sel = '1') his_d_o <= (his_d_o'range => '0') when (ha_sel = '1')
else std_logic_vector(unsigned(his_d_i) + 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 -- main FSM
process(clk_i) process(clk_i)
begin begin
...@@ -162,10 +234,35 @@ begin ...@@ -162,10 +234,35 @@ begin
state <= OC_WAITM; state <= OC_WAITM;
when OC_WAITM => when OC_WAITM =>
if oc_ready_i = '1' then 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; state <= OC_NEXTCHANNEL;
else
state <= OC_WAITMUL1;
end if; end if;
when OC_NEXTCHANNEL => 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; state <= OC_STARTM;
end if;
end case; end case;
end if; end if;
end if; end if;
...@@ -182,18 +279,25 @@ begin ...@@ -182,18 +279,25 @@ begin
ha_inc <= '0'; ha_inc <= '0';
ha_sel <= '0'; ha_sel <= '0';
acc_reset <= '0';
acc_en <= '0';
div_start <= '0';
next_o <= '0'; next_o <= '0';
calib_sel_o <= '0'; calib_sel_o <= '0';
lut_we_o <= '0'; lut_we_o <= '0';
his_we_o <= '0'; his_we_o <= '0';
oc_start_o <= '0'; oc_start_o <= '0';
oc_store_o <= '0'; oc_store_o <= '0';
freeze_ack_o <= '0';
case state is case state is
when SC_NEWCHANNEL => when SC_NEWCHANNEL =>
hc_reset <= '1'; hc_reset <= '1';
ha_reset <= '1'; ha_reset <= '1';
when SC_CLEARHIST => when SC_CLEARHIST =>
calib_sel_o <= '1';
ha_inc <= '1'; ha_inc <= '1';
ha_sel <= '1'; ha_sel <= '1';
his_we_o <= '1'; his_we_o <= '1';
...@@ -214,13 +318,30 @@ begin ...@@ -214,13 +318,30 @@ begin
when OC_STARTM => when OC_STARTM =>
oc_start_o <= '1'; oc_start_o <= '1';
ha_reset <= '1';
acc_reset <= '1';
when OC_WAITM => when OC_WAITM =>
null; 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 => when OC_NEXTCHANNEL =>
next_o <= '1'; next_o <= '1';
if last_i = '1' then if last_i = '1' then
ready_p <= '1'; ready_p <= '1';
end if; end if;
when FREEZE =>
freeze_ack_o <= '1';
end case; end case;
end process; end process;
end architecture; end architecture;
...@@ -52,7 +52,10 @@ component tdc_controller is ...@@ -52,7 +52,10 @@ component tdc_controller is
oc_ready_i : in std_logic; oc_ready_i : in std_logic;
oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0); oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_o : out std_logic; 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; 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