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