]> jspc29.x-matter.uni-frankfurt.de Git - dirich.git/commitdiff
entity to send data from event packer to API/CRI; not debugged yet
authorAdrian Weber <adrian.a.weber@exp2.physik.uni-giessen.de>
Thu, 2 Jul 2020 15:00:18 +0000 (17:00 +0200)
committerAdrian Weber <adrian.a.weber@exp2.physik.uni-giessen.de>
Thu, 2 Jul 2020 15:00:18 +0000 (17:00 +0200)
combiner_cts/cri/cri_data_sender.vhd [new file with mode: 0644]

diff --git a/combiner_cts/cri/cri_data_sender.vhd b/combiner_cts/cri/cri_data_sender.vhd
new file mode 100644 (file)
index 0000000..f08e432
--- /dev/null
@@ -0,0 +1,410 @@
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.std_logic_ARITH.ALL;
+USE IEEE.std_logic_UNSIGNED.ALL;
+library work;
+use work.trb_net_std.all;
+
+
+entity cri_data_sender is
+  port(
+    --  Misc
+    CLK                     : in std_logic;
+    RESET                   : in std_logic;
+    CLK_EN                  : in std_logic;
+    -- Port to API
+    API_DATA_OUT            : out std_logic_vector (c_DATA_WIDTH-1 downto 0);
+    API_PACKET_NUM_OUT      : out std_logic_vector (c_NUM_WIDTH-1  downto 0);
+    API_DATAREADY_OUT       : out std_logic;
+    API_READ_IN             : in  std_logic;
+    API_SHORT_TRANSFER_OUT  : out std_logic;
+    API_DTYPE_OUT           : out std_logic_vector (3 downto 0);
+    API_ERROR_PATTERN_OUT   : out std_logic_vector (31 downto 0);
+    API_SEND_OUT            : out std_logic;
+    -- Receiver port
+    API_DATA_IN             : in  std_logic_vector (c_DATA_WIDTH-1 downto 0);
+    API_PACKET_NUM_IN       : in  std_logic_vector (c_NUM_WIDTH-1  downto 0);
+    API_TYP_IN              : in  std_logic_vector (2 downto 0);
+    API_DATAREADY_IN        : in  std_logic;
+    API_READ_OUT            : out std_logic;
+    -- APL Control port
+    API_RUN_IN              : in  std_logic;
+    API_SEQNR_IN            : in  std_logic_vector (7  downto 0);
+    API_LENGTH_OUT          : out std_logic_vector (15 downto 0);
+    MY_ADDRESS_IN           : in  std_logic_vector (15 downto 0);
+
+    --data from event packer
+    CRI_DATA_IN             : in  std_logic_vector (8 downto 0); --8 is EOD
+    CRI_DATAREADY_IN        : in  std_logic;
+    --no more data, send TRM
+    CRI_READOUT_FINISHED_IN : in  std_logic; --currently not used
+    CRI_READ_OUT            : out std_logic;
+    CRI_LENGTH_IN           : in  std_logic_vector (15 downto 0);
+
+    STAT_DEBUG              : out std_logic_vector(31 downto 0)
+    );
+end entity;
+
+architecture cri_data_sender_arch of cri_data_sender is
+
+  type send_state_t is (IDLE, WAITING, SEND_DATA, READ_ANSWER);
+  signal send_state_current, send_state_next : send_state_t;
+  signal send_state_bits : std_logic_vector( 2 downto 0);
+
+  attribute syn_encoding : string;
+
+  type   fifo_states is (IDLE, PREPARE_DATA, WAIT_FOR_READY, SAVE, CLOSE, WAIT_FOR_TRANS, DIVIDE, CLEANUP);
+  signal fifo_machine_current_state, fifo_machine_next_state : fifo_states;
+  attribute syn_encoding of fifo_machine_current_state : signal is "onehot";
+  signal fifo_state_bits : std_logic_vector( 2 downto 0);
+
+  type loc_buffer_t is array (0 to 15) of std_logic_vector(17 downto 0);
+  signal local_buffer  : loc_buffer_t := (others => (others=> '0'));  
+  
+  signal fifo_wr_en     : std_logic;
+  signal fifo_almFull   : std_logic;
+  signal fifo_full      : std_logic;
+  signal fifo_empty     : std_logic;
+  
+  signal local_end      : std_logic_vector(15 downto 0);
+  signal fifo_rd_en     : std_logic;
+  signal fifo_data_in   : std_logic_vector(17 downto 0);
+  signal fifo_wcnt      : std_logic_vector(11 downto 0);
+  signal fifo_data_out  : std_logic_vector(17 downto 0);
+
+  signal cri_rd         : std_logic;
+  signal cri_rd_q       : std_logic;
+  signal cri_rd_qq      : std_logic;
+  signal cri_data_avail : std_logic;
+  
+  signal data_word_pos       : std_logic;
+  signal local_buffer_empty  : std_logic;
+  
+  signal data_ready_q   : std_logic;
+  signal data_ready_qq  : std_logic;
+  signal buf_data_ready : std_logic;
+  signal buf_data_out   : std_logic_vector(15 downto 0);
+  signal buf_eod        : std_logic_vector( 1 downto 0);
+  
+  signal loc_sending_flag : std_logic;
+  
+  signal buf_API_READ_OUT : std_logic;
+  signal buf_API_SEND_OUT : std_logic;
+  
+begin
+
+
+-----------------------------------------------------------------
+--  Receive finaly packed events
+-----------------------------------------------------------------
+--
+-- 8 bit words with all headers are reordered to 16 bit words for 
+-- trbnet. The Fifo is buffering and the readout is controled by
+-- the status of trbnet and event packer.
+--
+
+  THE_CRI_BUFF : entity work.fifo_18x2k_oreg
+  port map (
+    Data         => fifo_data_in,
+    Clock        => CLK,
+    WrEn         => fifo_wr_en,
+    RdEn         => fifo_rd_en,
+    Reset        => RESET,
+    AmFullThresh => b"11111110000",
+    Q            => fifo_data_out, 
+    WCNT         => fifo_wcnt,
+    Empty        => fifo_empty,
+    Full         => fifo_full,
+    AlmostFull   => fifo_almFull
+    );
+  
+                          
+  FIFO_MACHINE_PROC : process(RESET, CLK)
+  begin
+    if RESET = '1' then
+      fifo_machine_current_state <= IDLE;
+    elsif rising_edge(CLK) then
+      fifo_machine_current_state <= transmit_next_state;
+    end if;
+  end process FIFO_MACHINE_PROC;
+
+
+  FIFO_MACHINE : process(fifo_machine_current_state, CRI_DATAREADY_IN, local_end, fifo_almFull)
+  begin
+    fifo_machine_state <= x"0";
+    case fifo_machine_current_state is
+      when IDLE =>
+             fifo_machine_state <= x"1";
+             if (CRI_DATAREADY_IN = '1') then
+               fifo_machine_next_state <= PREPARE_DATA;
+             else
+               fifo_machine_next_state <= IDLE;
+             end if;
+
+      when PREPARE_DATA =>
+             fifo_machine_state <= x"2";
+             if (fifo_almFull = '0') then
+               fifo_machine_next_state <= WAIT_FOR_READY;
+             else 
+               fifo_machine_next_state <= PREPARE_DATA;
+             end if;
+      when WAIT_FOR_READY =>
+             fifo_machine_state <= x"3";
+             if (fifo_almFull = '0') then
+               fifo_machine_next_state <= SAVE;
+             else
+               fifo_machine_next_state <= WAIT_FOR_READY;
+             end if;
+
+      when SAVE =>
+             fifo_machine_state <= x"4";
+             if (local_end = x"0000") then -- or look for DataIn(8) ??
+               fifo_machine_next_state <= CLOSE;
+             else
+               if (fifo_almFull = '1') then
+                 fifo_machine_next_state <= WAIT_FOR_READY;
+               else
+                 fifo_machine_next_state <= SAVE;
+               end if;
+             end if;
+
+      when CLOSE =>
+             fifo_machine_state <= x"5";
+             fifo_machine_next_state <= IDLE;
+             
+    end case;
+  end process FIFO_MACHINE;
+    
+
+  LOCAL_END_PROC : process begin
+    wait until rising_edge(CLK);
+    if (fifo_machine_current_state = IDLE and CRI_DATAREADY_IN = '1') then
+      local_end <= CRI_LENGTH_IN - x"1";
+      --full_packet_size <= CRI_LENGTH_IN;
+    elsif (transmit_current_state = SAVE) then
+      local_end <= local_end - x"1";
+      --full_packet_size <= full_packet_size;
+    else
+      local_end <= local_end;
+      --full_packet_size <= full_packet_size;
+    end if; 
+  end process LOCAL_END_PROC;    
+
+  SYNC_PROC : process begin
+    wait until rising_edge(CLK);
+    cri_rd_q       <= cri_rd;
+    cri_rd_qq      <= cri_rd_q;
+    cri_data_avail <= cri_rd_qq;
+  end process SYNC_PROC;
+
+  
+  -- If a 8bit word is available, it is putt in the correct position of the
+  -- 16bit words with the EOD bit in the MSB positions
+  ARRANGE_DATA_WORDS_PROC : process begin
+    wait until rising_edge(CLK);
+    fifo_wr_en     <= '0';
+    if RESET = '1' then
+       data_word_pos <= '0';
+    else
+      if cri_data_avail = 1 then
+         if data_word_pos = '0' then
+           fifo_data_in(7 downto 0) <= CRI_DATA_IN(7 downto 0);
+           fifo_data_in(16)         <= CRI_DATA_IN(8);      --16: mark lower 8 bit as end;
+
+           data_word_pos  <= '1';
+           
+           -- case that event size is odd;
+           if (CRI_DATA_IN(8) = 1) then
+             fifo_data_in(15 downto 8) <= (others => '0');
+             fifo_data_in(17)          <= CRI_DATA_IN(8);   --17: mark 16bit as EOD; 
+             
+             fifo_wr_en     <= '1';
+             data_word_pos  <= '0';
+           end if;
+           
+         else 
+           fifo_data_in(15 downto 8) <= CRI_DATA_IN(7 downto 0);
+           fifo_data_in(17)          <= CRI_DATA_IN(8);
+           
+           data_word_pos  <= '0';
+           fifo_wr_en     <= '1';
+         end if;
+      end if;
+    end if;
+  end process LOCAL_END_PROC;
+  
+  cri_rd <= '1' when fifo_machine_current_state = SAVE else '0';
+  CRI_READ_OUT <= cri_rd;
+
+-----------------------------------------------------------------  
+--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--
+-----------------------------------------------------------------
+
+
+-----------------------------------------------------------------
+--  Send data to API for transfer to CRI
+-----------------------------------------------------------------
+
+--load data from fifo
+  fifo_rd_en <= API_READ_IN and (not fifo_empty) and local_buffer_empty and loc_sending_flag;
+
+
+  FIFO_DATARDY_PROC : process begin
+    wait until rising_edge(CLK);
+    if RESET = '1' then
+      data_ready_q   <= '0';
+      data_ready_qq  <= '0';
+    else
+      data_ready_q  <= fifo_rd_en;
+      data_ready_qq <= data_ready_q;
+    end if;      
+  end process;
+  
+  -- buffer words from fifo if the API FIFO is going full while we are reding from our fifo
+  local_buffer_process : process 
+    variable wcnt : unsigned( 2 downto 0) := 0;
+  begin
+    wait until rising_edge(CLK);
+    
+    buf_data_ready <= '0';
+    
+    if RESET = '1' then
+      local_buffer_empty <= '1';
+      packet_number      <= c_F0;
+      wcnt := 0;
+      buf_eod <= "00";
+    else
+      -- buffer if data is read and API FIFO is full OR buffer also if the transmission
+      -- has finished, but a few words are still coming from FIFO.
+      if (((data_ready_qq = '1') and (API_READ_IN      = '0')) or
+          ((data_ready_qq = '1') and (loc_sending_flag = '0')))
+      then
+        local_buffer(to_integer(wcnt)) <= fifo_data_out;  
+        wcnt := wcnt + 1;
+      end if;
+      
+      -- Data output to API:
+      if ((loc_sending_flag = '1') and (API_READ_IN = '1')) then 
+        if (wcnt > 0) then
+          buf_data_ready <= '1';
+          buf_data_out   <= local_buffer(to_integer(wcnt-1))(15 downto  0);
+          buf_eod        <= local_buffer(to_integer(wcnt-1))(17 downto 16);
+          wcnt := wcnt - 1;
+        else -- standard output from FIFO
+          buf_data_ready <= data_ready_qq;
+          buf_data_out   <= fifo_data_out(15 downto  0);
+          buf_eod        <= fifo_data_out(17 downto 16);
+        end if;
+        
+        -- Generate packet number
+        packet_number <= packet_number + 1;
+        if packet_number = c_F3 then
+          packet_number <= c_F0;
+        end if;
+      end if;
+      
+      if wcnt = 0 then
+        local_buffer_empty <= '1';
+      else 
+        local_buffer_empty <= '0';
+      end if;
+      
+    end if;      
+  end process;
+
+
+--send loaded data to CRI
+
+  SEND_STATE_PROC : process(RESET, CLK)
+  begin
+    if RESET = '1' then
+      send_state_current <= IDLE;
+      buf_API_READ_OUT  <= '0';
+    elsif rising_edge(CLK) then
+      send_state_current <= send_state_next;
+      buf_API_READ_OUT  <= '1';
+    end if;
+  end process;
+    
+    
+  SEND_STATE_MACHINE : process(send_state_current, API_RUN_IN, fifo_empty, API_READ_IN, buf_eod)
+    begin
+      send_state_bits   <= x"0";
+      case send_state_current is
+        when IDLE =>
+               send_state_bits   <= x"1";
+               buf_API_SEND_OUT  <= '0';
+               loc_sending_flag  <= '0';
+               
+               if (API_RUN_IN = '0' and (not fifo_empty)) then  
+                  send_state_next <= WAITING;
+               end if;
+
+        when WAITING =>
+               send_state_bits   <= x"2";
+               loc_sending_flag <= '0';
+               if (fifo_empty = '0') and API_READ_IN = '1' then
+                 -- read signal for DHDR
+                 send_state_next  <= SEND_DATA;
+                 loc_sending_flag <= '1';
+               end if;
+
+        when SEND_DATA => -- send DHDR packet
+               send_state_bits   <= x"3";
+               loc_sending_flag <= '1';
+               buf_API_SEND_OUT <= '1';
+               if buf_eod(1) = '1' then  --TO CHECK: is this to late? maybe one word too much send!
+                 loc_sending_flag <= '0';
+                 send_state_next <= READ_ANSWER;
+               end if;
+
+        when READ_ANSWER =>
+               send_state_bits   <= x"4";
+               buf_API_SEND_OUT <= '0';
+               loc_sending_flag <= '0';
+               if API_DATAREADY_IN = '1' and buf_API_READ_OUT = '1' and API_TYP_IN = TYPE_TRM then
+                 case API_PACKET_NUM_IN is
+                   when c_F0 =>  null;  --crc field, ignore
+                   when c_F1 =>  null;
+                   when c_F2 =>  null;
+                   when c_F3 =>  --buf_TYPE        <= API_DATA_IN(3 downto 0);
+                                 null;
+                                 send_state_next <= IDLE;
+                   when others => null;
+                 end case;
+               end if;
+          
+        when others =>
+              send_state_bits   <= x"5";
+              send_state_next <= IDLE;
+            
+      end case;
+    end process;
+   
+    
+  
+    
+---------------------------------------------------------------------
+--Connect Outputs
+---------------------------------------------------------------------
+
+  API_ERROR_PATTERN_OUT <= (others => '0');
+  API_LENGTH_OUT        <= (others => '0');
+  API_READ_OUT          <= buf_API_READ_OUT;
+  API_DATAREADY_OUT     <= buf_data_ready;
+  API_DATA_OUT          <= buf_data_out;
+  API_PACKET_NUM_OUT    <= packet_number;
+  API_SEND_OUT          <= buf_API_SEND_OUT;
+  API_SHORT_TRANSFER_OUT<= '0';
+  API_DTYPE_OUT         <= (others => '0');--buf_TYPE;
+
+---------------------------------------------------------------------
+--Debugging
+---------------------------------------------------------------------
+  STAT_DEBUG( 2 downto 0) <= fifo_state_bits;
+  STAT_DEBUG( 5 downto 3) <= send_state_bits;
+  STAT_DEBUG(31 downto 3) <= (others => '0');
+
+  
+
+end architecture;