]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
new files for sync media interface
authorhadeshyp <hadeshyp>
Wed, 30 Jan 2013 17:32:38 +0000 (17:32 +0000)
committerhadeshyp <hadeshyp>
Wed, 30 Jan 2013 17:32:38 +0000 (17:32 +0000)
media_interfaces/ecp3_sfp/sfp_0_200_int.vhd
media_interfaces/med_ecp3_sfp_sync.vhd
media_interfaces/sync/med_sync_define.vhd [new file with mode: 0644]
media_interfaces/sync/rx_reset_fsm.vhd
media_interfaces/sync/tb/tx_control_tb.vhd [new file with mode: 0644]
media_interfaces/sync/tx_control.vhd [new file with mode: 0644]

index 59f7a45c822c10e1ffa75ca108795d4c381f779a..4fbccd94b0a811d7afdb97f01d30b21b59b8504d 100644 (file)
@@ -9,7 +9,7 @@ library IEEE;
 use IEEE.std_logic_1164.all;
 
 entity PCSD is
-GENERIC(
+generic(
   CONFIG_FILE : String;
   QUAD_MODE : String;
   CH0_CDR_SRC   : String := "REFCLK_EXT";
@@ -518,7 +518,7 @@ architecture PCSD_arch of PCSD is
 
 
 component PCSD_sim
-GENERIC(
+generic(
   CONFIG_FILE : String;
   QUAD_MODE : String;
   CH0_CDR_SRC   : String;
@@ -1881,7 +1881,7 @@ use IEEE.std_logic_1164.all;
 use STD.TEXTIO.all;
 
 entity sfp_0_200_int is
-   GENERIC (USER_CONFIG_FILE    :  String := "sfp_0_200_int.txt");
+   generic (USER_CONFIG_FILE    :  String := "sfp_0_200_int.txt");
  port (
 ------------------
 -- CH0 --
@@ -1969,7 +1969,7 @@ end component;
 
 component PCSD
 --synopsys translate_off
-GENERIC(
+generic(
   CONFIG_FILE : String;
   QUAD_MODE : String;
   CH0_CDR_SRC   : String := "REFCLK_EXT";
index ee186ce5dbe4b71effff35a539142a019f165ecd..d642153d905a137951a94080e6a886ab7b1c124a 100644 (file)
@@ -8,6 +8,7 @@ USE IEEE.numeric_std.all;
 library work;
 use work.trb_net_std.all;
 use work.trb_net_components.all;
+use work.med_sync_define.all;
 
 entity med_ecp3_sfp_sync is
   generic(
@@ -48,7 +49,7 @@ entity med_ecp3_sfp_sync is
     SCI_READ           : in  std_logic := '0';
     SCI_WRITE          : in  std_logic := '0';
     SCI_ACK            : out std_logic := '0';
-        
+    SCI_NACK           : out std_logic := '0';
     -- Status and control port
     STAT_OP            : out std_logic_vector (15 downto 0);
     CTRL_OP            : in  std_logic_vector (15 downto 0) := (others => '0');
@@ -117,32 +118,10 @@ component serdes_sync_0 is
     serdes_rst_qd_c    :   in std_logic
     );
 end component;
-  
-component rx_reset_fsm is
-  port (
-    RST_N             : in std_logic;
-    RX_REFCLK         : in std_logic;
-    TX_PLL_LOL_QD_S   : in std_logic;
-    RX_SERDES_RST_CH_C: out std_logic;
-    RX_CDR_LOL_CH_S   : in std_logic;
-    RX_LOS_LOW_CH_S   : in std_logic;
-    RX_PCS_RST_CH_C   : out std_logic;
-    STATE_OUT         : out std_logic_vector(3 downto 0)
-    );
-end component;
 
-component tx_reset_fsm is
-  port (
-    RST_N           : in std_logic;
-    TX_REFCLK       : in std_logic;   
-    TX_PLL_LOL_QD_S : in std_logic;
-    RST_QD_C        : out std_logic;
-    TX_PCS_RST_CH_C : out std_logic;
-    STATE_OUT       : out std_logic_vector(3 downto 0)
-    );
-end component;
-  
-constant K_IDLE : std_logic_vector(7 downto 0) := x"BC";
+
+
+
 
 signal clk_200_i         : std_logic;
 signal clk_200_internal  : std_logic;
@@ -181,10 +160,19 @@ signal sci_write_i       : std_logic;
 signal sci_write_shift_i : std_logic_vector(2 downto 0);
 signal sci_read_shift_i  : std_logic_vector(2 downto 0);
 
+signal wa_position       : std_logic_vector(15 downto 0) := x"FFFF";
+signal tx_allow          : std_logic;
+signal rx_allow          : std_logic;
+
 signal rx_fsm_state      : std_logic_vector(3 downto 0);
 signal tx_fsm_state      : std_logic_vector(3 downto 0);
 signal debug_reg         : std_logic_vector(63 downto 0);
 
+type sci_ctrl is (IDLE, SCTRL, SCTRL_WAIT, SCTRL_WAIT2, SCTRL_FINISH, GET_WA, GET_WA_WAIT, GET_WA_WAIT2, GET_WA_FINISH);
+signal sci_state         : sci_ctrl;
+signal sci_timer         : unsigned(12 downto 0) := (others => '0');
+
+
 begin
 clk_200_internal <= CLK;
 clk_200_i        <= clk_rx_full;
@@ -265,6 +253,7 @@ THE_RX_FSM : rx_reset_fsm
     RX_CDR_LOL_CH_S     => rx_cdr_lol,
     RX_LOS_LOW_CH_S     => rx_los_low,
     RX_PCS_RST_CH_C     => rx_pcs_rst,
+    WA_POSITION         => wa_position(3 downto 0),
     STATE_OUT           => rx_fsm_state
     );
     
@@ -279,41 +268,166 @@ THE_TX_FSM : tx_reset_fsm
     );
 
     
+PROC_ALLOW : process begin
+  wait until rising_edge(clk_200_i);
+  if rx_fsm_state = x"6" then
+    rx_allow <= '1';
+  else
+    rx_allow <= '0';
+  end if;
+  if rx_fsm_state = x"6" then   --TODO: needs to be comma detection
+    tx_allow <= '1';
+  else
+    tx_allow <= '0';
+  end if;
+end process;
+    
+    
 -------------------------------------------------      
 -- TX Data
 -------------------------------------------------         
-  tx_data <= x"BC";
-  tx_k    <= '1';
+THE_TX : tx_control
+  port map(
+    CLK_200                => clk_200_i,
+    CLK_100                => SYSCLK,
+    RESET_IN               => RESET,
+
+    TX_DATA_IN             => MED_DATA_IN,
+    TX_PACKET_NUMBER_IN    => MED_PACKET_NUM_IN,
+    TX_WRITE_IN            => MED_DATAREADY_IN,
+    TX_READ_OUT            => MED_READ_OUT,
+
+    TX_DATA_OUT            => tx_data,
+    TX_K_OUT               => tx_k,
+
+    REQUEST_RETRANSMIT_IN  => open,          --TODO
+    REQUEST_POSITION_IN    => open,          --TODO
+
+    START_RETRANSMIT_IN    => open,          --TODO
+    START_POSITION_IN      => open,          --TODO
+
+    SEND_DLM               => open,          --TODO
+    SEND_DLM_WORD          => open,          --TODO
+    
+    SEND_LINK_RESET_IN     => CTRL_OP(15),
+    TX_ALLOW_IN            => tx_allow,
+    RX_ALLOW_IN            => rx_allow,
+
+    DEBUG_OUT              => open,
+    STAT_REG_OUT           => open
+    );  
+
     
 -------------------------------------------------      
 -- SCI
 -------------------------------------------------      
-PROC_SCI : process begin
+-- PROC_SCI : process begin
+--   wait until rising_edge(SYSCLK);
+--   if SCI_READ = '1' or SCI_WRITE = '1' then
+--     sci_ch_i(0)   <= not SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+--     sci_ch_i(1)   <=     SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+--     sci_ch_i(2)   <= not SCI_ADDR(6) and     SCI_ADDR(7) and not SCI_ADDR(8);
+--     sci_ch_i(3)   <=     SCI_ADDR(6) and     SCI_ADDR(7) and not SCI_ADDR(8);
+--     sci_qd_i      <= not SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8);
+--     sci_reg_i     <=     SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8);
+--     sci_addr_i    <= SCI_ADDR;
+--     sci_data_in_i <= SCI_DATA_IN;
+--   end if;
+--   sci_read_shift_i  <= sci_read_shift_i(1 downto 0) & SCI_READ;
+--   sci_write_shift_i <= sci_write_shift_i(1 downto 0) & SCI_WRITE;
+--   if sci_reg_i = '1' then
+--     SCI_DATA_OUT        <= debug_reg(8*(to_integer(unsigned(SCI_ADDR(2 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(2 downto 0)))));
+--     sci_read_shift_i(2) <= '1';
+--   else
+--     SCI_DATA_OUT      <= sci_data_out_i;
+--   end if;
+-- end process;
+
+-- sci_write_i <= or_all(sci_write_shift_i);
+-- sci_read_i  <= or_all(sci_read_shift_i);
+-- SCI_ACK     <= sci_write_shift_i(2) or sci_read_shift_i(2);
+
+
+PROC_SCI_CTRL: process 
+  variable cnt : integer range 0 to 3 := 0;
+begin
   wait until rising_edge(SYSCLK);
-  if SCI_READ = '1' or SCI_WRITE = '1' then
-    sci_ch_i(0)   <= not SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
-    sci_ch_i(1)   <=     SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
-    sci_ch_i(2)   <= not SCI_ADDR(6) and     SCI_ADDR(7) and not SCI_ADDR(8);
-    sci_ch_i(3)   <=     SCI_ADDR(6) and     SCI_ADDR(7) and not SCI_ADDR(8);
-    sci_qd_i      <= not SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8);
-    sci_reg_i     <=     SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8);
-    sci_addr_i    <= SCI_ADDR;
-    sci_data_in_i <= SCI_DATA_IN;
-  end if;
-  sci_read_shift_i  <= sci_read_shift_i(1 downto 0) & SCI_READ;
-  sci_write_shift_i <= sci_write_shift_i(1 downto 0) & SCI_WRITE;
-  if sci_reg_i = '1' then
-    SCI_DATA_OUT        <= debug_reg(8*(to_integer(unsigned(SCI_ADDR(2 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(2 downto 0)))));
-    sci_read_shift_i(2) <= '1';
+  SCI_ACK <= '0';
+  case sci_state is
+    when IDLE =>
+      sci_ch_i        <= x"0";
+      sci_qd_i        <= '0';
+      sci_reg_i       <= '0';
+      sci_read_i      <= '0';
+      sci_write_i     <= '0';
+      sci_timer       <= sci_timer + 1;
+      if SCI_READ = '1' or SCI_WRITE = '1' then
+        sci_ch_i(0)   <= not SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+        sci_ch_i(1)   <=     SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+        sci_ch_i(2)   <= not SCI_ADDR(6) and     SCI_ADDR(7) and not SCI_ADDR(8);
+        sci_ch_i(3)   <=     SCI_ADDR(6) and     SCI_ADDR(7) and not SCI_ADDR(8);
+        sci_qd_i      <= not SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8);
+        sci_reg_i     <=     SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8);
+        sci_addr_i    <= SCI_ADDR;
+        sci_data_in_i <= SCI_DATA_IN;
+        sci_read_i    <= SCI_READ and not (SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8));
+        sci_write_i   <= SCI_WRITE and not (SCI_ADDR(6) and not SCI_ADDR(7) and     SCI_ADDR(8));
+        sci_state     <= SCTRL;
+      elsif sci_timer(sci_timer'left) = '1' then
+        sci_timer     <= (others => '0');
+        sci_state     <= GET_WA;
+      end if;      
+    when SCTRL =>
+      if sci_reg_i = '1' then
+        SCI_DATA_OUT  <= debug_reg(8*(to_integer(unsigned(SCI_ADDR(2 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(2 downto 0)))));
+        SCI_ACK       <= '1';
+        sci_write_i   <= '0';
+        sci_read_i    <= '0';
+        sci_state     <= IDLE;
+      else
+        sci_state     <= SCTRL_WAIT;
+      end if;
+    when SCTRL_WAIT   =>
+      sci_state       <= SCTRL_WAIT2;
+    when SCTRL_WAIT2  =>
+      sci_state       <= SCTRL_FINISH;
+    when SCTRL_FINISH =>
+      SCI_DATA_OUT    <= sci_data_out_i;
+      SCI_ACK         <= '1';
+      sci_write_i     <= '0';
+      sci_read_i      <= '0';
+      sci_state       <= IDLE;
+    
+    when GET_WA =>
+      if cnt = 3 then
+        cnt           := 0;
+        sci_state     <= IDLE;
+      else
+        sci_state     <= GET_WA_WAIT;
+        sci_addr_i    <= '0' & x"22";
+        sci_ch_i      <= x"0";
+        sci_ch_i(cnt) <= '1';
+        sci_read_i    <= '1';
+      end if;
+    when GET_WA_WAIT  =>
+      sci_state       <= GET_WA_WAIT2;
+    when GET_WA_WAIT2 =>
+      sci_state       <= GET_WA_FINISH;
+    when GET_WA_FINISH =>
+      wa_position(cnt*4+3 downto cnt*4) <= sci_data_out_i(3 downto 0);
+      sci_state       <= GET_WA;    
+      cnt             := cnt + 1;
+  end case;
+  
+  if (SCI_READ = '1' or SCI_WRITE = '1') and sci_state /= IDLE then
+    SCI_NACK <= '1';
   else
-    SCI_DATA_OUT      <= sci_data_out_i;
+    SCI_NACK <= '0';
   end if;
+  
 end process;
 
-sci_write_i <= or_all(sci_write_shift_i);
-sci_read_i  <= or_all(sci_read_shift_i);
-SCI_ACK     <= sci_write_shift_i(2) or sci_read_shift_i(2);
-  
+
 -------------------------------------------------      
 -- Debug Registers
 -------------------------------------------------            
@@ -331,7 +445,9 @@ debug_reg(19)           <= lsm_status;
 debug_reg(23 downto 20) <= tx_fsm_state;
 debug_reg(31 downto 24) <= tx_data;
 
-debug_reg(63 downto 32)  <= (others => '0');
+
+debug_reg(47 downto 32) <= wa_position;
+debug_reg(63 downto 48) <= (others => '0');
 
       
 STAT_DEBUG <= debug_reg;
diff --git a/media_interfaces/sync/med_sync_define.vhd b/media_interfaces/sync/med_sync_define.vhd
new file mode 100644 (file)
index 0000000..793234e
--- /dev/null
@@ -0,0 +1,83 @@
+library ieee;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.std_logic_ARITH.ALL;
+USE IEEE.std_logic_UNSIGNED.ALL;
+
+package med_sync_define is
+
+constant K_IDLE   : std_logic_vector(7 downto 0) := x"BC";
+constant D_IDLE0  : std_logic_vector(7 downto 0) := x"C5";
+constant D_IDLE1  : std_logic_vector(7 downto 0) := x"50";
+constant K_SOP    : std_logic_vector(7 downto 0) := x"FB";
+constant K_EOP    : std_logic_vector(7 downto 0) := x"FD";
+constant K_BGN    : std_logic_vector(7 downto 0) := x"1C";
+constant K_REQ    : std_logic_vector(7 downto 0) := x"7C";
+constant K_RST    : std_logic_vector(7 downto 0) := x"FE";
+constant K_DLM    : std_logic_vector(7 downto 0) := x"DC";
+
+
+
+component tx_control is
+  port(
+    CLK_200                        : in  std_logic;
+    CLK_100                        : in  std_logic;
+    RESET_IN                       : in  std_logic;
+
+    TX_DATA_IN                     : in  std_logic_vector(15 downto 0);
+    TX_PACKET_NUMBER_IN            : in  std_logic_vector( 2 downto 0);
+    TX_WRITE_IN                    : in  std_logic;
+    TX_READ_OUT                    : out std_logic;
+
+    TX_DATA_OUT                    : out std_logic_vector( 7 downto 0);
+    TX_K_OUT                       : out std_logic;
+
+    REQUEST_RETRANSMIT_IN          : in  std_logic := '0';
+    REQUEST_POSITION_IN            : in  std_logic_vector( 7 downto 0) := (others => '0');
+
+    START_RETRANSMIT_IN            : in  std_logic := '0';
+    START_POSITION_IN              : in  std_logic_vector( 7 downto 0) := (others => '0');
+
+    SEND_DLM                       : in  std_logic := '0';
+    SEND_DLM_WORD                  : in  std_logic_vector( 7 downto 0) := (others => '0');
+    
+    SEND_LINK_RESET_IN             : in  std_logic := '0';
+    TX_ALLOW_IN                    : in  std_logic := '0';
+    RX_ALLOW_IN                    : in  std_logic := '0';
+
+    DEBUG_OUT                      : out std_logic_vector(31 downto 0);
+    STAT_REG_OUT                   : out std_logic_vector(31 downto 0)
+    );
+end component;
+
+
+  
+component rx_reset_fsm is
+  port (
+    RST_N             : in std_logic;
+    RX_REFCLK         : in std_logic;
+    TX_PLL_LOL_QD_S   : in std_logic;
+    RX_SERDES_RST_CH_C: out std_logic;
+    RX_CDR_LOL_CH_S   : in std_logic;
+    RX_LOS_LOW_CH_S   : in std_logic;
+    RX_PCS_RST_CH_C   : out std_logic;
+    --fix word alignment position to 0 for non-slave links!
+    WA_POSITION       : in std_logic_vector(3 downto 0) := x"0";
+    STATE_OUT         : out std_logic_vector(3 downto 0)
+    );
+end component;
+
+component tx_reset_fsm is
+  port (
+    RST_N           : in std_logic;
+    TX_REFCLK       : in std_logic;   
+    TX_PLL_LOL_QD_S : in std_logic;
+    RST_QD_C        : out std_logic;
+    TX_PCS_RST_CH_C : out std_logic;
+    STATE_OUT       : out std_logic_vector(3 downto 0)
+    );
+end component;
+  
+
+
+
+end package;
\ No newline at end of file
index 9b7047f20e8378ed0f0be440587618c97839df17..a5d713145ea191c5a98ce3e1a8032d0bacdee2b9 100644 (file)
@@ -15,6 +15,8 @@ entity rx_reset_fsm is
     RX_CDR_LOL_CH_S   : in std_logic;
     RX_LOS_LOW_CH_S   : in std_logic;
     RX_PCS_RST_CH_C   : out std_logic;
+    --fix word alignment position to 0 for non-slave links!
+    WA_POSITION       : in  std_logic_vector(3 downto 0) := x"0";
     STATE_OUT         : out std_logic_vector(3 downto 0)
     );
 end entity ;
@@ -154,7 +156,7 @@ begin
       rx_serdes_rst_ch_c_int <= '0';
       if rx_lol_los_int = rx_lol_los_del then   --NO RISING OR FALLING EDGES
         if timer2 = '1' then
-          if rx_lol_los_int = '1' then
+          if rx_lol_los_int = '1' or WA_POSITION /= x"0" then
             ns <= WAIT_FOR_PLOL;
           else
             ns <= NORMAL;
@@ -184,6 +186,8 @@ begin
   end case;
                                                                                               
 end process;
-                                                                                              
+
+
+
                                                                                               
 end architecture;
\ No newline at end of file
diff --git a/media_interfaces/sync/tb/tx_control_tb.vhd b/media_interfaces/sync/tb/tx_control_tb.vhd
new file mode 100644 (file)
index 0000000..dbf9f8d
--- /dev/null
@@ -0,0 +1,105 @@
+LIBRARY ieee  ; 
+LIBRARY work  ; 
+USE ieee.NUMERIC_STD.all  ; 
+USE ieee.std_logic_1164.all  ; 
+USE work.med_sync_define.all  ; 
+USE work.trb_net_components.all  ; 
+USE work.trb_net_std.all  ; 
+
+entity tx_control_tb  is 
+end entity; 
+architecture tx_control_tb_arch of tx_control_tb is
+  signal stat_reg_out   :  std_logic_vector (31 downto 0)  ; 
+  signal start_position_in   :  std_logic_vector (7 downto 0) := (others => '0')  ; 
+  signal clk_100   :  std_logic  := '1'; 
+  signal clk_200   :  std_logic  := '1'; 
+  signal request_position_in   :  std_logic_vector (7 downto 0) := (others => '0')  ; 
+  signal tx_k_out   :  std_logic  ; 
+  signal send_dlm   :  std_logic := '0'  ; 
+  signal tx_read_out   :  std_logic  ; 
+  signal tx_allow_in   :  std_logic := '1'  ; 
+  signal send_dlm_word   :  std_logic_vector (7 downto 0) := (others => '0')  ; 
+  signal reset_in   :  std_logic  := '0' ; 
+  signal tx_packet_number_in   :  std_logic_vector (2 downto 0)  ; 
+  signal tx_data_in   :  std_logic_vector (15 downto 0) := (others => '0') ; 
+  signal tx_write_in   :  std_logic  := '0'; 
+  signal tx_data_out   :  std_logic_vector (7 downto 0)  ; 
+  signal start_retransmit_in   :  std_logic := '0'  ; 
+  signal debug_out   :  std_logic_vector (31 downto 0)  ; 
+  signal send_link_reset_in   :  std_logic := '0'  ; 
+  signal request_retransmit_in   :  std_logic := '0'  ; 
+  
+  
+  component tx_control  
+    port ( 
+      STAT_REG_OUT  : out std_logic_vector (31 downto 0) ; 
+      START_POSITION_IN  : in std_logic_vector (7 downto 0) ; 
+      CLK_100  : in STD_LOGIC ; 
+      CLK_200  : in STD_LOGIC ; 
+      REQUEST_POSITION_IN  : in std_logic_vector (7 downto 0) ; 
+      TX_K_OUT  : out STD_LOGIC ; 
+      SEND_DLM  : in STD_LOGIC ; 
+      TX_READ_OUT  : out STD_LOGIC ; 
+      TX_ALLOW_IN  : in STD_LOGIC ; 
+      SEND_DLM_WORD  : in std_logic_vector (7 downto 0) ; 
+      RESET_IN  : in STD_LOGIC ; 
+      TX_PACKET_NUMBER_IN  : in std_logic_vector (2 downto 0) ; 
+      TX_DATA_IN  : in std_logic_vector (15 downto 0) ; 
+      TX_WRITE_IN  : in STD_LOGIC ; 
+      TX_DATA_OUT  : out std_logic_vector (7 downto 0) ; 
+      START_RETRANSMIT_IN  : in STD_LOGIC ; 
+      DEBUG_OUT  : out std_logic_vector (31 downto 0) ; 
+      SEND_LINK_RESET_IN  : in STD_LOGIC ; 
+      REQUEST_RETRANSMIT_IN  : in STD_LOGIC ); 
+  end component ; 
+  
+  
+begin
+  DUT  : tx_control  
+    port map ( 
+      STAT_REG_OUT   => STAT_REG_OUT  ,
+      START_POSITION_IN   => START_POSITION_IN  ,
+      CLK_100   => CLK_100  ,
+      CLK_200   => CLK_200  ,
+      REQUEST_POSITION_IN   => REQUEST_POSITION_IN  ,
+      TX_K_OUT   => TX_K_OUT  ,
+      SEND_DLM   => SEND_DLM  ,
+      TX_READ_OUT   => TX_READ_OUT  ,
+      TX_ALLOW_IN   => TX_ALLOW_IN  ,
+      SEND_DLM_WORD   => SEND_DLM_WORD  ,
+      RESET_IN   => RESET_IN  ,
+      TX_PACKET_NUMBER_IN   => TX_PACKET_NUMBER_IN  ,
+      TX_DATA_IN   => TX_DATA_IN  ,
+      TX_WRITE_IN   => TX_WRITE_IN  ,
+      TX_DATA_OUT   => TX_DATA_OUT  ,
+      START_RETRANSMIT_IN   => START_RETRANSMIT_IN  ,
+      DEBUG_OUT   => DEBUG_OUT  ,
+      SEND_LINK_RESET_IN   => SEND_LINK_RESET_IN  ,
+      REQUEST_RETRANSMIT_IN   => REQUEST_RETRANSMIT_IN   
+      ); 
+      
+CLK_100 <= not CLK_100 after 5 ns;
+CLK_200 <= not CLK_200 after 2.5 ns;
+
+TX_ALLOW_IN <= '0', '1' after 50 ns;
+
+
+process begin
+  wait for 100 ns;
+  wait until rising_edge(clk_100); wait for 1 ns;
+  TX_DATA_IN <= x"0038";  TX_PACKET_NUMBER_IN <= "100"; TX_WRITE_IN <= '1';  
+  wait until rising_edge(clk_100); wait for 1 ns;
+  TX_DATA_IN <= x"1111";  TX_PACKET_NUMBER_IN <= "000"; TX_WRITE_IN <= '1';  
+  wait until rising_edge(clk_100); wait for 1 ns;
+  TX_DATA_IN <= x"2222";  TX_PACKET_NUMBER_IN <= "001"; TX_WRITE_IN <= '1';  
+  wait until rising_edge(clk_100); wait for 1 ns;
+  TX_DATA_IN <= x"3333";  TX_PACKET_NUMBER_IN <= "010"; TX_WRITE_IN <= '1';  
+  wait until rising_edge(clk_100); wait for 1 ns;
+  TX_DATA_IN <= x"4444";  TX_PACKET_NUMBER_IN <= "011"; TX_WRITE_IN <= '1';  
+  wait until rising_edge(clk_100); wait for 1 ns;
+  TX_DATA_IN <= x"0000";  TX_PACKET_NUMBER_IN <= "100"; TX_WRITE_IN <= '0';  
+end process;
+
+end architecture; 
+
diff --git a/media_interfaces/sync/tx_control.vhd b/media_interfaces/sync/tx_control.vhd
new file mode 100644 (file)
index 0000000..8fe468d
--- /dev/null
@@ -0,0 +1,530 @@
+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.med_sync_define.all;
+
+entity tx_control is
+  port(
+    CLK_200                        : in  std_logic;
+    CLK_100                        : in  std_logic;
+    RESET_IN                       : in  std_logic;
+
+    TX_DATA_IN                     : in  std_logic_vector(15 downto 0);
+    TX_PACKET_NUMBER_IN            : in  std_logic_vector(2 downto 0);
+    TX_WRITE_IN                    : in  std_logic;
+    TX_READ_OUT                    : out std_logic;
+
+    TX_DATA_OUT                    : out std_logic_vector( 7 downto 0);
+    TX_K_OUT                       : out std_logic;
+
+    REQUEST_RETRANSMIT_IN          : in  std_logic := '0';
+    REQUEST_POSITION_IN            : in  std_logic_vector( 7 downto 0) := (others => '0');
+
+    START_RETRANSMIT_IN            : in  std_logic := '0';
+    START_POSITION_IN              : in  std_logic_vector( 7 downto 0) := (others => '0');
+
+    SEND_DLM                       : in  std_logic := '0';
+    SEND_DLM_WORD                  : in  std_logic_vector( 7 downto 0) := (others => '0');
+    
+    SEND_LINK_RESET_IN             : in  std_logic := '0';
+    TX_ALLOW_IN                    : in  std_logic := '0';
+    RX_ALLOW_IN                    : in  std_logic := '0';
+
+    DEBUG_OUT                      : out std_logic_vector(31 downto 0);
+    STAT_REG_OUT                   : out std_logic_vector(31 downto 0)
+    );
+end entity;
+
+
+
+architecture arch of tx_control is
+
+-- gk 05.10.10
+  component lattice_ecp3_fifo_18x16_dualport_oreg
+    port (
+      Data: in  std_logic_vector(17 downto 0);
+      WrClock: in  std_logic;
+      RdClock: in  std_logic;
+      WrEn: in  std_logic;
+      RdEn: in  std_logic;
+      Reset: in  std_logic;
+      RPReset: in  std_logic;
+      Q: out  std_logic_vector(17 downto 0);
+      Empty: out  std_logic;
+      Full: out  std_logic;
+      AlmostFull: out std_logic
+      );
+  end component;
+
+-- gk 05.10.10
+component trb_net_CRC8 is
+  port(
+    CLK       : in  std_logic;
+    RESET     : in  std_logic;
+    CLK_EN    : in  std_logic;
+    DATA_IN   : in  std_logic_vector(7 downto 0);
+    CRC_OUT   : out std_logic_vector(7 downto 0);
+    CRC_match : out std_logic
+    );
+end component;
+
+  type state_t is (SEND_IDLE_L, SEND_IDLE_H, SEND_DATA_L, SEND_DATA_H, SEND_DLM_L, SEND_DLM_H,
+                   SEND_START_L, SEND_START_H, SEND_REQUEST_L, SEND_REQUEST_H,
+                   SEND_RESET, SEND_CHKSUM_L, SEND_CHKSUM_H);  -- gk 05.10.10
+  signal current_state           : state_t;
+
+  type ram_t is array(0 to 255) of std_logic_vector(17 downto 0);
+  signal ram                     : ram_t;
+
+  signal ram_write               : std_logic := '0';
+  signal ram_write_addr          : unsigned(7 downto 0) := (others => '0');
+  signal ram_read                : std_logic := '0';
+  signal ram_read_addr           : unsigned(7 downto 0) := (others => '0');
+  signal ram_dout                : std_logic_vector(17 downto 0);
+  signal next_ram_dout           : std_logic_vector(17 downto 0);
+  signal ram_fill_level          : unsigned(7 downto 0);
+  signal ram_empty               : std_logic;
+  signal ram_afull               : std_logic;
+
+  signal request_position_q      : std_logic_vector( 7 downto 0);
+  signal restart_position_q      : std_logic_vector( 7 downto 0);
+  signal request_position_i      : std_logic_vector( 7 downto 0);
+  signal restart_position_i      : std_logic_vector( 7 downto 0);
+  signal make_request_i          : std_logic;
+  signal make_restart_i          : std_logic;
+  signal load_read_pointer_i     : std_logic;
+  signal send_dlm_in_i           : std_logic;
+  signal send_dlm_i              : std_logic;
+  signal start_retransmit_i      : std_logic;
+  signal request_retransmit_i    : std_logic;
+
+  signal buf_tx_read_out         : std_logic;
+  signal tx_data_200             : std_logic_vector(17 downto 0);
+  signal tx_allow_qtx            : std_logic;
+  signal rx_allow_qtx            : std_logic;
+  signal tx_allow_q              : std_logic;
+  signal send_link_reset_qtx     : std_logic;
+  signal ct_fifo_empty           : std_logic;
+  signal ct_fifo_write           : std_logic := '0';
+  signal ct_fifo_read            : std_logic := '0';
+  signal ct_fifo_full            : std_logic;
+  signal ct_fifo_afull           : std_logic;
+  signal ct_fifo_reset           : std_logic;
+  signal last_ct_fifo_empty      : std_logic;
+  signal last_ct_fifo_read       : std_logic;
+
+  -- gk 05.10.10
+  signal save_sop                : std_logic;
+  signal save_eop                : std_logic;
+  signal load_sop                : std_logic;
+  signal load_eop                : std_logic;
+  signal crc_reset               : std_logic;
+  signal crc_q                   : std_logic_vector(7 downto 0);
+  signal crc_en                  : std_logic;
+  signal crc_data                : std_logic_vector(7 downto 0);
+
+begin
+
+----------------------------------------------------------------------
+-- Clock Domain Transfer
+----------------------------------------------------------------------
+-- gk 05.10.10
+  THE_CT_FIFO : lattice_ecp3_fifo_18x16_dualport_oreg
+    port map(
+      Data(15 downto 0) => TX_DATA_IN,
+      Data(16)          => save_sop,
+      Data(17)          => save_eop,
+      WrClock           => CLK_100,
+      RdClock           => CLK_200,
+      WrEn              => ct_fifo_write,
+      RdEn              => ct_fifo_read,
+      Reset             => ct_fifo_reset,
+      RPReset           => ct_fifo_reset,
+      Q(17 downto 0)    => tx_data_200,
+      Empty             => ct_fifo_empty,
+      Full              => ct_fifo_full,
+      AlmostFull        => ct_fifo_afull
+      );
+
+  THE_RD_PROC : process(CLK_100)
+    begin
+      if rising_edge(CLK_100) then
+        buf_tx_read_out  <= tx_allow_q  and not ct_fifo_afull ;
+      end if;
+    end process;
+
+  ct_fifo_reset <= not tx_allow_qtx;
+  TX_READ_OUT   <= buf_tx_read_out;
+
+  ct_fifo_write <= buf_tx_read_out and TX_WRITE_IN;
+  ct_fifo_read  <= tx_allow_qtx and not ram_afull and not ct_fifo_empty;
+  
+  last_ct_fifo_read   <= ct_fifo_read  when rising_edge(CLK_200);
+  last_ct_fifo_empty  <= ct_fifo_empty when rising_edge(CLK_200);
+  
+  save_sop <= '1' when (TX_PACKET_NUMBER_IN = c_H0) else '0';
+  save_eop <= '1' when (TX_PACKET_NUMBER_IN = c_F3) else '0';
+
+----------------------------------------------------------------------
+-- RAM
+----------------------------------------------------------------------
+
+
+  THE_RAM_WR_PROC : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        ram_write <= '0';
+      elsif rising_edge(CLK_200) then
+        ram_write   <= last_ct_fifo_read and not last_ct_fifo_empty;
+      end if;
+    end process;
+
+--RAM
+  THE_RAM_PROC : process(CLK_200)
+    begin
+      if rising_edge(CLK_200) then
+        if ram_write = '1' then
+          ram((to_integer(ram_write_addr))) <= tx_data_200;
+        end if;
+        next_ram_dout <= ram(to_integer(ram_read_addr));
+        ram_dout <= next_ram_dout;
+      end if;
+    end process;
+
+--RAM read pointer
+  THE_READ_CNT : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        ram_read_addr <= (others => '0');
+      elsif rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          ram_read_addr <= (others => '0');
+        elsif load_read_pointer_i = '1' then
+          ram_read_addr <= unsigned(restart_position_i);
+        elsif ram_read = '1' then
+          ram_read_addr <= ram_read_addr + to_unsigned(1,1);
+        end if;
+      end if;
+    end process;
+
+--RAM write pointer
+  THE_WRITE_CNT : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        ram_write_addr <= (others => '0');
+      elsif rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          ram_write_addr <= (others => '0');
+        elsif ram_write = '1' then
+          ram_write_addr <= ram_write_addr + to_unsigned(1,1);
+        end if;
+      end if;
+    end process;
+
+
+--RAM fill level counter
+  THE_FILL_CNT : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        ram_fill_level <= (others => '0');
+      elsif rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          ram_fill_level <= (others => '0');
+        else
+          ram_fill_level <= ram_write_addr - ram_read_addr;
+        end if;
+      end if;
+    end process;
+
+
+--RAM empty
+--   ram_empty <= not or_all(std_logic_vector(ram_write_addr) xor std_logic_vector(ram_read_addr)) and not RESET_IN;
+  ram_empty <= '1' when (ram_write_addr = ram_read_addr) or RESET_IN = '1' else '0';
+  ram_afull <= '1' when ram_fill_level >= 4 else '0';
+
+
+
+----------------------------------------------------------------------
+-- TX control state machine
+----------------------------------------------------------------------
+
+  THE_DATA_CONTROL_FSM : process(CLK_200, RESET_IN)
+    begin
+      if rising_edge(CLK_200) then
+--         ram_read               <= '0';
+        TX_K_OUT               <= '0';
+
+        case current_state is
+          when SEND_IDLE_L =>
+            TX_DATA_OUT        <= K_IDLE;
+            TX_K_OUT           <= '1';
+            current_state      <= SEND_IDLE_H;
+
+          when SEND_IDLE_H =>
+            if rx_allow_qtx = '1' then
+              TX_DATA_OUT        <= D_IDLE1;
+            else
+              TX_DATA_OUT        <= D_IDLE0;
+            end if;
+
+          when SEND_DATA_L =>
+            TX_DATA_OUT        <= ram_dout(7 downto 0);
+            load_sop           <= ram_dout(16);
+            load_eop           <= ram_dout(17);
+            current_state      <= SEND_DATA_H;
+
+          when SEND_DATA_H =>
+            TX_DATA_OUT        <= ram_dout(15 downto 8);
+
+          when SEND_CHKSUM_L =>
+            TX_DATA_OUT        <= K_EOP;
+            TX_K_OUT           <= '1';
+            load_sop           <= '0';
+            load_eop           <= '0';
+            current_state      <= SEND_CHKSUM_H;
+
+          when SEND_CHKSUM_H =>
+            TX_DATA_OUT        <= crc_q;
+
+          when SEND_START_L =>
+            TX_DATA_OUT        <= K_BGN;
+            TX_K_OUT           <= '1';
+            current_state      <= SEND_START_H;
+
+          when SEND_START_H =>
+            TX_DATA_OUT        <= std_logic_vector(ram_read_addr);
+
+          when SEND_REQUEST_L =>
+            TX_DATA_OUT        <= K_REQ;
+            TX_K_OUT           <= '1';
+            current_state      <= SEND_REQUEST_H;
+
+          when SEND_DLM_L =>
+            TX_DATA_OUT        <= K_DLM;
+            TX_K_OUT           <= '1';
+            current_state      <= SEND_DLM_H;
+          
+          when SEND_DLM_H =>
+            TX_DATA_OUT        <= SEND_DLM_WORD;
+            
+          when SEND_REQUEST_H =>
+            TX_DATA_OUT        <= request_position_i;
+
+          when SEND_RESET =>
+            TX_DATA_OUT        <= K_RST;
+            TX_K_OUT           <= '1';
+            if send_link_reset_qtx = '0' then
+              current_state    <= SEND_IDLE_L;
+            end if;
+
+          when others =>
+            current_state      <= SEND_IDLE_L;
+        end case;
+
+        if  current_state = SEND_START_H or
+            current_state = SEND_IDLE_H  or
+            current_state = SEND_DATA_H  or
+            current_state = SEND_DLM_H  or
+            current_state = SEND_REQUEST_H or
+            current_state = SEND_CHKSUM_H  then
+          if tx_allow_qtx = '0' then
+            current_state    <= SEND_IDLE_L;
+          elsif send_link_reset_qtx = '1' then
+            current_state    <= SEND_RESET;
+          elsif make_request_i = '1' then
+            current_state    <= SEND_REQUEST_L;
+          elsif make_restart_i = '1' then
+            current_state    <= SEND_START_L;
+          elsif send_dlm_i = '1' then
+            current_state    <= SEND_DLM_L;
+--          elsif (load_eop = '1') then
+--            current_state    <= SEND_CHKSUM_L;
+          elsif ram_empty = '0' then
+--             ram_read         <= '1';
+            current_state    <= SEND_DATA_L;
+          else
+            current_state    <= SEND_IDLE_L;
+          end if;
+
+        end if;
+      end if;
+      --async because of oreg.
+      if  (current_state = SEND_START_H or current_state = SEND_IDLE_H  or current_state = SEND_DATA_H  or
+            current_state = SEND_DLM_H or current_state = SEND_REQUEST_H or current_state = SEND_CHKSUM_H) 
+            and ram_empty = '0' and tx_allow_qtx = '1' and send_link_reset_qtx = '0' 
+            and make_request_i = '0' and make_restart_i = '0' and send_dlm_i = '0' then
+        ram_read <= '1';
+      else 
+        ram_read <= '0';
+      end if;
+      if RESET_IN = '1' then
+        ram_read <= '0';
+      end if;
+    end process;
+
+----------------------------------------------------------------------
+--
+----------------------------------------------------------------------
+
+tx_allow_qtx        <= TX_ALLOW_IN when rising_edge(CLK_200);
+rx_allow_qtx        <= RX_ALLOW_IN when rising_edge(CLK_200);
+
+send_link_reset_qtx <= SEND_LINK_RESET_IN when rising_edge(CLK_200);
+tx_allow_q          <= tx_allow_qtx when rising_edge(CLK_100);
+
+  THE_RETRANSMIT_PULSE_SYNC_1 : pulse_sync
+    port map(
+      CLK_A_IN        => CLK_100,
+      RESET_A_IN      => RESET_IN,
+      PULSE_A_IN      => REQUEST_RETRANSMIT_IN,
+      CLK_B_IN        => CLK_200,
+      RESET_B_IN      => RESET_IN,
+      PULSE_B_OUT     => request_retransmit_i
+    );
+
+  THE_RETRANSMIT_PULSE_SYNC_2 : pulse_sync
+    port map(
+      CLK_A_IN        => CLK_100,
+      RESET_A_IN      => RESET_IN,
+      PULSE_A_IN      => START_RETRANSMIT_IN,
+      CLK_B_IN        => CLK_200,
+      RESET_B_IN      => RESET_IN,
+      PULSE_B_OUT     => start_retransmit_i
+    );
+
+  THE_RETRANSMIT_PULSE_SYNC_3 : pulse_sync
+    port map(
+      CLK_A_IN        => CLK_100,
+      RESET_A_IN      => RESET_IN,
+      PULSE_A_IN      => SEND_DLM,
+      CLK_B_IN        => CLK_200,
+      RESET_B_IN      => RESET_IN,
+      PULSE_B_OUT     => send_dlm_in_i
+    );    
+    
+  THE_POSITION_REG : process(CLK_100)
+    begin
+      if rising_edge(CLK_100) then
+        if REQUEST_RETRANSMIT_IN = '1' then
+          request_position_q <= REQUEST_POSITION_IN;
+        end if;
+        if START_RETRANSMIT_IN = '1' then
+          restart_position_q <= START_POSITION_IN;
+        end if;
+      end if;
+    end process;
+
+
+--Store Request Retransmit position
+  THE_STORE_REQUEST_PROC : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        make_request_i <= '0';
+        request_position_i <= (others => '0');
+      elsif rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          make_request_i     <= '0';
+          request_position_i <= (others => '0');
+        elsif request_retransmit_i = '1' then
+          make_request_i     <= '1';
+          request_position_i <= request_position_q;
+        elsif current_state = SEND_REQUEST_L then
+          make_request_i     <= '0';
+        elsif current_state = SEND_REQUEST_H then
+          request_position_i <= (others => '0');
+        end if;
+      end if;
+    end process;
+
+
+--Store Restart position
+  THE_STORE_RESTART_PROC : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        make_restart_i           <= '0';
+        restart_position_i       <= (others => '0');
+      elsif rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          make_restart_i         <= '0';
+          restart_position_i     <= (others => '0');
+        elsif start_retransmit_i = '1' then
+          make_restart_i         <= '1';
+          restart_position_i     <= restart_position_q;
+        elsif current_state = SEND_START_L then
+          make_restart_i         <= '0';
+        elsif current_state = SEND_START_H then
+          restart_position_i     <= (others => '0');
+        end if;
+      end if;
+    end process;
+
+--Store Restart position
+  THE_STORE_DLM_PROC : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        send_dlm_i           <= '0';
+      elsif rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          send_dlm_i         <= '0';
+        elsif send_dlm_in_i = '1' then
+          send_dlm_i         <= '1';
+        elsif current_state = SEND_DLM_L then
+          send_dlm_i         <= '0';
+        end if;
+      end if;
+    end process;    
+    
+  load_read_pointer_i    <= '1' when current_state = SEND_START_L else '0';
+
+  -- gk 05.10.10
+  crc_reset <= '1' when ((RESET_IN = '1') or (current_state = SEND_CHKSUM_H) or (current_state = SEND_START_H)) else '0';
+  crc_en    <= '1' when ((current_state = SEND_DATA_L) or (current_state = SEND_DATA_H)) else '0';
+  crc_data  <= ram_dout(15 downto 8) when (current_state = SEND_DATA_H) else ram_dout(7 downto 0);
+
+  -- gk 05.10.10
+  CRC_CALC : trb_net_CRC8
+    port map(
+      CLK       => CLK_200,
+      RESET     => crc_reset,
+      CLK_EN    => crc_en,
+      DATA_IN   => crc_data,
+      CRC_OUT   => crc_q,
+      CRC_match => open
+      );
+
+
+----------------------------------------------------------------------
+-- Debug
+----------------------------------------------------------------------
+  DEBUG_OUT(0) <= ram_read;
+  DEBUG_OUT(1) <= ct_fifo_write;
+  DEBUG_OUT(2) <= ct_fifo_read;
+  DEBUG_OUT(3) <= tx_allow_qtx;
+  DEBUG_OUT(4) <= ram_empty;
+  DEBUG_OUT(5) <= ram_afull;
+
+
+  process(CLK_100)
+    begin
+      if rising_edge(CLK_100) then
+        STAT_REG_OUT(7 downto 0)   <= std_logic_vector(ram_fill_level);
+        STAT_REG_OUT(15 downto 8)  <= std_logic_vector(ram_read_addr);
+        STAT_REG_OUT(16)           <= ram_afull;
+        STAT_REG_OUT(17)           <= ram_empty;
+        STAT_REG_OUT(18)           <= tx_allow_qtx;
+        STAT_REG_OUT(19)           <= TX_ALLOW_IN;
+        STAT_REG_OUT(20)           <= make_restart_i;
+        STAT_REG_OUT(21)           <= make_request_i;
+        STAT_REG_OUT(22)           <= load_eop;
+        STAT_REG_OUT(31 downto 23) <= (others => '0');
+      end if;
+    end process;
+
+
+
+
+end architecture;
\ No newline at end of file