]> jspc29.x-matter.uni-frankfurt.de Git - cri.git/commitdiff
new DLM to CTS entity. This entity substitutes the previously use MBS chain. A trigge...
authorAdrian Weber <adrian.a.weber@exp2.physik.uni-giessen.de>
Tue, 19 Jan 2021 15:26:18 +0000 (16:26 +0100)
committerAdrian Weber <adrian.a.weber@exp2.physik.uni-giessen.de>
Tue, 19 Jan 2021 15:26:18 +0000 (16:26 +0100)
src/DLM_CTS_generator.vhd [new file with mode: 0644]

diff --git a/src/DLM_CTS_generator.vhd b/src/DLM_CTS_generator.vhd
new file mode 100644 (file)
index 0000000..a9f2779
--- /dev/null
@@ -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;