--input monitor and trigger generation logic
constant INCLUDE_TRIGGER_LOGIC : integer := c_YES;
constant INCLUDE_STATISTICS : integer := c_YES;
- constant TRIG_GEN_INPUT_NUM : integer := 16;
+ constant TRIG_GEN_INPUT_NUM : integer := 32;
constant TRIG_GEN_OUTPUT_NUM : integer := 4;
- constant MONITOR_INPUT_NUM : integer := 24;
+ constant MONITOR_INPUT_NUM : integer := 36;
constant USE_SINGLE_FIFO : integer := c_YES; -- single fifo for statistics
--Run wih 125 MHz instead of 100 MHz, use received clock from serdes or external clock input
add_file -vhdl -lib work "../../trbnet/optical_link/f_divider.vhd"
add_file -vhdl -lib work "../../trb3sc/code/load_settings.vhd"
add_file -vhdl -lib work "../../trb3sc/code/spi_master_generic.vhd"
-add_file -vhdl -lib work "../base/code/input_to_trigger_logic.vhd"
+add_file -vhdl -lib work "../base/code/input_to_trigger_logic_record.vhd"
add_file -vhdl -lib work "../base/code/input_statistics.vhd"
add_file -vhdl -lib work "../base/code/sedcheck.vhd"
DEBUG_TX_OUT => debug_tx,
--Trigger & Monitor
- MONITOR_INPUTS(19 downto 0) => INP(19 downto 0),
- MONITOR_INPUTS(23 downto 20) => trig_gen_out_i,
- TRIG_GEN_INPUTS => INP(15 downto 0),
+ MONITOR_INPUTS(31 downto 0) => INP(31 downto 0),
+ MONITOR_INPUTS(35 downto 32) => trig_gen_out_i,
+ TRIG_GEN_INPUTS => INP(31 downto 0),
TRIG_GEN_OUTPUTS => trig_gen_out_i,
LCD_OUT => lcd_out,
--SED
entity input_statistics is
generic(
- INPUTS : integer range 1 to 32 := 16;
+ INPUTS : integer range 1 to 96 := 16;
SINGLE_FIFO_ONLY : integer := 0
);
port(
signal inp_reg_last : std_logic_vector(INPUTS-1 downto 0);
signal inp_inv : std_logic_vector(INPUTS-1 downto 0);
signal inp_stretch : std_logic_vector(INPUTS-1 downto 0);
+signal inp_reg_95 : std_logic_vector(95 downto 0);
signal trigger_fifo : std_logic;
signal reset_cnt : std_logic;
signal timer_rst : std_logic;
-signal enable : std_logic_vector(31 downto 0);
-signal invert : std_logic_vector(31 downto 0);
+signal enable : std_logic_vector(95 downto 0);
+signal invert : std_logic_vector(95 downto 0);
signal rate : unsigned(31 downto 0);
signal fifo_cnt_in : std_logic_vector(17 downto 0);
signal fifo_wait,fifo_wait2,fifo_wait3 : std_logic;
signal fifo_empty : std_logic_vector(LAST_FIFO_NUM downto 0);
signal fifo_write : std_logic;
-signal fifo_select : integer range 0 to 31;
-signal fifo_in_sel : integer range 0 to 31;
+signal fifo_select : integer range 0 to 95;
+signal fifo_in_sel : integer range 0 to 95;
type cnt_t is array(0 to INPUTS-1) of unsigned(23 downto 0);
if ADDR_IN(6 downto 4) = "000" then
ACK_OUT <= '1';
case ADDR_IN(3 downto 0) is
- when x"0" => enable <= DATA_IN;
- when x"1" => invert <= DATA_IN;
+ when x"0" => enable(31 downto 0) <= DATA_IN;
+ when x"1" => invert(31 downto 0) <= DATA_IN;
when x"2" => rate <= unsigned(DATA_IN);
timer_rst <= '1';
+ when x"5" => enable(63 downto 32) <= DATA_IN;
+ when x"6" => invert(63 downto 32) <= DATA_IN;
+ when x"7" => enable(95 downto 64) <= DATA_IN;
+ when x"8" => invert(95 downto 64) <= DATA_IN;
+
when x"f" => trigger_fifo <= DATA_IN(0);
reset_cnt <= DATA_IN(1);
fifo_in_sel <= to_integer(unsigned(DATA_IN(20 downto 16)));
if ADDR_IN(6 downto 4) = "000" then
ACK_OUT <= '1';
case ADDR_IN(3 downto 0) is
- when x"0" => DATA_OUT <= enable;
- when x"1" => DATA_OUT <= invert;
+ when x"0" => DATA_OUT <= enable(31 downto 0);
+ when x"1" => DATA_OUT <= invert(31 downto 0);
when x"2" => DATA_OUT <= std_logic_vector(rate);
when x"3" => DATA_OUT <= timer;
when x"4" => DATA_OUT <= status_reg;
- when x"e" => DATA_OUT <= (others => '0'); DATA_OUT(INPUTS-1 downto 0) <= inp_reg;
+ when x"5" => DATA_OUT <= enable(63 downto 32);
+ when x"6" => DATA_OUT <= invert(63 downto 32);
+ when x"7" => DATA_OUT <= enable(95 downto 64);
+ when x"8" => DATA_OUT <= invert(95 downto 64);
+ when x"c" => DATA_OUT <= (others => '0'); DATA_OUT <= inp_reg_95(31 downto 0);
+ when x"d" => DATA_OUT <= (others => '0'); DATA_OUT <= inp_reg_95(63 downto 32);
+ when x"e" => DATA_OUT <= (others => '0'); DATA_OUT <= inp_reg_95(95 downto 64);
when x"f" => DATA_OUT <= (others => '0'); DATA_OUT(20 downto 16) <= std_logic_vector(to_unsigned(fifo_in_sel,5));
- DATA_OUT(12 downto 8) <= std_logic_vector(to_unsigned(INPUTS,5));
+ DATA_OUT(14 downto 8) <= std_logic_vector(to_unsigned(INPUTS,7));
DATA_OUT(15 downto 15) <= std_logic_vector(to_unsigned(SINGLE_FIFO_ONLY,1));
when others => DATA_OUT <= (others => '0');
end case;
inp_inv <= INPUT xor invert(INPUTS-1 downto 0);
inp_stretch <= (inp_inv or inp_stretch) and not inp_reg;
+inp_reg_95(INPUTS-1 downto 0) <= inp_reg;
+
process begin
wait until rising_edge(CLK);
inp_reg <= inp_inv or inp_stretch;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.trb_net_std.all;
+
+
+entity input_to_trigger_logic_record is
+ generic(
+ INPUTS : integer range 1 to 96 := 24;
+ OUTPUTS : integer range 1 to 8 := 4
+ );
+ port(
+ CLK : in std_logic;
+
+ INPUT : in std_logic_vector(INPUTS-1 downto 0);
+ OUTPUT : out std_logic_vector(OUTPUTS-1 downto 0);
+
+ BUS_RX : in CTRLBUS_RX;
+ BUS_TX : out CTRLBUS_TX
+ );
+end entity;
+
+
+architecture input_to_trigger_logic_arch of input_to_trigger_logic_record is
+constant register_bits : integer := (INPUTS-1)/32*32+32-1;
+type reg_t is array(0 to OUTPUTS-1) of std_logic_vector(register_bits downto 0);
+signal enable : reg_t;
+signal invert : std_logic_vector(register_bits downto 0);
+signal coincidence1 : std_logic_vector(register_bits downto 0);
+signal coincidence2 : std_logic_vector(register_bits downto 0);
+signal coin_in_1 : std_logic;
+signal coin_in_2 : std_logic;
+signal stretch_inp : std_logic_vector(register_bits downto 0);
+
+type inp_t is array(0 to 4) of std_logic_vector(INPUTS-1 downto 0);
+signal inp_shift : inp_t;
+
+signal inp_inv : std_logic_vector(INPUTS-1 downto 0);
+signal inp_long : std_logic_vector(INPUTS-1 downto 0);
+signal inp_verylong : std_logic_vector(INPUTS-1 downto 0);
+
+signal output_i : std_logic_vector(OUTPUTS-1 downto 0);
+signal out_reg : std_logic_vector(OUTPUTS-1 downto 0);
+signal got_coincidence : std_logic;
+signal coin_enable : std_logic;
+
+begin
+THE_CONTROL : process
+ variable outchan : integer range 0 to 7;
+ variable slice : integer range 0 to 3;
+begin
+ wait until rising_edge(CLK);
+ BUS_TX.ack <= '0';
+ BUS_TX.nack <= '0';
+ BUS_TX.unknown <= '0';
+ outchan := to_integer(unsigned(BUS_RX.addr(4 downto 2)));
+ slice := to_integer(unsigned(BUS_RX.addr(1 downto 0)));
+
+ if BUS_RX.write = '1' then
+ BUS_TX.ack <= '1';
+ if BUS_RX.addr(5) = '0' and outchan < OUTPUTS then
+ if slice=0 then enable(outchan)(31 downto 0) <= BUS_RX.data;
+ elsif slice=1 and INPUTS > 32 then enable(outchan)(63 downto 32) <= BUS_RX.data;
+ elsif slice=2 and INPUTS > 64 then enable(outchan)(95 downto 64) <= BUS_RX.data;
+ end if;
+ elsif BUS_RX.addr(5 downto 4) = "10" then
+ if slice=0 then
+ case BUS_RX.addr(3 downto 2) is
+ when "00" => stretch_inp(31 downto 0) <= BUS_RX.data;
+ when "01" => invert(31 downto 0) <= BUS_RX.data;
+ when "10" => coincidence1(31 downto 0)<= BUS_RX.data;
+ when "11" => coincidence2(31 downto 0)<= BUS_RX.data;
+ end case;
+ elsif slice=1 and INPUTS > 32 then
+ case BUS_RX.addr(3 downto 2) is
+ when "00" => stretch_inp(63 downto 32) <= BUS_RX.data;
+ when "01" => invert(63 downto 32) <= BUS_RX.data;
+ when "10" => coincidence1(63 downto 32)<= BUS_RX.data;
+ when "11" => coincidence2(63 downto 32)<= BUS_RX.data;
+ end case;
+ elsif slice=2 and INPUTS > 64 then
+ case BUS_RX.addr(3 downto 2) is
+ when "00" => stretch_inp(95 downto 64) <= BUS_RX.data;
+ when "01" => invert(95 downto 64) <= BUS_RX.data;
+ when "10" => coincidence1(95 downto 64)<= BUS_RX.data;
+ when "11" => coincidence2(95 downto 64)<= BUS_RX.data;
+ end case;
+ end if;
+ else
+ BUS_TX.nack <= '1';
+ BUS_TX.ack <= '0';
+ end if;
+ end if;
+ if BUS_RX.read = '1' then
+ BUS_TX.ack <= '1';
+ if BUS_RX.addr(5) = '0' and outchan < OUTPUTS then
+ if slice=0 then BUS_TX.data <= enable(outchan)(31 downto 0);
+ elsif slice=1 and INPUTS > 32 then BUS_TX.data <= enable(outchan)(63 downto 32);
+ elsif slice=2 and INPUTS > 64 then BUS_TX.data <= enable(outchan)(95 downto 64);
+ else BUS_TX.data <= (others => '0');
+ end if;
+ elsif BUS_RX.addr(5 downto 4) = "10" then
+ if slice=0 then
+ case BUS_RX.addr(3 downto 2) is
+ when "00" => BUS_TX.data <= stretch_inp(31 downto 0) ;
+ when "01" => BUS_TX.data <= invert(31 downto 0) ;
+ when "10" => BUS_TX.data <= coincidence1(31 downto 0);
+ when "11" => BUS_TX.data <= coincidence2(31 downto 0);
+ end case;
+ elsif slice=1 and INPUTS > 32 then
+ case BUS_RX.addr(3 downto 2) is
+ when "00" => BUS_TX.data <= stretch_inp(63 downto 32) ;
+ when "01" => BUS_TX.data <= invert(63 downto 32) ;
+ when "10" => BUS_TX.data <= coincidence1(63 downto 32);
+ when "11" => BUS_TX.data <= coincidence2(63 downto 32);
+ end case;
+ elsif slice=2 and INPUTS > 64 then
+ case BUS_RX.addr(3 downto 2) is
+ when "00" => BUS_TX.data <= stretch_inp(95 downto 64) ;
+ when "01" => BUS_TX.data <= invert(95 downto 64) ;
+ when "10" => BUS_TX.data <= coincidence1(95 downto 64);
+ when "11" => BUS_TX.data <= coincidence2(95 downto 64);
+ end case;
+ else BUS_TX.data <= (others => '0');
+ end if;
+ elsif BUS_RX.addr(5 downto 0) = "110000" then
+ BUS_TX.data(OUTPUTS-1 downto 0) <= out_reg;
+ BUS_TX.data(31 downto OUTPUTS) <= (others => '0');
+ elsif BUS_RX.addr(5 downto 0) = "110001" then
+ BUS_TX.data <= (others => '0');
+ BUS_TX.data( 6 downto 0) <= std_logic_vector(to_unsigned(INPUTS,7));
+ BUS_TX.data(11 downto 8) <= std_logic_vector(to_unsigned(OUTPUTS,4));
+ else
+ BUS_TX.nack <= '1';
+ BUS_TX.ack <= '0';
+ end if;
+ end if;
+
+end process;
+
+
+ inp_shift(0) <= (inp_inv or inp_shift(0)) and not (inp_shift(1) and not inp_inv);
+gen_shift: for i in 1 to 4 generate
+ inp_shift(i) <= inp_shift(i-1) when rising_edge(CLK);
+end generate;
+
+coin_enable <= or_all(coincidence1) when rising_edge(CLK);
+
+inp_inv <= INPUT xor invert(INPUTS-1 downto 0);
+inp_long <= inp_shift(0) or inp_shift(1);
+inp_verylong <= inp_shift(1) or inp_shift(2) or inp_shift(3) or inp_shift(4) when rising_edge(CLK);
+
+coin_in_1 <= or_all(coincidence1(INPUTS-1 downto 0) and inp_verylong) when rising_edge(CLK);
+coin_in_2 <= or_all(coincidence2(INPUTS-1 downto 0) and inp_verylong) when rising_edge(CLK);
+got_coincidence <= coin_in_1 and coin_in_2 and coin_enable when rising_edge(CLK);
+
+gen_outs : for i in 0 to OUTPUTS-1 generate
+ output_i(i) <= or_all(((inp_long and stretch_inp(INPUTS-1 downto 0)) or (inp_inv(INPUTS-1 downto 0) and not stretch_inp(INPUTS-1 downto 0))) and enable(i)(INPUTS-1 downto 0)) or got_coincidence;
+end generate;
+
+
+out_reg <= output_i when rising_edge(CLK);
+
+OUTPUT <= output_i;
+
+end architecture;
\ No newline at end of file
-- Trigger logic
---------------------------------------------------------------------------
gen_TRIG_LOGIC : if INCLUDE_TRIGGER_LOGIC = 1 generate
- THE_TRIG_LOGIC : input_to_trigger_logic
+ THE_TRIG_LOGIC : entity work.input_to_trigger_logic_record
generic map(
INPUTS => TRIG_GEN_INPUT_NUM,
OUTPUTS => TRIG_GEN_OUTPUT_NUM
INPUT => TRIG_GEN_INPUTS,
OUTPUT => TRIG_GEN_OUTPUTS,
- DATA_IN => bustrig_rx.data,
- DATA_OUT => bustrig_tx.data,
- WRITE_IN => bustrig_rx.write,
- READ_IN => bustrig_rx.read,
- ACK_OUT => bustrig_tx.ack,
- NACK_OUT => bustrig_tx.nack,
- ADDR_IN => bustrig_rx.addr
+ BUS_RX => bustrig_rx,
+ BUS_TX => bustrig_tx
);
end generate;
DAT_DATA_IN => handler_data_out,
DAT_DATA_OUT => regio_data_in,
DAT_READ_ENABLE_IN => handler_read,
- DAT_WRITE_ENABLE_IN => handler_read,
+ DAT_WRITE_ENABLE_IN => handler_write,
DAT_TIMEOUT_IN => regio_timeout_out,
DAT_DATAREADY_OUT => regio_dataready_in,
DAT_WRITE_ACK_OUT => regio_write_ack_in,
handler_write <= bus_debug_rx_out.write when debug_active = '1' else regio_write_enable_out;
bus_debug_tx_in.data <= regio_data_in;
- bus_debug_tx_in.ack <= regio_dataready_in or regio_write_ack_in;
+ bus_debug_tx_in.ack <= regio_dataready_in or regio_write_ack_in ;
bus_debug_tx_in.nack <= regio_no_more_data_in;
bus_debug_tx_in.unknown <= regio_unknown_addr_in;