Commit 9e4aa942 authored by Mathias Kreider's avatar Mathias Kreider

TLU: V3 - complete rework of capture logic

parent 0c1b0fb9
files = ["tlu_pkg.vhd",
"tlu_fsm.vhd",
"tlu.vhd"]
This diff is collapsed.
--! @file wr_tlu.vhd
--! @brief Timestamp latch unit for WR core with WB b4 interface
--!
--! Copyright (C) 2011-2012 GSI Helmholtz Centre for Heavy Ion Research GmbH
--!
--!----------------------------------------------------------------------------
--1
--! @author Mathias Kreider <m.kreider@gsi.de>
--!
--! @bug No know bugs.
--!
--------------------------------------------------------------------------------
--! This library is free software; you can redistribute it and/or
--! modify it under the terms of the GNU Lesser General Public
--! License as published by the Free Software Foundation; either
--! version 3 of the License, or (at your option) any later version.
--!
--! This library is distributed in the hope that it will be useful,
--! but WITHOUT ANY WARRANTY; without even the implied warranty of
--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
--! Lesser General Public License for more details.
--!
--! You should have received a copy of the GNU Lesser General Public
--! License along with this library. If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------------------
--! Standard library
library IEEE;
--! Standard packages
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library work;
use work.wishbone_pkg.all;
use work.gencores_pkg.all;
use work.tlu_pkg.all;
entity wr_tlu_fsm is
generic( g_offset : natural);
port (
clk_ref_i : in std_logic; -- tranceiver clock domain
rst_ref_n_i : in std_logic;
trigger_i : in t_trigger; -- trigger vector for latch. meant to be used with 8bits from
tm_tai_cyc_i : in std_logic_vector(63 downto 0); -- TAI Timestamp in 8ns cycles
captured_time_o : out std_logic_vector(64 + 3 - 1 downto 0);
valid_o : out std_logic;
-- sys clk domain signals, sync them first
stable_i : t_wishbone_data;
active_i : std_logic;
edge_i : std_logic
);
end wr_tlu_fsm;
architecture behavioral of wr_tlu_fsm is
function f_count(input : std_logic_vector; thing2count : std_logic) return natural is
variable result, i : natural;
begin
result := 0;
for i in input'left downto 0 loop
if input(i) = thing2count then
result := result + 1;
end if;
end loop;
return result;
end f_count;
function f_countUnbroken(input : std_logic_vector; thing2count : std_logic; dir : string := "lsb") return natural is
variable result, i : natural;
begin
result := 0;
if(dir = "lsb") then
for i in 0 to input'left loop
if input(i) = thing2count then
result := result + 1;
else
exit;
end if;
end loop;
else
for i in input'left downto 0 loop
if input(i) = thing2count then
result := result + 1;
else
exit;
end if;
end loop;
end if;
return result;
end f_countUnbroken;
-------------------------------------------------------------------------------
constant c_datbits : natural := 72;
type t_state is (e_LOW, e_TRANS_RISE, e_HIGH, e_TRANS_FALL);
signal r_state : t_state;
signal r_wed0,
r_wed1 : std_logic;
signal s_wed_start : std_logic;
signal r_timeshift : unsigned(31 downto 0);
signal r_cnt : unsigned(31 downto 0);
signal r_cntUnbr : unsigned(31 downto 0);
signal s_add_a,
s_add_b,
s_add_x : std_logic_vector(c_datbits-1 downto 0);
----------------------------------------------------------------------------
begin -- behavioral
----------------------------------------------------------------------------
--Adder
----------------------------------------------------------------------------
-- ref cycle count * 8 => ns. Pad to 72 bits ( 9 * 8) for adder stages
s_add_a <= "00000" & tm_tai_cyc_i & "000";
--negate timeshift value to create Ones Clomplement for subtraction
s_add_b <= x"ffffffffff" & not std_logic_vector(r_timeshift);
--take ns value from result for output to fifo
captured_time_o <= s_add_x(66 downto 0);
correct_time : gc_big_adder
generic map(
g_data_bits => c_datbits,
g_parts => 9)
port map(
clk_i => clk_ref_i,
a_i => s_add_a, -- time in ns
b_i => s_add_b, -- timeshift value in ns to subtract
c_i => '1', -- set carry to 1 to create timeshift Twos complement
x2_o => s_add_x
);
valid_o <= r_wed1;
--delay valid signal to compensate for adder delay
we_delay: process(clk_ref_i)
begin
if rising_edge(clk_ref_i) then
if(rst_ref_n_i = '0') then
r_wed0 <= '0';
else
r_wed0 <= s_wed_start;
r_wed1 <= r_wed0;
end if;
end if;
end process;
--edge detection/deglitcher state machine
deglitch : process(clk_ref_i)
variable v_diff : unsigned (stable_i'range);
variable v_1unbr_msb : unsigned(r_cntUnbr'range);
variable v_0unbr_msb : unsigned(r_cntUnbr'range);
variable v_1unbr_lsb : unsigned(r_cntUnbr'range);
variable v_0unbr_lsb : unsigned(r_cntUnbr'range);
variable v_1 : unsigned(r_cnt'range);
variable v_0 : unsigned(r_cnt'range);
begin
if rising_edge(clk_ref_i) then
if(rst_ref_n_i = '0') then
r_state <= e_LOW;
r_cnt <= (others => '0');
r_cntUnbr <= (others => '0');
else
s_wed_start <= '0';
v_1unbr_msb := to_unsigned(f_countUnbroken(trigger_i, '1', "msb"), r_cntUnbr'length);
v_0unbr_msb := to_unsigned(f_countUnbroken(trigger_i, '0', "msb"), r_cntUnbr'length);
v_1unbr_lsb := to_unsigned(f_countUnbroken(trigger_i, '1', "lsb"), r_cntUnbr'length);
v_0unbr_lsb := to_unsigned(f_countUnbroken(trigger_i, '0', "lsb"), r_cntUnbr'length);
v_1 := to_unsigned(f_count(trigger_i, '1'), r_cnt'length);
v_0 := to_unsigned(f_count(trigger_i, '0'), r_cnt'length);
v_diff := (r_cnt + r_cntUnbr);
case r_state is
when e_LOW => if(trigger_i /= x"00") then
r_cnt <= v_1;
r_cntUnbr <= v_1unbr_lsb;
r_state <= e_TRANS_RISE;
end if;
when e_TRANS_RISE => r_cnt <= r_cnt + v_1;
if(trigger_i /= x"ff") then
r_cntUnbr <= v_1unbr_lsb;
else
r_cntUnbr <= r_cntUnbr + 8;
end if;
if(r_cntUnbr + v_1unbr_msb >= unsigned(stable_i)) then
s_wed_start <= edge_i and active_i;
r_timeshift <= (r_cntUnbr + 8 + ('0' & v_diff(v_diff'left downto 1)) + to_unsigned(g_offset, 32));
r_state <= e_HIGH;
end if;
when e_HIGH => if(trigger_i /= x"ff") then
r_cnt <= v_0;
r_cntUnbr <= v_0unbr_lsb;
r_state <= e_TRANS_FALL;
end if;
when e_TRANS_FALL => r_cnt <= r_cnt + v_0;
if(trigger_i /= x"00") then
r_cntUnbr <= v_0unbr_lsb;
else
r_cntUnbr <= r_cntUnbr + 8;
end if;
if(r_cntUnbr + v_0unbr_msb >= unsigned(stable_i)) then
s_wed_start <= not edge_i and active_i;
r_timeshift <= (r_cntUnbr +('0' & v_diff(v_diff'left downto 1)) + to_unsigned(g_offset, 32)) ;
r_state <= e_LOW;
end if;
when others => r_state <= e_LOW;
end case;
end if;
end if;
end process deglitch;
end behavioral;
......@@ -53,6 +53,26 @@ package tlu_pkg is
irq_master_i : in t_wishbone_master_in
);
end component;
component wr_tlu_fsm is
generic( g_offset : natural := 10);
port (
clk_ref_i : in std_logic; -- tranceiver clock domain
rst_ref_n_i : in std_logic;
trigger_i : in t_trigger; -- trigger vector for latch. meant to be used with 8bits from
tm_tai_cyc_i : in std_logic_vector(63 downto 0); -- TAI Timestamp in 8ns cycles
captured_time_o : out std_logic_vector(64 + 3 - 1 downto 0);
valid_o : out std_logic;
-- sys clk domain signals, sync them first
stable_i : t_wishbone_data;
active_i : std_logic;
edge_i : std_logic
);
end component;
end tlu_pkg;
......
......@@ -22,8 +22,8 @@ architecture rtl of tlu_tb is
signal rst_n : std_logic := '0';
-- Clock period definitions
constant clk_period_sys : time := 8 ns;
constant clk_period_ref : time := 7 ns;
constant clk_period_sys : time := 10 ns;
constant clk_period_ref : time := 8 ns;
signal s_ctrl_i : t_wishbone_slave_in;
signal s_ctrl_o : t_wishbone_slave_out;
......@@ -39,7 +39,7 @@ architecture rtl of tlu_tb is
constant c_STAT : natural := 0; --0x00, ro, fifo n..0 status (0 empty, 1 ne)
constant c_CLR : natural := c_STAT +4; --0x04, wo, Clear channels n..0
constant c_TEST : natural := c_CLR +4; --0x08, ro, trigger n..0 status
constant c_ACT_GET : natural := c_TEST +4; --0x08, ro, trigger n..0 status
constant c_ACT_GET : natural := c_TEST +4; --0x0C, ro, trigger n..0 status
constant c_ACT_SET : natural := c_ACT_GET +4; --0x10, wo, Activate trigger n..0
constant c_ACT_CLR : natural := c_ACT_SET +4; --0x14, wo, deactivate trigger n..0
constant c_EDG_GET : natural := c_ACT_CLR +4; --0x18, ro, trigger n..0 latch edge (1 pos, 0 neg)
......@@ -57,13 +57,14 @@ architecture rtl of tlu_tb is
constant c_CH_SEL : natural := c_TC_LO +4; --0x58, rw, channels select
-- ***** CAREFUL! From here on, all addresses depend on channels select Reg !
constant c_TS_POP : natural := c_CH_SEL +4; --0x5C, wo writing anything here will pop selected channel
constant c_TS_TEST : natural := c_TS_POP +4; --0x60, wo, Test channels n..0
constant c_TS_TEST : natural := c_TS_POP +4; --0x60, wo, Test selected channel
constant c_TS_CNT : natural := c_TS_TEST +4; --0x64, ro, fifo fill count
constant c_TS_HI : natural := c_TS_CNT +4; --0x68, ro, fifo q - Cycle Count Hi
constant c_TS_LO : natural := c_TS_HI +4; --0x68, ro, fifo q - Cycle Count Lo
constant c_TS_SUB : natural := c_TS_LO +4; --0x6C, ro, fifo q - Sub cycle word
constant c_TS_MSG : natural := c_TS_SUB +4; --0x70, rw, MSI msg to be sent
constant c_TS_DST_ADR: natural := c_TS_MSG +4; --0x74, rw, MSI adr to send to
constant c_TS_LO : natural := c_TS_HI +4; --0x6C, ro, fifo q - Cycle Count Lo
constant c_TS_SUB : natural := c_TS_LO +4; --0x70, ro, fifo q - Sub cycle word
constant c_STABLE : natural := c_TS_SUB +4; --0x70, rw, stable time in ns, how long a signal has to be constant before edges are detected
constant c_TS_MSG : natural := c_STABLE +4; --0x74, rw, MSI msg to be sent
constant c_TS_DST_ADR: natural := c_TS_MSG +4; --0x78, rw, MSI adr to send to
--------------------------------------------------------
......@@ -123,7 +124,7 @@ begin
s_irq_i.stall <= '0';
s_irq_i.dat <= (others => '0');
else
r_ref_time <= std_logic_vector(unsigned(r_ref_time) +2);
r_ref_time <= std_logic_vector(unsigned(r_ref_time) +1);
s_irq_i.ack <= s_irq_o.cyc and s_irq_o.stb;
end if;
end if;
......@@ -156,18 +157,18 @@ begin
i := 50;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000");
s_triggers <= (x"00", x"ff", x"00");
s_triggers <= (x"00", x"00", x"00");
wait until rst_n = '1';
wait until rising_edge(clk_sys);
wait for v_T*5;
wait for v_T*5.5;
s_triggers <= (x"00", x"ff", x"00");
s_triggers <= (x"00", x"00", x"00");
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_EDG_NEG, 32)), x"F", '1', x"00000002"); wait for v_T;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_EDG_POS, 32)), x"F", '1', x"0000000f"); wait for v_T;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_MSK_SET, 32)), x"F", '1', x"00000007"); wait for v_T;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_IE, 32)), x"F", '1', x"00000001"); wait for v_T;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_ACT_SET, 32)), x"F", '1', x"00000007"); wait for v_T;
......@@ -181,38 +182,74 @@ begin
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"000000FF"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000000"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
--s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"000000FF"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000000"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
--
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000007F"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000003F"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000001F"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000000F"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000007"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000003"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
-- s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000001"); wait for v_T;
-- s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
-- wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000007F"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000003F"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000001F"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"0000000F"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000007"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000003"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
s_ctrl_i <= ('1', '1', std_logic_vector(to_unsigned(16#100# + c_TEST, 32)), x"F", '1', x"00000001"); wait for v_T;
s_ctrl_i <= ('0', '0', x"00000000", x"F", '0', x"00000000"); wait for v_T;
wait for v_T*9;
wait until rising_edge(clk_ref);
v_t := clk_period_ref;
wait for v_T/2;
s_triggers <= (x"00", x"00", x"00");
wait for v_T*20;
report "TRIGGER!" severity warning;
s_triggers <= (x"00", x"ff", x"00");
s_triggers <= (x"00", x"01", x"00");
wait for v_T;
s_triggers <= (x"00", x"0f", x"00");
wait for v_T;
s_triggers <= (x"00", x"a1", x"00");
wait for v_T;
s_triggers <= (x"00", x"fe", x"00");
wait for v_T;
s_triggers <= (x"00", x"00", x"00");
wait for v_T*20;
report "TRIGGER!" severity warning;
s_triggers <= (x"00", x"AF", x"00");
wait for v_T;
s_triggers <= (x"00", x"f0", x"00");
wait for v_T;
s_triggers <= (x"00", x"00", x"00");
wait for v_T*10;
s_triggers <= (x"00", x"FF", x"00");
wait for v_T*10;
report "TRIGGER!" severity warning;
s_triggers <= (x"00", x"F0", x"00");
wait for v_T;
s_triggers <= (x"00", x"0F", x"00");
wait for v_T;
s_triggers <= (x"00", x"ff", x"00");
wait for v_T*20;
------------------------------------------
report "Glitch" severity note;
s_triggers <= (x"0f", x"0f", x"0f");
......
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