]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
keep current working status2
authorhadaq <hadaq>
Thu, 17 Jan 2013 22:45:51 +0000 (22:45 +0000)
committerhadaq <hadaq>
Thu, 17 Jan 2013 22:45:51 +0000 (22:45 +0000)
nxyter/source/nx_fpga_timestamp.vhd [new file with mode: 0644]
nxyter/source/nx_timestamp_decode.vhd [new file with mode: 0644]
nxyter/source/nx_trigger_generator.vhd [new file with mode: 0644]
nxyter/source/nx_trigger_handler.vhd [new file with mode: 0644]

diff --git a/nxyter/source/nx_fpga_timestamp.vhd b/nxyter/source/nx_fpga_timestamp.vhd
new file mode 100644 (file)
index 0000000..1262c19
--- /dev/null
@@ -0,0 +1,127 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.nxyter_components.all;
+
+entity nx_fpga_timestamp is
+  port (
+    CLK_IN                : in  std_logic;
+    RESET_IN              : in  std_logic;
+
+    TIMESTAMP_SYNC_IN     : in  std_logic;
+    TRIGGER_IN            : in  std_logic;
+
+    TIMESTAMP_OUT         : out unsigned(11 downto 0);
+    NX_TIMESTAMP_SYNC_OUT : out std_logic;
+
+    -- Slave bus         
+    SLV_READ_IN           : in  std_logic;
+    SLV_WRITE_IN          : in  std_logic;
+    SLV_DATA_OUT          : out std_logic_vector(31 downto 0);
+    SLV_DATA_IN           : in  std_logic_vector(31 downto 0);
+    SLV_ACK_OUT           : out std_logic;
+    SLV_NO_MORE_DATA_OUT  : out std_logic;
+    SLV_UNKNOWN_ADDR_OUT  : out std_logic;
+    
+    -- Debug Line
+    DEBUG_OUT             : out std_logic_vector(15 downto 0)
+    );
+end entity;
+
+architecture Behavioral of nx_fpga_timestamp is
+
+  signal timestamp_ctr       : unsigned(11 downto 0);
+  signal timestamp_o         : unsigned(11 downto 0);
+  signal trigger_x           : std_logic;
+  signal trigger_l           : std_logic;
+  signal trigger             : std_logic;
+  signal timestamp_sync_x    : std_logic;
+  signal timestamp_sync_l    : std_logic;
+  signal timestamp_sync      : std_logic;
+
+  signal nx_timestamp_sync_o : std_logic;
+  
+begin
+
+  DEBUG_OUT(0)           <= CLK_IN;
+  DEBUG_OUT(1)           <= trigger;
+  DEBUG_OUT(2)           <= timestamp_sync;
+  DEBUG_OUT(3)           <= '0';
+  DEBUG_OUT(15 downto 4) <= TIMESTAMP_OUT;
+  
+  -- Cross the abyss for trigger and sync signal
+
+  PROC_SYNC: process (CLK_IN)
+  begin
+    if( rising_edge(CLK_IN) ) then
+      if (RESET_IN = '1') then
+        trigger_x        <= '0';
+        trigger_l        <= '0';
+        timestamp_sync_x <= '0';
+        timestamp_sync_l <= '0';
+      else
+        trigger_x        <= TRIGGER_IN;
+        trigger_l        <= trigger_x;
+        timestamp_sync_x <= TIMESTAMP_SYNC_IN;
+        timestamp_sync_l <= timestamp_sync_x;
+      end if;
+    end if;
+  end process PROC_SYNC;
+
+  -- Convert TRIGGER_IN to Pulse
+
+  level_to_pulse_1: level_to_pulse
+    port map (
+      CLK_IN    => CLK_IN,
+      RESET_IN  => RESET_IN,
+      LEVEL_IN  => trigger_l,
+      PULSE_OUT => trigger
+      );
+
+  -- Convert TIMESTAMP_SYNC_IN to Pulse
+
+  level_to_pulse_2: level_to_pulse
+    port map (
+      CLK_IN    => CLK_IN,
+      RESET_IN  => RESET_IN,
+      LEVEL_IN  => timestamp_sync_l,
+      PULSE_OUT => timestamp_sync
+      );
+
+  -- Timestamp Process + Trigger
+  
+  PROC_TIMESTAMP_CTR: process (CLK_IN)
+  begin
+    if( rising_edge(CLK_IN) ) then
+      if( RESET_IN = '1' ) then
+        timestamp_ctr       <= (others => '0');
+        timestamp_o         <= (others => '0');
+        nx_timestamp_sync_o <= '0';
+      else
+        nx_timestamp_sync_o <= '0';
+        
+        if (timestamp_sync = '1') then
+          timestamp_ctr       <= (others => '0');
+          timestamp_o         <= (others => '0');
+          nx_timestamp_sync_o <= '1';
+        else
+          if (trigger = '1') then
+            timestamp_o       <= timestamp_ctr - 3;
+          end if;
+          timestamp_ctr       <= timestamp_ctr + 1;
+        end if;
+      end if;
+    end if;
+  end process;
+
+  
+  -----------------------------------------------------------------------------
+  -- Output Signals
+  -----------------------------------------------------------------------------
+
+  TIMESTAMP_OUT         <= timestamp_o;
+  NX_TIMESTAMP_SYNC_OUT <= nx_timestamp_sync_o;
+
+end Behavioral;
diff --git a/nxyter/source/nx_timestamp_decode.vhd b/nxyter/source/nx_timestamp_decode.vhd
new file mode 100644 (file)
index 0000000..277df30
--- /dev/null
@@ -0,0 +1,407 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+use work.trb_net_std.all;\r
+use work.nxyter_components.all;\r
+\r
+entity nx_timestamp_decode is\r
+  port (\r
+    CLK_IN               : in  std_logic;  \r
+    RESET_IN             : in  std_logic;\r
+\r
+    -- Inputs\r
+    NX_NEW_TIMESTAMP_IN  : in  std_logic;\r
+    NX_TIMESTAMP_IN      : in  std_logic_vector(31 downto 0);\r
+    TIMESTAMP_REF_IN     : in  unsigned(11 downto 0);\r
+\r
+    -- Outputs\r
+    TIMESTAMP_DATA_OUT   : out std_logic_vector(31 downto 0);\r
+    TIMESTAMP_VALID_OUT  : out std_logic;\r
+    NX_TOKEN_RETURN      : out std_logic;\r
+    NX_NOMORE_DATA       : out std_logic;\r
+\r
+    -- Slave bus         \r
+    SLV_READ_IN          : in  std_logic;\r
+    SLV_WRITE_IN         : in  std_logic;\r
+    SLV_DATA_OUT         : out std_logic_vector(31 downto 0);\r
+    SLV_DATA_IN          : in std_logic_vector(31 downto 0);\r
+    SLV_ADDR_IN          : in std_logic_vector(15 downto 0);\r
+    SLV_ACK_OUT          : out std_logic;\r
+    SLV_NO_MORE_DATA_OUT : out std_logic;\r
+    SLV_UNKNOWN_ADDR_OUT : out std_logic;\r
+    \r
+    DEBUG_OUT            : out std_logic_vector(15 downto 0)\r
+    );\r
+\r
+end entity;\r
+\r
+architecture Behavioral of nx_timestamp_decode is\r
+  \r
+  -- Sync Ref\r
+  signal timestamp_ref_x      : unsigned(11 downto 0);\r
+  signal timestamp_ref        : unsigned(11 downto 0);\r
+\r
+  -- Gray Decoder\r
+  signal nx_timestamp         : std_logic_vector(13 downto 0);\r
+  signal nx_channel_id        : std_logic_vector( 6 downto 0);\r
+\r
+  -- TIMESTAMP_BITS\r
+  signal new_timestamp        : std_logic;\r
+  signal valid_frame_bits     : std_logic_vector(3 downto 0);\r
+  signal status_bits          : std_logic_vector(1 downto 0);\r
+  signal parity_bit           : std_logic;\r
+  signal parity               : std_logic;\r
+  signal timstamp_raw         : std_logic_vector(31 downto 0);\r
+  \r
+  -- Validate Timestamp\r
+  signal timestamp_data_o     : std_logic_vector(31 downto 0);\r
+  signal timestamp_valid_o    : std_logic;\r
+  signal nx_token_return_o    : std_logic;\r
+  signal nx_nomore_data_o     : std_logic;\r
+  signal nx_data_notvalid_ctr : unsigned(1 downto 0);\r
+  signal invalid_frame_ctr    : unsigned(15 downto 0);\r
+  signal overflow_ctr         : unsigned(15 downto 0);\r
+  signal pileup_ctr           : unsigned(15 downto 0);\r
+  signal parity_error_ctr     : unsigned(15 downto 0);\r
+  \r
+  -- Config\r
+  signal readout_type         : std_logic_vector(1 downto 0);\r
+\r
+  -- Slave Bus                    \r
+  signal slv_data_out_o       : std_logic_vector(31 downto 0);\r
+  signal slv_no_more_data_o   : std_logic;\r
+  signal slv_unknown_addr_o   : std_logic;\r
+  signal slv_ack_o            : std_logic;\r
+  signal clear_counters       : std_logic;\r
+  signal trigger_window_width : unsigned(13 downto 0);\r
+  signal trigger_window_delay : unsigned(13 downto 0);\r
+  signal readout_mode         : std_logic_vector(1 downto 0);\r
+\r
+begin\r
+\r
+  -- Debug Line\r
+  DEBUG_OUT(0)                    <= CLK_IN;\r
+  DEBUG_OUT(1)                    <= NX_NEW_TIMESTAMP_IN;\r
+  DEBUG_OUT(2)                    <= TIMESTAMP_VALID_OUT;\r
+  DEBUG_OUT(3)                    <= new_timestamp;\r
+  DEBUG_OUT(5 downto 4)           <= status_bits;\r
+\r
+  DEBUG_OUT(6)                    <= parity;\r
+  DEBUG_OUT(7)                    <= '0';\r
+  \r
+  DEBUG_OUT(14 downto 8)          <= nx_channel_id;\r
+  DEBUG_OUT(15)                   <= '0';\r
+  \r
+  -----------------------------------------------------------------------------\r
+  -- Gray Decoder for Timestamp and Chgannel Id\r
+  -----------------------------------------------------------------------------\r
+\r
+  Gray_Decoder_1: Gray_Decoder          -- Decode nx_timestamp\r
+    generic map (\r
+      WIDTH => 14\r
+      )\r
+    port map (\r
+      CLK_IN               => CLK_IN,\r
+      RESET_IN             => RESET_IN,\r
+      GRAY_IN(13 downto 7) => not NX_TIMESTAMP_IN(30 downto 24),\r
+      GRAY_IN( 6 downto 0) => not NX_TIMESTAMP_IN(22 downto 16),\r
+      BINARY_OUT           => nx_timestamp\r
+      );\r
+\r
+  Gray_Decoder_2: Gray_Decoder          -- Decode Channel_ID\r
+    generic map (\r
+      WIDTH => 7\r
+      )\r
+    port map (\r
+      CLK_IN     => CLK_IN,\r
+      RESET_IN   => RESET_IN,\r
+      GRAY_IN    => NX_TIMESTAMP_IN(14 downto 8),\r
+      BINARY_OUT => nx_channel_id\r
+      );\r
+\r
+  -- Sync Timestamp Ref\r
+  PROC_SYNC_TIMESTAMP_REF: process (CLK_IN)\r
+  begin\r
+    if( rising_edge(CLK_IN) ) then\r
+      if (RESET_IN = '1') then\r
+        timestamp_ref_x <= (others => '0');\r
+        timestamp_ref   <= (others => '0');\r
+      else\r
+        timestamp_ref_x <= TIMESTAMP_REF_IN;\r
+        timestamp_ref   <= timestamp_ref_x;\r
+      end if;\r
+    end if;\r
+  end process PROC_SYNC_TIMESTAMP_REF;\r
+  \r
+  -- Separate Status-, Parity- and Frame-bits, calculate parity\r
+  PROC_TIMESTAMP_BITS: process (CLK_IN)\r
+    variable parity_bits : std_logic_vector(22 downto 0);\r
+  begin\r
+    if( rising_edge(CLK_IN) ) then\r
+      if (RESET_IN = '1') then\r
+        valid_frame_bits    <= (others => '0');\r
+        status_bits         <= (others => '0');\r
+        parity_bit          <= '0';\r
+        parity              <= '0';\r
+        new_timestamp       <= '0';\r
+        timstamp_raw        <= (others => '0');\r
+      else\r
+        -- Timestamp Bit #6 is excluded (funny nxyter-bug)\r
+        parity_bits         := NX_TIMESTAMP_IN(31 downto 24) &\r
+                               NX_TIMESTAMP_IN(21 downto 16) &\r
+                               NX_TIMESTAMP_IN(14 downto  8) &\r
+                               NX_TIMESTAMP_IN( 2 downto  1);\r
+        valid_frame_bits    <= (others => '0');\r
+        status_bits         <= (others => '0');\r
+        parity_bit          <= '0';\r
+        parity              <= '0';\r
+        new_timestamp       <= '0';\r
+        timstamp_raw        <= (others => '0');\r
+        \r
+        if (NX_NEW_TIMESTAMP_IN = '1') then\r
+          valid_frame_bits(3) <= NX_TIMESTAMP_IN(31);\r
+          valid_frame_bits(2) <= NX_TIMESTAMP_IN(23);\r
+          valid_frame_bits(1) <= NX_TIMESTAMP_IN(15);\r
+          valid_frame_bits(0) <= NX_TIMESTAMP_IN(7);\r
+          status_bits         <= NX_TIMESTAMP_IN(2 downto 1);\r
+          parity_bit          <= NX_TIMESTAMP_IN(0);\r
+          parity              <= xor_all(parity_bits);\r
+          timstamp_raw        <= NX_TIMESTAMP_IN;\r
+          new_timestamp       <= '1';\r
+        end if;\r
+      end if;\r
+    end if;\r
+  end process PROC_TIMESTAMP_BITS;    \r
+\r
+  -----------------------------------------------------------------------------\r
+  -- Filter only valid events\r
+  -----------------------------------------------------------------------------\r
+\r
+  PROC_VALIDATE_TIMESTAMP: process (CLK_IN)\r
+    variable ref    : unsigned(13 downto 0);\r
+    variable deltaT : unsigned(13 downto 0);\r
+  begin \r
+    if( rising_edge(CLK_IN) ) then\r
+      if (RESET_IN = '1') then\r
+        timestamp_data_o     <= (others => '0');\r
+        timestamp_valid_o    <= '0';\r
+        nx_token_return_o    <= '0';\r
+        nx_nomore_data_o     <= '1';\r
+        nx_data_notvalid_ctr <= (others => '0');\r
+        invalid_frame_ctr    <= (others => '0');\r
+        overflow_ctr         <= (others => '0');\r
+        pileup_ctr           <= (others => '0');\r
+        parity_error_ctr     <= (others => '0');\r
+      else\r
+        timestamp_data_o(31 downto 0)  <= (others => '0');\r
+        timestamp_valid_o              <= '0';\r
+        nx_token_return_o              <= '0';\r
+        nx_nomore_data_o               <= '0';\r
+    \r
+        if (new_timestamp = '1') then\r
+          case valid_frame_bits is\r
+            when "1000" =>\r
+              ---- Check Overflow\r
+              if (status_bits(0) = '1') then\r
+                if (clear_counters = '0') then\r
+                  overflow_ctr <= overflow_ctr + 1;\r
+                end if;\r
+              end if;\r
+\r
+              ---- Check Parity\r
+              if ((parity_bit /= parity) and (clear_counters = '0')) then\r
+                parity_error_ctr <= parity_error_ctr + 1;\r
+              end if;\r
+\r
+              -- Check PileUp\r
+              if ((status_bits(1) = '1') and (clear_counters = '0')) then\r
+                pileup_ctr <= pileup_ctr + 1;\r
+              end if;\r
+              \r
+              -- Take Timestamp\r
+              ref                 := timestamp_ref & "00";\r
+              deltaT              := ref - unsigned(nx_timestamp);\r
+              \r
+              case readout_mode is\r
+                \r
+                when "00" => \r
+                  -- Raw\r
+                  timestamp_data_o(13 downto  0)   <= nx_timestamp;  \r
+                  timestamp_valid_o                <= '1';\r
+                \r
+                when "01" =>\r
+                  -- Ref\r
+                  timestamp_data_o(13 downto  0)   <= std_logic_vector(deltaT);\r
+                  timestamp_valid_o                <= '1';\r
+\r
+                when "10" =>\r
+                  -- Trigger Window\r
+                  if ((deltaT < trigger_window_delay) and\r
+                      (deltaT > (trigger_window_delay - trigger_window_width)))\r
+                  then\r
+                    timestamp_data_o(13 downto  0) <= std_logic_vector(deltaT);\r
+                    timestamp_valid_o              <= '1';\r
+                  end if;\r
+\r
+                when others => null;\r
+              end case;\r
+              \r
+              timestamp_data_o(15 downto 14) <= (others => '0');\r
+              timestamp_data_o(22 downto 16) <= nx_channel_id;\r
+              timestamp_data_o(23)           <= '0';\r
+              timestamp_data_o(24)           <= parity_bit;\r
+              timestamp_data_o(25)           <= parity;\r
+              timestamp_data_o(29 downto 26) <= (others => '0');\r
+              timestamp_data_o(31 downto 30) <= status_bits;\r
+\r
+              nx_data_notvalid_ctr           <= (others => '0');\r
+                \r
+            when "0000" =>\r
+              case nx_data_notvalid_ctr is\r
+                when "00"   =>\r
+                  nx_token_return_o    <= '1';\r
+                  nx_data_notvalid_ctr <= nx_data_notvalid_ctr + 1;\r
+                when "01"   =>\r
+                  nx_nomore_data_o     <= '1';\r
+                  nx_data_notvalid_ctr <= nx_data_notvalid_ctr + 1;\r
+                when others => null;\r
+              end case;\r
+              \r
+            when others =>\r
+              -- Invalid frame, not empty, discard timestamp\r
+              if (clear_counters = '0') then\r
+                invalid_frame_ctr <= invalid_frame_ctr + 1;\r
+              end if;\r
+          end case;\r
+        end if;\r
+\r
+        -- Reset Counters\r
+        if (clear_counters = '1') then\r
+          invalid_frame_ctr   <= (others => '0');\r
+          overflow_ctr        <= (others => '0');\r
+          pileup_ctr          <= (others => '0');\r
+          parity_error_ctr    <= (others => '0');\r
+        end if;\r
+      end if;\r
+    end if;\r
+  end process PROC_VALIDATE_TIMESTAMP;\r
+\r
+  -----------------------------------------------------------------------------\r
+  -- TRBNet Slave Bus\r
+  -----------------------------------------------------------------------------\r
+\r
+  -- Give status info to the TRB Slow Control Channel\r
+  PROC_FIFO_REGISTERS: process(CLK_IN)\r
+  begin\r
+    if( rising_edge(CLK_IN) ) then\r
+      if( RESET_IN = '1' ) then\r
+        slv_data_out_o         <= (others => '0');\r
+        slv_ack_o              <= '0';\r
+        slv_unknown_addr_o     <= '0';\r
+        slv_no_more_data_o     <= '0';\r
+        readout_mode           <= "00";\r
+        clear_counters         <= '0';\r
+        trigger_window_width   <= (others => '0');\r
+        trigger_window_delay   <= (others => '0');\r
+      else\r
+        slv_data_out_o         <= (others => '0');\r
+        slv_unknown_addr_o     <= '0';\r
+        slv_no_more_data_o     <= '0';\r
+        clear_counters         <= '0';\r
+        \r
+        if (SLV_READ_IN  = '1') then\r
+          case SLV_ADDR_IN is\r
+            when x"0000" =>\r
+              slv_data_out_o(1 downto 0)   <= readout_mode;\r
+              slv_data_out_o(31 downto 2)  <= (others => '0');\r
+              slv_ack_o                    <= '1';\r
+\r
+            when x"0001" =>\r
+              slv_data_out_o(13 downto 0)            <=\r
+                std_logic_vector(trigger_window_width);\r
+              slv_data_out_o(31 downto 14) <= (others => '0');\r
+              slv_ack_o                    <= '1';\r
+\r
+            when x"0002" =>\r
+              slv_data_out_o(13 downto 0)            <=\r
+                std_logic_vector(trigger_window_delay);\r
+              slv_data_out_o(31 downto 14) <= (others => '0');\r
+              slv_ack_o                    <= '1'; \r
+              \r
+            when x"000a" =>\r
+              slv_data_out_o(15 downto 0)  <=\r
+                std_logic_vector(invalid_frame_ctr);\r
+              slv_data_out_o(31 downto 16) <= (others => '0');\r
+              slv_ack_o                    <= '1';\r
+\r
+            when x"000b" =>\r
+              slv_data_out_o(15 downto 0)  <=\r
+                std_logic_vector(overflow_ctr);\r
+              slv_data_out_o(31 downto 16) <= (others => '0');\r
+              slv_ack_o                    <= '1';\r
+\r
+            when x"000c" =>\r
+              slv_data_out_o(15 downto 0)  <=\r
+                std_logic_vector(pileup_ctr);\r
+              slv_data_out_o(31 downto 16) <= (others => '0');\r
+              slv_ack_o                    <= '1';\r
+\r
+            when x"000d" =>\r
+              slv_data_out_o(15 downto 0)  <=\r
+                std_logic_vector(parity_error_ctr);\r
+              slv_data_out_o(31 downto 16) <= (others => '0');\r
+              slv_ack_o                    <= '1';\r
+              \r
+            when others  =>\r
+              slv_unknown_addr_o           <= '1';\r
+              slv_ack_o                    <= '0';\r
+          end case;\r
+          \r
+        elsif (SLV_WRITE_IN  = '1') then\r
+          case SLV_ADDR_IN is\r
+            when x"0000" =>\r
+              readout_mode                 <= SLV_DATA_IN(1 downto 0);\r
+              slv_ack_o                    <= '1';\r
+\r
+            when x"0001" =>\r
+              trigger_window_width         <=\r
+                unsigned(SLV_DATA_IN(13 downto 0));\r
+              slv_ack_o                    <= '1';\r
+\r
+            when x"0002" =>\r
+              trigger_window_delay         <=\r
+                unsigned(SLV_DATA_IN(13 downto 0));\r
+              slv_ack_o                    <= '1'; \r
+\r
+            when x"000f" =>\r
+              clear_counters               <= '1';\r
+              slv_ack_o                    <= '1';\r
+              \r
+            when others  =>\r
+              slv_unknown_addr_o           <= '1';\r
+              slv_ack_o                    <= '0';\r
+          end case;                \r
+        else\r
+          slv_ack_o <= '0';\r
+        end if;\r
+      end if;\r
+    end if;\r
+  end process PROC_FIFO_REGISTERS;\r
+  \r
+  -----------------------------------------------------------------------------\r
+  -- Output Signals\r
+  -----------------------------------------------------------------------------\r
+\r
+  TIMESTAMP_DATA_OUT    <= timestamp_data_o;\r
+  TIMESTAMP_VALID_OUT   <= timestamp_valid_o;\r
+  NX_TOKEN_RETURN       <= nx_token_return_o;\r
+  NX_NOMORE_DATA        <= nx_nomore_data_o;\r
+  \r
+  -- Slave \r
+  SLV_DATA_OUT          <= slv_data_out_o;    \r
+  SLV_NO_MORE_DATA_OUT  <= slv_no_more_data_o; \r
+  SLV_UNKNOWN_ADDR_OUT  <= slv_unknown_addr_o;\r
+  SLV_ACK_OUT           <= slv_ack_o;\r
+end Behavioral;\r
diff --git a/nxyter/source/nx_trigger_generator.vhd b/nxyter/source/nx_trigger_generator.vhd
new file mode 100644 (file)
index 0000000..d8e69b8
--- /dev/null
@@ -0,0 +1,259 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+use work.nxyter_components.all;\r
+\r
+entity nx_trigger_generator is\r
+  port (\r
+    CLK_IN               : in    std_logic;\r
+    RESET_IN             : in    std_logic;\r
+\r
+    TRIGGER_OUT          : out   std_logic;\r
+    TS_RESET_OUT         : out   std_logic;\r
+    \r
+    -- Slave bus         \r
+    SLV_READ_IN          : in    std_logic;\r
+    SLV_WRITE_IN         : in    std_logic;\r
+    SLV_DATA_OUT         : out   std_logic_vector(31 downto 0);\r
+    SLV_DATA_IN          : in    std_logic_vector(31 downto 0);\r
+    SLV_ADDR_IN          : in    std_logic_vector(15 downto 0);\r
+    SLV_ACK_OUT          : out   std_logic;\r
+    SLV_NO_MORE_DATA_OUT : out   std_logic;\r
+    SLV_UNKNOWN_ADDR_OUT : out   std_logic;\r
+    \r
+    -- Debug Line\r
+    DEBUG_OUT            : out std_logic_vector(15 downto 0)\r
+    );\r
+end entity;\r
+\r
+architecture Behavioral of nx_trigger_generator is\r
+\r
+  signal start_cycle         : std_logic;\r
+  signal trigger_cycle_ctr   : unsigned(7 downto 0);\r
+  signal trigger_cycle_ctr_x : unsigned(7 downto 0);\r
+  signal wait_timer_init     : unsigned(15 downto 0);\r
+  signal wait_timer_init_x   : unsigned(15 downto 0);\r
+  signal wait_timer_done     : std_logic;\r
+  signal trigger_o           : std_logic;\r
+  signal trigger_o_x         : std_logic;\r
+  signal ts_reset_o          : std_logic;\r
+  signal ts_reset_o_x        : std_logic;\r
+  \r
+  type STATES is (S_IDLE,\r
+                  S_WAIT_TS_RESET,\r
+                  S_NEXT_CYCLE,\r
+                  S_SET_TRIGGER,\r
+                  S_WAIT_TRIGGER\r
+                  );\r
+  signal STATE, NEXT_STATE : STATES;\r
+  \r
+  -- TRBNet Slave Bus            \r
+  signal slv_data_out_o          : std_logic_vector(31 downto 0);\r
+  signal slv_no_more_data_o      : std_logic;\r
+  signal slv_unknown_addr_o      : std_logic;\r
+  signal slv_ack_o               : std_logic;\r
+\r
+  signal reg_trigger_period      : unsigned(15 downto 0);\r
+  signal reg_trigger_length      : unsigned(15 downto 0);\r
+  signal reg_trigger_num_cycles  : unsigned(7 downto 0);      \r
+  signal reg_reset_on            : std_logic;\r
+  \r
+begin\r
+\r
+  -- Debug Line\r
+  DEBUG_OUT(0)           <= CLK_IN;\r
+  DEBUG_OUT(1)           <= TRIGGER_OUT;\r
+  DEBUG_OUT(2)           <= start_cycle;\r
+  DEBUG_OUT(3)           <= wait_timer_done;\r
+  DEBUG_OUT(4)           <= ts_reset_o;\r
+  DEBUG_OUT(7 downto 5)  <= (others => '0');\r
+  DEBUG_OUT(15 downto 8) <= trigger_cycle_ctr;\r
+\r
+  -- Timer\r
+  nx_timer_1: nx_timer\r
+    generic map (\r
+      CTR_WIDTH => 16\r
+      )\r
+    port map (\r
+      CLK_IN         => CLK_IN,\r
+      RESET_IN       => RESET_IN,\r
+      TIMER_START_IN => wait_timer_init,\r
+      TIMER_DONE_OUT => wait_timer_done\r
+      );\r
+\r
+  -----------------------------------------------------------------------------\r
+  -- Gernerate Trigger\r
+  -----------------------------------------------------------------------------\r
+\r
+  PROC_TRIGGER_OUT_TRANSFER: process (CLK_IN)\r
+  begin \r
+    if( rising_edge(CLK_IN) ) then\r
+      if (RESET_IN = '1') then\r
+        trigger_o         <= '0';\r
+        ts_reset_o        <= '0';\r
+        wait_timer_init   <= (others => '0');\r
+        trigger_cycle_ctr <= (others => '0');\r
+        STATE             <= S_IDLE;\r
+      else\r
+        trigger_o         <= trigger_o_x;\r
+        ts_reset_o        <= ts_reset_o_x;\r
+        wait_timer_init   <= wait_timer_init_x;\r
+        trigger_cycle_ctr <= trigger_cycle_ctr_x;\r
+        STATE             <= NEXT_STATE;\r
+      end if;\r
+    end if;\r
+  end process PROC_TRIGGER_OUT_TRANSFER;\r
+\r
+  PROC_TRIGGER_OUT: process(STATE,\r
+                            start_cycle,\r
+                            reg_trigger_num_cycles,\r
+                            wait_timer_done\r
+                            )\r
+  begin\r
+    trigger_o_x         <= '0';\r
+    ts_reset_o_x        <= '0';\r
+    wait_timer_init_x   <= (others => '0');\r
+    trigger_cycle_ctr_x <= trigger_cycle_ctr;\r
+    \r
+    case STATE is\r
+      when  S_IDLE =>\r
+        if (start_cycle = '1') then\r
+          trigger_cycle_ctr_x   <= reg_trigger_num_cycles;\r
+          if reg_reset_on = '1' then\r
+            ts_reset_o_x        <= '1';\r
+            wait_timer_init_x   <= reg_trigger_period;\r
+            NEXT_STATE          <= S_WAIT_TS_RESET;\r
+          else\r
+            NEXT_STATE          <= S_NEXT_CYCLE;\r
+          end if;\r
+        else\r
+          NEXT_STATE            <= S_IDLE;\r
+        end if;\r
+\r
+      when S_WAIT_TS_RESET =>\r
+        if (wait_timer_done = '0') then\r
+          NEXT_STATE        <= S_WAIT_TS_RESET;\r
+        else\r
+          NEXT_STATE        <= S_NEXT_CYCLE;\r
+        end if;\r
+        \r
+      when S_NEXT_CYCLE =>\r
+        if (trigger_cycle_ctr > 0) then\r
+          trigger_cycle_ctr_x <= trigger_cycle_ctr - 1;\r
+          wait_timer_init_x   <= reg_trigger_length;\r
+          NEXT_STATE          <= S_SET_TRIGGER;\r
+        else\r
+          NEXT_STATE          <= S_IDLE;\r
+        end if;\r
+\r
+      when S_SET_TRIGGER =>\r
+        trigger_o_x <= '1';\r
+        if (wait_timer_done = '0') then\r
+          NEXT_STATE          <= S_SET_TRIGGER;\r
+        else\r
+          wait_timer_init_x   <= reg_trigger_period - reg_trigger_length;\r
+          NEXT_STATE          <= S_WAIT_TRIGGER;\r
+        end if;\r
+        \r
+      when S_WAIT_TRIGGER =>\r
+        if (wait_timer_done = '0') then\r
+          NEXT_STATE        <= S_WAIT_TRIGGER;\r
+        else\r
+          NEXT_STATE        <= S_NEXT_CYCLE;\r
+        end if;\r
+\r
+    end case;\r
+  end process PROC_TRIGGER_OUT;\r
+\r
+  -----------------------------------------------------------------------------\r
+  -- TRBNet Slave Bus\r
+  -----------------------------------------------------------------------------\r
+  \r
+  PROC_SLAVE_BUS: process(CLK_IN)\r
+  begin\r
+    if( rising_edge(CLK_IN) ) then\r
+      if( RESET_IN = '1' ) then\r
+        reg_trigger_period     <= x"00ff";\r
+        reg_trigger_num_cycles <= x"01";\r
+        reg_trigger_length     <= x"000a";\r
+        reg_reset_on           <= '0';\r
+        slv_data_out_o         <= (others => '0');\r
+        slv_no_more_data_o     <= '0';\r
+        slv_unknown_addr_o     <= '0';\r
+        start_cycle            <= '0';\r
+        slv_ack_o              <= '0';\r
+      else\r
+        slv_unknown_addr_o <= '0';\r
+        slv_no_more_data_o <= '0';\r
+        slv_data_out_o     <= (others => '0');\r
+        start_cycle        <= '0';\r
+\r
+\r
+        if (SLV_WRITE_IN  = '1') then\r
+          case SLV_ADDR_IN is\r
+            when x"0000" =>\r
+              start_cycle              <= '1';\r
+              slv_ack_o                <= '1';\r
+            when x"0001" =>\r
+              reg_trigger_period       <= unsigned(SLV_DATA_IN(15 downto 0));\r
+              slv_ack_o                <= '1';\r
+            when x"0002" =>\r
+              reg_trigger_num_cycles   <= unsigned(SLV_DATA_IN(7 downto 0));\r
+              slv_ack_o                <= '1';\r
+            when x"0003" =>\r
+              reg_trigger_length       <= unsigned(SLV_DATA_IN(15 downto 0));\r
+              slv_ack_o                <= '1';\r
+            when x"0004" =>\r
+              reg_reset_on             <=  SLV_DATA_IN(0);\r
+              slv_ack_o                <= '1';\r
+            when others =>\r
+              slv_unknown_addr_o       <= '1';\r
+              slv_ack_o                <= '0';\r
+          end case;\r
+\r
+        elsif (SLV_READ_IN = '1') then\r
+          case SLV_ADDR_IN is\r
+            when x"0001" =>\r
+              slv_data_out_o(15 downto 0) <=\r
+                std_logic_vector(reg_trigger_period);\r
+              slv_ack_o                   <= '1';\r
+            when x"0002" =>\r
+              slv_data_out_o(7 downto 0)  <=\r
+                std_logic_vector(reg_trigger_num_cycles);\r
+              slv_ack_o                   <= '1';\r
+            when x"0003" =>\r
+              slv_data_out_o(15 downto 0) <=\r
+                std_logic_vector(reg_trigger_length);\r
+              slv_ack_o                   <= '1';\r
+            when x"0004" =>\r
+              slv_data_out_o(0)           <= reg_reset_on;\r
+              slv_ack_o                   <= '1';\r
+            when others =>\r
+              slv_unknown_addr_o          <= '1';\r
+              slv_ack_o                   <= '0';\r
+          end case;\r
+\r
+        else\r
+          slv_ack_o            <= '0';\r
+        end if;\r
+      end if;\r
+    end if;           \r
+  end process PROC_SLAVE_BUS;\r
+  \r
+  -----------------------------------------------------------------------------\r
+  -- Output Signals\r
+  -----------------------------------------------------------------------------\r
+  \r
+  -- Trigger Output\r
+  TRIGGER_OUT          <= trigger_o;\r
+  TS_RESET_OUT         <= ts_reset_o;\r
+\r
+  -- Slave Bus\r
+  SLV_DATA_OUT         <= slv_data_out_o;    \r
+  SLV_NO_MORE_DATA_OUT <= slv_no_more_data_o; \r
+  SLV_UNKNOWN_ADDR_OUT <= slv_unknown_addr_o;\r
+  SLV_ACK_OUT          <= slv_ack_o;    \r
+\r
+end Behavioral;\r
diff --git a/nxyter/source/nx_trigger_handler.vhd b/nxyter/source/nx_trigger_handler.vhd
new file mode 100644 (file)
index 0000000..8771524
--- /dev/null
@@ -0,0 +1,215 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+use work.nxyter_components.all;\r
+\r
+entity nx_trigger_handler is\r
+  port (\r
+    CLK_IN               : in    std_logic;\r
+    RESET_IN             : in    std_logic;\r
+\r
+    -- IN\r
+    TRIGGER_IN           : in    std_logic;\r
+    TRIGGER_RELEASE_IN   : in    std_logic;\r
+\r
+    -- OUT\r
+    TRIGGER_OUT          : out   std_logic;\r
+    TIMESTAMP_HOLD_OUT   : out   std_logic;\r
+    TRIGGER_BUSY_OUT     : out   std_logic;\r
+    \r
+    -- Slave bus         \r
+    SLV_READ_IN          : in    std_logic;\r
+    SLV_WRITE_IN         : in    std_logic;\r
+    SLV_DATA_OUT         : out   std_logic_vector(31 downto 0);\r
+    SLV_DATA_IN          : in    std_logic_vector(31 downto 0);\r
+    SLV_ADDR_IN          : in    std_logic_vector(15 downto 0);\r
+    SLV_ACK_OUT          : out   std_logic;\r
+    SLV_NO_MORE_DATA_OUT : out   std_logic;\r
+    SLV_UNKNOWN_ADDR_OUT : out   std_logic;\r
+    \r
+    -- Debug Line\r
+    DEBUG_OUT            : out std_logic_vector(15 downto 0)\r
+    );\r
+end entity;\r
+\r
+architecture Behavioral of nx_trigger_handler is\r
+\r
+  signal start_cycle         : std_logic;\r
+  signal trigger_cycle_ctr   : unsigned(7 downto 0);\r
+  signal trigger_cycle_ctr_x : unsigned(7 downto 0);\r
+  signal wait_timer_init     : unsigned(15 downto 0);\r
+  signal wait_timer_init_x   : unsigned(15 downto 0);\r
+  signal wait_timer_done     : std_logic;\r
+  signal trigger_o           : std_logic;\r
+  signal trigger_o_x         : std_logic;\r
+  signal timestamp_hold_o    : std_logic;\r
+  signal timestamp_hold_o_x  : std_logic;\r
+  signal trigger_busy_o      : std_logic;\r
+  signal trigger_busy_o_x    : std_logic;\r
+  \r
+  type STATES is (S_IDLE,\r
+                  S_WAIT_HOLD,\r
+                  S_WAIT_TRIGGER_RELEASE\r
+                  );\r
+  signal STATE, NEXT_STATE : STATES;\r
+  \r
+  -- TRBNet Slave Bus            \r
+  signal slv_data_out_o           : std_logic_vector(31 downto 0);\r
+  signal slv_no_more_data_o       : std_logic;\r
+  signal slv_unknown_addr_o       : std_logic;\r
+  signal slv_ack_o                : std_logic;\r
+\r
+  signal reg_timestamp_hold_delay : unsigned(15 downto 0);\r
+  \r
+begin\r
+\r
+  -- Debug Line\r
+  DEBUG_OUT(0)            <= CLK_IN;\r
+  DEBUG_OUT(1)            <= TRIGGER_IN;\r
+  DEBUG_OUT(2)            <= trigger_o;\r
+  DEBUG_OUT(3)            <= timestamp_hold_o;\r
+  DEBUG_OUT(4)            <= wait_timer_done;\r
+  DEBUG_OUT(15 downto 5)  <= (others => '0');\r
+\r
+  -- Timer\r
+  nx_timer_1: nx_timer\r
+    generic map (\r
+      CTR_WIDTH => 16\r
+      )\r
+    port map (\r
+      CLK_IN         => CLK_IN,\r
+      RESET_IN       => RESET_IN,\r
+      TIMER_START_IN => wait_timer_init,\r
+      TIMER_DONE_OUT => wait_timer_done\r
+      );\r
+\r
+  -----------------------------------------------------------------------------\r
+  -- Trigger Handler\r
+  -----------------------------------------------------------------------------\r
+\r
+  PROC_TRIGGER_HANDLER_TRANSFER: process (CLK_IN)\r
+  begin \r
+    if( rising_edge(CLK_IN) ) then\r
+      if (RESET_IN = '1') then\r
+        trigger_o         <= '0';\r
+        timestamp_hold_o  <= '0';\r
+        trigger_busy_o    <= '1';\r
+        wait_timer_init   <= (others => '0');\r
+        STATE             <= S_IDLE;\r
+      else\r
+        trigger_o         <= trigger_o_x;\r
+        timestamp_hold_o  <= timestamp_hold_o_x;\r
+        trigger_busy_o    <= trigger_busy_o_x;\r
+        wait_timer_init   <= wait_timer_init_x;\r
+        STATE             <= NEXT_STATE;\r
+      end if;\r
+    end if;\r
+  end process PROC_TRIGGER_HANDLER_TRANSFER;\r
+\r
+  PROC_TRIGGER_HANDLER: process(STATE,\r
+                                TRIGGER_IN,\r
+                                TRIGGER_RELEASE_IN,\r
+                                wait_timer_done\r
+                                )\r
+  begin\r
+    trigger_o_x         <= '0';\r
+    timestamp_hold_o_x  <= '0';\r
+    trigger_busy_o_x    <= '1';\r
+    wait_timer_init_x   <= (others => '0');\r
+    \r
+    case STATE is\r
+      when  S_IDLE =>\r
+        if (TRIGGER_IN = '1') then\r
+          trigger_o_x         <= '1';\r
+          wait_timer_init_x   <= reg_timestamp_hold_delay;\r
+          NEXT_STATE          <= S_WAIT_HOLD;\r
+        else\r
+           trigger_busy_o_x   <= '0';\r
+           NEXT_STATE         <= S_IDLE;\r
+        end if;\r
+\r
+      when S_WAIT_HOLD =>\r
+        if (wait_timer_done = '1') then\r
+          timestamp_hold_o_x  <= '1';\r
+          NEXT_STATE          <= S_IDLE;\r
+        else\r
+          NEXT_STATE          <= S_WAIT_HOLD ;\r
+        end if;\r
+\r
+      when S_WAIT_TRIGGER_RELEASE =>\r
+        if (TRIGGER_RELEASE_IN = '0') then\r
+          NEXT_STATE          <= S_WAIT_TRIGGER_RELEASE;\r
+        else\r
+          NEXT_STATE          <= S_IDLE;\r
+        end if;\r
+        \r
+    end case;\r
+  end process PROC_TRIGGER_HANDLER;\r
+\r
+  -----------------------------------------------------------------------------\r
+  -- TRBNet Slave Bus\r
+  -----------------------------------------------------------------------------\r
+  \r
+  PROC_SLAVE_BUS: process(CLK_IN)\r
+  begin\r
+    if( rising_edge(CLK_IN) ) then\r
+      if( RESET_IN = '1' ) then\r
+        slv_data_out_o           <= (others => '0');\r
+        slv_no_more_data_o       <= '0';\r
+        slv_unknown_addr_o       <= '0';\r
+        start_cycle              <= '0';\r
+        slv_ack_o                <= '0';\r
+        reg_timestamp_hold_delay <= x"00ff";\r
+      else\r
+        slv_unknown_addr_o <= '0';\r
+        slv_no_more_data_o <= '0';\r
+        slv_data_out_o     <= (others => '0');\r
+        start_cycle        <= '0';\r
+\r
+        if (SLV_WRITE_IN  = '1') then\r
+          case SLV_ADDR_IN is\r
+            when x"0000" =>\r
+              reg_timestamp_hold_delay <= SLV_DATA_IN(15 downto 0);\r
+              slv_ack_o                <= '1';\r
+            when others =>\r
+              slv_unknown_addr_o       <= '1';\r
+              slv_ack_o                <= '0';\r
+          end case;\r
+\r
+        elsif (SLV_READ_IN = '1') then\r
+          case SLV_ADDR_IN is\r
+            when x"0000" =>\r
+              slv_data_out_o(15 downto 0)  <=\r
+                std_logic_vector(reg_timestamp_hold_delay);\r
+              slv_data_out_o(31 downto 16) <= (others => '0');\r
+              slv_ack_o                    <= '1';\r
+            when others =>\r
+              slv_unknown_addr_o           <= '1';\r
+              slv_ack_o                    <= '0';\r
+          end case;\r
+\r
+        else\r
+          slv_ack_o            <= '0';\r
+        end if;\r
+      end if;\r
+    end if;           \r
+  end process PROC_SLAVE_BUS;\r
+  \r
+  -----------------------------------------------------------------------------\r
+  -- Output Signals\r
+  -----------------------------------------------------------------------------\r
+  \r
+  -- Trigger Output\r
+  TRIGGER_OUT          <= trigger_o;\r
+  TIMESTAMP_HOLD_OUT   <= timestamp_hold_o;\r
+  TRIGGER_BUSY_OUT     <= trigger_busy_o;\r
+  \r
+  -- Slave Bus\r
+  SLV_DATA_OUT         <= slv_data_out_o;    \r
+  SLV_NO_MORE_DATA_OUT <= slv_no_more_data_o; \r
+  SLV_UNKNOWN_ADDR_OUT <= slv_unknown_addr_o;\r
+  SLV_ACK_OUT          <= slv_ack_o;    \r
+\r
+end Behavioral;\r