--******************************************************************************
--* @short Readout Processor Module, in the ROP Chip, reads data from the
--* input chips and sort chip. Sends it to GTFE via channel link.
--*
--******************************************************************************
--* @author SAKULIN Hannes <hsakulin@dsy-srv3.cern.ch>
--* @version $Revision: 1.2 $
--* @date $Date: 2004/12/16 18:58:22 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.all;
-- pragma translate_on
use IEEE.NUMERIC_STD.all;
use work.VMEMux.all;
use work.ROPVMEAddrMap.all;
entity ROPROP is
port (
-- ROP: Readout Data Ports to Input and Sort Chips
ro_data_INF : in std_logic_vector(23 downto 0);
ro_rdfifo_INF : out std_logic;
ro_fetch_INF : out std_logic;
ro_data_INC : in std_logic_vector(23 downto 0);
ro_rdfifo_INC : out std_logic;
ro_fetch_INC : out std_logic;
ro_data_IND : in std_logic_vector(23 downto 0);
ro_rdfifo_IND : out std_logic;
ro_fetch_IND : out std_logic;
ro_data_INB : in std_logic_vector(23 downto 0);
ro_rdfifo_INB : out std_logic;
ro_fetch_INB : out std_logic;
ro_data_SRT : in std_logic_vector(23 downto 0);
ro_rdfifo_SRT : out std_logic;
ro_fetch_SRT : out std_logic;
-- Output of ROP to Channel Links with CLK signal
ch_link1 : out std_logic_vector(27 downto 0);
ch_link1_clk : out std_logic;
en_link1 : out std_logic;
-- second channel link as spare
ch_link2 : out std_logic_vector(27 downto 0);
ch_link2_clk : out std_logic;
en_link2 : out std_logic;
-- BAckplane Timing and Control Signals
-- L1A, L1reset, bcreset
l1a_ROP : in std_logic; -- Level-1 accept
bcreset_ROP : in std_logic; -- Bunch Counter reset
l1reset_ROP : in std_logic; -- Level-1 reset
-- RO-bus from backplane comes from TTCrx chip on TIM board
-- and carries BGo commands of TTC system
-- Start Stop, HardRes, etc.
-- Can be used to send in addition to VME commands
-- a RESET_xxx to the GMT chips.
ro_bus : in std_logic_vector(11 downto 0);
ro_strobe : in std_logic_vector(2 downto 0);
ro_rdrqst : in std_logic;
-- VME port
vme_addr : in std_logic_vector;
vme_data : in std_logic_vector;
vme_en : in std_logic;
vme_wr : in std_logic;
vme_data_out : out std_logic_vector(15 downto 0);
vme_en_out : out std_logic;
-- Clock and control
clk : in std_logic;
reset : in std_logic
);
end;
architecture behavioral of ROPROP is
attribute syn_useioff : boolean;
attribute syn_useioff of behavioral : architecture is true;
signal bigor : std_logic;
component bc_l1a_fifo1k
port (
clk: IN std_logic;
sinit: IN std_logic;
din: IN std_logic_VECTOR(15 downto 0);
wr_en: IN std_logic;
rd_en: IN std_logic;
dout: OUT std_logic_VECTOR(15 downto 0);
full: OUT std_logic;
empty: OUT std_logic);
end component;
-- Synplicity black box declaration
attribute syn_black_box : boolean;
attribute syn_black_box of bc_l1a_fifo1k: component is true;
-- decoded TCS signals
signal l1a_reg : std_logic;
signal bcreset_reg : std_logic;
signal l1reset_reg : std_logic;
signal ecreset_reg : std_logic;
-- signals for writing bc's into BC_L1A FIOF
signal sDo5BX : std_logic;
signal sBXReadCount : std_logic_vector(11 downto 0); -- the bx count
signal l1a_reg_d1 : std_logic;
signal sBXReadCount_d1 : std_logic_vector(11 downto 0); -- the bx count
signal l1a_reg_d2 : std_logic;
signal sBXReadCount_d2 : std_logic_vector(11 downto 0); -- the bx count
-- signals for reading the FIFO and starting the readout
signal fifo_rd_en, fifo_rd_en_d : std_logic;
signal fifo_din, fifo_dout : std_logic_vector(15 downto 0);
signal fifo_full, fifo_empty : std_logic;
signal fifo_sinit : std_logic;
signal readout_active : std_logic;
signal reference_bx_count : std_logic_vector(11 downto 0);
signal ro_stages : std_logic_vector(71 downto 0);
signal ro_endpulse : std_logic;
-- the incoming registered readout data
signal ro_data_INF_reg : std_logic_vector(23 downto 0);
signal ro_data_INC_reg : std_logic_vector(23 downto 0);
signal ro_data_IND_reg : std_logic_vector(23 downto 0);
signal ro_data_INB_reg : std_logic_vector(23 downto 0);
signal ro_data_SRT_reg : std_logic_vector(23 downto 0);
-- the data words to be sent on the channel link
signal idle_word : std_logic_vector(27 downto 0);
signal a_word : std_logic_vector(27 downto 0);
signal b_word : std_logic_vector(27 downto 0);
signal c_word : std_logic_vector(27 downto 0);
signal d_word : std_logic_vector(27 downto 0);
signal e_word1 : std_logic_vector(27 downto 0);
signal e_word2 : std_logic_vector(27 downto 0);
signal e_word3 : std_logic_vector(27 downto 0);
signal e_word4 : std_logic_vector(27 downto 0);
signal f_word : std_logic_vector(27 downto 0);
signal data_word1 : std_logic_vector(27 downto 0);
signal data_word2 : std_logic_vector(27 downto 0);
signal data_word3 : std_logic_vector(27 downto 0);
signal data_word4 : std_logic_vector(27 downto 0);
signal data_word5 : std_logic_vector(27 downto 0);
signal event_count : std_logic_vector(23 downto 0);
signal bc_error_bits : std_logic_vector(7 downto 0);
signal bx_in_event : signed(3 downto 0);
signal last_bx_in_event: std_logic;
signal board_id : std_logic_vector(7 downto 0);
signal length_in_w64 : std_logic_vector(4 downto 0);
signal bccount_IND : std_logic_vector(11 downto 0);
signal bccount_INB : std_logic_vector(11 downto 0);
signal bccount_INC : std_logic_vector(11 downto 0);
signal bccount_INF : std_logic_vector(11 downto 0);
signal bccount_SRT : std_logic_vector(11 downto 0);
-- internal FIFO read and fetch signals
signal ro_rdfifo_i : std_logic;
signal ro_fetch_IND_i : std_logic;
signal ro_fetch_INB_i : std_logic;
signal ro_fetch_INC_i : std_logic;
signal ro_fetch_INF_i : std_logic;
signal ro_fetch_SRT_i : std_logic;
constant nbx_pre : integer := 5; -- number of bx, fetch has to be set before switching mux
-- stages (mux enables)
signal stage_a : std_logic;
signal stage_b : std_logic;
signal stage_c : std_logic;
signal stage_d : std_logic;
signal stage_data1 : std_logic;
signal stage_data2 : std_logic;
signal stage_data3 : std_logic;
signal stage_data4 : std_logic;
signal stage_data5 : std_logic;
signal stage_e1 : std_logic;
signal stage_e2 : std_logic;
signal stage_e3 : std_logic;
signal stage_e4 : std_logic;
signal stage_f : std_logic;
signal ch_link1_i : std_logic_vector(27 downto 0);
-- VME Mux
signal vme_data_out_i : TVMEData_vec (0 to 0);
signal vme_en_out_i : TVMEEnable_vec (0 to 0);
begin
--
-- Upon a L1A:
-- ===========
--
-- * wait a few bx
-- * store the reference bunch counter at the L1A in a fifo
-- at the other end of the FIFO
-- * while L1As queued
--
-- * while more bxes to read
-- * send read_fifo to all chips
-- * send A, B, C, D, records on channel link
-- * fetch chip 0, 8x 24 bit
-- * fetch chip 1, => .
-- * increment event number
--
--
-----------------------------------------------------------------------------
-- register inputs
-----------------------------------------------------------------------------
register_rodata: process (clk) is
begin
if clk'event and clk = '1' then -- rising clock edge
ro_data_INF_reg <= ro_data_INF;
ro_data_INC_reg <= ro_data_INC;
ro_data_IND_reg <= ro_data_IND;
ro_data_INB_reg <= ro_data_INB;
ro_data_SRT_reg <= ro_data_SRT;
end if;
end process register_rodata;
-----------------------------------------------------------------------------
-- Register and decode TCS signals
-----------------------------------------------------------------------------
tcs_decoder: entity work.TCSCommandDecoder
port map (
iL1A => l1a_ROP,
iBCReset => bcreset_ROP,
iL1Reset => l1reset_ROP,
oL1A => l1a_reg,
oBCReset => bcreset_reg,
oL1Reset => l1reset_reg,
oECReset => ecreset_reg,
clk => clk,
reset => reset);
-----------------------------------------------------------------------------
-- Reference BX counter
-----------------------------------------------------------------------------
-- In the input chips and sort chip two sets of bunch counters exist:
-- The write counters are reset- so that they are in sync with the incoming data,
-- i.e., the write counter in the sort chip is started a few bx after the
-- ones in the input chip.
-- The read counters on the entire GMT board all run in parallel, i.e. they
-- lag further behind the write counters in the input chips than in the sort
-- chip.
--
-- The ROP chip needs a bx counter that runs in sync with all other the read counters.
--
-- An L1A will capture data starting from the current read counter.
-- it will capture 3 or 5 consecutive bunch crossings.
bxcounter: entity work.BXReadCounter
generic map (
lat_delay_reg_addr => ROP_LATDelayReg_addr)
port map (
iBCReset => bcreset_reg,
iL1A => l1a_reg,
oDo5BX => sDo5BX,
oBXReadCounter => sBXReadCount,
oL1A_pulse => open,
vme_addr => vme_addr,
vme_data => vme_data,
vme_en => vme_en,
vme_wr => vme_wr,
vme_data_out => vme_data_out_i(0),
vme_en_out => vme_en_out_i(0),
clk => clk,
reset => reset);
-----------------------------------------------------------------------------
-- Store L1As in fifo
-----------------------------------------------------------------------------
-- delay L1A pulse and bx count
delay_l1a: process (clk, reset) is
begin -- process delay_l1a
if reset = '1' then
l1a_reg_d1 <= '0';
l1a_reg_d2 <= '0';
sBXReadCount_d1 <= (others => '0');
sBXReadCount_d2 <= (others => '0');
elsif clk'event and clk = '1' then -- rising clock edge
l1a_reg_d1 <= l1a_reg;
l1a_reg_d2 <= l1a_reg_d1;
sBXReadCount_d1 <= sBXReadCount;
sBXReadCount_d2 <= sBXReadCount_d1;
end if;
end process delay_l1a;
-- L1A FIFO: stores bccount of first bc to be read for each L1A
fifo_din <= ( "0000" & sBXReadCount_d2 );
fifo_sinit <= reset or l1reset_reg;
bc_l1a_fifo: bc_l1a_fifo1k
port map (
clk => clk,
sinit => fifo_sinit,
din => fifo_din,
wr_en => l1a_reg_d2,
rd_en => fifo_rd_en,
dout => fifo_dout,
full => fifo_full,
empty => fifo_empty);
-----------------------------------------------------------------------------
-- now comes the FIFO reading part
-----------------------------------------------------------------------------
-- purpose: read the FIFO and start readout operations
-- store the FIFO output as the reference bx count
read_fifo: process (clk, reset) is
begin -- process read_fifo
if reset = '1' then
ro_stages(ro_stages'high) <= '0';
fifo_rd_en_d <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
if (l1reset_reg = '1') then
ro_stages(ro_stages'high) <= '0';
else
if fifo_empty = '0' and readout_active = '0' then
ro_stages(ro_stages'high) <= '1'; -- go into first readout stage
else
-- write a zero or restart the cycle
ro_stages(ro_stages'high) <= ro_stages(4) and (not last_bx_in_event);
end if;
-- delay read enable
fifo_rd_en_d <= fifo_rd_en;
end if;
end if;
end process read_fifo;
-- generate read enable asynchronously to save one bx
fifo_rd_en <= (not fifo_empty) and (not readout_active);
-- readout is active if any of the stages is active
readout_active <= '1' when (ro_stages(71 downto 0) /=
"000000000000000000000000000000000000000000000000000000000000000000000000")
else '0';
-- reference bx counter, bx in event counter and event counter are used in
-- the beginning of the ro_cycle (stages a to d, around index 65)
--
-- reference bx counter, bx in event counter are incremented around stage 40
--
-- if we are in the last bx of the event, then event counter is incremented
-- around stage 20;
reference_bx_counter: process (clk, reset) is
begin -- process reference_bx_counter
if reset = '1' then
reference_bx_count <= (others => '0');
elsif clk'event and clk = '1' then -- rising clock edge
if (fifo_rd_en_d = '1') then
reference_bx_count <= fifo_dout (11 downto 0);
elsif ro_stages(40) = '1' then
reference_bx_count <= std_logic_vector( UNSIGNED ( reference_bx_count ) + 1);
end if;
end if;
end process reference_bx_counter;
bx_in_event_counter: process (clk, reset) is
begin -- process bx_in_event_counter
if reset = '1' then
last_bx_in_event <= '0';
bx_in_event <= (others => '0');
elsif clk'event and clk = '1' then -- rising clock edge
if l1reset_reg = '1' then
last_bx_in_event <= '0';
else
if (fifo_rd_en_d = '1') then
if sDo5BX = '1' then
bx_in_event <= to_signed(-2, 4);
else
bx_in_event <= to_signed(-1, 4);
end if;
elsif ro_stages(40) = '1' then
if (sDo5BX = '1' and bx_in_event = to_signed(2,4)) or
(sDo5BX = '0' and bx_in_event = to_signed(1,4)) then
last_bx_in_event <= '1';
else
last_bx_in_event <= '0';
end if;
bx_in_event <= bx_in_event + 1;
end if;
end if;
end if;
end process bx_in_event_counter;
event_counter: process (clk, reset) is
begin -- process event_counter
if reset = '1' then
event_count <= "000000000000000000000000";
elsif clk'event and clk = '1' then -- rising clock edge
if ecreset_reg = '1' then
event_count <= "000000000000000000000000";
else
if ro_stages(20) = '1' and last_bx_in_event ='1' then
event_count <= std_logic_vector ( unsigned(event_count) + 1 );
end if;
end if;
end if;
end process event_counter;
-----------------------------------------------------------------------------
-- Create the readout cycle for one bx
-----------------------------------------------------------------------------
-- a pulse ist shifted through the ro_stages (from high to low)
-- depending on the position of the pulse, the output mux is switched
-- and the readfifo and fetch signals are generated.
ro_cycle: process (clk, reset) is
begin -- process ro_cycle
if reset = '1' then
ro_stages(ro_stages'high-1 downto 0) <= (others => '0' );
ro_endpulse <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
if l1reset_reg = '1' then
ro_stages(ro_stages'high-1 downto 0) <= (others => '0' );
else
-- shift right the ro-stages
ro_stages(ro_stages'high-1 downto 0) <= ro_stages(ro_stages'high downto 1);
ro_endpulse <= ro_stages(0);
end if;
end if;
end process ro_cycle;
-- read_fifo and fetch signals
ro_rdfifo_i <= ro_stages(66 + nbx_pre); -- need the bx counter in stage b
-- fetch has to start one cycle earlier in order to fetch the second word of
-- bunch counter data (which is ignored)
ro_fetch_IND_i <= '1' when ro_stages(64+nbx_pre downto 56+nbx_pre) /= "000000000" else '0';
ro_fetch_INB_i <= '1' when ro_stages(56+nbx_pre downto 48+nbx_pre) /= "000000000" else '0';
ro_fetch_INC_i <= '1' when ro_stages(48+nbx_pre downto 40+nbx_pre) /= "000000000" else '0';
ro_fetch_INF_i <= '1' when ro_stages(40+nbx_pre downto 32+nbx_pre) /= "000000000" else '0';
ro_fetch_SRT_i <= '1' when ro_stages(32+nbx_pre downto 4+nbx_pre) /= "00000000000000000000000000000" else '0';
-- mux enable signals
stage_a <= ro_stages(67);
stage_b <= ro_stages(66);
stage_c <= ro_stages(65);
stage_d <= ro_stages(64);
stage_data1 <= '1' when ro_stages(63 downto 56) /= "00000000" else '0';
stage_data2 <= '1' when ro_stages(55 downto 48) /= "00000000" else '0';
stage_data3 <= '1' when ro_stages(47 downto 40) /= "00000000" else '0';
stage_data4 <= '1' when ro_stages(39 downto 32) /= "00000000" else '0';
stage_data5 <= '1' when ro_stages(31 downto 4) /= "0000000000000000000000000000" else '0';
stage_e1 <= ro_stages(3);
stage_e2 <= ro_stages(2);
stage_e3 <= ro_stages(1);
stage_e4 <= ro_stages(0);
stage_f <= ro_endpulse and last_bx_in_event;
-----------------------------------------------------------------------------
-- Read out the chips
-----------------------------------------------------------------------------
length_in_w64 <= "10000"; -- gmt record is 16 w64 (including header A-D,
-- not including trailer E and F)
board_id <= "00001111";
register_bccounts: process (clk, reset) is
begin -- process register_bccounts
if reset = '1' then
bccount_IND <= (others => '0');
bccount_INB <= (others => '0');
bccount_INC <= (others => '0');
bccount_INF <= (others => '0');
bccount_SRT <= (others => '0');
elsif clk'event and clk = '1' then -- rising clock edge
if stage_b = '1' then
bccount_IND <= ro_data_IND_reg(11 downto 0);
bccount_INB <= ro_data_INB_reg(11 downto 0);
bccount_INC <= ro_data_INC_reg(11 downto 0);
bccount_INF <= ro_data_INF_reg(11 downto 0);
bccount_SRT <= ro_data_SRT_reg(11 downto 0);
end if;
end if;
end process register_bccounts;
--
-- set-up of channel link records
--
-- calculate bc error bits asynchronously. assumes that ro_data_XXX counatns
-- the bunch counters exactly when the error bits are needed (stage b)
bc_error_bits(0) <= '1' when reference_bx_count /= ro_data_IND_reg(11 downto 0) else '0';
bc_error_bits(1) <= '1' when reference_bx_count /= ro_data_INB_reg(11 downto 0) else '0';
bc_error_bits(2) <= '1' when reference_bx_count /= ro_data_INC_reg(11 downto 0) else '0';
bc_error_bits(3) <= '1' when reference_bx_count /= ro_data_INF_reg(11 downto 0) else '0';
bc_error_bits(4) <= '1' when reference_bx_count /= ro_data_SRT_reg(11 downto 0) else '0';
bc_error_bits(7 downto 5) <= (others => '0');
a_word <= "1010" & "00000000" & event_count(15 downto 0);
b_word <= "1011" & "00000000" & bc_error_bits & event_count(23 downto 16);
c_word <= "1100" & "00000000" & std_logic_vector(bx_in_event) & reference_bx_count;
d_word <= "1101" & "00000000" & board_id & "000" & length_in_w64;
data_word1 <= "0001" & ro_data_IND_reg;
data_word2 <= "0010" & ro_data_INB_reg;
data_word3 <= "0011" & ro_data_INC_reg;
data_word4 <= "0100" & ro_data_INF_reg;
data_word5 <= "0101" & ro_data_SRT_reg;
e_word1 <= "1110" & bccount_INB & bccount_IND ;
e_word2 <= "1110" & bccount_INF & bccount_INC ;
e_word3 <= "1110" & "000000000000" & bccount_SRT ;
e_word4 <= "1110" & "000000000000" & "000000000000" ;
f_word <= "1111" & "11111111" & "1111111111111111";
idle_word <= (others => '0'); -- fixme: idle word should contain ones
-- and 0's, or minimize power consumption
-----------------------------------------------------------------------------
-- the channel link mux
-----------------------------------------------------------------------------
ch_link1_i <= a_word when stage_a = '1' else
b_word when stage_b = '1' else
c_word when stage_c = '1' else
d_word when stage_d = '1' else
data_word1 when stage_data1 = '1' else
data_word2 when stage_data2 = '1' else
data_word3 when stage_data3 = '1' else
data_word4 when stage_data4 = '1' else
data_word5 when stage_data5 = '1' else
e_word1 when stage_e1 = '1' else
e_word2 when stage_e2 = '1' else
e_word3 when stage_e3 = '1' else
e_word4 when stage_e4 = '1' else
f_word when stage_f = '1' else
idle_word;
-----------------------------------------------------------------------------
-- register rdfifo and fetch signals
-----------------------------------------------------------------------------
register_ro: process (clk, reset) is
begin -- process register_ro
if (reset = '1') then
ro_rdfifo_IND <= '0';
ro_rdfifo_INB <= '0';
ro_rdfifo_INC <= '0';
ro_rdfifo_INF <= '0';
ro_rdfifo_SRT <= '0';
ro_fetch_IND <= '0';
ro_fetch_INB <= '0';
ro_fetch_INC <= '0';
ro_fetch_INF <= '0';
ro_fetch_SRT <= '0';
elsif clk'event and clk = '1' then
-- rising clock edge
ro_rdfifo_IND <= ro_rdfifo_i;
ro_rdfifo_INB <= ro_rdfifo_i;
ro_rdfifo_INC <= ro_rdfifo_i;
ro_rdfifo_INF <= ro_rdfifo_i;
ro_rdfifo_SRT <= ro_rdfifo_i;
ro_fetch_IND <= ro_fetch_IND_i;
ro_fetch_INB <= ro_fetch_INB_i;
ro_fetch_INC <= ro_fetch_INC_i;
ro_fetch_INF <= ro_fetch_INF_i;
ro_fetch_SRT <= ro_fetch_SRT_i;
end if;
end process register_ro;
-----------------------------------------------------------------------------
-- register channel link signals
-----------------------------------------------------------------------------
register_chlink: process (clk, reset) is
begin -- process register_chlink
if (reset = '1') then
ch_link1 <= (others => '0');
elsif clk'event and clk = '1' then
ch_link1 <= ch_link1_i;
end if;
end process register_chlink;
en_link1 <= '1';
ch_link1_clk <= clk;
-- multiplex vme_data_output
mux_vme(vme_data_out_i, vme_en_out_i, vme_data_out, vme_en_out);
-- so some stupid dummy logic
bigor <=
ro_bus(0) or
ro_bus(1) or
ro_bus(2) or
ro_bus(3) or
ro_bus(4) or
ro_bus(5) or
ro_bus(6) or
ro_bus(7) or
ro_bus(8) or
ro_bus(9) or
ro_bus(10) or
ro_bus(11) or
ro_strobe(0) or
ro_strobe(1) or
ro_strobe(2) or
ro_rdrqst;
-- second channel link as spare
ch_link2 <= ( others => '0' );
en_link2 <= bigor;
ch_link2_clk <= '0';
end architecture behavioral;