Commit e66d3b45 authored by Dimitris Lampridis's avatar Dimitris Lampridis

[hdl] move offset calculation outside of channel generation loop.

This reduces the required resources since we only use one set of adders for all channels (instead of one per).

There is no issue with multiple timestamps arriving simultaneously, since the previous stages serialise the
delivery of timestamps and this stage is fully pipelined, so it can process one timestamp per cycle.
parent d693db67
...@@ -65,7 +65,7 @@ begin ...@@ -65,7 +65,7 @@ begin
regs_in.fifo_cycles_i <= timestamp_i(channel_select).coarse; regs_in.fifo_cycles_i <= timestamp_i(channel_select).coarse;
regs_in.fifo_edge_i <= timestamp_i(channel_select).slope; regs_in.fifo_edge_i <= timestamp_i(channel_select).slope;
regs_in.fifo_seconds_i <= timestamp_i(channel_select).tai; regs_in.fifo_seconds_i <= timestamp_i(channel_select).tai;
regs_in.fifo_channel_i <= std_logic_vector(to_unsigned(channel_select, 4)); regs_in.fifo_channel_i <= '0' & timestamp_i(channel_select).channel;
regs_in.fifo_bins_i <= "000000" & timestamp_i(channel_select).frac; regs_in.fifo_bins_i <= "000000" & timestamp_i(channel_select).frac;
regs_in.fifo_wr_req_i <= f_to_std_logic(fifo_wr(channel_select) = '1' and regs_in.fifo_wr_req_i <= f_to_std_logic(fifo_wr(channel_select) = '1' and
regs_out.fifo_wr_full_o = '0'); regs_out.fifo_wr_full_o = '0');
......
...@@ -61,7 +61,7 @@ entity tdc_ts_addsub is ...@@ -61,7 +61,7 @@ entity tdc_ts_addsub is
a_i : in t_tdc_timestamp; a_i : in t_tdc_timestamp;
b_i : in t_tdc_timestamp; b_i : in t_tdc_timestamp;
valid_o : out std_logic; valid_o : out std_logic;
q_o : out t_tdc_timestamp q_o : out t_tdc_timestamp
); );
...@@ -72,11 +72,12 @@ architecture rtl of tdc_ts_addsub is ...@@ -72,11 +72,12 @@ architecture rtl of tdc_ts_addsub is
constant c_NUM_PIPELINE_STAGES : integer := 4; constant c_NUM_PIPELINE_STAGES : integer := 4;
type t_internal_sum is record type t_internal_sum is record
tai : signed(32 downto 0); tai : signed(32 downto 0);
coarse : signed(31 downto 0); coarse : signed(31 downto 0);
frac : signed(15 downto 0); frac : signed(15 downto 0);
meta : std_logic_vector(31 downto 0); channel : std_logic_vector(2 downto 0);
slope : std_logic; meta : std_logic_vector(31 downto 0);
slope : std_logic;
end record; end record;
type t_internal_sum_array is array (integer range <>) of t_internal_sum; type t_internal_sum_array is array (integer range <>) of t_internal_sum;
...@@ -88,7 +89,7 @@ architecture rtl of tdc_ts_addsub is ...@@ -88,7 +89,7 @@ architecture rtl of tdc_ts_addsub is
signal unf_frac : std_logic; signal unf_frac : std_logic;
signal ovf_coarse : std_logic_vector(1 downto 0); signal ovf_coarse : std_logic_vector(1 downto 0);
signal unf_coarse : std_logic_vector(1 downto 0); signal unf_coarse : std_logic_vector(1 downto 0);
begin -- rtl begin -- rtl
-- Pipeline stage 0: just subtract the two timestamps field by field -- Pipeline stage 0: just subtract the two timestamps field by field
...@@ -100,8 +101,9 @@ begin -- rtl ...@@ -100,8 +101,9 @@ begin -- rtl
elsif(enable_i = '1') then elsif(enable_i = '1') then
pipe(0) <= valid_i; pipe(0) <= valid_i;
sums(0).slope <= a_i.slope; sums(0).channel <= a_i.channel;
sums(0).meta <= a_i.meta; sums(0).slope <= a_i.slope;
sums(0).meta <= a_i.meta;
sums(0).tai <= signed(resize(unsigned(a_i.tai) + unsigned(b_i.tai), 33)); sums(0).tai <= signed(resize(unsigned(a_i.tai) + unsigned(b_i.tai), 33));
sums(0).coarse <= signed(a_i.coarse) + signed(b_i.coarse); sums(0).coarse <= signed(a_i.coarse) + signed(b_i.coarse);
...@@ -120,16 +122,16 @@ begin -- rtl ...@@ -120,16 +122,16 @@ begin -- rtl
p_stage1 : process(clk_i) p_stage1 : process(clk_i)
begin begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if rst_n_i = '0' then if rst_n_i = '0' then
pipe(1) <= '0'; pipe(1) <= '0';
else else
pipe(1) <= pipe(0); pipe(1) <= pipe(0);
sums(1).meta <= sums(0).meta; sums(1) <= sums(0);
sums(1).slope <= sums(0).slope; sums(1) <= sums(0);
sums(1) <= sums(0);
if(ovf_frac = '1') then if(ovf_frac = '1') then
sums(1).frac <= sums(0).frac - g_frac_range; sums(1).frac <= sums(0).frac - g_frac_range;
sums(1).coarse <= sums(0).coarse + 1; sums(1).coarse <= sums(0).coarse + 1;
...@@ -141,7 +143,6 @@ begin -- rtl ...@@ -141,7 +143,6 @@ begin -- rtl
sums(1).coarse <= sums(0).coarse; sums(1).coarse <= sums(0).coarse;
end if; end if;
sums(1).tai <= sums(0).tai;
end if; end if;
end if; end if;
end process; end process;
...@@ -173,7 +174,7 @@ begin -- rtl ...@@ -173,7 +174,7 @@ begin -- rtl
else else
ovf_coarse <= "00"; ovf_coarse <= "00";
end if; end if;
end if; end if;
end if; end if;
end process; end process;
...@@ -188,8 +189,7 @@ begin -- rtl ...@@ -188,8 +189,7 @@ begin -- rtl
else else
pipe(3) <= pipe(2); pipe(3) <= pipe(2);
sums(3).slope <= sums(2).slope; sums(3) <= sums(2);
sums(3).meta <= sums(2).meta;
if(unf_coarse = "10") then if(unf_coarse = "10") then
sums(3).coarse <= sums(2).coarse + g_coarse_range; sums(3).coarse <= sums(2).coarse + g_coarse_range;
...@@ -208,17 +208,16 @@ begin -- rtl ...@@ -208,17 +208,16 @@ begin -- rtl
sums(3).tai <= sums(2).tai; sums(3).tai <= sums(2).tai;
end if; end if;
sums(3).frac <= sums(2).frac;
end if; end if;
end if; end if;
end process; end process;
-- clip the extra bits and output the result -- clip the extra bits and output the result
valid_o <= pipe(c_NUM_PIPELINE_STAGES-1); valid_o <= pipe(c_NUM_PIPELINE_STAGES-1);
q_o.tai <= std_logic_vector(sums(c_NUM_PIPELINE_STAGES-1).tai(31 downto 0)); q_o.tai <= std_logic_vector(sums(c_NUM_PIPELINE_STAGES-1).tai(31 downto 0));
q_o.coarse <= std_logic_vector(sums(c_NUM_PIPELINE_STAGES-1).coarse(31 downto 0)); q_o.coarse <= std_logic_vector(sums(c_NUM_PIPELINE_STAGES-1).coarse(31 downto 0));
q_o.frac <= std_logic_vector(sums(c_NUM_PIPELINE_STAGES-1).frac(11 downto 0)); q_o.frac <= std_logic_vector(sums(c_NUM_PIPELINE_STAGES-1).frac(11 downto 0));
q_o.slope <= sums(c_NUM_PIPELINE_STAGES-1).slope; q_o.slope <= sums(c_NUM_PIPELINE_STAGES-1).slope;
q_o.meta <= sums(c_NUM_PIPELINE_STAGES-1).meta; q_o.meta <= sums(c_NUM_PIPELINE_STAGES-1).meta;
q_o.channel <= sums(c_NUM_PIPELINE_STAGES-1).channel;
end rtl; end rtl;
...@@ -69,20 +69,19 @@ architecture rtl of timestamp_convert_filter is ...@@ -69,20 +69,19 @@ architecture rtl of timestamp_convert_filter is
signal s1_channel, s2_channel, s3_channel : std_logic_vector(2 downto 0); signal s1_channel, s2_channel, s3_channel : std_logic_vector(2 downto 0);
signal s1_edge, s2_edge, s3_edge : std_logic; signal s1_edge, s2_edge, s3_edge : std_logic;
signal s3_ts : t_tdc_timestamp; signal fifo_we, fifo_rd : std_logic;
signal fifo_empty, fifo_rd_d : std_logic;
signal ts_valid_sys : std_logic; signal fifo_d, fifo_q : std_logic_vector(127 downto 0);
signal fifo_we, fifo_rd, fifo_empty, fifo_full, fifo_rd_d : std_logic;
signal fifo_d, fifo_q : std_logic_vector(127 downto 0);
signal ts_fifo_out : t_acam_timestamp; signal ts_fifo_out : t_acam_timestamp;
signal ts_valid_preoffset, ts_ready_preoffset : std_logic_vector(4 downto 0); signal ts_valid_postoffset : std_logic;
signal ts_valid_postoffset, ts_valid_postoffset_with_seq : std_logic_vector(4 downto 0); signal ts_valid_preseq : std_logic_vector(4 downto 0);
signal ts_preoffset, ts_postoffset : t_tdc_timestamp_array(4 downto 0); signal ts_valid_postseq : std_logic_vector(4 downto 0);
signal ts_postoffset_with_seq : t_tdc_timestamp_array(4 downto 0); signal ts_preoffset, ts_postoffset : t_tdc_timestamp;
signal s1_meta, s2_meta, s3_meta : std_logic_vector(31 downto 0); signal ts_offset : t_tdc_timestamp;
signal ts_preseq, ts_postseq : t_tdc_timestamp_array(4 downto 0);
signal s1_meta, s2_meta, s3_meta : std_logic_vector(31 downto 0);
function f_pack_acam_timestamp (ts : t_acam_timestamp) return std_logic_vector is function f_pack_acam_timestamp (ts : t_acam_timestamp) return std_logic_vector is
variable rv : std_logic_vector(127 downto 0); variable rv : std_logic_vector(127 downto 0);
...@@ -96,48 +95,48 @@ architecture rtl of timestamp_convert_filter is ...@@ -96,48 +95,48 @@ architecture rtl of timestamp_convert_filter is
return rv; return rv;
end f_pack_acam_timestamp; end f_pack_acam_timestamp;
function f_unpack_acam_timestamp ( p : std_logic_vector ) return t_acam_timestamp is function f_unpack_acam_timestamp (p : std_logic_vector) return t_acam_timestamp is
variable ts : t_acam_timestamp; variable ts : t_acam_timestamp;
begin begin
ts.tai := p(31 downto 0); ts.tai := p(31 downto 0);
ts.coarse := p(63 downto 32); ts.coarse := p(63 downto 32);
ts.n_bins := p(80 downto 64); ts.n_bins := p(80 downto 64);
ts.channel := p(83 downto 81); ts.channel := p(83 downto 81);
ts.slope := p(84); ts.slope := p(84);
ts.meta := p(116 downto 85); ts.meta := p(116 downto 85);
return ts; return ts;
end f_unpack_acam_timestamp; end f_unpack_acam_timestamp;
begin begin
fifo_d <= f_pack_acam_timestamp(ts_i); fifo_d <= f_pack_acam_timestamp(ts_i);
fifo_we <= ts_valid_i; fifo_we <= ts_valid_i;
U_Sync_FIFO: generic_async_fifo U_Sync_FIFO : generic_async_fifo
generic map ( generic map (
g_data_width => 128, g_data_width => 128,
g_size => 16, g_size => 16,
g_show_ahead => false) g_show_ahead => FALSE)
port map ( port map (
rst_n_i => rst_sys_n_i, rst_n_i => rst_sys_n_i,
clk_wr_i => clk_tdc_i, clk_wr_i => clk_tdc_i,
d_i => fifo_d, d_i => fifo_d,
we_i => fifo_we, we_i => fifo_we,
clk_rd_i => clk_sys_i, clk_rd_i => clk_sys_i,
q_o => fifo_q, q_o => fifo_q,
rd_i => fifo_rd, rd_i => fifo_rd,
rd_empty_o => fifo_empty); rd_empty_o => fifo_empty);
ts_fifo_out <= f_unpack_acam_timestamp(fifo_q); ts_fifo_out <= f_unpack_acam_timestamp(fifo_q);
fifo_rd <= not fifo_empty; fifo_rd <= not fifo_empty;
process(clk_sys_i) process(clk_sys_i)
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' then if rst_sys_n_i = '0' then
s1_valid <= '0'; s1_valid <= '0';
s2_valid <= '0'; s2_valid <= '0';
s3_valid <= '0'; s3_valid <= '0';
fifo_rd_d <= '0'; fifo_rd_d <= '0';
else else
...@@ -161,7 +160,7 @@ architecture rtl of timestamp_convert_filter is ...@@ -161,7 +160,7 @@ architecture rtl of timestamp_convert_filter is
s2_tai <= s1_tai; s2_tai <= s1_tai;
s2_edge <= s1_edge; s2_edge <= s1_edge;
s2_channel <= s1_channel; s2_channel <= s1_channel;
s2_meta <= s1_meta; s2_meta <= s1_meta;
s2_valid <= s1_valid; s2_valid <= s1_valid;
-- stage 3: roll-over coarse -- stage 3: roll-over coarse
...@@ -176,7 +175,7 @@ architecture rtl of timestamp_convert_filter is ...@@ -176,7 +175,7 @@ architecture rtl of timestamp_convert_filter is
s3_tai <= s2_tai; s3_tai <= s2_tai;
end if; end if;
s3_meta <= s2_meta; s3_meta <= s2_meta;
s3_frac <= s2_frac; s3_frac <= s2_frac;
s3_edge <= s2_edge; s3_edge <= s2_edge;
s3_channel <= s2_channel; s3_channel <= s2_channel;
...@@ -185,12 +184,25 @@ architecture rtl of timestamp_convert_filter is ...@@ -185,12 +184,25 @@ architecture rtl of timestamp_convert_filter is
end if; end if;
end process; end process;
s3_ts.frac <= std_logic_vector(s3_frac); ts_preoffset.frac <= std_logic_vector(s3_frac);
s3_ts.coarse <= std_logic_vector(s3_coarse); ts_preoffset.coarse <= std_logic_vector(s3_coarse);
s3_ts.tai <= std_logic_vector(s3_tai); ts_preoffset.tai <= std_logic_vector(s3_tai);
s3_ts.slope <= s3_edge; ts_preoffset.slope <= s3_edge;
s3_ts.channel <= s3_channel; ts_preoffset.channel <= s3_channel;
s3_ts.meta <= s3_meta; ts_preoffset.meta <= s3_meta;
ts_offset <= ts_offset_i(to_integer(unsigned(s3_channel)));
U_Offset_Adder : entity work.tdc_ts_addsub
port map (
clk_i => clk_sys_i,
rst_n_i => rst_sys_n_i,
valid_i => s3_valid,
enable_i => '1',
a_i => ts_preoffset,
b_i => ts_offset,
valid_o => ts_valid_postoffset,
q_o => ts_postoffset);
gen_channels : for i in 0 to 4 generate gen_channels : for i in 0 to 4 generate
...@@ -199,17 +211,16 @@ architecture rtl of timestamp_convert_filter is ...@@ -199,17 +211,16 @@ architecture rtl of timestamp_convert_filter is
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' or enable_i(i) = '0' then if rst_sys_n_i = '0' or enable_i(i) = '0' then
ts_valid_preoffset(i) <= '0'; ts_valid_preseq(i) <= '0';
channels(i).s1_valid <= '0'; channels(i).s1_valid <= '0';
channels(i).s2_valid <= '0'; channels(i).s2_valid <= '0';
channels(i).last_valid <= '0'; channels(i).last_valid <= '0';
else else
channels(i).s1_valid <= '0'; channels(i).s1_valid <= '0';
if s3_valid = '1' and unsigned(s3_channel) = i then if ts_valid_postoffset = '1' and unsigned(ts_postoffset.channel) = i then
if (ts_postoffset.slope = '1') then -- rising edge
if (s3_ts.slope = '1') then -- rising edge channels(i).last_ts <= ts_postoffset;
channels(i).last_ts <= s3_ts;
channels(i).last_valid <= '1'; channels(i).last_valid <= '1';
channels(i).s1_valid <= '0'; channels(i).s1_valid <= '0';
else else
...@@ -217,13 +228,16 @@ architecture rtl of timestamp_convert_filter is ...@@ -217,13 +228,16 @@ architecture rtl of timestamp_convert_filter is
channels(i).s1_valid <= '1'; channels(i).s1_valid <= '1';
end if; end if;
channels(i).s1_delta_coarse <= unsigned(s3_ts.coarse) - unsigned(channels(i).last_ts.coarse); channels(i).s1_delta_coarse <=
channels(i).s1_delta_tai <= unsigned(s3_ts.tai) - unsigned(channels(i).last_ts.tai); unsigned(ts_postoffset.coarse) - unsigned(channels(i).last_ts.coarse);
end if;
channels(i).s1_delta_tai <=
unsigned(ts_postoffset.tai) - unsigned(channels(i).last_ts.tai);
end if;
if channels(i).s1_delta_coarse(31) = '1' then if channels(i).s1_delta_coarse(31) = '1' then
channels(i).s2_delta_coarse <= channels(i).s1_delta_coarse + to_unsigned(125000000, 32); channels(i).s2_delta_coarse <=
channels(i).s1_delta_coarse + to_unsigned(125000000, 32);
channels(i).s2_delta_tai <= channels(i).s1_delta_tai - 1; channels(i).s2_delta_tai <= channels(i).s1_delta_tai - 1;
else else
channels(i).s2_delta_coarse <= channels(i).s1_delta_coarse; channels(i).s2_delta_coarse <= channels(i).s1_delta_coarse;
...@@ -235,19 +249,19 @@ architecture rtl of timestamp_convert_filter is ...@@ -235,19 +249,19 @@ architecture rtl of timestamp_convert_filter is
if channels(i).s2_valid = '1' then if channels(i).s2_valid = '1' then
if channels(i).s2_delta_tai = 0 and channels(i).s2_delta_coarse >= 12 then if channels(i).s2_delta_tai = 0 and channels(i).s2_delta_coarse >= 12 then
ts_preoffset(i).tai <= channels(i).last_ts.tai; ts_preseq(i).tai <= channels(i).last_ts.tai;
ts_preoffset(i).coarse <= channels(i).last_ts.coarse; ts_preseq(i).coarse <= channels(i).last_ts.coarse;
ts_preoffset(i).frac <= channels(i).last_ts.frac; ts_preseq(i).frac <= channels(i).last_ts.frac;
ts_preoffset(i).channel <= channels(i).last_ts.channel; ts_preseq(i).channel <= channels(i).last_ts.channel;
ts_preoffset(i).slope <= channels(i).last_ts.slope; ts_preseq(i).slope <= channels(i).last_ts.slope;
ts_preoffset(i).meta <= channels(i).last_ts.meta; ts_preseq(i).meta <= channels(i).last_ts.meta;
ts_valid_preoffset(i) <= '1'; ts_valid_preseq(i) <= '1';
else else
ts_valid_preoffset(i) <= '0'; ts_valid_preseq(i) <= '0';
end if; end if;
else else
ts_valid_preoffset(i) <= '0'; ts_valid_preseq(i) <= '0';
end if; end if;
end if; end if;
...@@ -260,43 +274,32 @@ architecture rtl of timestamp_convert_filter is ...@@ -260,43 +274,32 @@ architecture rtl of timestamp_convert_filter is
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' or enable_i(i) = '0' then if rst_sys_n_i = '0' or enable_i(i) = '0' then
ts_valid_preoffset(i) <= '0'; ts_valid_preseq(i) <= '0';
else else
if s3_valid = '1' and unsigned(s3_channel) = i then if ts_valid_postoffset = '1' and unsigned(ts_postoffset.channel) = i then
ts_valid_preoffset(i) <= '1'; ts_valid_preseq(i) <= '1';
ts_preoffset(i) <= s3_ts; ts_preseq(i) <= ts_postoffset;
else else
ts_valid_preoffset(i) <= '0'; ts_valid_preseq(i) <= '0';
end if; end if;
end if; end if;
end if; end if;
end process p_fsm; end process p_fsm;
end generate gen_without_pwidth_filter; end generate gen_without_pwidth_filter;
U_Offset_Adder : entity work.tdc_ts_addsub
port map (
clk_i => clk_sys_i,
rst_n_i => rst_sys_n_i,
valid_i => ts_valid_preoffset(i),
enable_i => enable_i(i),
a_i => ts_preoffset(i),
b_i => ts_offset_i(i),
valid_o => ts_valid_postoffset(i),
q_o => ts_postoffset(i));
p_seq_count : process(clk_sys_i) is p_seq_count : process(clk_sys_i) is
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' or enable_i(i) = '0' or reset_seq_i(i) = '1' then if rst_sys_n_i = '0' or enable_i(i) = '0' or reset_seq_i(i) = '1' then
channels(i).seq <= (others => '0'); channels(i).seq <= (others => '0');
else else
if ts_valid_postoffset(i) = '1' then if ts_valid_preseq(i) = '1' then
channels(i).seq <= channels(i).seq + 1; channels(i).seq <= channels(i).seq + 1;
ts_valid_postoffset_with_seq(i) <= '1'; ts_valid_postseq(i) <= '1';
ts_postoffset_with_seq(i) <= ts_postoffset(i); ts_postseq(i) <= ts_preseq(i);
ts_postoffset_with_seq(i).seq <= std_logic_vector(channels(i).seq); ts_postseq(i).seq <= std_logic_vector(channels(i).seq);
else else
ts_valid_postoffset_with_seq(i) <= '0'; ts_valid_postseq(i) <= '0';
end if; end if;
end if; end if;
end if; end if;
...@@ -314,27 +317,21 @@ architecture rtl of timestamp_convert_filter is ...@@ -314,27 +317,21 @@ architecture rtl of timestamp_convert_filter is
end if; end if;
if raw_enable_i(i) = '1' then if raw_enable_i(i) = '1' then
--if ts_valid_sys = '1' and unsigned(ts_latched.channel) = i then --if ts_valid_sys = '1' and unsigned(ts_latched.channel) = i then
-- ts_valid_o(i) <= '1'; -- ts_valid_o(i) <= '1';
-- ts_o(i).raw <= ts_latched.raw; -- ts_o(i).raw <= ts_latched.raw;
--end if; --end if;
else else
if ts_valid_postseq(i) = '1' then
if ts_valid_postoffset_with_seq(i) = '1' then
ts_valid_o(i) <= '1'; ts_valid_o(i) <= '1';
ts_o(i) <= ts_postoffset_with_seq(i); ts_o(i) <= ts_postseq(i);
end if; end if;
end if; end if;
end if; end if;
end if; end if;
end process; end process;
end generate gen_channels; end generate gen_channels;
end rtl; end rtl;
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