--******************************************************************************
--* @short Readout logic that goes into the Input or Sort FPGA
--*
--******************************************************************************
--* @author SAKULIN Hannes <hsakulin@dsy-srv5.cern.ch>
--* @version $Revision: 1.5 $
--* @date $Date: 2004/12/17 09:30:38 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_std.all;
use work.ReadOutBufTypes.all;
-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.all;
-- pragma translate_on
entity ReadOutLogic is
generic (
nwords : integer := 4; -- width of readout logic in 32bit words
-- not counting on 32bit reg for the bx counter
lat_delay_reg_addr : integer); -- address of LATENCY delay register
port (
data : in TReadoutData_vec(0 to nwords-1);
mondata : in TReadoutMonData_vec(0 to 2*(nwords+1)-1 );
iBXCount : in std_logic_vector(11 downto 0);
iBCReset : in std_logic; -- BCReset from input FF (decoded)
iL1A : in std_logic; -- L1A from input FF (decoded)
iL1Reset : in std_logic; -- clears the FIFO
-- VME port (for latency delay register)
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;
-- Readout port
ro_data : out std_logic_vector(23 downto 0);
ro_rdfifo : in std_logic;
ro_fetch : in std_logic;
-- Clock, control
clk : in std_logic;
reset : in std_logic
);
end entity ReadOutLogic;
architecture behavioral of ReadOutLogic is
signal sReadCounter : std_logic_vector(11 downto 0);
signal read_addr : std_logic_vector(8 downto 0);
signal bccnt_word32 : std_logic_vector(31 downto 0);
signal l1a_pulse : std_logic;
signal we_fifo : std_logic;
subtype TOutReg is std_logic_vector(15 downto 0);
type TOutReg_vec is array (integer range <>) of TOutReg;
signal out_regs : TOutReg_vec(0 to (2*(nwords+1))-1);
signal out_counter1 : integer := 0;
begin -- architecture behavioral
-----------------------------------------------------------------------------
-- Read counter and L1A pulse generator
-----------------------------------------------------------------------------
read_counter: entity work.BXReadCounter
generic map (
lat_delay_reg_addr => lat_delay_reg_addr)
port map (
iBCReset => iBCReset,
iL1A => iL1A,
oDo5BX => open,
oBXReadCounter => sReadCounter,
oL1A_pulse => l1a_pulse,
vme_addr => vme_addr,
vme_data => vme_data,
vme_en => vme_en,
vme_wr => vme_wr,
vme_data_out => vme_data_out,
vme_en_out => vme_en_out,
clk => clk,
reset => reset);
read_addr <= sReadCounter(8 downto 0); -- ring buffers are 512 steps long
-- need to delay the l1a pulse. l1a pulse comes synchronous with the
-- read address, but reading the data takes one cycle.
generate_fifo_we: process (clk, reset) is
begin -- process generate_fifo_we
if reset = '1' then
we_fifo <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
we_fifo <= l1a_pulse;
end if;
end process generate_fifo_we;
-----------------------------------------------------------------------------
-- instantiate the Readout Blocks
-----------------------------------------------------------------------------
bccnt_word32(31 downto 12) <= (others => '0');
bccnt_word32(11 downto 0) <= iBXCount;
rop_block_bc: entity work.ROPBlock32
port map (
data => bccnt_word32,
wr_addr => iBXCount(8 downto 0),
rd_addr => read_addr,
we_fifo => we_fifo,
rd_fifo => ro_rdfifo,
dout_low => out_regs(0),
dout_high => out_regs(1),
clk => clk,
sinit_fifo => iL1Reset);
per_dataword: for i in 0 to (nwords -1) generate
begin -- generate per_dataword
rop_block_data: entity work.ROPBlock32
port map (
data => data(i),
wr_addr => iBXCount(8 downto 0),
rd_addr => read_addr,
we_fifo => we_fifo,
rd_fifo => ro_rdfifo,
dout_low => out_regs((i+1)*2),
dout_high => out_regs((i+1)*2+1),
clk => clk,
sinit_fifo => iL1Reset);
end generate per_dataword;
-----------------------------------------------------------------------------
-- steering for readout of FIFOs
-----------------------------------------------------------------------------
select_output: process (clk, reset) is
variable out_counter : integer:= 0;
begin -- process select_output
if reset = '1' then
out_counter := 0;
out_counter1 <= out_counter;
elsif clk'event and clk = '1' then -- rising clock edge
if ro_rdfifo = '1' then
out_counter := 0;
else
if ro_fetch = '1' and (out_counter < ((nwords+1)*2-1)) then
out_counter := out_counter+1;
end if;
end if;
out_counter1 <= out_counter;
end if;
end process select_output;
ro_data(15 downto 0) <= out_regs(out_counter1);
ro_data(23 downto 16) <= mondata(out_counter1);
end architecture behavioral;