Commit 1e647446 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

fmc_tdc_core: treat int_flag_i as a synchronous signal, added an IODELAY line…

fmc_tdc_core: treat int_flag_i as a synchronous signal, added an IODELAY line programmable from the host to adjust the timing. Possible fix for the 131us bug
parent e0addd9d
......@@ -52,11 +52,11 @@
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
use work.gencores_pkg.all;
......@@ -66,51 +66,37 @@ use work.gencores_pkg.all;
entity acam_timecontrol_interface is
port
-- INPUTS
-- INPUTS
-- Signals from the clk_rst_manager unit
(clk_i : in std_logic; -- 125 MHz clock
rst_i : in std_logic; -- reset
acam_refclk_r_edge_p_i : in std_logic; -- pulse upon ACAM RefClk rising edge
(clk_i : in std_logic; -- 125 MHz clock
rst_i : in std_logic; -- reset
-- upc_p from the WRabbit or the local generator
utc_p_i : in std_logic;
-- upc_p from the WRabbit or the local generator
utc_p_i : in std_logic;
-- Signals from the data_engine unit
state_active_p_i : in std_logic; -- the core ready to follow the ACAM EF
-- Signals from the data_engine unit
state_active_p_i : in std_logic; -- the core ready to follow the ACAM EF
-- Signals from the reg_ctrl unit
activate_acq_p_i : in std_logic; -- signal from GN4124/VME to start following the ACAM chip
-- for tstamps aquisition
deactivate_acq_p_i : in std_logic; -- acquisition deactivated
-- Signals from the reg_ctrl unit
activate_acq_p_i : in std_logic; -- signal from GN4124/VME to start following the ACAM chip
-- for tstamps aquisition
deactivate_acq_p_i : in std_logic; -- acquisition deactivated
-- Signals from the ACAM chip
err_flag_i : in std_logic; -- ACAM error flag, active HIGH; through ACAM config
-- reg 11 is set to report for any HitFIFOs full flags
int_flag_i : in std_logic; -- ACAM interrupt flag, active HIGH; through ACAM config
-- reg 12 it is set to the MSB of Start#
-- OUTPUTS
-- Signals to the ACAM chip
start_from_fpga_o : out std_logic;
-- OUTPUTS
-- Signals to the ACAM chip
start_from_fpga_o : out std_logic;
stop_dis_o : out std_logic;
-- Signals to the
acam_errflag_r_edge_p_o : out std_logic; -- ACAM ErrFlag rising edge
acam_errflag_f_edge_p_o : out std_logic; -- ACAM ErrFlag falling edge
acam_intflag_f_edge_p_o : out std_logic);-- ACAM IntFlag falling edge
stop_dis_o : out std_logic);
end acam_timecontrol_interface;
--=================================================================================================
-- architecture declaration
end entity;
--=================================================================================================
architecture rtl of acam_timecontrol_interface is
signal int_flag_synch, err_flag_synch : std_logic_vector(2 downto 0);
signal acam_intflag_f_edge_p : std_logic;
signal start_pulse, wait_for_utc, rst_n, wait_for_state_active : std_logic;
--=================================================================================================
-- architecture begin
--=================================================================================================
......@@ -120,30 +106,7 @@ begin
-- IntFlag and ERRflag Input Synchronizers --
---------------------------------------------------------------------------------------------------
rst_n <= not(rst_i);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
sync_err_flag: process (clk_i) -- synchronisation registers for ERR external signal
begin
if rising_edge (clk_i) then
if rst_i ='1' then
err_flag_synch <= (others => '0');
int_flag_synch <= (others => '0');
else
err_flag_synch <= err_flag_i & err_flag_synch(2 downto 1);
int_flag_synch <= int_flag_i & int_flag_synch(2 downto 1);
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
acam_errflag_f_edge_p_o <= not(err_flag_synch(1)) and err_flag_synch(0);
acam_errflag_r_edge_p_o <= err_flag_synch(1) and not(err_flag_synch(0));
acam_intflag_f_edge_p <= not(int_flag_synch(1)) and int_flag_synch(0);
acam_intflag_f_edge_p_o <= acam_intflag_f_edge_p;
rst_n <= not(rst_i);
---------------------------------------------------------------------------------------------------
-- start_from_fpga_o generation --
......@@ -152,27 +115,27 @@ begin
-- after the state_active_p_i (coming from the data_engine unit).
-- The pulse is synchronous to the utc_p_i
start_pulse_from_fpga: process (clk_i)
start_pulse_from_fpga : process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' or deactivate_acq_p_i = '1' then
wait_for_utc <= '0';
start_pulse <= '0';
wait_for_state_active <= '0';
stop_dis_o <= '1';
else
if rst_i = '1' or deactivate_acq_p_i = '1' then
wait_for_utc <= '0';
start_pulse <= '0';
wait_for_state_active <= '0';
stop_dis_o <= '1';
else
if activate_acq_p_i = '1' then
wait_for_utc <= '1';
start_pulse <= '0';
wait_for_utc <= '1';
start_pulse <= '0';
elsif utc_p_i = '1' and wait_for_utc = '1' then
wait_for_utc <= '0';
start_pulse <= '1';
wait_for_state_active <= '1';
elsif wait_for_state_active = '1' and state_active_p_i = '1' then -- data_engine starts following ACAM EF
stop_dis_o <= '0';
wait_for_state_active <= '0';
else
start_pulse <= '0';
wait_for_state_active <= '1';
elsif wait_for_state_active = '1' and state_active_p_i = '1' then -- data_engine starts following ACAM EF
stop_dis_o <= '0';
wait_for_state_active <= '0';
else
start_pulse <= '0';
end if;
end if;
end if;
......@@ -180,8 +143,8 @@ begin
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
extend_pulse : gc_extend_pulse
generic map (g_width => 4)
port map
generic map (g_width => 4)
port map
(clk_i => clk_i,
rst_n_i => rst_n,
pulse_i => start_pulse,
......
......@@ -235,7 +235,6 @@ architecture rtl of fmc_tdc_core is
signal acm_cyc, acm_stb, acm_we, acm_ack : std_logic;
signal acm_dat_r, acm_dat_w : std_logic_vector(g_width-1 downto 0);
signal acam_ef1, acam_ef2 : std_logic;
signal acam_errflag_f_edge_p, acam_errflag_r_edge_p : std_logic;
signal acam_intflag_f_edge_p : std_logic;
signal acam_tstamp1, acam_tstamp2 : std_logic_vector(g_width-1 downto 0);
signal acam_tstamp1_ok_p, acam_tstamp2_ok_p : std_logic;
......@@ -282,6 +281,9 @@ architecture rtl of fmc_tdc_core is
signal gen_fake_ts_enable : std_logic;
signal gen_fake_ts_channel : std_logic_vector(2 downto 0);
signal gen_fake_ts_period : std_logic_vector(27 downto 0);
signal r_int_flag_dly_ce : std_logic;
signal r_int_flag_dly_inc : std_logic;
signal r_int_flag_dly_rst : std_logic;
--=================================================================================================
-- architecture begin
......@@ -342,7 +344,10 @@ begin
one_hz_phase_o => pulse_delay,
gen_fake_ts_period_o => gen_fake_ts_period,
gen_fake_ts_enable_o => gen_fake_ts_enable,
gen_fake_ts_channel_o => gen_fake_ts_channel
gen_fake_ts_channel_o => gen_fake_ts_channel,
int_flag_dly_ce_o => r_int_flag_dly_ce,
int_flag_dly_inc_o => r_int_flag_dly_inc,
int_flag_dly_rst_o => r_int_flag_dly_rst
);
process(clk_tdc_i)
......@@ -385,7 +390,7 @@ begin
---------------------------------------------------------------------------------------------------
-- LOCAL ONE HZ GENERATOR --
---------------------------------------------------------------------------------------------------
local_one_second_block : local_pps_gen
local_one_second_block : entity work.local_pps_gen
generic map
(g_width => g_width)
port map
......@@ -403,30 +408,26 @@ begin
---------------------------------------------------------------------------------------------------
-- ACAM TIMECONTROL INTERFACE --
---------------------------------------------------------------------------------------------------
acam_timing_block : acam_timecontrol_interface
acam_timing_block : entity work.acam_timecontrol_interface
port map
(err_flag_i => err_flag_i,
int_flag_i => int_flag_i,
(
start_from_fpga_o => start_from_fpga,
stop_dis_o => stop_dis_o,
acam_refclk_r_edge_p_i => acam_refclk_r_edge_p_i,
utc_p_i => utc_p,
clk_i => clk_tdc_i,
activate_acq_p_i => activate_acq_p,
state_active_p_i => state_active_p,
deactivate_acq_p_i => deactivate_acq_p,
rst_i => rst_tdc,
acam_errflag_f_edge_p_o => acam_errflag_f_edge_p,
acam_errflag_r_edge_p_o => acam_errflag_r_edge_p,
acam_intflag_f_edge_p_o => acam_intflag_f_edge_p);
rst_i => rst_tdc);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
start_from_fpga_o <= start_from_fpga;
---------------------------------------------------------------------------------------------------
-- ACAM DATABUS INTERFACE --
---------------------------------------------------------------------------------------------------
acam_data_block : acam_databus_interface
acam_data_block : entity work.acam_databus_interface
port map
(ef1_i => ef1_i,
ef2_i => ef2_i,
......@@ -452,11 +453,13 @@ begin
---------------------------------------------------------------------------------------------------
-- ACAM START RETRIGGER CONTROLLER --
---------------------------------------------------------------------------------------------------
start_retrigger_block : start_retrig_ctrl
generic map
(g_width => g_width)
start_retrigger_block : entity work.start_retrig_ctrl
port map
(acam_intflag_f_edge_p_i => acam_intflag_f_edge_p,
(
r_int_flag_dly_rst_i => r_int_flag_dly_rst,
r_int_flag_dly_inc_i => r_int_flag_dly_inc,
r_int_flag_dly_ce_i => r_int_flag_dly_ce,
int_flag_i => int_flag_i,
clk_i => clk_tdc_i,
utc_p_i => utc_p,
rst_i => rst_tdc,
......@@ -572,7 +575,7 @@ begin
port map
(clk_i => clk_tdc_i,
rst_i => rst_tdc,
utc_p_i => local_utc_p,
utc_p_i => utc_p,
tstamp_wr1_p_i => final_timestamp_valid(0),
tstamp_wr2_p_i => final_timestamp_valid(1),
tstamp_wr3_p_i => final_timestamp_valid(2),
......
......@@ -106,7 +106,7 @@ use work.TDC_OW_wbgen2_pkg.all;
--=================================================================================================
entity fmc_tdc_mezzanine is
generic
(g_with_wrabbit_core : boolean := false;
(g_with_wrabbit_core : boolean := true;
g_span : integer := 32;
g_width : integer := 32;
g_simulation : boolean := false;
......@@ -115,7 +115,6 @@ entity fmc_tdc_mezzanine is
port
-- TDC core
(
-- System clock & reset (Wishbone)
clk_sys_i : in std_logic; -- 62.5 MHz clock
rst_sys_n_i : in std_logic; -- reset for 62.5 MHz logic
......
......@@ -151,7 +151,12 @@ entity reg_ctrl is
wrabbit_ctrl_reg_o : out std_logic_vector(g_width-1 downto 0); --
-- Signal to the acam_timecontrol_interface unit -- eva: i think it s not needed
start_phase_o : out std_logic_vector(g_width-1 downto 0));
start_phase_o : out std_logic_vector(g_width-1 downto 0);
int_flag_dly_ce_o : out std_logic;
int_flag_dly_inc_o : out std_logic;
int_flag_dly_rst_o : out std_logic
);
end reg_ctrl;
......@@ -181,6 +186,7 @@ architecture rtl of reg_ctrl is
signal dat_out_pipe2, dat_out_pipe3 : std_logic_vector(g_span-1 downto 0);
signal cyc_in_progress : std_logic;
signal cyc2_in_progress : std_logic;
signal wb_in : t_wishbone_slave_in;
signal wb_out : t_wishbone_slave_out;
......@@ -357,9 +363,15 @@ begin
dac_word <= c_DEFAULT_DAC_WORD; -- default DAC Vout = 1.65
gen_fake_ts_enable_o <= '0';
elsif wb_in.cyc = '1' and wb_in.stb = '1' and wb_in.we = '1' then
int_flag_dly_rst_o <= '0';
int_flag_dly_ce_o <= '0';
int_flag_dly_inc_o <= '0';
cyc2_in_progress <= '0';
elsif wb_in.cyc = '1' and wb_in.stb = '1' and wb_in.we = '1' then
cyc2_in_progress <= '1';
if reg_adr = c_STARTING_UTC_ADR then
starting_utc <= wb_in.dat;
end if;
......@@ -398,7 +410,17 @@ begin
gen_fake_ts_period_o <= wb_in.dat(27 downto 0);
end if;
int_flag_dly_ce_o <= '0';
if reg_adr = c_TEST1_ADR then
int_flag_dly_ce_o <= wb_in.dat(0) and not cyc2_in_progress;
int_flag_dly_inc_o <= wb_in.dat(1);
int_flag_dly_rst_o <= wb_in.dat(2);
end if;
else
int_flag_dly_ce_o <= '0';
cyc2_in_progress <= '0';
end if;
end if;
end process;
......
......@@ -123,36 +123,40 @@
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
library unisim;
use unisim.vcomponents.all;
--=================================================================================================
-- Entity declaration for start_retrig_ctrl
--=================================================================================================
entity start_retrig_ctrl is
generic
(g_width : integer := 32);
port
-- INPUTS
-- Signal from the clk_rst_manager
(clk_i : in std_logic;
rst_i : in std_logic;
-- INPUTS
-- Signal from the clk_rst_manager
(clk_i : in std_logic;
rst_i : in std_logic;
-- Signal from the acam_timecontrol_interface
acam_intflag_f_edge_p_i : in std_logic;
int_flag_i : in std_logic;
r_int_flag_dly_rst_i : in std_logic;
r_int_flag_dly_inc_i : in std_logic;
r_int_flag_dly_ce_i : in std_logic;
-- Signal from the one_hz_generator unit
utc_p_i : in std_logic;
-- OUTPUTS
utc_p_i : in std_logic;
-- OUTPUTS
-- Signals to the data_formatting unit
current_retrig_nb_o : out std_logic_vector(g_width-1 downto 0);
current_retrig_nb_o : out std_logic_vector(31 downto 0);
roll_over_incr_recent_o : out std_logic;
clk_i_cycles_offset_o : out std_logic_vector(g_width-1 downto 0);
roll_over_nb_o : out std_logic_vector(g_width-1 downto 0);
retrig_nb_offset_o : out std_logic_vector(g_width-1 downto 0));
clk_i_cycles_offset_o : out std_logic_vector(31 downto 0);
roll_over_nb_o : out std_logic_vector(31 downto 0);
retrig_nb_offset_o : out std_logic_vector(31 downto 0));
end start_retrig_ctrl;
......@@ -163,13 +167,14 @@ end start_retrig_ctrl;
architecture rtl of start_retrig_ctrl is
signal clk_i_cycles_offset : std_logic_vector(g_width-1 downto 0);
signal current_cycles : std_logic_vector(g_width-1 downto 0);
signal current_retrig_nb : std_logic_vector(g_width-1 downto 0);
signal retrig_nb_offset : std_logic_vector(g_width-1 downto 0);
signal clk_i_cycles_offset : std_logic_vector(31 downto 0);
signal current_cycles : std_logic_vector(31 downto 0);
signal current_retrig_nb : std_logic_vector(31 downto 0);
signal retrig_nb_offset : std_logic_vector(31 downto 0);
signal retrig_p : std_logic;
signal roll_over_c : unsigned(g_width-1 downto 0);
signal roll_over_c : unsigned(31 downto 0);
signal int_flag_stb_p, int_flag_dly, int_flag, int_flag_d, int_flag_p : std_logic;
--=================================================================================================
-- architecture begin
......@@ -233,46 +238,94 @@ begin
-- These two counters keep a track of the current internal start retrigger
-- of the ACAM in parallel with the ACAM itself. Counting up to c_ACAM_RETRIG_PERIOD = 64
retrig_period_counter: free_counter -- retrigger periods
generic map
(width => g_width)
port map
(clk_i => clk_i,
rst_i => acam_intflag_f_edge_p_i,
counter_en_i => '1',
counter_top_i => c_ACAM_RETRIG_PERIOD,
-------------------------------------------
counter_is_zero_o => retrig_p,
counter_o => current_cycles);
-------------------------------------------
retrig_nb_counter: incr_counter -- number of retriggers counting from 0 to 255 and restarting
generic map -- through the acam_intflag_f_edge_p_i
(width => g_width)
iodelay2_bus : IODELAY2
generic map (
DATA_RATE => "SDR",
IDELAY_VALUE => 0,
IDELAY_TYPE => "VARIABLE_FROM_ZERO",
COUNTER_WRAPAROUND => "STAY_AT_LIMIT",
DELAY_SRC => "IDATAIN",
SERDES_MODE => "NONE",
SIM_TAPDELAY_VALUE => 75)
port map (
-- required datapath
IDATAIN => int_flag_i,
DATAOUT => int_flag_dly,
T => '1',
-- inactive data connections
DATAOUT2 => open,
DOUT => open,
ODATAIN => '0',
TOUT => open,
-- connect up the clocks
IOCLK0 => clk_i, -- High speed clock for calibration for SDR/DDR
IOCLK1 => '0', -- High speed clock for calibration for DDR
CLK => clk_i,
CAL => '0',
INC => r_int_flag_dly_inc_i,
CE => r_int_flag_dly_ce_i,
BUSY => open,
RST => r_int_flag_dly_rst_i);
p_sample_int_flag : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
int_flag_d <= '0';
int_flag <= '0';
else
int_flag <= int_flag_dly;
int_flag_d <= int_flag;
end if;
end if;
end process;
int_flag_p <= not int_flag and int_flag_d;
retrig_period_counter : free_counter -- retrigger periods
generic map
(width => 32)
port map
(clk_i => clk_i,
rst_i => acam_intflag_f_edge_p_i,
counter_top_i => x"00000100",
counter_incr_en_i => retrig_p,
counter_is_full_o => open,
(clk_i => clk_i,
rst_i => int_flag_p,
counter_en_i => '1',
counter_top_i => c_ACAM_RETRIG_PERIOD,
-------------------------------------------
counter_o => current_retrig_nb);
counter_is_zero_o => retrig_p,
counter_o => current_cycles);
-------------------------------------------
retrig_nb_counter : incr_counter -- number of retriggers counting from 0 to 255 and restarting
generic map -- through the acam_intflag_f_edge_p_i
(width => 32)
port map
(clk_i => clk_i,
rst_i => int_flag_p,
counter_top_i => x"00000100",
counter_incr_en_i => retrig_p,
counter_is_full_o => open,
-------------------------------------------
counter_o => current_retrig_nb);
-------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- This counter keeps track of the number of overflows of the ACAM counter within one second
roll_over_counter: process (clk_i)
roll_over_counter : process (clk_i)
begin
if rising_edge (clk_i) then
if utc_p_i = '1' and acam_intflag_f_edge_p_i = '0' then
roll_over_c <= x"00000000";
-- the following case covers the rare possibility when utc_p_i and acam_intflag_f_edge_p_i
-- arrive on the exact same moment
elsif utc_p_i = '1' and acam_intflag_f_edge_p_i = '1' then
roll_over_c <= x"00000001";
elsif acam_intflag_f_edge_p_i = '1' then
if utc_p_i = '1' and int_flag_p = '0' then
roll_over_c <= x"00000000";
-- the following case covers the rare possibility when utc_p_i and acam_intflag_f_edge_p_i
-- arrive on the exact same moment
elsif utc_p_i = '1' and int_flag_p = '1' then
roll_over_c <= x"00000001";
elsif int_flag_p = '1' then
roll_over_c <= roll_over_c + "1";
end if;
end if;
......@@ -282,12 +335,12 @@ begin
-- When a new second starts, all values are captured and stored as offsets.
-- when a timestamp arrives, these offsets will be subtracted in order
-- to base the final timestamp with respect to the current second.
capture_offset: process (clk_i)
capture_offset : process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
clk_i_cycles_offset <= (others=>'0');
retrig_nb_offset <= (others=>'0');
if rst_i = '1' then
clk_i_cycles_offset <= (others => '0');
retrig_nb_offset <= (others => '0');
elsif utc_p_i = '1' then
clk_i_cycles_offset <= current_cycles;
......@@ -302,7 +355,7 @@ begin
clk_i_cycles_offset_o <= clk_i_cycles_offset;
retrig_nb_offset_o <= retrig_nb_offset;
roll_over_nb_o <= std_logic_vector(roll_over_c);
current_retrig_nb_o <= current_retrig_nb; -- for debug
current_retrig_nb_o <= current_retrig_nb; -- for debug
end architecture rtl;
......@@ -312,4 +365,4 @@ end architecture rtl;
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
---------------------------------------------------------------------------------------------------
......@@ -360,6 +360,7 @@ package tdc_core_pkg is
constant c_WRABBIT_CTRL_ADR : std_logic_vector(7 downto 0) := x"2D"; -- address 0x510B4 of GN4124 BAR 0
constant c_TEST0_ADR : std_logic_vector(7 downto 0) := x"2E"; -- address 0x510B4 of GN4124 BAR 0
constant c_TEST1_ADR : std_logic_vector(7 downto 0) := x"2f"; -- address 0x510B4 of GN4124 BAR 0
---------------------------------------------------------------------------------------------------
-- Address of TDC core Control register
......
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