From: Adrian Weber Date: Tue, 19 Jan 2021 15:26:18 +0000 (+0100) Subject: new DLM to CTS entity. This entity substitutes the previously use MBS chain. A trigge... X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=4406853fc6cb4423c0b5c2f72e94a0d9e920124e;p=cri.git new DLM to CTS entity. This entity substitutes the previously use MBS chain. A trigger is now generated from EACH DLM message. In case the DLM messag eis the same as in the DLM before, a subtrigger is counted up. A subtrigger is used to generate readouts inbetween microtimeslices. The DLM message itself indicates the microtimeslice index. Updates for higher stability and more features will follow. This is the first version of the entity. --- diff --git a/src/DLM_CTS_generator.vhd b/src/DLM_CTS_generator.vhd new file mode 100644 index 0000000..a9f2779 --- /dev/null +++ b/src/DLM_CTS_generator.vhd @@ -0,0 +1,270 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.trb3_components.all; + + +entity DLM_CTS_generator is + generic ( + INCL_REGIO : integer range c_NO to c_YES := c_YES + ); + port( + CLK : in std_logic; -- e.g. 100 MHz + RESET_IN : in std_logic; -- could be used after busy_release to make sure entity is in correct state + + -- recovered clock, synchronous to DLM + CLK_RCV : in std_logic; -- e.g. 240 MHz recovered from SERDES + + --DLM inputs + DLM_IN : in std_logic; -- DLM trigger + DLM_MSG_IN : in std_logic_vector(7 downto 0); -- DLM data word + + --trigger outputs + TRG_ASYNC_OUT : out std_logic; -- asynchronous rising edge, length varying, here: approx. 110 ns + TRG_SYNC_OUT : out std_logic; -- sync. to CLK + + --data output for read-out + TRIGGER_IN : in std_logic; + + -- Data connection to Streamer + DATA_OUT : out std_logic_vector(31 downto 0); + WRITE_OUT : out std_logic; + STATUSBIT_OUT : out std_logic_vector(31 downto 0) := (others => '0'); + FINISHED_OUT : out std_logic; + + --Registers / Debug + REGIO_IN : in CTRLBUS_RX := (data => x"00000000", addr => x"0000", others => '0'); + REGIO_OUT : out CTRLBUS_TX; + + + -- Ctrl and Status registers are only in use, if INCL_REGIO = c_NO ("ETM" mode) + CONTROL_REG_IN : in std_logic_vector(31 downto 0); + STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0'); + HEADER_REG_OUT : out std_logic_vector( 1 downto 0); + DEBUG : out std_logic_vector(31 downto 0) + ); + + --attribute syn_useioff : boolean; + --no IO-FF for MBS input + --attribute syn_useioff of MBS_IN : signal is false; +end entity; + + +architecture DLM_CTS_generator_arch of DLM_CTS_generator is + + signal dlm_i : std_logic; + signal dlm_ii : std_logic; + signal dlm_iii : std_logic; + signal trg_async : std_logic; + + signal dlm_ready : std_logic := '0'; + + type rdo_state_t is (RDO_IDLE, RDO_WAIT, RDO_WRITE, RDO_FINISH); + signal rdostate : rdo_state_t; + + signal number_reg : std_logic_vector(7 downto 0); + signal subtrigger : std_logic_vector(7 downto 0) := x"00"; + + signal status_reg : std_logic_vector(1 downto 0); + signal error_reg : std_logic; + + signal trg_sync_i : std_logic; + signal last_trg_sync_i : std_logic; + + signal dlm_msg_i : std_logic_vector(7 downto 0); + signal last_DLM_in : std_logic_vector(7 downto 0); + + signal config_rdo_disable_i : std_logic; + + signal rec_counter_i : unsigned(31 downto 0) := (others => '0'); + signal act_counter_i : unsigned(31 downto 0) := (others => '0'); + signal high_counter_i : unsigned(31 downto 0) := (others => '0'); + + + +begin + HEADER_REG_OUT <= b"01"; -- we tell the CTS that we send one word of over DATA_OUT + + PROC_TRIG_ASYN: process + begin + wait until rising_edge(CLK_RCV); + dlm_i <= DLM_IN; + dlm_ii <= dlm_i; + dlm_iii <= dlm_ii; + trg_async <= dlm_i xor dlm_ii xor dlm_iii; + end process; + + TRG_ASYNC_OUT <= trg_async; + TRG_SYNC_OUT <= trg_sync_i; + + -- handle DLM message to generate the Microtimeslice ID from it. + -- If same DLM mes is incoming as before, this indicates a second trigger in the same microtimeslice. A subtrigger is increased. + + PROC_DLM_MSG: process + begin + wait until rising_edge(CLK); + if RESET_IN = '1' then + dlm_ready <= '1'; + trg_sync_i <= '0'; + last_trg_sync_i <= '0'; + last_DLM_in <= (others => '0'); + subtrigger <= x"00"; + rec_counter_i <= (others => '0'); + error_reg <= '0'; + else + trg_sync_i <= trg_async; -- high for 1 or 2 clock cycles. + last_trg_sync_i <= trg_sync_i; + + -- To Think About: use dlm_ready in this if? Better or worse? + if last_trg_sync_i = '0' and trg_sync_i = '1' then --rising edge detection + rec_counter_i <= rec_counter_i + 1;-- cntr for RegIO + + number_reg <= DLM_MSG_IN; -- wait until trigge rarrives + last_DLM_in <= DLM_MSG_IN; + + if DLM_MSG_IN = last_DLM_in then -- next trigger in same microtimeslice + subtrigger <= std_logic_vector(unsigned(subtrigger) + 1); + --if subtrigger = x"FF" then + -- error_reg <= '1'; + --end if; + else -- new microtimeslice + subtrigger <= x"00"; + end if; + + dlm_ready <= '1'; + end if; + + if rdostate = RDO_FINISH then + dlm_ready <= '0'; + error_reg <= '0'; + end if; + + status_reg <= "00"; + dlm_ready <= '1'; + + end if; + end process; + + + + PROC_RDO : process + begin + wait until rising_edge(CLK); + WRITE_OUT <= '0'; + FINISHED_OUT <= config_rdo_disable_i; + case rdostate is + when RDO_IDLE => + if TRIGGER_IN = '1' and config_rdo_disable_i = '0' then + if dlm_ready = '0' then + rdostate <= RDO_WAIT; + else + rdostate <= RDO_WRITE; + end if; + end if; + + when RDO_WAIT => + if dlm_ready = '1' then + rdostate <= RDO_WRITE; + end if; + + when RDO_WRITE => + rdostate <= RDO_FINISH; + DATA_OUT <= error_reg & status_reg & "0000" & '0' & x"00"& number_reg & subtrigger; + WRITE_OUT <= '1'; + + when RDO_FINISH => + FINISHED_OUT <= '1'; + rdostate <= RDO_IDLE; + end case; + end process; + + STATUSBIT_OUT(23) <= error_reg when rising_edge(CLK); + STATUS_REG_OUT <= error_reg & '1' & "000000" & x"00"& number_reg & subtrigger; -- TODO ?? --'0' was previously MBS_IN + DEBUG <= x"00000000"; + + +-- REGIO + GEN_REGIO: if INCL_REGIO = c_YES generate + proc_regio: process is + variable addr : integer range 0 to 3; + begin + wait until rising_edge(CLK); + + addr := to_integer(UNSIGNED(REGIO_IN.addr(1 downto 0))); + REGIO_OUT.rack <= REGIO_IN.read; + REGIO_OUT.wack <= REGIO_IN.write; + REGIO_OUT.nack <= '0'; + REGIO_OUT.unknown <= '0'; + REGIO_OUT.data <= (others => '0'); + + case addr is + when 0 => + REGIO_OUT.data( 1 downto 0) <= '0' & (not config_rdo_disable_i); + REGIO_OUT.data(7) <= error_reg; + REGIO_OUT.data(31 downto 8) <= x"00" & number_reg & subtrigger; + + when 1 => + REGIO_OUT.data <= std_logic_vector(rec_counter_i); + + when 2 => + REGIO_OUT.data <= (others => '0');--std_logic_vector(act_counter_i); + + when 3 => + REGIO_OUT.data <= (others => '0');--std_logic_vector(high_counter_i); + + end case; + + if REGIO_IN.write='1' then + if addr=0 then + config_rdo_disable_i <= not REGIO_IN.data(0); + else + REGIO_OUT.unknown <= '1'; + end if; + end if; + + if RESET_IN = '1' then + config_rdo_disable_i <= '0'; + end if; + end process; + +-- proc_stats: process is +-- variable this_mbs : std_logic; +-- variable last_mbs : std_logic; +-- variable last_trg_sync : std_logic; +-- begin +-- wait until rising_edge(CLK); +-- +-- this_mbs := reg_MBS_IN or reg_MBS_DELAY; +-- +-- -- if this_mbs = '1' then +-- -- high_counter_i <= high_counter_i + 1; +-- -- end if; +-- +-- --if trg_sync = '1' and last_trg_sync='0' then +-- -- rec_counter_i <= rec_counter_i + 1; +-- --end if; +-- +-- --if this_mbs /= last_mbs then +-- -- act_counter_i <= act_counter_i + 1; +-- --end if; +-- +-- --if RESET_IN='1' then +-- --high_counter_i <= (others => '0'); +-- -- rec_counter_i <= (others => '0'); +-- --act_counter_i <= (others => '0'); +-- --end if; +-- +-- last_trg_sync := trg_sync; +-- last_mbs := this_mbs; +-- end process; + end generate; + + GEN_NO_REGIO: if INCL_REGIO /= c_YES generate + config_rdo_disable_i <= CONTROL_REG_IN(0); + REGIO_OUT.unknown <= REGIO_IN.read or REGIO_IN.write; + end generate; +end architecture;