From e5b58438beae70e1ebc011f29f466bdfface1a93 Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Thu, 16 Jul 2015 12:32:35 +0000
Subject: [PATCH] Removed g_link_status_check from tech_eth_10g entity. Added
 g_direction = TX_RX default or TX_ONLY, RX_ONLY. Implemented TX_ONLY by
 internal loopback of MAC Tx xgmii to MAX Rx.

---
 libraries/technology/eth_10g/tech_eth_10g.vhd | 23 +----
 .../eth_10g/tech_eth_10g_arria10.vhd          | 85 +++++++++++++------
 .../eth_10g/tech_eth_10g_stratixiv.vhd        | 73 +++++++++++++---
 3 files changed, 120 insertions(+), 61 deletions(-)

diff --git a/libraries/technology/eth_10g/tech_eth_10g.vhd b/libraries/technology/eth_10g/tech_eth_10g.vhd
index b8275ea41c..0faf79b407 100644
--- a/libraries/technology/eth_10g/tech_eth_10g.vhd
+++ b/libraries/technology/eth_10g/tech_eth_10g.vhd
@@ -56,22 +56,7 @@
 --                    |
 --                  mac_mm
 --
---
--- . g_link_status_check:
---   A link fault eg. due to rx disconnect is detected by the link fault status:
---     0 = OK
---     1 = local fault
---     2 = remote fault
---   
---   From google search:
---     Link fault Operation
---     1) Device B detects loss of signal. Local fault is signaled by PHY of Device B to Device B.
---     2) Device B ceases transmission of MAC frames and transmits remote fault to Device A.
---     3) Device A receives remote fault from Device B.
---     4) Device A stops sending frames, continuously generates Idle.
---
--- . g_pre_header_padding:
---   See tech_mac10g.vhd
+-- . g_pre_header_padding: See tech_mac10g.vhd
 --
 
 LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_mac_10g_lib;
@@ -90,7 +75,7 @@ ENTITY tech_eth_10g IS
     g_sim                 : BOOLEAN := FALSE;
     g_sim_level           : NATURAL := 0;     -- 0 = use IP; 1 = use fast serdes model
     g_nof_channels        : NATURAL := 1;
-    g_link_status_check   : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0) := "11";  -- check remote fault & check local fault
+    g_direction           : STRING := "TX_RX";  -- "TX_RX", "TX_ONLY", "RX_ONLY"
     g_pre_header_padding  : BOOLEAN := FALSE
   );
   PORT (
@@ -151,7 +136,7 @@ BEGIN
       g_sim                 => g_sim,
       g_sim_level           => g_sim_level,
       g_nof_channels        => g_nof_channels,
-      g_link_status_check   => g_link_status_check,
+      g_direction           => g_direction,
       g_pre_header_padding  => g_pre_header_padding
     )
     PORT MAP (
@@ -198,7 +183,7 @@ BEGIN
       g_sim                 => g_sim,
       g_sim_level           => g_sim_level,
       g_nof_channels        => g_nof_channels,
-      g_link_status_check   => g_link_status_check,
+      g_direction           => g_direction,
       g_pre_header_padding  => g_pre_header_padding
     )
     PORT MAP (
diff --git a/libraries/technology/eth_10g/tech_eth_10g_arria10.vhd b/libraries/technology/eth_10g/tech_eth_10g_arria10.vhd
index 7e00652158..a29dac0b0c 100644
--- a/libraries/technology/eth_10g/tech_eth_10g_arria10.vhd
+++ b/libraries/technology/eth_10g/tech_eth_10g_arria10.vhd
@@ -47,32 +47,48 @@
 --                       (   v    xgmii_tx_ready)
 --     tx_snk_out.xon <--(xgmii_link_status[1:0])
 --
---  When the xgmii_tx_ready from the 10gbase_r and the xgmii_link_status from
---  the mac_10g are both be OK then the tx_snk.xon is asserted to allow the
---  user data transmission.
---  The tb_tech_eth_10g reveals that xgmii_tx_ready goes high after some power
---  up time and then remains active independent of link_fault. A link fault
---  eg. due to rx disconnect is detected by xgmii_link_status:
---    0 = OK
---    1 = local fault
---    2 = remote fault
---
---  From google search:
---    Link fault Operation
---    1) Device B detects loss of signal. Local fault is signaled by PHY of Device B to Device B.
---    2) Device B ceases transmission of MAC frames and transmits remote fault to Device A.
---    3) Device A receives remote fault from Device B.
---    4) Device A stops sending frames, continuously generates Idle.
+-- . g_direction
+--   "TX_RX" = Default support bidir
+--   "TX_ONLY" = Uses a bidir MAC and connects the MAC TX to the XAUI TX and
+--       also to the MAC RX. The MAC RX needs to see XGMII Rx data otherwise
+--       the Tx does not start. Therefore the simple approach using
+--       xgmii_internal_dc_arr is implemented. Two other implementations have
+--       been considered:
+--       . Instead also a Tx only MAC IP could have been used but that is
+--         not tried.
+--       . Configuring the bidir MAC to Tx unidirectional via MM still does
+--         not seem to work without activity on the XGMII Rx data.
+--   "RX_ONLY" = Same as "TX_RX", just leave the Tx ST and Tx XAUI pins not
+--       connected.
+-- 
+-- Remarks:
+-- . xgmii_link_status:
+--   When the xgmii_tx_ready from the 10gbase_r and the xgmii_link_status from
+--   the mac_10g are both be OK then the tx_snk.xon is asserted to allow the
+--   user data transmission.
+--   The tb_tech_eth_10g reveals that xgmii_tx_ready goes high after some power
+--   up time and then remains active independent of link_fault.
+--   A link fault eg. due to rx disconnect is detected by the link fault status:
+--     0 = OK
+--     1 = local fault
+--     2 = remote fault
+--   
+--   From google search:
+--     Link fault Operation
+--     1) Device B detects loss of signal. Local fault is signaled by PHY of Device B to Device B.
+--     2) Device B ceases transmission of MAC frames and transmits remote fault to Device A.
+--     3) Device A receives remote fault from Device B.
+--     4) Device A stops sending frames, continuously generates Idle.
 --
---  Hence when the xgmii_link_status is OK then the other side is also OK so
---  then it is also appropriate to release tx_snk.xon.
+--   Hence when the xgmii_link_status is OK then the other side is also OK so
+--   then it is also appropriate to release tx_snk.xon.
 --
---  The XGMII link status can be monitored via the reg_eth10 MM register:
+--   The XGMII link status can be monitored via the reg_eth10 MM register:
 --
---    addr  data[31:0]
---     0      [0] = tx_snk_out_arr(I).xon
---            [1] = xgmii_tx_ready_arr(I)
---          [3:2] = xgmii_link_status_arr(I)
+--     addr  data[31:0]
+--      0      [0] = tx_snk_out_arr(I).xon
+--             [1] = xgmii_tx_ready_arr(I)
+--           [3:2] = xgmii_link_status_arr(I)
 --  
 
 LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_10gbase_r_lib, tech_mac_10g_lib;
@@ -89,7 +105,7 @@ ENTITY tech_eth_10g_arria10 IS
     g_sim                 : BOOLEAN := FALSE;
     g_sim_level           : NATURAL := 0;     -- 0 = use IP; 1 = use fast serdes model
     g_nof_channels        : NATURAL := 1;
-    g_link_status_check   : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0) := "11";
+    g_direction           : STRING := "TX_RX";  -- "TX_RX", "TX_ONLY", "RX_ONLY"
     g_pre_header_padding  : BOOLEAN := FALSE
   );
   PORT (
@@ -127,6 +143,10 @@ END tech_eth_10g_arria10;
 
 ARCHITECTURE str OF tech_eth_10g_arria10 IS
 
+  -- Enable or disable the conditions that must be ok to release tx_snk_out_arr xon
+  CONSTANT c_check_link_status       : BOOLEAN := g_direction/="TX_ONLY";
+  CONSTANT c_check_xgmii_tx_ready    : BOOLEAN := g_direction/="RX_ONLY";
+  
   SIGNAL i_tx_snk_out_arr      : t_dp_siso_arr(g_nof_channels-1 DOWNTO 0);
   
   -- MAG_10G control status registers
@@ -141,6 +161,7 @@ ARCHITECTURE str OF tech_eth_10g_arria10 IS
   SIGNAL xgmii_tx_ready_arr    : STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0);                 -- 1 bit, from PHY 10gbase_r
   SIGNAL xgmii_tx_dc_arr       : t_xgmii_dc_arr(g_nof_channels-1 DOWNTO 0);    -- 72 bit
   SIGNAL xgmii_rx_dc_arr       : t_xgmii_dc_arr(g_nof_channels-1 DOWNTO 0);    -- 72 bit
+  SIGNAL xgmii_internal_dc_arr : t_xgmii_dc_arr(g_nof_channels-1 DOWNTO 0);    -- 72 bit
   
   -- Link status monitor
   CONSTANT c_mem_reg_eth10g_adr_w     : NATURAL := 1;
@@ -161,12 +182,18 @@ BEGIN
     i_tx_snk_out_arr(I).ready <= mac_snk_out_arr(I).ready;  -- pass on MAC cycle accurate backpressure
     
     p_xon_flow_control : PROCESS(clk_156)
-      VARIABLE v_xgmii_link_status : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0);
+      VARIABLE v_xgmii_link_status     : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0) := "00";
+      VARIABLE v_xgmii_tx_ready        : STD_LOGIC := '1';
     BEGIN
       IF rising_edge(clk_156) THEN
         i_tx_snk_out_arr(I).xon <= '0';
-        v_xgmii_link_status := xgmii_link_status_arr(I) AND g_link_status_check;  -- use mask to check Tx, Rx, both or none. 
-        IF xgmii_tx_ready_arr(I)='1' AND v_xgmii_link_status="00" THEN
+        
+        -- First gather all conditions that are enabled to affect xon. The default value is such that it enables xon when the condition is not checked.
+        IF c_check_link_status   =TRUE THEN v_xgmii_link_status := xgmii_link_status_arr(I); END IF;  -- check both remote fault [1] and local fault [0]
+        IF c_check_xgmii_tx_ready=TRUE THEN v_xgmii_tx_ready    := xgmii_tx_ready_arr(I);    END IF;
+        
+        -- Now apply the conditions to xon
+        IF v_xgmii_tx_ready='1' AND v_xgmii_link_status="00" THEN
           i_tx_snk_out_arr(I).xon <= '1';  -- XON when Tx PHY is ready and XGMII is ok
         END IF;
       END IF;
@@ -200,10 +227,12 @@ BEGIN
       -- XGMII
       xgmii_link_status => xgmii_link_status_arr(I),
       xgmii_tx_data     => xgmii_tx_dc_arr(I),
-      xgmii_rx_data     => xgmii_rx_dc_arr(I)
+      xgmii_rx_data     => xgmii_internal_dc_arr(I)
     );
   END GENERATE;  
   
+  xgmii_internal_dc_arr <= xgmii_tx_dc_arr WHEN g_direction="TX_ONLY" ELSE xgmii_rx_dc_arr;
+  
   u_tech_10gbase_r: ENTITY tech_10gbase_r_lib.tech_10gbase_r
   GENERIC MAP (
     g_technology     => c_tech_arria10,
diff --git a/libraries/technology/eth_10g/tech_eth_10g_stratixiv.vhd b/libraries/technology/eth_10g/tech_eth_10g_stratixiv.vhd
index 9b18418cbe..4e4e35285d 100644
--- a/libraries/technology/eth_10g/tech_eth_10g_stratixiv.vhd
+++ b/libraries/technology/eth_10g/tech_eth_10g_stratixiv.vhd
@@ -41,8 +41,37 @@
 --                    |      |       |
 --                  mac_mm   |       |
 --                           |       v
---                       (   v    xgmii_tx_ready)
---     tx_snk_out.xon <--(xgmii_link_status[1:0])
+--                       (   |    xgmii_tx_ready       )
+--                       (   v    txc_rx_channelaligned)
+--     tx_snk_out.xon <--(xgmii_link_status[1:0]       )
+--
+-- . g_direction
+--   "TX_RX" = Default support bidir
+--   "TX_ONLY" = Uses a bidir MAC and connects the MAC TX to the XAUI TX and
+--       also to the MAC RX. The MAC RX needs to see XGMII Rx data otherwise
+--       the Tx does not start. Therefore the simple approach using
+--       xgmii_internal_dc_arr is implemented. Two other implementations have
+--       been considered:
+--       . Instead also a Tx only MAC IP could have been used but that is
+--         not tried.
+--       . Configuring the bidir MAC to Tx unidirectional via MM still does
+--         not seem to work without activity on the XGMII Rx data.
+--   "RX_ONLY" = Same as "TX_RX", just leave the Tx ST and Tx XAUI pins not
+--       connected.
+--
+-- Remarks:
+-- . xgmii_link_status:
+--   A link fault eg. due to rx disconnect is detected by the link fault status:
+--     0 = OK
+--     1 = local fault
+--     2 = remote fault
+--   
+--   From google search:
+--     Link fault Operation
+--     1) Device B detects loss of signal. Local fault is signaled by PHY of Device B to Device B.
+--     2) Device B ceases transmission of MAC frames and transmits remote fault to Device A.
+--     3) Device A receives remote fault from Device B.
+--     4) Device A stops sending frames, continuously generates Idle.
 --
 
 LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_xaui_lib, tech_mac_10g_lib;
@@ -56,11 +85,11 @@ USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL;
 
 ENTITY tech_eth_10g_stratixiv IS
   GENERIC (
-    g_sim                 : BOOLEAN := FALSE;
-    g_sim_level           : NATURAL := 0;     -- 0 = use XAUI IP; 1 = use fast serdes model
-    g_nof_channels        : NATURAL := 1;
-    g_link_status_check   : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0) := "11";
-    g_pre_header_padding  : BOOLEAN := FALSE
+    g_sim                     : BOOLEAN := FALSE;
+    g_sim_level               : NATURAL := 0;     -- 0 = use XAUI IP; 1 = use fast serdes model
+    g_nof_channels            : NATURAL := 1;
+    g_direction               : STRING := "TX_RX";  -- "TX_RX", "TX_ONLY", "RX_ONLY"
+    g_pre_header_padding      : BOOLEAN := FALSE
   );
   PORT (
     -- Transceiver PLL reference clock
@@ -103,6 +132,11 @@ END tech_eth_10g_stratixiv;
 
 ARCHITECTURE str OF tech_eth_10g_stratixiv IS
 
+  -- Enable or disable the conditions that must be ok to release tx_snk_out_arr xon
+  CONSTANT c_check_link_status       : BOOLEAN := g_direction/="TX_ONLY";
+  CONSTANT c_check_rx_channelaligned : BOOLEAN := g_direction/="TX_ONLY";
+  CONSTANT c_check_xgmii_tx_ready    : BOOLEAN := g_direction/="RX_ONLY";
+  
   -- MAG_10G control status registers
   SIGNAL mac_mosi_arr              : t_mem_mosi_arr(g_nof_channels-1 DOWNTO 0);
   SIGNAL mac_miso_arr              : t_mem_miso_arr(g_nof_channels-1 DOWNTO 0); 
@@ -125,6 +159,7 @@ ARCHITECTURE str OF tech_eth_10g_stratixiv IS
   SIGNAL xgmii_tx_ready_arr        : STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0);                 -- 1 bit, from PHY XAUI
   SIGNAL xgmii_tx_dc_arr           : t_xgmii_dc_arr(g_nof_channels-1 DOWNTO 0);    -- 72 bit
   SIGNAL xgmii_rx_dc_arr           : t_xgmii_dc_arr(g_nof_channels-1 DOWNTO 0);    -- 72 bit
+  SIGNAL xgmii_internal_dc_arr     : t_xgmii_dc_arr(g_nof_channels-1 DOWNTO 0);    -- 72 bit
 
 BEGIN
 
@@ -132,8 +167,8 @@ BEGIN
   tx_rst_arr_out <= i_tx_rst_arr_out;
   rx_rst_arr_out <= i_rx_rst_arr_out;
   
-  i_tx_rst_arr_out <= NOT txc_tx_ready_arr;
-  i_rx_rst_arr_out <= NOT rxc_rx_ready_arr;
+  i_tx_rst_arr_out <= NOT txc_tx_ready_arr WHEN g_direction/="RX_ONLY" ELSE i_rx_rst_arr_out;  -- in case of RX_ONLY use the rx rst also for tx to have an active rst release, clock domain crossing issues can be ignored
+  i_rx_rst_arr_out <= NOT rxc_rx_ready_arr WHEN g_direction/="TX_ONLY" ELSE i_tx_rst_arr_out;  -- in case of TX_ONLY use the tx rst also for rx to have an active rst release, clock domain crossing issues can be ignored
   
   xgmii_tx_ready_arr <= txc_tx_ready_arr;
 
@@ -142,12 +177,20 @@ BEGIN
     tx_snk_out_arr(I).ready <= mac_snk_out_arr(I).ready;  -- pass on MAC cycle accurate backpressure
     
     p_xon_flow_control : PROCESS(tx_clk_arr_in)
-      VARIABLE v_xgmii_link_status : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0);
+      VARIABLE v_xgmii_link_status     : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0) := "00";
+      VARIABLE v_txc_rx_channelaligned : STD_LOGIC := '1';
+      VARIABLE v_xgmii_tx_ready        : STD_LOGIC := '1';
     BEGIN
       IF rising_edge(tx_clk_arr_in(I)) THEN
         tx_snk_out_arr(I).xon <= '0';
-        v_xgmii_link_status := xgmii_link_status_arr(I) AND g_link_status_check;  -- use mask to check Tx, Rx, both or none. 
-        IF xgmii_tx_ready_arr(I)='1' AND txc_rx_channelaligned_arr(I)='1' AND v_xgmii_link_status="00" THEN
+        
+        -- First gather all conditions that are enabled to affect xon. The default value is such that it enables xon when the condition is not checked.
+        IF c_check_link_status      =TRUE THEN v_xgmii_link_status     := xgmii_link_status_arr(I);     END IF;  -- check both remote fault [1] and local fault [0]
+        IF c_check_rx_channelaligned=TRUE THEN v_txc_rx_channelaligned := txc_rx_channelaligned_arr(I); END IF;  -- check that all 4 RX channels are aligned
+        IF c_check_xgmii_tx_ready   =TRUE THEN v_xgmii_tx_ready        := xgmii_tx_ready_arr(I);        END IF;
+        
+        -- Now apply the conditions to xon
+        IF v_xgmii_tx_ready='1' AND v_txc_rx_channelaligned='1' AND v_xgmii_link_status="00" THEN
           tx_snk_out_arr(I).xon <= '1';  -- XON when Tx PHY is ready and XGMII is ok
         END IF;
       END IF;
@@ -179,10 +222,12 @@ BEGIN
       -- XGMII
       xgmii_link_status => xgmii_link_status_arr(I),
       xgmii_tx_data     => xgmii_tx_dc_arr(I),
-      xgmii_rx_data     => xgmii_rx_dc_arr(I)
+      xgmii_rx_data     => xgmii_internal_dc_arr(I)
     );
   END GENERATE;
-    
+  
+  xgmii_internal_dc_arr <= xgmii_tx_dc_arr WHEN g_direction="TX_ONLY" ELSE xgmii_rx_dc_arr;
+  
   u_tech_xaui: ENTITY tech_xaui_lib.tech_xaui
   GENERIC MAP (
     g_technology      => c_tech_stratixiv,
-- 
GitLab