From 076ac97905d2b6782324d34fc82c453f7065074f Mon Sep 17 00:00:00 2001 From: Jan Michel Date: Tue, 28 Jun 2022 16:48:37 +0200 Subject: [PATCH] add hades spill mon and R3B timestamp receiver options to CTS design --- code/hadesspillmon.vhd | 319 ++++++++++++++++++++++++++++++++ cts/config_compile_frankfurt.pl | 2 +- cts/config_spillmon.vhd | 212 +++++++++++++++++++++ cts/trb3sc_cts.prj | 35 ++++ cts/trb3sc_cts.vhd | 154 +++++++++++---- 5 files changed, 686 insertions(+), 36 deletions(-) create mode 100644 code/hadesspillmon.vhd create mode 100644 cts/config_spillmon.vhd diff --git a/code/hadesspillmon.vhd b/code/hadesspillmon.vhd new file mode 100644 index 0000000..002512c --- /dev/null +++ b/code/hadesspillmon.vhd @@ -0,0 +1,319 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.trb_net_components.all; + use work.trb_net_std.all; + use work.trb3_components.all; + use work.config.all; + +entity hadesspillmon is + generic( + INPUT_NUM : integer := 16 + ); + port( + CLK : in std_logic; + CLK_200 : in std_logic; + RESET : in std_logic; + + INP : in std_logic_vector(INPUT_NUM-1 downto 0); + START : in std_logic; + + BUS_RX : in CTRLBUS_RX; + BUS_TX : out CTRLBUS_TX + ); +end entity; + + +architecture arch of hadesspillmon is + + signal CONF_binwidth : integer range 0 to 65000 := 2000; + signal CONF_meanwidth : integer range 0 to 65000 := 2100; + signal CONF_disable : std_logic_vector(INPUT_NUM-1 downto 0); + signal CONF_recordoffset : unsigned(23 downto 0); + + signal inp_reg, inp_reg_last : std_logic_vector(INPUT_NUM-1 downto 0); + + type state_t is (RUN, SUMUP, MAKEMEAN, SAVE); + signal state : state_t; + + type count_arr is array(0 to INPUT_NUM-1) of unsigned(27 downto 0); + signal counter, counter_reg : count_arr; + signal counter_totalbin, counter_totalmean : unsigned(27 downto 0); + signal counter_maxbin, counter_minbin : unsigned(27 downto 0); + + signal timer : unsigned(27 downto 0); + signal timer_bin, timer_mean : integer range 0 to 65000; + signal reset_counter : std_logic := '0'; + + signal qffifo_data, qffifo_dout : std_logic_vector(31 downto 0); + signal qffifo_read, qffifo_write : std_logic; + signal qffifo_count : std_logic_vector(9 downto 0); + signal qffifo_empty, qffifo_full : std_logic; + signal qffifo_reset : std_logic := '1'; + + signal binfifo_data, binfifo_dout : std_logic_vector(15 downto 0); + signal binfifo_read, binfifo_write : std_logic; + signal binfifo_count : std_logic_vector(13 downto 0); + signal binfifo_empty, binfifo_full : std_logic; + signal binfifo_reset : std_logic := '1'; + signal binfifo_reset_1, binfifo_reset_2 : std_logic; + + signal qffifo_read_q, qffifo_read_qq : std_logic; + signal binfifo_read_q, binfifo_read_qq : std_logic; + + signal start_store, reg_start, last_start : std_logic; + signal start_counter : unsigned(23 downto 0); + signal triggered, reset_triggered : std_logic; + +begin +--------------------------------------------------------------------------- +-- Input Counters +--------------------------------------------------------------------------- + +inp_reg <= INP when rising_edge(CLK_200); +inp_reg_last <= inp_reg when rising_edge(CLK_200); +reg_start <= START when rising_edge(CLK); + + +gen_counters : for i in 0 to INPUT_NUM-1 generate + process begin + wait until rising_edge(CLK_200); + if reset_counter = '1' then + counter(i) <= (others => '0'); + elsif inp_reg(i) = '1' and inp_reg_last(i) = '0' and CONF_disable(i) = '0' then + counter(i) <= counter(i) + 1; + end if; + end process; +end generate; + +--------------------------------------------------------------------------- +-- Control State Machine +--------------------------------------------------------------------------- +PROC_CONTROL : process + variable i : integer range 0 to 16; +begin + wait until rising_edge(CLK); + timer_bin <= timer_bin + 1; + timer <= timer + 1; + reset_counter <= '0'; + binfifo_write <= '0'; + binfifo_reset_2 <= '0'; + triggered <= triggered and not reset_triggered; + last_start <= reg_start; + start_store <= start_store or (reg_start and not last_start); + + + case state is + when RUN => + if timer_bin = CONF_binwidth then + timer_bin <= 1; + timer_mean <= timer_mean + 1; + reset_counter <= '1'; + counter_reg <= counter; + counter_totalbin <= 0; + i := 0; + state <= SUMUP; + end if; + + when SUMUP => + counter_totalbin <= counter_totalbin + counter_reg(i); + if i = INPUT_NUM - 1 then + state <= MAKEMEAN; + else + i := i + 1; + end if; + + when MAKEMEAN => + counter_totalmean <= counter_totalmean + counter_totalbin; + if counter_maxbin < counter_totalbin then + counter_maxbin <= counter_totalbin; + end if; + + if start_counter = x"000001" then + binfifo_reset_2 <= '1'; + end if; + if start_counter /= 0 then + start_counter <= start_counter - 1; + end if; + if start_store = '1' then + start_store <= '0'; + triggered <= '1'; + start_counter <= CONF_recordoffset; + end if; + + binfifo_data <= counter_totalbin(15 downto 0); + binfifo_write <= not binfifo_full; + + if timer_mean = CONF_meanwidth then + state <= SAVE; + qffifo_write <= not qffifo_full; + qffifo_data <= x"8" & std_logic_vector(timer); + i := 0; + else + state <= RUN; + end if; + + when SAVE => + if i = 0 then + qffifo_data <= x"9" & std_logic_vector(counter_maxbin); + elsif i = 1 then + qffifo_data <= x"a" & std_logic_vector(counter_totalmean); + elsif i = 2 then + state <= RUN; + qffifo_write <= '0'; + counter_maxbin <= 0; + counter_totalmean <= 0; + timer_mean <= 0; + end if; + + i := i + 1; + + + end case; + if RESET = '1' then + state <= RUN; + timer_bin <= 0; + timer_mean <= 0; + reset_counter <= '1'; + counter_totalmean <= 0; + counter_totalbin <= 0; + triggered <= '0'; + end if; +end process; + + +--------------------------------------------------------------------------- +-- Data Fifo +--------------------------------------------------------------------------- +THE_QF_FIFO : entity work.fifo_36x512_oreg + port map ( + Data(31 downto 0) => qffifo_data, + Data(35 downto 32) => x"0", + Clock => CLK, + WrEn => qffifo_write, + RdEn => qffifo_read, + Reset => qffifo_reset, + AmFullThresh => "111111000", + Q(31 downto 0) => qffifo_dout, + WCNT => qffifo_count, + Empty => qffifo_empty, + Full => open, + AlmostFull => qffifo_full + ); + +THE_BIN_FIFO : entity work.fifo_18x8k_oreg + port map ( + Data(15 downto 0) => binfifo_data, + Data(17 downto 16) => "00", + Clock => CLK, + WrEn => binfifo_write, + RdEn => binfifo_read, + Reset => binfifo_reset, + AmFullThresh => "1111110100100", + Q(15 downto 0) => binfifo_dout, + WCNT => binfifo_count, + Empty => binfifo_empty, + Full => open, + AlmostFull => binfifo_full + ); + +binfifo_reset <= binfifo_reset_1 or binfifo_reset_2; + + + +--------------------------------------------------------------------------- +-- Slow Control +--------------------------------------------------------------------------- +PROC_REG : process begin + wait until rising_edge(CLK); + BUS_TX.ack <= '0'; + BUS_TX.nack <= '0'; + BUS_TX.unknown <= '0'; + BUS_TX.data <= (others => '0'); + + qffifo_reset <= '0'; + qffifo_read <= '0'; qffifo_read_q <= qffifo_read; qffifo_read_qq <= qffifo_read_q; + binfifo_read <= '0'; binfifo_read_q <= binfifo_read; binfifo_read_qq <= binfifo_read_q; + binfifo_reset_1 <= '0'; + reset_triggered <= '0'; + + if BUS_RX.read = '1' then + BUS_TX.ack <= '1'; + if BUS_RX.addr(7 downto 0) = x"00" then + BUS_TX.data(15 downto 0) <= std_logic_vector(to_unsigned(CONF_binwidth,16)); + BUS_TX.data(31 downto 16) <= std_logic_vector(to_unsigned(CONF_meanwidth,16)); + elsif BUS_RX.addr(7 downto 0) = x"01" then + BUS_TX.data <= (others => '0'); + elsif BUS_RX.addr(7 downto 0) = x"02" then + BUS_TX.data(9 downto 0) <= qffifo_count; + BUS_TX.data(14) <= qffifo_empty; + BUS_TX.data(15) <= qffifo_full; + BUS_TX.data(29 downto 16) <= binfifo_count; + BUS_TX.data(30) <= binfifo_empty; + BUS_TX.data(31) <= binfifo_full; + elsif BUS_RX.addr(7 downto 0) = x"03" then + BUS_TX.data(27 downto 0) <= std_logic_vector(counter_totalbin); + elsif BUS_RX.addr(7 downto 0) = x"04" then + BUS_TX.data(INPUT_NUM-1 downto 0) <= CONF_disable; + elsif BUS_RX.addr(7 downto 0) = x"05" then + BUS_TX.data(23 downto 0) <= std_logic_vector(CONF_recordoffset); + elsif BUS_RX.addr(7 downto 0) = x"06" then + BUS_TX.data(0) <= triggered; + BUS_TX.data(1) <= binfifo_full; + reset_triggered <= binfifo_full; + elsif BUS_RX.addr(7 downto 0) = x"10" then + if qffifo_empty = '1' then + BUS_TX.ack <= '0'; + BUS_TX.nack <= '1'; + else + BUS_TX.ack <= '0'; + qffifo_read <= '1'; + end if; + elsif BUS_RX.addr(7 downto 0) = x"11" then + if binfifo_empty = '1' then + BUS_TX.ack <= '0'; + BUS_TX.nack <= '1'; + else + BUS_TX.ack <= '0'; + binfifo_read <= '1'; + end if; + elsif BUS_RX.addr(7 downto 4) = x"2" then + BUS_TX.data <= x"0" & std_logic_vector(counter_reg(to_integer(unsigned(BUS_RX.addr(3 downto 0))))); + else + BUS_TX.ack <= '0'; + BUS_TX.unknown <= '1'; + end if; + end if; + if BUS_RX.write = '1' then + BUS_TX.ack <= '1'; + if BUS_RX.addr(7 downto 0) = x"00" then + CONF_binwidth <= to_integer(unsigned(BUS_RX.data(15 downto 0))); + CONF_meanwidth <= to_integer(unsigned(BUS_RX.data(31 downto 16))); + + elsif BUS_RX.addr(7 downto 0) = x"01" then + qffifo_reset <= BUS_RX.data(30); + binfifo_reset_1 <= BUS_RX.data(31); + elsif BUS_RX.addr(7 downto 0) = x"04" then + CONF_disable <= BUS_RX.data(INPUT_NUM-1 downto 0); + elsif BUS_RX.addr(7 downto 0) = x"05" then + CONF_recordoffset <= unsigned(BUS_RX.data(23 downto 0)); + else + BUS_TX.ack <= '0'; + BUS_TX.unknown <= '1'; + end if; + end if; + + if qffifo_read_qq = '1' then + BUS_TX.ack <= '1'; + BUS_TX.data <= qffifo_dout; + end if; + + if binfifo_read_qq = '1' then + BUS_TX.ack <= '1'; + BUS_TX.data(15 downto 0) <= binfifo_dout; + end if; +end process; + +end architecture; diff --git a/cts/config_compile_frankfurt.pl b/cts/config_compile_frankfurt.pl index f2124c6..840d113 100644 --- a/cts/config_compile_frankfurt.pl +++ b/cts/config_compile_frankfurt.pl @@ -2,7 +2,7 @@ TOPNAME => "trb3sc_cts", lm_license_file_for_synplify => "27020\@jspc29", #"27000\@lxcad01.gsi.de"; lm_license_file_for_par => "1702\@hadeb05.gsi.de", lattice_path => '/d/jspc29/lattice/diamond/3.11_x64', -synplify_path => '/d/jspc29/lattice/synplify/P-2019.09-SP1', +synplify_path => '/d/jspc29/lattice/synplify/R-2020.09-SP1', #synplify_command => "/d/jspc29/lattice/diamond/3.5_x64/bin/lin64/synpwrap -fg -options", #synplify_command => "/d/jspc29/lattice/synplify/J-2014.09-SP2/bin/synplify_premier_dp", diff --git a/cts/config_spillmon.vhd b/cts/config_spillmon.vhd new file mode 100644 index 0000000..219c583 --- /dev/null +++ b/cts/config_spillmon.vhd @@ -0,0 +1,212 @@ +library ieee; +USE IEEE.std_logic_1164.ALL; +use ieee.numeric_std.all; +use work.trb_net_std.all; +use work.trb_net16_hub_func.all; + +package config is + + +------------------------------------------------------------------------------ +--Begin of design configuration +------------------------------------------------------------------------------ + +--design options: backplane or front SFP, with or without GBE + constant USE_BACKPLANE : integer := c_NO; --c_YES doesn't work + constant USE_ADDON : integer := c_NO; + constant USE_RJADAPT : integer := c_NO; --!!! Change pin-out file! + constant INCLUDE_GBE : integer := c_YES; --c_NO doesn't work + +--Runs with 120 MHz instead of 100 MHz + constant USE_120_MHZ : integer := c_NO; + constant USE_200MHZOSCILLATOR : integer := c_YES; + constant USE_EXTERNAL_CLOCK : integer := c_YES; --'no' not implemented. + constant CLOCK_FAST_SELECT : integer := c_YES; --fast clock select (135us) or slow (280ms)? + +--Use sync mode, RX clock for all parts of the FPGA + constant USE_RXCLOCK : integer := c_NO; + +--Address settings + constant INIT_ADDRESS : std_logic_vector := x"F3C7"; + constant BROADCAST_SPECIAL_ADDR : std_logic_vector := x"62"; --62 for SFP, 63 for backplane + + + constant INCLUDE_UART : integer := c_NO; + constant INCLUDE_SPI : integer := c_YES; + constant INCLUDE_LCD : integer := c_NO; + constant INCLUDE_DEBUG_INTERFACE: integer := c_NO; + + --input monitor and trigger generation logic + constant INCLUDE_TDC : integer := c_NO; + constant INCLUDE_TRIGGER_LOGIC : integer := c_NO; + constant INCLUDE_STATISTICS : integer := c_YES; + constant TRIG_GEN_INPUT_NUM : integer := 18; + constant TRIG_GEN_OUTPUT_NUM : integer := 2; + constant MONITOR_INPUT_NUM : integer := 18; + + + constant FPGA_TYPE : integer := 3; --3: ECP3, 5: ECP5 + + + constant NUM_TDC_MODULES : integer range 1 to 4 := 1; -- number of tdc modules to implement + constant NUM_TDC_CHANNELS : integer range 1 to 65 := 33; -- number of tdc channels per module + constant NUM_TDC_CHANNELS_POWER2 : integer range 0 to 6 := 4; --the nearest power of two, for convenience reasons + constant DOUBLE_EDGE_TYPE : integer range 0 to 3 := 3; --double edge type: 0, 1, 2, 3 + -- 0: single edge only, + -- 1: same channel, + -- 2: alternating channels, + -- 3: same channel with stretcher + constant RING_BUFFER_SIZE : integer range 0 to 7 := 7; --ring buffer size: 0, 1, 2, 3, 7 --> change names in constraints file + --ring buffer size: 32,64,96,128,dyn + constant TDC_DATA_FORMAT : integer := 0; + + constant EVENT_BUFFER_SIZE : integer range 9 to 13 := 13; -- size of the event buffer, 2**N + constant EVENT_MAX_SIZE : integer := 1023; --maximum event size. Should not exceed + + constant GEN_BUSY_OUTPUT : integer := c_NO; + + constant TRIGGER_COIN_COUNT : integer := 0; + constant TRIGGER_PULSER_COUNT : integer := 3; + constant TRIGGER_RAND_PULSER : integer := 1; + constant TRIGGER_ADDON_COUNT : integer := 2; + constant PERIPH_TRIGGER_COUNT : integer := 0; + constant ADDON_LINE_COUNT : integer := 36 - USE_RJADAPT*12; --36 with Padiwa, 22 with RJ-adapter + constant CTS_OUTPUT_MULTIPLEXERS : integer := 0; +--TODO: +-- constant INCLUDE_MBS_MASTER : integer range c_NO to c_YES := c_NO; +--Which external trigger module (ETM) to use? + constant INCLUDE_ETM : integer range c_NO to c_YES := c_YES; + type ETM_CHOICE_type is (ETM_CHOICE_MBS_VULOM, ETM_CHOICE_MAINZ_A2, ETM_CHOICE_CBMNET, ETM_CHOICE_M26, ETM_CHOICE_R3B, ETM_CHOICE_SPILLMON); + constant ETM_CHOICE : ETM_CHOICE_type := ETM_CHOICE_SPILLMON; + constant ETM_ID : std_logic_vector(7 downto 0); + + constant INCLUDE_TIMESTAMP_GENERATOR : integer := c_NO; + + + +------------------------------------------------------------------------------ +--End of design configuration +------------------------------------------------------------------------------ + + type data_t is array (0 to 1023) of std_logic_vector(7 downto 0); + constant LCD_DATA : data_t := ( + others => x"00"); + + + type hub_mii_t is array(0 to 3) of integer; + type hub_ct is array(0 to 16) of integer; + type hub_cfg_t is array(0 to 3) of hub_ct; + type hw_info_t is array(0 to 3) of std_logic_vector(31 downto 0); + type intlist_t is array(0 to 7) of integer; +-- 0 opt. link opt. link +-- 0-7 SFP 1-8 +-- 1(8) CTS read-out internal 0 1 - X X O --downlink only +-- 2(9) CTS TRG Sctrl GbE 2 3 4 X X X --uplink only + + --Order: + -- no backplane, no AddOn, 1x SFP, 1x GBE +-- -- -- -- no backplane, 4x AddOn, 1x SFP, 1x GBE + -- no backplane, 8x AddOn, 0x SFP, 1x GBE +-- -- -- -- backplane, 9x backplane, 1x GBE + constant SFP_NUM_ARR : hub_mii_t := (1,0,8,0); + constant INTERFACE_NUM_ARR : hub_mii_t := (1,5,8,10); +-- 0 1 2 3 4 5 6 7 8 9 a b c d e f + constant IS_UPLINK_ARR : hub_cfg_t := ((0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + (0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0), +-- (0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0), + (0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), + (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); + constant IS_DOWNLINK_ARR : hub_cfg_t := ((1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + (1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0), +-- (1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0), + (1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0), + (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); + constant IS_UPLINK_ONLY_ARR : hub_cfg_t := ((0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + (0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0), + (0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), +-- (0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0), + (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); + + constant INTERFACE_NUM : integer; + constant IS_UPLINK : hub_ct; + constant IS_DOWNLINK : hub_ct; + constant IS_UPLINK_ONLY : hub_ct; + +------------------------------------------------------------------------------ +--Select settings by configuration +------------------------------------------------------------------------------ + constant cts_rdo_additional_ports : integer := INCLUDE_TDC + INCLUDE_TIMESTAMP_GENERATOR + INCLUDE_ETM; --for TDC + + constant HW_INFO_BASE : unsigned(31 downto 0) := x"9500A000"; + + constant CLOCK_FREQUENCY_ARR : intlist_t := (100,120, others => 0); + constant MEDIA_FREQUENCY_ARR : intlist_t := (200,240, others => 0); + + --declare constants, filled in body + constant HARDWARE_INFO : std_logic_vector(31 downto 0); + constant CLOCK_FREQUENCY : integer; + constant MEDIA_FREQUENCY : integer; + constant INCLUDED_FEATURES : std_logic_vector(63 downto 0); + + +end; + +package body config is +--compute correct configuration mode + + constant HARDWARE_INFO : std_logic_vector(31 downto 0) := std_logic_vector( + HW_INFO_BASE ); + constant CLOCK_FREQUENCY : integer := CLOCK_FREQUENCY_ARR(USE_120_MHZ); + constant MEDIA_FREQUENCY : integer := MEDIA_FREQUENCY_ARR(USE_120_MHZ); + + constant CFG_MODE : integer := USE_ADDON*2;--*2 + USE_BACKPLANE; + + constant INTERFACE_NUM : integer := INTERFACE_NUM_ARR(CFG_MODE); + constant IS_UPLINK : hub_ct := IS_UPLINK_ARR(CFG_MODE); + constant IS_DOWNLINK : hub_ct := IS_DOWNLINK_ARR(CFG_MODE); + constant IS_UPLINK_ONLY : hub_ct := IS_UPLINK_ONLY_ARR(CFG_MODE); + + function etm_id_func return std_logic_vector is + variable res : unsigned(7 downto 0); + begin + res := x"00"; + if INCLUDE_ETM=c_YES then + res := x"60"; + res := res + TO_UNSIGNED(ETM_CHOICE_type'pos(ETM_CHOICE), 4); + end if; + return std_logic_vector(res); + end function; + + constant ETM_ID : std_logic_vector(7 downto 0) := etm_id_func; + + +function generateIncludedFeatures return std_logic_vector is + variable t : std_logic_vector(63 downto 0); + begin + t := (others => '0'); + t(63 downto 56) := std_logic_vector(to_unsigned(1,8)); --table version 1 + t(3 downto 0) := std_logic_vector(TO_UNSIGNED(ETM_CHOICE_type'pos(ETM_CHOICE), 4)); + t(7 downto 7) := std_logic_vector(to_unsigned(USE_RJADAPT,1)); + t(11 downto 8) := std_logic_vector(to_unsigned(DOUBLE_EDGE_TYPE,4)); + t(14 downto 12) := std_logic_vector(to_unsigned(RING_BUFFER_SIZE,3)); + t(15 downto 15) := std_logic_vector(to_unsigned(INCLUDE_TDC,1)); --TDC + t(16 downto 16) := std_logic_vector(to_unsigned(INCLUDE_GBE,1)); --data via GbE + t(17 downto 17) := std_logic_vector(to_unsigned(INCLUDE_GBE,1)); --sctrl via GbE + t(23 downto 23) := std_logic_vector(to_unsigned(INCLUDE_GBE,1)); + t(26 downto 24) := std_logic_vector(to_unsigned(SFP_NUM_ARR(CFG_MODE),3)); --num SFPs with TrbNet + t(28 downto 28) := std_logic_vector(to_unsigned(USE_BACKPLANE,1)); + t(40 downto 40) := std_logic_vector(to_unsigned(INCLUDE_LCD,1)); + t(42 downto 42) := std_logic_vector(to_unsigned(INCLUDE_SPI,1)); + t(43 downto 43) := std_logic_vector(to_unsigned(INCLUDE_UART,1)); + t(44 downto 44) := std_logic_vector(to_unsigned(INCLUDE_STATISTICS,1)); + t(51 downto 48) := std_logic_vector(to_unsigned(INCLUDE_TRIGGER_LOGIC,4)); + t(52 downto 52) := std_logic_vector(to_unsigned(USE_120_MHZ,1)); + t(53 downto 53) := std_logic_vector(to_unsigned(USE_RXCLOCK,1)); + t(54 downto 54) := std_logic_vector(to_unsigned(USE_EXTERNAL_CLOCK,1)); + t(55 downto 55) := std_logic_vector(to_unsigned(USE_200MHZOSCILLATOR,1)); + return t; + end function; + + constant INCLUDED_FEATURES : std_logic_vector(63 downto 0) := generateIncludedFeatures; + +end package body; diff --git a/cts/trb3sc_cts.prj b/cts/trb3sc_cts.prj index 1ad9b45..646d4a6 100644 --- a/cts/trb3sc_cts.prj +++ b/cts/trb3sc_cts.prj @@ -99,6 +99,7 @@ add_file -vhdl -lib work "../../trbnet/lattice/ecp3/fifo/fifo_18x256_oreg.vhd" add_file -vhdl -lib work "../../trbnet/lattice/ecp3/fifo/fifo_18x512_oreg.vhd" add_file -vhdl -lib work "../../trbnet/lattice/ecp3/fifo/fifo_18x1k_oreg.vhd" add_file -vhdl -lib work "../../trbnet/lattice/ecp3/fifo/fifo_18x2k_oreg.vhd" +add_file -vhdl -lib work "../../trbnet/lattice/ecp3/fifo/fifo_18x8k_oreg.vhd" add_file -vhdl -lib work "../../trbnet/lattice/ecp3/fifo/fifo_9x2k_oreg.vhd" add_file -vhdl -lib work "../../trbnet/lattice/ecp2m/fifo/fifo_var_oreg.vhd" add_file -vhdl -lib work "../../trbnet/lattice/ecp3/fifo/fifo_19x16_obuf.vhd" @@ -264,6 +265,9 @@ add_file -vhdl -lib work "../../trb3/cts/source/cts_trg_pseudorand_pulser.vhd" add_file -vhdl -lib work "../../trb3/cts/source/cts_trigger.vhd" add_file -vhdl -lib work "../../trb3/cts/source/cts.vhd" add_file -vhdl -lib work "../../trb3/base/code/mbs_vulom_recv.vhd" +add_file -vhdl -lib work "../../trb3/cts/source/r3b_timestamp_recv.vhd" +add_file -vhdl -lib work "../../trb3sc/code/hadesspillmon.vhd" + #TDC add_file -vhdl -lib work "../../trb3sc/tdc_release/tdc_version.vhd" @@ -297,6 +301,37 @@ add_file -vhdl -lib work "../../tdc/base/cores/ecp3/FIFO/FIFO_36x32_OutReg.vhd" add_file -vhdl -lib work "../../tdc/base/cores/ecp3/PLL/pll_in125_out33.vhd" +#R3B timestamps +add_file -vhdl -lib work "../../rataser-20211012/vhdl/generic/rataser_4phase_sample.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_4phase_deser.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_big_xor.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_clock_recv.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_clock_send.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_hamming_decode_dual.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_hamming_decode.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_hamming_encode.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_hamming_util.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_min_max_filter.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_records.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_signals_recv.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_signals_send.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_sym24word8_decode.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_sym24word8_diff.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_sym24word8_util.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_sym8word1_decode.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_symburst_decode.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_symburst_diff.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_symburst_util.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_sync_count.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_timestamp_decode.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_track_bitslots.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_track_bitstream.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_track_edge.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_trig_recv.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_trig_send.vhd" +add_file -vhdl -lib work "../../rataser-20211012/vhdl/rataser_util.vhd" + + add_file -vhdl -lib work "./trb3sc_cts.vhd" #add_file -fpga_constraint "./synplify.fdc" diff --git a/cts/trb3sc_cts.vhd b/cts/trb3sc_cts.vhd index 9c49e5d..9db196f 100644 --- a/cts/trb3sc_cts.vhd +++ b/cts/trb3sc_cts.vhd @@ -28,6 +28,7 @@ entity trb3sc_cts is SPARE_IN : in std_logic_vector( 1 downto 0); INP : in std_logic_vector(31-12*USE_RJADAPT downto 0); RJ_IO : out std_logic_vector( 3 downto 0); --0, inner RJ trigger output + RJ_IO_IN : in std_logic_vector( 1 downto 0); REFOUT : out std_logic_vector( 8*USE_RJADAPT-1 downto 0); --LED @@ -125,9 +126,9 @@ architecture trb3sc_arch of trb3sc_cts is signal med2int : med2int_array_t(0 to INTERFACE_NUM-1); signal int2med : int2med_array_t(0 to INTERFACE_NUM-1); - signal ctrlbus_rx, bussci1_rx, bussci2_rx, bussci3_rx, bustools_rx, buscts_rx, + signal ctrlbus_rx, bussci1_rx, bussci2_rx, bussci3_rx, bustools_rx, buscts_rx, busr3b_rx, bustc_rx, busgbeip_rx, busgbereg_rx, bus_master_out, handlerbus_rx, bustdc_rx : CTRLBUS_RX; - signal ctrlbus_tx, bussci1_tx, bussci2_tx, bussci3_tx, bustools_tx, buscts_tx, + signal ctrlbus_tx, bussci1_tx, bussci2_tx, bussci3_tx, bustools_tx, buscts_tx, busr3b_tx, bustc_tx, busgbeip_tx, busgbereg_tx, bus_master_in, bustdc_tx : CTRLBUS_TX; signal sed_error_i : std_logic; @@ -821,7 +822,7 @@ end generate; CLK => clk_sys, RESET_IN => reset_i, - MBS_IN => INP(0), + MBS_IN => RJ_IO_IN(1), CLK_200 => clk_full, TRG_ASYNC_OUT => mbs_async_out, --TODO MBS async connect to TDC @@ -845,15 +846,79 @@ end generate; ); end generate; + +--------------------------------------------------------------------------- +-- R3B Input Adapter +--------------------------------------------------------------------------- + gen_r3b_etm : if ETM_CHOICE = ETM_CHOICE_R3B and INCLUDE_ETM = c_YES generate + signal etm_trigger_in : std_logic; + begin + etm_trigger_in <= cts_rdo_rx.valid_timing_trg or cts_rdo_rx.valid_notiming_trg or cts_rdo_rx.invalid_trg; + + + THE_R3B : entity work.r3b_timestamp_recv + port map( + CLK => clk_sys, + CLK_SENDER => CLK_SUPPL_PCLK, --125 Mhz + RESET_IN => reset_i, + + SERIAL_IN => RJ_IO_IN(1), + SERIAL_OUT => RJ_IO(2), + TRG_SYNC_OUT => cts_ext_trigger, + + BUS_RX => busr3b_rx, + BUS_TX => busr3b_tx, + + --data output for read-out + TRIGGER_IN => etm_trigger_in, + DATA_OUT => cts_rdo_additional(0).data, + WRITE_OUT => cts_rdo_additional(0).data_write, + FINISHED_OUT => cts_rdo_additional(0).data_finished, + STATUSBIT_OUT => cts_rdo_additional(0).statusbits, + HEADER_REG_OUT => cts_ext_header, + + --Registers / Debug + CONTROL_REG_IN => cts_ext_control, + STATUS_REG_OUT => cts_ext_status + ); + end generate; + gen_nor3b_etm : if (ETM_CHOICE /= ETM_CHOICE_R3B and ETM_CHOICE /= ETM_CHOICE_SPILLMON) or INCLUDE_ETM = c_NO generate + busr3b_tx.unknown <= busr3b_rx.read or busr3b_rx.write when rising_edge(clk_sys); + end generate; + + +--------------------------------------------------------------------------- +-- Hades Spill Mon - not a real CTS module, but CTS framework needed +--------------------------------------------------------------------------- + gen_hsm_etm : if ETM_CHOICE = ETM_CHOICE_SPILLMON and INCLUDE_ETM = c_YES generate + THE_SPILLMON : entity work.hadesspillmon + port map( + CLK => clk_sys, + CLK_200 => clk_full, + RESET => reset_i, + + INP => INP(15 downto 0), + START => SPARE_IN(0), + + BUS_RX => busr3b_rx, + BUS_TX => busr3b_tx + ); + + cts_rdo_additional(0).data <= (others => '0'); + cts_rdo_additional(0).data_write <= '0'; + cts_rdo_additional(0).data_finished <= '1'; + cts_rdo_additional(0).statusbits <= (others => '0'); + end generate; + --------------------------------------------------------------------------- -- Bus Handler --------------------------------------------------------------------------- THE_BUS_HANDLER : entity work.trb_net16_regio_bus_handler_record generic map( - PORT_NUMBER => 9, - PORT_ADDRESSES => (0 => x"d000", 1 => x"d300", 2 => x"b000", 3 => x"b200", 4 => x"b400", 5 => x"8100", 6 => x"8300", 7 => x"a000", 8 => x"c000", others => x"0000"), - PORT_ADDR_MASK => (0 => 12, 1 => 1, 2 => 9, 3 => 9, 4 => 9, 5 => 8, 6 => 8, 7 => 11, 8 => 12, others => 0), + PORT_NUMBER => 10, + PORT_ADDRESSES => (0 => x"d000", 1 => x"d300", 2 => x"b000", 3 => x"b200", 4 => x"b400", 5 => x"8100", 6 => x"8300", 7 => x"a000", 8 => x"c000", 9 => x"b800", others => x"0000"), + PORT_ADDR_MASK => (0 => 12, 1 => 1, 2 => 9, 3 => 9, 4 => 9, 5 => 8, 6 => 8, 7 => 11, 8 => 12, 9 => 8, others => 0), PORT_MASK_ENABLE => 1 ) port map( @@ -872,6 +937,7 @@ end generate; BUS_RX(6) => busgbereg_rx, BUS_RX(7) => buscts_rx, BUS_RX(8) => bustdc_rx, + BUS_RX(9) => busr3b_rx, BUS_TX(0) => bustools_tx, BUS_TX(1) => bustc_tx, BUS_TX(2) => bussci1_tx, @@ -881,6 +947,7 @@ end generate; BUS_TX(6) => busgbereg_tx, BUS_TX(7) => buscts_tx, BUS_TX(8) => bustdc_tx, + BUS_TX(9) => busr3b_tx, STAT_DEBUG => open ); @@ -931,7 +998,7 @@ end generate; DEBUG_OUT => open ); -monitor_inputs_i <= cts_addon_triggers_in; --INP; +monitor_inputs_i <= cts_addon_triggers_in(MONITOR_INPUT_NUM-1 downto 0); --INP; gen_reboot_no_gbe : if INCLUDE_GBE = c_NO generate do_reboot_i <= common_ctrl_reg(15); @@ -966,6 +1033,12 @@ gen_reftime_out : if USE_RJADAPT = 1 generate end generate; RJ_IO(0) <= cts_trigger_out; + + +gen_busy : if GEN_BUSY_OUTPUT = c_YES generate + RJ_IO(3) <= trigger_busy_i; +end generate; + --------------------------------------------------------------------------- -- LED @@ -1013,34 +1086,45 @@ end generate; ------------------------------------------------------------------------------- -- TDC ------------------------------------------------------------------------------- - THE_TDC : entity work.TDC_record - generic map ( - CHANNEL_NUMBER => NUM_TDC_CHANNELS, -- Number of TDC channels per module - STATUS_REG_NR => 21, -- Number of status regs - DEBUG => c_YES, - SIMULATION => c_NO) - port map ( - RESET => reset_i, - CLK_TDC => clk_full_osc, - CLK_READOUT => clk_sys, -- Clock for the readout - REFERENCE_TIME => cts_trigger_out, -- Reference time input - HIT_IN => hit_in_i(NUM_TDC_CHANNELS-1 downto 1), -- Channel start signals - HIT_CAL_IN => clk_cal, -- Hits for calibrating the TDC - -- Trigger signals from handler - BUSRDO_RX => cts_rdo_rx, - BUSRDO_TX => cts_rdo_additional(INCLUDE_TIMESTAMP_GENERATOR + INCLUDE_ETM), - -- Slow control bus - BUS_RX => bustdc_rx, - BUS_TX => bustdc_tx, - -- Dubug signals - INFO_IN => timer, - LOGIC_ANALYSER_OUT => open - ); - - -- For single edge measurements - gen_single : if DOUBLE_EDGE_TYPE = 0 or DOUBLE_EDGE_TYPE = 1 or DOUBLE_EDGE_TYPE = 3 generate - hit_in_i(NUM_TDC_CHANNELS-1 downto 1) <= INP(NUM_TDC_CHANNELS-2 downto 0); - end generate; + --THE_TDC : entity work.TDC_record + --generic map ( + --CHANNEL_NUMBER => NUM_TDC_CHANNELS, -- Number of TDC channels per module + --STATUS_REG_NR => 21, -- Number of status regs + --DEBUG => c_YES, + --SIMULATION => c_NO) + --port map ( + --RESET => reset_i, + --CLK_TDC => clk_full_osc, + --CLK_READOUT => clk_sys, -- Clock for the readout + --REFERENCE_TIME => cts_trigger_out, -- Reference time input + --HIT_IN => hit_in_i(NUM_TDC_CHANNELS-1 downto 1), -- Channel start signals + --HIT_CAL_IN => clk_cal, -- Hits for calibrating the TDC + ---- Trigger signals from handler + --BUSRDO_RX => cts_rdo_rx, + --BUSRDO_TX => cts_rdo_additional(INCLUDE_TIMESTAMP_GENERATOR + INCLUDE_ETM), + ---- Slow control bus + --BUS_RX => bustdc_rx, + --BUS_TX => bustdc_tx, + ---- Dubug signals + --INFO_IN => timer, + --LOGIC_ANALYSER_OUT => open + --); + + ---- For single edge measurements + --gen_single : if ETM_CHOICE /= ETM_CHOICE_R3B generate + --hit_in_i(NUM_TDC_CHANNELS-1 downto 1) <= INP(NUM_TDC_CHANNELS-2 downto 0); + --end generate; + + --gen_TDC_R3B : if ETM_CHOICE = ETM_CHOICE_R3B generate + --hit_in_i(2 downto 1) <= SPARE_IN; + --hit_in_i(NUM_TDC_CHANNELS-1 downto 3) <= INP(NUM_TDC_CHANNELS-4 downto 0); + --end generate; + + +--Handle Control bus without TDC +gen_sctrl_dummy : if INCLUDE_TDC = c_NO generate + bustdc_tx.unknown <= bustdc_rx.read or bustdc_rx.write when rising_edge(clk_sys); +end generate; end architecture; -- 2.43.0