--******************************************************************************
--* @short Sort FPGA (there is only one, so this is the chip)
--******************************************************************************
--* @author SAKULIN Hannes <hsakulin@dsy-srv3.cern.ch>
--* @date $Date: 2006/06/02 09:29:39 $
--* @version $Revision: 1.24 $
--******************************************************************************
-- Revision 1.19: feed 0001 22nov2005
-- Revision 1.20: feed 0002 30nov2005 receive bad LFB bit 56 via spare bit 104
-- Revision 1.21: feed 0003 23may2006 inverted GTLp outputs to GTL board
-- Revision 1.22: feed 0004 29may2006 exchanged muon1 & muon2 in SFDDROutput
-- Revision 1.23: feed 0005 01jun2006 SFDOutput with 80MHz OFD, DCM with clk80
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use WORK.GMTTypes.all;
use WORK.ReadOutBufTypes.all;
use WORK.VMEMux.all;
use WORK.SFVMEAddrMap.all;
use IEEE.NUMERIC_STD.all;
entity SortFPGA is
port ( -- CHIP INPUTS
SortRanks_brl : in TSortRank_vector(0 to 3);
SortRanks_fwd : in TSortRank_vector(0 to 3);
OutMuons_brl : in TFourGMTMu_flat;
OutMuons_fwd : in TFourGMTMu_flat;
IdxBits_brl : in TIndexBits_vector(0 to 3);
IdxBits_fwd : in TIndexBits_vector(0 to 3);
IsRPCMu_brl : in std_logic_vector (0 to 3);
IsRPCMu_fwd : in std_logic_vector (0 to 3);
-- OUTPUTS (include two spare bits, each)
Muon12 : out std_logic_vector(29 downto 0);
Muon34 : out std_logic_vector(29 downto 0);
-- VME port
vme_addr : in std_logic_vector(19 downto 1);
vme_data : inout std_logic_vector(15 downto 0);
vme_en_SRT : in std_logic;
vme_wr_SRT : in std_logic;
vme_ndtack_SRT : out std_logic; -- low active
vme_nirq_SRT : out std_logic; -- low active
-- Readout Data Port
ro_data_SRT : out std_logic_vector(23 downto 0);
ro_rdfifo_SRT : in std_logic;
ro_fetch_SRT : in std_logic;
l1a_SRT : in std_logic; -- Level-1 accept
bcreset_SRT : in std_logic; -- Bunch Counter reset
l1reset_SRT : in std_logic; -- Level-1 reset
-- Clock and control
clk_SRT : in std_logic;
clk_test_SRT : out std_logic; -- clock1x from DCM
clk_out_SRT : out std_logic; -- clock output for feedback (use optional)
-- same as clk_test
clk_fb_SRT : in std_logic; -- clock feedback input (use optional)
dcm_locked_SRT : out std_logic; -- DCM is locked => goes to VME chip
reset_dcm : in std_logic; -- crate reset (crate reset button and after
-- power-up) => resets DCM
inactive : in std_logic; -- from front panel button (to GTS)
reset_SRT : in std_logic; -- hard reset from trigger control
--
-- register input
-- same function as level-1 reset
-- or hard reset from trigger control
--
-- generated by VME chip
-- resets only state machines, FFs,
-- counters, error flags
-- but not memories and registers
status_SRT : out std_logic_vector(1 downto 0);
test_SRT : out std_logic_vector(3 downto 0);
dummyb : in std_logic);
end;
architecture behavioral of SortFPGA is
attribute syn_useioff : boolean;
attribute syn_useioff of behavioral : architecture is true;
constant date_string : string := "$Date: 2006/06/02 09:29:39 $";
-- signal clk_frombuf : std_logic; -- not used by Hannes
-- signal RST_i : std_logic; -- not used by Hannes
signal clk, clk80 : std_logic; --clk80 included 1.6.2006
-- registered inputs
signal sMuons_reg : TGMTMu_vector(0 to 7);
signal sSortRanks_reg : TSortRank_vector(0 to 7);
signal sIdxBits_reg : TIndexBits_vector(0 to 7);
signal sIsRPCMu_reg : std_logic_vector (0 to 7);
signal reset : std_logic;
-- output signals
signal oMuons : TGMTMu_vector(0 to 3);
signal sMuxMuons : TGMTMu_vector(0 to 3);
signal sSimMuons0, sSimMuons1, sSimMuons2, sSimMuons3 : TGMTMu_flat;
signal oIdxBits : TIndexBits_vector(0 to 3);
signal oIsRPCMu : std_logic_vector(0 to 3);
signal oIsFwd : std_logic_vector(0 to 3);
signal oSortRanks : TSortRank_vector(0 to 3);
signal sEmpty : std_logic_vector(0 to 7);
signal vme_addr_i : std_logic_vector (vme_addr'range);
signal vme_data_i : std_logic_vector (vme_data'range);
signal vme_en_i : std_logic;
signal vme_wr_i : std_logic;
-- VME data and enable from various units
signal vme_data_out_i : TVMEData_vec (0 to 15);
signal vme_en_out_i : TVMEEnable_vec (0 to 15);
-- VME data muxed
signal vme_data_out_muxed : std_logic_vector (15 downto 0);
signal vme_en_out_muxed : std_logic;
-- readout data
signal ro_rdfifo_reg : std_logic;
signal ro_fetch_reg : std_logic;
signal l1a_reg : std_logic; -- Level-1 accept
signal bcreset_reg : std_logic; -- Bunch Counter reset
signal bcreset_or_dummy : std_logic; -- Bunch Counter reset
signal l1reset_reg : std_logic; -- Level-1 reset
signal ro_data_i : std_logic_vector(23 downto 0);
-- readout data
signal readout_data : TReadoutData_vec(0 to 13);
signal spy_data : TReadoutData_vec(0 to 4);
signal sSimulatedData : TReadoutData_vec(0 to 4);
signal mon_data : TReadoutMonData_vec(0 to 29); -- 2x15 words
signal sSimuMode : std_logic;
signal sDummyIsBCReset : std_logic;
signal sBCReset_pre : std_logic;
signal sBCReset_main : std_logic;
signal sBXCount : std_logic_vector(11 downto 0); -- the bx count
-- signal addrb_i : std_logic_vector(9 downto 0); -- not used by Hannes
signal sDummy : std_logic_vector(15 downto 0);
signal dummy_reg : std_logic;
signal dummy_reg_d : std_logic;
signal dummy_pulse : std_logic;
signal clk_fb_reg : std_logic;
signal sOutMuons_brl_104_reg : std_logic;
signal sOutMuons_fwd_104_reg : std_logic;
signal OutMuons_brl_reg : TFourGMTMu_flat; -- 30nov2005 input registers in 'flat'format
begin
-------------------------------------------------------------------------------
-- register inputs
-------------------------------------------------------------------------------
-- muons
register_inputs : process (clk, reset) is
begin
if reset = '1' then
ro_rdfifo_reg <= '0';
ro_fetch_reg <= '0';
dummy_reg <= '0';
dummy_reg_d <= '0';
elsif (clk'event and clk = '1') then
sSortRanks_reg(0 to 3) <= SortRanks_brl;
sSortRanks_reg(4 to 7) <= SortRanks_fwd;
sMuons_reg(4 to 7) <= GMTMu_vec_from_flat( OutMuons_fwd );
-- 30nov2005: replace original registers by the loop below
-- sMuons_reg(0 to 3) <= GMTMu_vec_from_flat( OutMuons_brl );
-- sOutMuons_brl_104_reg <= OutMuons_brl(104);
sOutMuons_fwd_104_reg <= OutMuons_fwd(104);
sIdxBits_reg(0 to 3) <= IdxBits_brl(0 to 3);
sIdxBits_reg(4 to 7) <= IdxBits_fwd(0 to 3);
sIsRPCMu_reg(0 to 3) <= IsRPCMu_brl(0 to 3);
sIsRPCMu_reg(4 to 7) <= IsRPCMu_fwd(0 to 3);
ro_rdfifo_reg <= ro_rdfifo_SRT;
ro_fetch_reg <= ro_fetch_SRT;
clk_fb_reg <= clk_fb_SRT;
dummy_reg <= dummyb;
dummy_reg_d <= dummy_reg;
-- 30nov2005: Connect spare bit 104 instead of bad bit 56
for i in 0 to 103 loop
if (i=56) then
OutMuons_brl_reg(56) <= OutMuons_brl(104);
else
OutMuons_brl_reg(i) <= OutMuons_brl(i);
end if;
end loop;
-- 30nov2005: Also keep bad bit 56 and connect it to dummy
sOutMuons_brl_104_reg <= OutMuons_brl(56);
end if;
end process register_inputs;
-- 30nov2005: Convert registered barrel muons to vector format
sMuons_reg(0 to 3) <= GMTMu_vec_from_flat( OutMuons_brl_reg );
-- Dummy pulse
dummy_pulse <= dummy_reg and (not dummy_reg_d);
check_empty : for i in 0 to 7 generate
sEmpty(i) <= '1'when sMuons_reg(i).pt = "00000" else '0';
end generate; -- i
-----------------------------------------------------------------------------
-- Sorter
-----------------------------------------------------------------------------
sorter : entity work.SFSortStage2
port map (
iSortRanks => sSortRanks_reg,
iEmpty => sEmpty,
iMuons => sMuons_reg,
oMuons => oMuons,
iIdxBits => sIdxBits_reg,
oIdxBits => oIdxBits,
iIsRPCMu => sIsRPCMu_reg,
oIsRPCMu => oIsRPCMu,
oIsFwd => oIsFwd,
oSortRanks => oSortRanks,
clk => clk,
sinit => reset);
-----------------------------------------------------------------------------
-- Mux simulated data with muons
-----------------------------------------------------------------------------
muxProc: process(sSimulatedData)
begin
for i in 0 to 25 loop
sSimMuons0(i) <= sSimulatedData(0)(i); -- convert TReadoutData_vec to
-- TGMTMu_flat
sSimMuons1(i) <= sSimulatedData(1)(i);
sSimMuons2(i) <= sSimulatedData(2)(i);
sSimMuons3(i) <= sSimulatedData(3)(i);
end loop;
end process muxProc;
sMuxMuons(0) <= GMTMu_from_flat(sSimMuons0) when (sSimuMode = '1') else oMuons(0);
sMuxMuons(1) <= GMTMu_from_flat(sSimMuons1) when (sSimuMode = '1') else oMuons(1);
sMuxMuons(2) <= GMTMu_from_flat(sSimMuons2) when (sSimuMode = '1') else oMuons(2);
sMuxMuons(3) <= GMTMu_from_flat(sSimMuons3) when (sSimuMode = '1') else oMuons(3);
-----------------------------------------------------------------------------
-- Double Data Rate Outputs
-----------------------------------------------------------------------------
-- 80 MHz FD added to receive muons correctly in GTL board
-- SFDOutput works without DDR regs
ddr_12 : entity work.SFDOutput
port map (
iMuon1 => sMuxMuons(0),
iMuon2 => sMuxMuons(1),
oMuon => Muon12(25 downto 0),
clk => clk,
clk80 => clk80);
ddr_34 : entity work.SFDOutput
port map (
iMuon1 => sMuxMuons(2),
iMuon2 => sMuxMuons(3),
oMuon => Muon34(25 downto 0),
clk => clk,
clk80 => clk80);
---------------------------------
-- Original code from Hannes S. with Double-Rate Registers
-- ddr_12 : entity work.SFDDROutput
-- port map (
-- iMuon1 => sMuxMuons(0),
-- iMuon2 => sMuxMuons(1),
-- oMuon => Muon12(25 downto 0),
-- clk => clk);
-- ddr_34 : entity work.SFDDROutput
-- port map (
-- iMuon1 => sMuxMuons(2),
-- iMuon2 => sMuxMuons(3),
-- oMuon => Muon34(25 downto 0),
-- clk => clk);
-------------------------------------
-- spare outputs
Muon12 (29 downto 26) <= "0000";
Muon34 (29 downto 26) <= "0000";
-----------------------------------------------------------------------------
-- register and decode TCS Signals
-----------------------------------------------------------------------------
tcs_decoder: entity work.TCSCommandDecoder
port map (
iL1A => l1a_SRT,
iBCReset => bcreset_SRT,
iL1Reset => l1reset_SRT,
oL1A => l1a_reg,
oBCReset => bcreset_reg,
oL1Reset => l1reset_reg,
oECReset => open, -- no event counter
clk => clk,
reset => reset);
-----------------------------------------------------------------------------
-- generate BCreset (dummy_pulse for testing, otherwise external bcreset)
-----------------------------------------------------------------------------
bcreset_or_dummy <= dummy_pulse when sDummyIsBCReset = '1' else
bcreset_reg;
-----------------------------------------------------------------------------
-- BX counter
-----------------------------------------------------------------------------
bxcounter : entity work.BXCounter
generic map (
reg_addr => SF_ReadoutSyncReg_addr,
bcreset_delay_reg_default => "0000000000010101")
port map (
iBCReset => bcreset_or_dummy,
oPreBCReset => sBCReset_pre,
oBCReset => sBCReset_main,
oBXCounter => sBXCount,
vme_addr => vme_addr_i,
vme_data => vme_data_i,
vme_en => vme_en_i,
vme_wr => vme_wr_i,
vme_data_out => vme_data_out_i(0),
vme_en_out => vme_en_out_i(0),
clk => clk,
reset => reset);
-----------------------------------------------------------------------------
-- Readout logic
-----------------------------------------------------------------------------
-- 14x 32bit readout data and (14+1)*2 = 30 registers
-- 30x 8bit monitoring data
-- assign readout data
readout_muons : for i in 0 to 7 generate
begin -- generate i
readout_data(i)(31) <= sIsRPCMu_reg(i);
readout_data(i)(30) <= '0' when (i < 4) else '1';
readout_data(i)(29 downto 26) <= sIdxBits_reg(i);
readout_data(i)(25 downto 0) <= GMTMu_to_flat(sMuons_reg(i));
end generate readout_muons;
gmt_muons: for i in 0 to 3 generate
begin -- generate gmt_muons
readout_data(i+8)(31) <= oIsRPCMu(i);
readout_data(i+8)(30) <= oIsFwd(i);
readout_data(i+8)(29 downto 26) <= oIdxBits(i);
readout_data(i+8)(25 downto 0) <= gmtmu_to_flat( oMuons(i) );
end generate gmt_muons;
readout_sortranks: for i in 0 to 3 generate
begin -- generate readout_sortranks
readout_data(12)((i+1)*8-1 downto i*8) <= sSortRanks_reg(i);
readout_data(13)((i+1)*8-1 downto i*8) <= sSortRanks_reg(i+4);
end generate readout_sortranks;
mon: for i in mon_data'range generate
begin -- generate mon_data
mon_data(i) <= (others => '0');
end generate mon;
readout_logic: entity work.ReadOutLogic
generic map (
nwords => 14,
lat_delay_reg_addr => SF_LATDelayReg_addr)
port map (
data => readout_data,
mondata => mon_data,
iBXCount => sBXCount,
iBCReset => bcreset_or_dummy,
iL1A => l1a_reg,
iL1Reset => l1reset_reg,
ro_data => ro_data_i,
ro_rdfifo => ro_rdfifo_reg,
ro_fetch => ro_fetch_reg,
vme_addr => vme_addr_i,
vme_data => vme_data_i,
vme_en => vme_en_i,
vme_wr => vme_wr_i,
vme_data_out => vme_data_out_i(2),
vme_en_out => vme_en_out_i(2),
clk => clk,
reset => reset);
-----------------------------------------------------------------------------
-- Simulation / Spy Logic
-----------------------------------------------------------------------------
--FIXME: in order to get the chip done, spy only one muon with a 4k buffer
--(this needs 8 out of the remaining 11 block rams in an XC2V2000)
-- In future need to change. (or move to an XC2V3000 chip)
make_spy_data: for i in 0 to 3 generate
begin -- generate make_spy_data
spy_data(i)(31) <= oIsRPCMu(i);
spy_data(i)(30) <= oIsFwd(i);
spy_data(i)(29 downto 26) <= oIdxBits(i);
spy_data(i)(25 downto 0) <= gmtmu_to_flat( oMuons(i) );
end generate make_spy_data;
spy_data(4) <= oSortRanks(3) & oSortRanks(2) & oSortRanks(1) & oSortRanks(0);
simuspy_logic: entity work.SimuSpyLogic
generic map (
depth1k => 1,
nwords => 5,
simuspyconfig_reg_addr => SF_SimuSpyConfig_addr,
spydepth_reg_addr => SF_SpyDepth_addr,
spyarmpulse_reg_addr => SF_SpyArmPulse_waddr,
spydone_reg_addr => SF_SpyDone_raddr,
simuspyram_vme_base_address => SF_SimuSpyRAM_base)
port map (
iData => spy_data,
iPreBCRes => sBCReset_pre,
iBCRes => sBCReset_main,
oData => sSimulatedData,
oSimuMode => sSimuMode,
oDummyIsBCReset => sDummyIsBCReset,
vme_addr => vme_addr_i,
vme_data => vme_data_i,
vme_en => vme_en_i,
vme_wr => vme_wr_i,
vme_data_out => vme_data_out_i(1),
vme_en_out => vme_en_out_i(1),
clk => clk,
reset => reset);
--TBD: use oSimuMode and oSimulatedData
-----------------------------------------------------------------------------
-- Chip ID and Revision
-- Revision 1.19: feed 0001 22nov2005
-- Revision 1.20: feed 0002 30nov2005
-- Revision 1.21: feed 0003 23may2006
-- Revision 1.22: feed 0004 29may2006
-- Revision 1.23: feed 0005 01jun2006
-----------------------------------------------------------------------------
ChipID: entity work.ChipIDRegisters
generic map (
idregisters_vme_base_address => SF_chip_id0_raddr,
chipID_h => 16#0001#, chipID_l => 16#9161#,
chipRev_h => 16#FEED#, chipRev_l => 16#0005#,
date_string => date_string)
port map (
vme_addr => vme_addr_i,
vme_en => vme_en_i,
vme_wr => vme_wr_i,
vme_data_out => vme_data_out_i(3),
vme_en_out => vme_en_out_i(3),
vme_clk => clk,
reset => reset);
-----------------------------------------------------------------------------
-- Dummy signals
-----------------------------------------------------------------------------
register_dummy: process (clk, reset) is
begin -- process register_dummy
if reset = '1' then
sDummy(0) <= '0';
else
if clk'event and clk = '1' then -- rising clock edge
sDummy(0) <= clk_fb_reg or sOutMuons_brl_104_reg or sOutMuons_fwd_104_reg;
end if;
end if;
end process register_dummy;
sDummy(15 downto 1) <= (others => '0');
-----------------------------------------------------------------------------
--* Dummy register
-----------------------------------------------------------------------------
dummy_register: entity work.VMEStatusReg
generic map (
my_vme_base_address => SF_dummy_raddr)
port map (
data => sDummy,
vme_addr => vme_addr_i,
vme_en => vme_en_i,
vme_wr => vme_wr_i,
vme_data_out => vme_data_out_i(4),
vme_en_out => vme_en_out_i(4),
vme_clk => clk,
reset => reset);
--FIXME
dummyvme : for i in 5 to 15 generate
begin -- generate dummyvme
vme_data_out_i(i) <= (others => '0');
vme_en_out_i(i) <= '0';
end generate dummyvme;
-------------------------------------------------------------------------------
-- multiplex VME outputs
-------------------------------------------------------------------------------
mux_vme(vme_data_out_i, vme_en_out_i, vme_data_out_muxed, vme_en_out_muxed);
-------------------------------------------------------------------------------
-- register outputs
-------------------------------------------------------------------------------
register_outputs : process (clk) is
begin
if (clk'event and clk = '1') then
ro_data_SRT <= ro_data_i;
end if;
end process register_outputs;
-----------------------------------------------------------------------------
-- VME Logic
-----------------------------------------------------------------------------
vme_logic: entity work.InChipVMELogic
port map (
vme_addr => vme_addr,
vme_data => vme_data,
vme_en => vme_en_SRT,
vme_wr => vme_wr_SRT,
vme_ndtack => vme_ndtack_SRT,
vme_nirq => vme_nirq_SRT,
vme_addr_i => vme_addr_i,
vme_data_i => vme_data_i,
vme_en_i => vme_en_i,
vme_wr_i => vme_wr_i,
vme_data_out => vme_data_out_muxed,
vme_en_out => vme_en_out_muxed,
clk => clk,
reset => reset);
-------------------------------------------------------------------------------
-- Digital Clock Management & Chip Startup
-------------------------------------------------------------------------------
-- 1.6.2006: A.T.: Changed to 80 MHz DCM unit
startup_dcm: entity work.StartupDCM80Virtex2
port map (
iResetToGSR => reset_SRT,
iTristateToGTS => inactive,
oResetNet => reset,
iClkFromPAD => clk_SRT,
oClkNet => clk,
oClk80 => clk80,
iResetDCM => reset_dcm,
oDCMLocked => dcm_locked_SRT);
-- Original code from Hannes without 80 MHz clock
-- startup_dcm: entity work.StartupDCMVirtex2
-- port map (
-- iResetToGSR => reset_SRT,
-- iTristateToGTS => inactive,
-- oResetNet => reset,
-- iClkFromPAD => clk_SRT,
-- oClkNet => clk,
-- iResetDCM => reset_dcm,
-- oDCMLocked => dcm_locked_SRT);
-- output clock on two pins
clk_out_SRT <= clk;
clk_test_SRT <= clk80; -- 1.6.2006 A.T: clk80 goes to test point
status_SRT <= "00"; --TODO!
test_SRT(0) <= sSimuMode;
test_SRT(1) <= sSimMuons0(0);
test_SRT(3) <= oMuons(0).phi(0);
test_SRT(2) <= sMuxMuons(0).phi(0);
end architecture behavioral;