From bc064cdff372b4f303557e95f997208f494f986b Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 20 Jun 2018 12:31:37 +0200 Subject: [PATCH] Working towards triggering with soda. --- mupix/.gitignore | 3 +- mupix/MupixSoda/sources/FrameGenerator.vhd | 168 ++++----- .../sources/LinearFeedbackShiftRegister.vhd | 52 +-- mupix/MupixSoda/sources/SodaBoard.vhd | 321 +++++++++++----- mupix/MupixSoda/sources/TriggerHandler.vhd | 343 ++++++++++++++++++ mupix/MupixSoda/trb3_periph.vhd | 74 +++- 6 files changed, 741 insertions(+), 220 deletions(-) create mode 100644 mupix/MupixSoda/sources/TriggerHandler.vhd diff --git a/mupix/.gitignore b/mupix/.gitignore index 7cce73c..1d34155 100644 --- a/mupix/.gitignore +++ b/mupix/.gitignore @@ -1,7 +1,6 @@ -version.vhd XilinxProjects .settings .library_mapping.xml .project .directory -vivado* \ No newline at end of file +vivado* diff --git a/mupix/MupixSoda/sources/FrameGenerator.vhd b/mupix/MupixSoda/sources/FrameGenerator.vhd index 935a6dc..143987c 100644 --- a/mupix/MupixSoda/sources/FrameGenerator.vhd +++ b/mupix/MupixSoda/sources/FrameGenerator.vhd @@ -5,92 +5,94 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity FrameGenerator is - port( - clk: in std_logic; --Taktsignal - reset: in std_logic; --Reset - trigger: in std_logic; --Startsignal zum Senden von Daten (wuerde sonst an MuPix gehen) - data_out: out std_logic_vector(31 downto 0); --Datenpaket variabler Laenge, immer 32 Bit lang - data_valid:out std_logic -- 1, wenn relevante Daten gesendet und mitgeschrieben werden sollte - ); + port( + clk : in std_logic; --Taktsignal + reset : in std_logic; --Reset + trigger : in std_logic; --Startsignal zum Senden von Daten (wuerde sonst an MuPix gehen) + data_out : out std_logic_vector(31 downto 0); --Datenpaket variabler Laenge, immer 32 Bit lang + data_valid : out std_logic; -- 1, wenn relevante Daten gesendet und mitgeschrieben werden sollte + data_finished : out std_logic); -- 1, wenn letztes datenwort gesendet wurde end FrameGenerator; - + architecture dataGeneration of FrameGenerator is - component LinearFeedbackShiftRegister - Port ( - lfsr_seed : in STD_LOGIC_VECTOR(3 downto 0); - output_number : out STD_LOGIC_VECTOR(3 downto 0); - clock : in std_logic; - reset : in std_logic; - start : in std_logic - ); - end component; - - type ZUSTAENDE is (waiting, header, data, trailer); - signal ZustandJetzt, Folge_Zustand: ZUSTAENDE; - signal counter: integer range 0 to 2**4 - 1; -- veraenderliches Datenpaket - signal trigger_edge : std_logic_vector(1 downto 0) := "00"; - signal lfsr_value, lfsr_value_i: std_logic_vector(3 downto 0); -- neuer Wert, der aus dem LinerFeedbackShiftRegister kommt - signal start_signal : std_logic := '0'; - -begin + component LinearFeedbackShiftRegister + port ( + lfsr_seed : in std_logic_vector(3 downto 0); + output_number : out std_logic_vector(3 downto 0); + clock : in std_logic; + reset : in std_logic; + start : in std_logic + ); + end component; + + type ZUSTAENDE is (waiting, header, data, trailer); + signal ZustandJetzt : ZUSTAENDE := waiting; + signal counter : integer range 0 to 2**4 - 1; -- veraenderliches Datenpaket + signal trigger_edge : std_logic_vector(1 downto 0) := "00"; + signal lfsr_value, lfsr_value_i : std_logic_vector(3 downto 0); -- neuer Wert, der aus dem LinerFeedbackShiftRegister kommt + signal start_signal : std_logic := '0'; + +begin + + lfsr1 : LinearFeedbackShiftRegister port map (clock => clk, reset => reset, output_number => lfsr_value, lfsr_seed => "0101", start => start_signal); + + trigger_edge_detect : process(clk) + begin + if rising_edge(clk) then + if reset = '1' then + trigger_edge <= "00"; + else + trigger_edge <= trigger_edge(0) & trigger; --dranhaengen beim vector, 01 ist der uebergang, der den Trigger darstellt + end if; + end if; + end process trigger_edge_detect; + + Z_Aenderung : process(clk) + begin + if rising_edge(clk) then + case ZustandJetzt is + when waiting => data_valid <= '0'; + data_finished <= '0'; + data_out <= (others => '0'); + if trigger_edge = "01" then + ZustandJetzt <= header; + else + ZustandJetzt <= waiting; + end if; + + when header => data_valid <= '1'; + data_out <= X"FABEABBA"; + ZustandJetzt <= data; + counter <= 0; + lfsr_value_i <= lfsr_value; + + when data => counter <= counter + 1; + if counter < to_integer(unsigned(lfsr_value_i)) then + data_valid <= '1'; + data_out <= std_logic_vector(to_unsigned(counter, 32)); + ZustandJetzt <= data; + else + ZustandJetzt <= trailer; + end if; + + when trailer => data_valid <= '1'; + data_finished <= '1'; + data_out <= X"BEEFBEEF"; + ZustandJetzt <= waiting; - lfsr1: LinearFeedbackShiftRegister port map ( clock=>clk, reset=>reset,output_number =>lfsr_value, lfsr_seed => "0101", start => start_signal); - - trigger_edge_detect : process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - trigger_edge <= "00"; - else - trigger_edge <= trigger_edge(0) & trigger;--dranhaengen beim vector, 01 ist der uebergang, der den Trigger darstellt - end if; - end if; - end process trigger_edge_detect; + end case; + end if; + end process Z_Aenderung; - Z_Aenderung: process(clk) - begin - if rising_edge(clk) then - case ZustandJetzt is - when waiting => data_valid <= '0'; - data_out <= (others => '0'); - if trigger_edge = "01" then - ZustandJetzt <= header; - else - ZustandJetzt <= waiting; - end if; - - when header => data_valid <= '1'; - data_out <= X"FABEABBA"; - ZustandJetzt <= data; - counter <= 0; - lfsr_value_i <= lfsr_value; - - when data => counter <= counter + 1; - if counter < to_integer(unsigned(lfsr_value_i)) then - data_valid <= '1'; - data_out <= std_logic_vector(to_unsigned(counter, 32)); - ZustandJetzt <= data; - else - ZustandJetzt <= trailer; - end if; - - when trailer => data_valid <= '1'; - data_out <= X"BEEFBEEF"; - ZustandJetzt <= waiting; - - end case; - end if; - end process Z_Aenderung; - - lfsr_val: process (clk) - begin - if (rising_edge(clk)) then - if ZustandJetzt = header then - start_signal <= '1'; - elsif ZustandJetzt = trailer then - start_signal <= '0'; - end if; - end if; - end process lfsr_val; + lfsr_val : process (clk) + begin + if (rising_edge(clk)) then + if ZustandJetzt = header then + start_signal <= '1'; + elsif ZustandJetzt = trailer then + start_signal <= '0'; + end if; + end if; + end process lfsr_val; end dataGeneration; diff --git a/mupix/MupixSoda/sources/LinearFeedbackShiftRegister.vhd b/mupix/MupixSoda/sources/LinearFeedbackShiftRegister.vhd index bfdfda7..1c01590 100644 --- a/mupix/MupixSoda/sources/LinearFeedbackShiftRegister.vhd +++ b/mupix/MupixSoda/sources/LinearFeedbackShiftRegister.vhd @@ -3,44 +3,44 @@ library IEEE; -use IEEE.STD_LOGIC_1164.ALL; - -use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; entity LinearFeedbackShiftRegister is - Port ( - lfsr_seed : in STD_LOGIC_VECTOR(3 downto 0); - output_number : out STD_LOGIC_VECTOR(3 downto 0); - clock : in std_logic; - reset : in std_logic; - start : in std_logic - ); + port ( + lfsr_seed : in std_logic_vector(3 downto 0); + output_number : out std_logic_vector(3 downto 0); + clock : in std_logic; + reset : in std_logic; + start : in std_logic + ); end LinearFeedbackShiftRegister; architecture Behavioral of LinearFeedbackShiftRegister is -signal lfsr_speicher : std_logic_vector(3 downto 0); -signal enable : std_logic := '0'; + signal lfsr_speicher : std_logic_vector(3 downto 0); + signal enable : std_logic := '0'; begin -output_number <= lfsr_speicher; + output_number <= lfsr_speicher; -lfsr_output: process(clock, reset) begin + lfsr_output : process(clock, reset) + begin if (reset = '1') then - lfsr_speicher <= (others => '1'); - enable <='0'; + lfsr_speicher <= (others => '1'); + enable <= '0'; elsif rising_edge(clock) then - if (start ='1' and enable = '0') then - lfsr_speicher <= lfsr_seed; - enable <= '1'; - elsif (start = '1' and enable = '1') then - lfsr_speicher(3) <= lfsr_speicher(0); - lfsr_speicher(2) <= lfsr_speicher(3) xor lfsr_speicher(0); - lfsr_speicher(1) <= lfsr_speicher(2); - lfsr_speicher(0) <= lfsr_speicher(1); - end if; + if (start = '1' and enable = '0') then + lfsr_speicher <= lfsr_seed; + enable <= '1'; + elsif (start = '1' and enable = '1') then + lfsr_speicher(3) <= lfsr_speicher(0); + lfsr_speicher(2) <= lfsr_speicher(3) xor lfsr_speicher(0); + lfsr_speicher(1) <= lfsr_speicher(2); + lfsr_speicher(0) <= lfsr_speicher(1); + end if; end if; -end process lfsr_output; + end process lfsr_output; end Behavioral; diff --git a/mupix/MupixSoda/sources/SodaBoard.vhd b/mupix/MupixSoda/sources/SodaBoard.vhd index 52b3bc1..0d38f26 100644 --- a/mupix/MupixSoda/sources/SodaBoard.vhd +++ b/mupix/MupixSoda/sources/SodaBoard.vhd @@ -7,104 +7,235 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity sodaBoard is - port( - clk_in : in std_logic ; --system clock - reset_in : in std_logic ; -- system reset - -- Slave bus - SLV_READ_IN : in std_logic; -- data shall be read - SLV_WRITE_IN : in std_logic; -- incoming data is meant for writing into some register - SLV_DATA_OUT : out std_logic_vector(31 downto 0);-- - SLV_DATA_IN : in std_logic_vector(31 downto 0);-- - SLV_ADDR_IN : in std_logic_vector(15 downto 0);-- defines the address which shall be read or written - SLV_ACK_OUT : out std_logic; -- high if data is put out - SLV_NO_MORE_DATA_OUT : out std_logic; -- - SLV_UNKNOWN_ADDR_OUT : out std_logic -- - ); + port( + clk_in : in std_logic; --system clock + reset_in : in std_logic; -- system reset + -- trigger and data logic from TRB + TIMING_TRG_IN : in std_logic; + LVL1_TRG_DATA_VALID_IN : in std_logic; + LVL1_VALID_TIMING_TRG_IN : in std_logic; + LVL1_VALID_NOTIMING_TRG_IN : in std_logic; + LVL1_INVALID_TRG_IN : in std_logic; + LVL1_TRG_TYPE_IN : in std_logic_vector(3 downto 0); + LVL1_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + LVL1_TRG_CODE_IN : in std_logic_vector(7 downto 0); + LVL1_TRG_INFORMATION_IN : in std_logic_vector(23 downto 0); + LVL1_INT_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + + --TRB data connections + FEE_TRG_RELEASE_OUT : out std_logic; + FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_WRITE_OUT : out std_logic; + FEE_DATA_FINISHED_OUT : out std_logic; + FEE_DATA_ALMOST_FULL_IN : in std_logic; + -- Slave bus + SLV_READ_IN : in std_logic; -- data shall be read + SLV_WRITE_IN : in std_logic; -- incoming data is meant for writing into some register + SLV_DATA_OUT : out std_logic_vector(31 downto 0); -- + SLV_DATA_IN : in std_logic_vector(31 downto 0); -- + SLV_ADDR_IN : in std_logic_vector(15 downto 0); -- defines the address which shall be read or written + SLV_ACK_OUT : out std_logic; -- high if data is put out + SLV_NO_MORE_DATA_OUT : out std_logic; -- + SLV_UNKNOWN_ADDR_OUT : out std_logic -- + ); end sodaBoard; architecture Behavioral of sodaBoard is - ---------------------------------- - --component of the frame generator - component FrameGenerator is - port( - clk: in std_logic; -- Taktsignal - reset: in std_logic; -- Reset - trigger: in std_logic; -- Startsignal zum Senden von Daten (wuerde sonst an MuPix gehen) - data_out: out std_logic_vector(31 downto 0); -- Datenpaket variabler Laenge, immer 32 Bit lang - data_valid:out std_logic -- 1, wenn relevante Daten gesendet und mitgeschrieben werden sollte - ); - end component FrameGenerator; - ---------------------------------- - --signals - signal readpointer, writepointer : integer range 0 to 17 := 0; -- pointers that tell, which one of the max 18 words shall be read or written - signal memory : std_logic_vector (18*32 - 1 downto 0) := (others => '0'); -- vector that can contain up to 18 32-bit words - signal single_word : std_logic_vector (31 downto 0); -- contains the actual word which is written out from the frame generator - signal start_generation : std_logic := '0'; -- start signal for the frame generator - signal data_valid : std_logic := '0'; -- logic that tells whether relevant data is put out from the frame generator - signal known_word : std_logic_vector(31 downto 0) := x"abcdefab"; - begin - -- port map for frame generator - framegen1: FrameGenerator port map( clk => clk_in, reset => reset_in, trigger => start_generation, data_out => single_word, data_valid => data_valid); + ---------------------------------- + --component of the frame generator + component FrameGenerator is + port( + clk : in std_logic; -- Taktsignal + reset : in std_logic; -- Reset + trigger : in std_logic; -- Startsignal zum Senden von Daten (wuerde sonst an MuPix gehen) + data_out : out std_logic_vector(31 downto 0); -- Datenpaket variabler Laenge, immer 32 Bit lang + data_valid : out std_logic; -- 1, wenn relevante Daten gesendet und mitgeschrieben werden sollte + data_finished : out std_logic + ); + end component FrameGenerator; + ---------------------------------- + + + ---------------------------------- + --component of the trigger handler + component TriggerHandler is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + TIMING_TRIGGER_IN : in std_logic; + LVL1_TRG_DATA_VALID_IN : in std_logic; + LVL1_VALID_TIMING_TRG_IN : in std_logic; + LVL1_VALID_NOTIMING_TRG_IN : in std_logic; + LVL1_INVALID_TRG_IN : in std_logic; + LVL1_TRG_TYPE_IN : in std_logic_vector(3 downto 0); + LVL1_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + LVL1_TRG_CODE_IN : in std_logic_vector(7 downto 0); + FEE_DATA_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_WRITE_OUT : out std_logic; + FEE_DATA_FINISHED_OUT : out std_logic; + FEE_TRG_RELEASE_OUT : out std_logic; + FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_0_IN : in std_logic_vector(31 downto 0); + FEE_DATA_WRITE_0_IN : in std_logic; + FEE_DATA_FINISHED_IN : in std_logic; + bypass_trigger : in std_logic; + reset_trigger_state : in std_logic; + VALID_TRIGGER_OUT : out std_logic; + trigger_handler_state_o : out std_logic_vector(7 downto 0); + trigger_rate_acc_o : out std_logic_vector(31 downto 0); + trigger_rate_tot_o : out std_logic_vector(31 downto 0); + invalid_trigger_counter_o : out std_logic_vector(31 downto 0); + valid_trigger_counter_o : out std_logic_vector(31 downto 0)); + end component TriggerHandler; + + ---------------------------------- + + --signals + signal readpointer, writepointer : integer range 0 to 17 := 0; -- pointers that tell, which one of the max 18 words shall be read or written + signal memory : std_logic_vector (18*32 - 1 downto 0) := (others => '0'); -- vector that can contain up to 18 32-bit words + signal single_word : std_logic_vector (31 downto 0); -- contains the actual word which is written out from the frame generator + signal start_generation : std_logic := '0'; -- start signal for the frame generator + signal start_generation_slow : std_logic := '0'; + signal start_generation_trigger : std_logic := '0'; + signal data_valid : std_logic := '0'; -- logic that tells whether relevant data is put out from the frame generator + signal data_finished : std_logic := '0'; + signal known_word : std_logic_vector(31 downto 0) := x"abcdefab"; + --control signals to trigger handler + signal bypass_trigger_i : std_logic := '1'; + signal reset_trigger_state_i : std_logic := '0'; + signal trigger_handler_state_i : std_logic_vector(7 downto 0); + signal trigger_rate_acc_i : std_logic_vector(31 downto 0); + signal trigger_rate_tot_i : std_logic_vector(31 downto 0); + signal invalid_trigger_counter_i : std_logic_vector(31 downto 0); + signal valid_trigger_counter_i : std_logic_vector(31 downto 0); + +begin + + start_generation <= start_generation_trigger or start_generation_slow; + + -- port map for frame generator + framegen1 : FrameGenerator port map(clk => clk_in, + reset => reset_in, + trigger => start_generation, + data_out => single_word, + data_valid => data_valid, + data_finished => data_finished); + + -- port map trigger handler + TriggerHandler_1 : entity work.TriggerHandler + port map ( + CLK_IN => CLK_IN, + RESET_IN => RESET_IN, + TIMING_TRIGGER_IN => TIMING_TRG_IN, + LVL1_TRG_DATA_VALID_IN => LVL1_TRG_DATA_VALID_IN, + LVL1_VALID_TIMING_TRG_IN => LVL1_VALID_TIMING_TRG_IN, + LVL1_VALID_NOTIMING_TRG_IN => LVL1_VALID_NOTIMING_TRG_IN, + LVL1_INVALID_TRG_IN => LVL1_INVALID_TRG_IN, + LVL1_TRG_TYPE_IN => LVL1_TRG_TYPE_IN, + LVL1_TRG_NUMBER_IN => LVL1_TRG_NUMBER_IN, + LVL1_TRG_CODE_IN => LVL1_TRG_CODE_IN, + FEE_DATA_OUT => FEE_DATA_OUT, + FEE_DATA_WRITE_OUT => FEE_DATA_WRITE_OUT, + FEE_DATA_FINISHED_OUT => FEE_DATA_FINISHED_OUT, + FEE_TRG_RELEASE_OUT => FEE_TRG_RELEASE_OUT, + FEE_TRG_STATUSBITS_OUT => FEE_TRG_STATUSBITS_OUT, + FEE_DATA_0_IN => single_word, + FEE_DATA_WRITE_0_IN => data_valid, + FEE_DATA_FINISHED_IN => data_finished, + bypass_trigger => bypass_trigger_i, + reset_trigger_state => reset_trigger_state_i, + VALID_TRIGGER_OUT => start_generation_trigger, + trigger_handler_state_o => trigger_handler_state_i, + trigger_rate_acc_o => trigger_rate_acc_i, + trigger_rate_tot_o => trigger_rate_tot_i, + invalid_trigger_counter_o => invalid_trigger_counter_i, + valid_trigger_counter_o => valid_trigger_counter_i); - ----------------------------------------------------------- - --TRB SLV-BUS Handler - ------------------------------------------------------------ - --Address Equivalents: - --0x0001: gen trigger - --0x0002: read word/write readpointer - slv_bus_handler: process (clk_in) is - begin - if rising_edge(clk_in) then - slv_data_out <= (others => '0'); - slv_ack_out <= '0'; - slv_no_more_data_out <= '0'; - slv_unknown_addr_out <= '0'; - if (slv_write_in = '1') then - case slv_addr_in is - when x"0001" => -- set trigger/start generation value - start_generation <= slv_data_in(0); - slv_ack_out <= '1'; - when x"0002" => -- write: readpointers value changing (word that might be read later) - if (to_integer(unsigned(slv_data_in(4 downto 0))) < 19) then - readpointer <= to_integer(unsigned(slv_data_in(4 downto 0))); - slv_ack_out <= '1'; - else - readpointer <= 0; - slv_ack_out <= '0'; - end if; - when x"0003" => known_word (7 downto 0) <= slv_data_in(7 downto 0); - slv_ack_out <= '1'; - when others => -- no useful address put in - slv_unknown_addr_out <= '1'; - end case; - end if; - if slv_read_in = '1' then - case slv_addr_in is - when x"0001" => -- read trigger value - slv_data_out(0) <= start_generation; - slv_ack_out <= '1'; - when x"0002" => -- read: get x-th word of the memory, value stored in the readpointer - slv_data_out <= memory(((readpointer + 1)*32 - 1) downto readpointer*32); - slv_ack_out <= '1'; - when x"0003" => slv_data_out <= known_word; - slv_ack_out <= '1'; - when others => -- no useful address put in - slv_unknown_addr_out <= '1'; - end case; - end if; - end if; - end process slv_bus_handler; + ----------------------------------------------------------- + --TRB SLV-BUS Handler + ------------------------------------------------------------ + --Address Equivalents: + --0x0001: gen trigger + --0x0002: read word/write readpointer + slv_bus_handler : process (clk_in) is + begin + if rising_edge(clk_in) then + slv_data_out <= (others => '0'); + slv_ack_out <= '0'; + slv_no_more_data_out <= '0'; + slv_unknown_addr_out <= '0'; + reset_trigger_state_i <= '1'; + + if (slv_write_in = '1') then + case slv_addr_in is + when x"0001" => -- set trigger/start generation value + start_generation_slow <= slv_data_in(0); + slv_ack_out <= '1'; + when x"0002" => -- write: readpointers value changing (word that might be read later) + if (to_integer(unsigned(slv_data_in(4 downto 0))) < 19) then + readpointer <= to_integer(unsigned(slv_data_in(4 downto 0))); + slv_ack_out <= '1'; + else + readpointer <= 0; + slv_ack_out <= '0'; + end if; + when x"0003" => + known_word (7 downto 0) <= slv_data_in(7 downto 0); + slv_ack_out <= '1'; + when x"0004" => + bypass_trigger_i <= slv_data_in(0); + slv_ack_out <= '1'; + when x"0005" => + reset_trigger_state_i <= '1'; + slv_ack_out <= '1'; + when others => -- no useful address put in + slv_unknown_addr_out <= '1'; + end case; + end if; + + if slv_read_in = '1' then + case slv_addr_in is + when x"0001" => -- read trigger value + slv_data_out(0) <= start_generation; + slv_ack_out <= '1'; + when x"0002" => -- read: get x-th word of the memory, value stored in the readpointer + slv_data_out <= memory(((readpointer + 1)*32 - 1) downto readpointer*32); + slv_ack_out <= '1'; + when x"0003" => slv_data_out <= known_word; + slv_ack_out <= '1'; + when x"0006" => + slv_data_out(7 downto 0) <= trigger_handler_state_i; + slv_ack_out <= '1'; + when x"0007" => + slv_data_out <= trigger_rate_acc_i; + slv_ack_out <= '1'; + when x"0008" => + slv_data_out <= trigger_rate_tot_i; + slv_ack_out <= '1'; + when x"0009" => + slv_data_out <= invalid_trigger_counter_i; + slv_ack_out <= '1'; + when x"000a" => + slv_data_out <= valid_trigger_counter_i; + slv_ack_out <= '1'; + when others => -- no useful address put in + slv_unknown_addr_out <= '1'; + end case; + end if; + end if; + end process slv_bus_handler; - word_generation: process (clk_in) is - begin - if reset_in = '1' then - writepointer <= 0; - memory <= (others => '0'); --reset clears memory and current value of writepointer - elsif rising_edge(clk_in) then - if data_valid = '1' then - memory ( (writepointer +1)*32 -1 downto writepointer*32 ) <= single_word; - writepointer <= writepointer + 1; - end if; - end if; - end process; + word_generation : process (clk_in) is + begin + if reset_in = '1' then + writepointer <= 0; + memory <= (others => '0'); --reset clears memory and current value of writepointer + elsif rising_edge(clk_in) then + if data_valid = '1' then + memory ((writepointer +1)*32 -1 downto writepointer*32) <= single_word; + writepointer <= writepointer + 1; + end if; + end if; + end process; end architecture; diff --git a/mupix/MupixSoda/sources/TriggerHandler.vhd b/mupix/MupixSoda/sources/TriggerHandler.vhd new file mode 100644 index 0000000..6b3d0c3 --- /dev/null +++ b/mupix/MupixSoda/sources/TriggerHandler.vhd @@ -0,0 +1,343 @@ +----------------------------------------------------------------------------- +-- Trigger Handler for TRBnet +-- Tobias Weber, University Mainz +----------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity TriggerHandler is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + + --Input Triggers + TIMING_TRIGGER_IN : in std_logic; -- The raw timing Trigger Signal + LVL1_TRG_DATA_VALID_IN : in std_logic; -- Data Trigger is valid + LVL1_VALID_TIMING_TRG_IN : in std_logic; -- Timin Trigger is valid + LVL1_VALID_NOTIMING_TRG_IN : in std_logic; -- calib trigger w/o ref time + LVL1_INVALID_TRG_IN : in std_logic; + + LVL1_TRG_TYPE_IN : in std_logic_vector(3 downto 0); + LVL1_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + LVL1_TRG_CODE_IN : in std_logic_vector(7 downto 0); + + --Response from FEE + FEE_DATA_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_WRITE_OUT : out std_logic; + FEE_DATA_FINISHED_OUT : out std_logic; + FEE_TRG_RELEASE_OUT : out std_logic; + FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); + + FEE_DATA_0_IN : in std_logic_vector(31 downto 0); + FEE_DATA_WRITE_0_IN : in std_logic; + FEE_DATA_FINISHED_IN : in std_logic; + + bypass_trigger : in std_logic; + reset_trigger_state : in std_logic; + + -- OUT + VALID_TRIGGER_OUT : out std_logic; + trigger_handler_state_o : out std_logic_vector(7 downto 0); + trigger_rate_acc_o : out std_logic_vector(31 downto 0); + trigger_rate_tot_o : out std_logic_vector(31 downto 0); + invalid_trigger_counter_o : out std_logic_vector(31 downto 0); + valid_trigger_counter_o : out std_logic_vector(31 downto 0)); +end entity TriggerHandler; + + +architecture behavioral of TriggerHandler is + +--trigger + signal reset_trigger_state_edge : std_logic_vector(1 downto 0) := "00"; + signal valid_trigger_int : std_logic := '0'; + signal timing_trigger_edge : std_logic_vector(1 downto 0) := "00"; + signal trigger_busy_int : std_logic := '0'; + signal buffer_readout_end_int : std_logic_vector(1 downto 0) := "00"; +--fee + signal fee_data_int : std_logic_vector(31 downto 0) := (others => '0'); + signal fee_data_write_int : std_logic := '0'; + signal fee_data_finished_int : std_logic := '0'; + signal fee_trg_release_int : std_logic := '0'; + signal fee_trg_statusbit_int : std_logic_vector(31 downto 0) := (others => '0'); +--event buffer + +--registers + signal reset_trigger_counters : std_logic := '0'; + signal reset_trigger_counters_edge : std_logic_vector(1 downto 0) := (others => '0'); + signal trigger_rate_acc : unsigned(31 downto 0) := (others => '0'); + signal trigger_rate_tot : unsigned(31 downto 0) := (others => '0'); + signal trigger_rate_time_counter : unsigned(31 downto 0) := (others => '0'); + signal invalid_trigger_counter : unsigned(31 downto 0) := (others => '0'); + signal valid_trigger_counter : unsigned(31 downto 0) := (others => '0'); + signal invalid_trigger_counter_t : unsigned(31 downto 0) := (others => '0'); + signal valid_trigger_counter_t : unsigned(31 downto 0) := (others => '0'); + signal trigger_handler_state : std_logic_vector(7 downto 0) := (others => '0'); + +--trigger types + constant c_trigger_physics_type : std_logic_vector(3 downto 0) := x"1"; + constant c_trigger_status_type : std_logic_vector(3 downto 0) := x"e"; + +--trigger handler + type trigger_handler_type is (idle, + timing_trigger, + no_timing_trigger, + check_trigger_type, + status_trigger, + write_data_to_ipu, + trigger_release_a, + trigger_release_b, + trigger_release_c, + wait_trigger_release, + ignore, + wait_trigger_data_valid_a, + wait_trigger_data_valid_b); + + type trigger_type_type is (t_timing, + t_physics, + t_status, + t_ignore, + t_unknown); + + signal trigger_handler_fsm : trigger_handler_type := idle; + signal trigger_type : trigger_type_type := t_unknown; + signal wr_header_int : std_logic := '0'; + signal wr_data_int : std_logic := '0'; + signal wr_status_int : std_logic := '0'; + signal wr_dummy_int : std_logic := '0'; + +begin + + Signal_Edge_Detect : process(CLK_IN) is + begin -- process Mupix_Readout_End_Detect + if rising_edge(CLK_IN) then + if reset_in = '1' then + buffer_readout_end_int <= (others => '0'); + timing_trigger_edge <= (others => '0'); + reset_trigger_state_edge <= (others => '0'); + else + timing_trigger_edge <= timing_trigger_edge(0) & TIMING_TRIGGER_IN; + reset_trigger_state_edge <= reset_trigger_state_edge(1) & reset_trigger_state; + end if; + end if; + end process Signal_Edge_Detect; + + ------------------------------------------------------------ + --Handling of LVL1 triggers + ------------------------------------------------------------ + trigger_handler_proc : process(clk_in) is + begin -- process trigger_handler_proc + if rising_edge(CLK_IN) then + trigger_busy_int <= '1'; + fee_trg_release_int <= '0'; + wr_header_int <= '0'; + wr_data_int <= '0'; + wr_status_int <= '0'; + wr_dummy_int <= '0'; + valid_trigger_int <= '0'; + fee_data_finished_int <= '0'; + fee_trg_release_int <= '0'; + if reset_in = '1' or LVL1_INVALID_TRG_IN = '1' or reset_trigger_state_edge = "01" then + valid_trigger_int <= '0'; + fee_data_finished_int <= '0'; + fee_trg_release_int <= '0'; + fee_trg_statusbit_int <= (others => '0'); + trigger_busy_int <= '1'; + fee_trg_release_int <= '0'; + wr_header_int <= '0'; + wr_data_int <= '0'; + wr_status_int <= '0'; + wr_dummy_int <= '0'; + else + case trigger_handler_fsm is + when idle => + trigger_busy_int <= '0'; + trigger_handler_state <= x"01"; + if LVL1_VALID_TIMING_TRG_IN = '1' then + wr_header_int <= '1'; + if bypass_trigger = '1' then + trigger_type <= t_ignore; + trigger_handler_fsm <= ignore; + else + trigger_type <= t_timing; + trigger_handler_fsm <= timing_trigger; + end if; + elsif (LVL1_VALID_NOTIMING_TRG_IN = '1') then + wr_header_int <= '1'; + if bypass_trigger = '1' then + trigger_type <= t_ignore; + trigger_handler_fsm <= ignore; + else + trigger_handler_fsm <= check_trigger_type; + end if; + end if; + + when check_trigger_type => + trigger_handler_state <= x"02"; + if (LVL1_TRG_DATA_VALID_IN = '1') then + if (LVL1_TRG_TYPE_IN = c_trigger_status_type) then + trigger_type <= t_status; + trigger_handler_fsm <= no_timing_trigger; + elsif (LVL1_TRG_TYPE_IN = c_trigger_physics_type) then + trigger_type <= t_physics; + trigger_handler_fsm <= no_timing_trigger; + else + --unknown trigger + trigger_type <= t_unknown; + trigger_handler_fsm <= no_timing_trigger; + end if; + else + trigger_handler_fsm <= check_trigger_type; + end if; + + when timing_trigger => --starts mupix readout fsm + trigger_handler_state <= x"03"; + valid_trigger_int <= '1'; + trigger_handler_fsm <= write_data_to_ipu; + + when no_timing_trigger => + trigger_handler_state <= x"04"; + if trigger_type = t_physics then + trigger_handler_fsm <= timing_trigger; + elsif trigger_type = t_status then + trigger_handler_fsm <= status_trigger; + else + trigger_handler_fsm <= ignore; + end if; + + when ignore => + wr_dummy_int <= '1'; --write a dummy value to identify inactive FEE + trigger_handler_state <= x"05"; + trigger_handler_fsm <= wait_trigger_data_valid_b; + + when status_trigger => --dummy implementation + trigger_handler_state <= x"06"; + wr_status_int <= '1'; + trigger_handler_fsm <= wait_trigger_data_valid_b; + + when write_data_to_ipu => + trigger_handler_state <= x"0A"; + wr_data_int <= '1'; + if buffer_readout_end_int = "10" then + wr_data_int <= '0'; + trigger_handler_fsm <= wait_trigger_data_valid_a; + else + trigger_handler_fsm <= write_data_to_ipu; + end if; + + when wait_trigger_data_valid_a => + trigger_handler_state <= x"0B"; + if LVL1_TRG_DATA_VALID_IN = '1' then + trigger_handler_fsm <= wait_trigger_data_valid_b; + end if; + + when wait_trigger_data_valid_b => + trigger_handler_state <= x"0C"; + trigger_handler_fsm <= trigger_release_a; + + when trigger_release_a => + trigger_handler_state <= x"0D"; + trigger_handler_fsm <= trigger_release_b; + + when trigger_release_b => + trigger_handler_state <= x"0E"; + fee_data_finished_int <= '1'; + trigger_handler_fsm <= trigger_release_c; + + when trigger_release_c => + trigger_handler_state <= x"0F"; + fee_trg_release_int <= '1'; + trigger_handler_fsm <= wait_trigger_release; + + when wait_trigger_release => + if (LVL1_TRG_DATA_VALID_IN = '1') then + trigger_handler_fsm <= wait_trigger_release; + else + trigger_handler_fsm <= idle; + end if; + end case; + end if; + end if; + end process trigger_handler_proc; + + ------------------------------------------------------------ + --Data Output Mux + ------------------------------------------------------------ + Data_Out_Mux : process(clk_in) is + begin -- process Data_Out_Mux + if rising_edge(clk_in) then + if Reset_in = '1' then + fee_data_write_int <= '0'; + fee_data_int <= (others => '0'); + else + if wr_header_int = '1' then + fee_data_write_int <= '1'; --header see Hades DAQ user guide + fee_data_int <= "001" & "0" & LVL1_TRG_TYPE_IN & LVL1_TRG_CODE_IN & LVL1_TRG_NUMBER_IN; + elsif wr_data_int = '1' then + fee_data_write_int <= FEE_DATA_WRITE_0_IN; + fee_data_int <= FEE_DATA_0_IN; + elsif wr_status_int = '1' then + fee_data_int <= x"deadbeef"; + fee_data_write_int <= '1'; + elsif wr_dummy_int = '1' then + fee_data_write_int <= '1'; + fee_data_int <= x"ffeeddcc"; + else + fee_data_write_int <= '0'; + fee_data_int <= (others => '1'); + end if; + end if; + end if; + end process Data_Out_Mux; + + + ------------------------------------------------------------ + --Trigger statistics + ------------------------------------------------------------ + Trigger_Statistics_Proc : process(clk_in) is + begin -- process Trigger_Statistics_Proc + if rising_edge(CLK_IN) then + reset_trigger_counters_edge <= reset_trigger_counters_edge(0) & reset_trigger_counters; + if reset_trigger_counters_edge = "01" or RESET_IN = '1' then + trigger_rate_acc <= (others => '0'); + invalid_trigger_counter_t <= (others => '0'); + valid_trigger_counter_t <= (others => '0'); + trigger_rate_time_counter <= (others => '0'); + else + if trigger_rate_time_counter < x"5f5e100" then --1s at 10ns clock period + --if trigger_rate_time_counter < x"000007e" then + trigger_rate_time_counter <= trigger_rate_time_counter + 1; + if valid_trigger_int = '1' then + valid_trigger_counter_t <= valid_trigger_counter_t + 1; + elsif LVL1_INVALID_TRG_IN = '1' or (trigger_busy_int = '1' and timing_trigger_edge = "01") then + invalid_trigger_counter_t <= invalid_trigger_counter_t + 1; + end if; + else + valid_trigger_counter <= valid_trigger_counter + valid_trigger_counter_t; + invalid_trigger_counter <= invalid_trigger_counter + invalid_trigger_counter_t; + trigger_rate_acc <= valid_trigger_counter_t; + trigger_rate_tot <= valid_trigger_counter_t + invalid_trigger_counter_t; + trigger_rate_time_counter <= (others => '0'); + valid_trigger_counter_t <= (others => '0'); + invalid_trigger_counter_t <= (others => '0'); + end if; + end if; + end if; + end process Trigger_Statistics_Proc; + + --map output signals + valid_trigger_out <= valid_trigger_int; + fee_data_out <= fee_data_int; + fee_data_write_out <= fee_data_write_int; + fee_data_finished_out <= fee_data_finished_int; + fee_trg_release_out <= fee_trg_release_int; + fee_trg_statusbits_out <= fee_trg_statusbit_int; + + trigger_handler_state_o <= trigger_handler_state; + trigger_rate_acc_o <= std_logic_vector(trigger_rate_acc); + trigger_rate_tot_o <= std_logic_vector(trigger_rate_tot); + invalid_trigger_counter_o <= std_logic_vector(invalid_trigger_counter); + valid_trigger_counter_o <= std_logic_vector(valid_trigger_counter); + +end architecture behavioral; diff --git a/mupix/MupixSoda/trb3_periph.vhd b/mupix/MupixSoda/trb3_periph.vhd index c8ef0d7..cfe6447 100644 --- a/mupix/MupixSoda/trb3_periph.vhd +++ b/mupix/MupixSoda/trb3_periph.vhd @@ -91,15 +91,34 @@ architecture trb3_periph_arch of trb3_periph is port ( clk_in : in std_logic ; --system clock reset_in : in std_logic ; -- system reset + -- trigger and data logic from TRB + TIMING_TRG_IN : in std_logic; + LVL1_TRG_DATA_VALID_IN : in std_logic; + LVL1_VALID_TIMING_TRG_IN : in std_logic; + LVL1_VALID_NOTIMING_TRG_IN : in std_logic; + LVL1_INVALID_TRG_IN : in std_logic; + LVL1_TRG_TYPE_IN : in std_logic_vector(3 downto 0); + LVL1_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + LVL1_TRG_CODE_IN : in std_logic_vector(7 downto 0); + LVL1_TRG_INFORMATION_IN : in std_logic_vector(23 downto 0); + LVL1_INT_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + + --TRB data connections + FEE_TRG_RELEASE_OUT : out std_logic; + FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_WRITE_OUT : out std_logic; + FEE_DATA_FINISHED_OUT : out std_logic; + FEE_DATA_ALMOST_FULL_IN : in std_logic; -- Slave bus SLV_READ_IN : in std_logic; -- data shall be read - SLV_WRITE_IN : in std_logic; -- incoming data is meant for writing into some register - SLV_DATA_OUT : out std_logic_vector(31 downto 0);-- - SLV_DATA_IN : in std_logic_vector(31 downto 0);-- - SLV_ADDR_IN : in std_logic_vector(15 downto 0);-- defines the address which shall be read or written - SLV_ACK_OUT : out std_logic; -- high if data is put out - SLV_NO_MORE_DATA_OUT : out std_logic; -- - SLV_UNKNOWN_ADDR_OUT : out std_logic -- + SLV_WRITE_IN : in std_logic; -- incoming data is meant for writing into some register + SLV_DATA_OUT : out std_logic_vector(31 downto 0);-- + SLV_DATA_IN : in std_logic_vector(31 downto 0);-- + SLV_ADDR_IN : in std_logic_vector(15 downto 0);-- defines the address which shall be read or written + SLV_ACK_OUT : out std_logic; -- high if data is put out + SLV_NO_MORE_DATA_OUT : out std_logic; -- + SLV_UNKNOWN_ADDR_OUT : out std_logic -- ); end component; @@ -151,6 +170,14 @@ architecture trb3_periph_arch of trb3_periph is signal trg_spurious_trg_i : std_logic; signal trg_missing_tmg_trg_i : std_logic; signal trg_spike_detected_i : std_logic; + + --Data channel + signal fee_trg_release_i : std_logic_vector(NumberFEECards-1 downto 0); + signal fee_trg_statusbits_i : std_logic_vector(NumberFEECards*32-1 downto 0); + signal fee_data_i : std_logic_vector(NumberFEECards*32-1 downto 0); + signal fee_data_write_i : std_logic_vector(NumberFEECards-1 downto 0); + signal fee_data_finished_i : std_logic_vector(NumberFEECards-1 downto 0); + signal fee_almost_full_i : std_logic_vector(NumberFEECards-1 downto 0); --Slow Control channel signal common_stat_reg : std_logic_vector(std_COMSTATREG*32-1 downto 0); @@ -370,13 +397,13 @@ begin TRG_MISSING_TMG_TRG_OUT => trg_missing_tmg_trg_i, TRG_SPIKE_DETECTED_OUT => trg_spike_detected_i, - --Response from FEE, i.e. MuPix - FEE_TRG_RELEASE_IN(0) => open, - FEE_TRG_STATUSBITS_IN(0*32+31 downto 0*32) => open, - FEE_DATA_IN(0*32+31 downto 0*32) => open, - FEE_DATA_WRITE_IN(0) => open, - FEE_DATA_FINISHED_IN(0) => open, - FEE_DATA_ALMOST_FULL_OUT(0) => open, + --Response from FEE, i.e. Soda board + FEE_TRG_RELEASE_IN(0) => fee_trg_release_i(0), + FEE_TRG_STATUSBITS_IN(0*32+31 downto 0*32) => fee_trg_statusbits_i(0*32+31 downto 0*32), + FEE_DATA_IN(0*32+31 downto 0*32) => fee_data_i(0*32+31 downto 0*32), + FEE_DATA_WRITE_IN(0) => fee_data_write_i(0), + FEE_DATA_FINISHED_IN(0) => fee_data_finished_i(0), + FEE_DATA_ALMOST_FULL_OUT(0) => fee_almost_full_i(0), -- Slow Control Data Port REGIO_COMMON_STAT_REG_IN => common_stat_reg, --0x00 @@ -503,6 +530,25 @@ begin port map( clk_in => clk_100_i, --system clock reset_in => reset_i, -- system reset + --trigger logic + TIMING_TRG_IN => TRIGGER_RIGHT, + LVL1_TRG_DATA_VALID_IN => trg_data_valid_i, + LVL1_VALID_TIMING_TRG_IN => trg_timing_valid_i, + LVL1_VALID_NOTIMING_TRG_IN => trg_notiming_valid_i, + LVL1_INVALID_TRG_IN => trg_invalid_i, + LVL1_TRG_TYPE_IN => trg_type_i, + LVL1_TRG_NUMBER_IN => trg_number_i, + LVL1_TRG_CODE_IN => trg_code_i, + LVL1_TRG_INFORMATION_IN => trg_information_i, + LVL1_INT_TRG_NUMBER_IN => trg_int_number_i, + + --TRB data connections + FEE_TRG_RELEASE_OUT => fee_trg_release_i(0), + FEE_TRG_STATUSBITS_OUT => fee_trg_statusbits_i(0*32+31 downto 0*32), + FEE_DATA_OUT => fee_data_i(0*32+31 downto 0*32), + FEE_DATA_WRITE_OUT => fee_data_write_i(0), + FEE_DATA_FINISHED_OUT => fee_data_finished_i(0), + FEE_DATA_ALMOST_FULL_IN => fee_almost_full_i(0), -- Slave bus SLV_READ_IN =>sodaboard_regio_read_enable_in_0, -- data shall be read SLV_WRITE_IN =>sodaboard_regio_write_enable_in_0, -- incoming data is meant for writing into some register -- 2.43.0