From 907f9d0d6e3eedf8b57d54c28acb9a5a12cf4e68 Mon Sep 17 00:00:00 2001
From: Reinier van der Walle <walle@astron.nl>
Date: Mon, 19 Dec 2022 16:43:54 +0100
Subject: [PATCH] corrected tb and added PCS registers

---
 libraries/io/eth/eth.peripheral.yaml         | 102 +++++++++++++++++++
 libraries/technology/tse/tb_tech_tse_pkg.vhd |  96 ++++++++++++++++-
 libraries/technology/tse/tech_tse_pkg.vhd    |   1 +
 3 files changed, 196 insertions(+), 3 deletions(-)

diff --git a/libraries/io/eth/eth.peripheral.yaml b/libraries/io/eth/eth.peripheral.yaml
index 3bf3936d47..70a08c66a5 100644
--- a/libraries/io/eth/eth.peripheral.yaml
+++ b/libraries/io/eth/eth.peripheral.yaml
@@ -463,6 +463,108 @@ peripherals:
               address_offset: 0x3E * MM_BUS_SIZE
               access_mode: RO
 
+          - - field_name: pcs_control
+              field_description: |
+                "PCS control register. Use this register to control and
+                 configure the PCS function."
+              address_offset: ( 0x80 + 0x00 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RW
+
+          - - field_name: pcs_status
+              field_description: |
+                "Status register. Provides information on the operation of the
+                 PCS function."
+              address_offset: ( 0x80 + 0x01 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RO
+
+          - - field_name: pcs_phy_identifier_msb
+              field_description: |
+                "32-bit PHY identification register. This register is set to the
+                 value of the PHY ID parameter. Bits 31:16 are written to
+                 word offset 0x02. Bits 15:0 are written to word offset 0x03."
+              address_offset: ( 0x80 + 0x02 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RO
+
+          - - field_name: pcs_phy_identifier_lsb
+              field_description: |
+                "see pcs_phy_identifier_msb"
+              address_offset: ( 0x80 + 0x03 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RO
+
+          - - field_name: pcs_dev_ability
+              field_description: |
+                "Use this register to advertise the device abilities to a link
+                 partner during auto-negotiation. In SGMII MAC mode, the
+                 PHY does not use this register during auto-negotiation."
+              address_offset: ( 0x80 + 0x04 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RW
+
+          - - field_name: pcs_partner_ability
+              field_description: |
+                "Contains the device abilities advertised by the link partner
+                 during auto-negotiation."
+              address_offset: ( 0x80 + 0x05 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RO
+
+          - - field_name: pcs_an_expansion
+              field_description: |
+                "Auto-negotiation expansion register. Contains the PCS
+                 function capability and auto-negotiation status."
+              address_offset: ( 0x80 + 0x06 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RO
+
+          - - field_name: pcs_scratch
+              field_description: |
+                "Scratch register. Provides a memory location to test register
+                 read and write operations."
+              address_offset: ( 0x80 + 0x10 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RW
+
+          - - field_name: pcs_rev
+              field_description: |
+                "The PCS function revision. Always set to the current version
+                 of the IP."
+              address_offset: ( 0x80 + 0x11 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RO
+
+          - - field_name: pcs_link_timer_lsb
+              field_description: |
+                "21-bit auto-negotiation link timer. Set the link timer value
+                 from 0 to 16 ms in 8 ns steps (125 MHz clock periods). The
+                 reset value sets the link timer to 10 ms.
+                 . Bits 15:0 are written to word offset 0x12. Bit 0 of word
+                   offset 0x12 is always set to 0, thus any value written to
+                   it is ignored.
+                 . Bits 20:16 are written to word offset 0x13. The
+                   remaining bits are reserved and always set to 0."
+              address_offset: ( 0x80 + 0x12 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RW
+
+          - - field_name: pcs_link_timer_msb
+              field_description: |
+                "see pcs_link_timer_lsb"
+              address_offset: ( 0x80 + 0x13 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RW
+
+          - - field_name: pcs_if_mode
+              field_description: |
+                "Interface mode. Use this register to specify the operating
+                 mode of the PCS function; 1000BASE-X or SGMII."
+              address_offset: ( 0x80 + 0x14 ) * MM_BUS_SIZE
+              mm_width: 16
+              access_mode: RW
+
           - - field_name: tx_period
               field_description: |
                 "Clock period for timestamp adjustment on the transmit
diff --git a/libraries/technology/tse/tb_tech_tse_pkg.vhd b/libraries/technology/tse/tb_tech_tse_pkg.vhd
index 43c6110b8d..0fcdd7b552 100644
--- a/libraries/technology/tse/tb_tech_tse_pkg.vhd
+++ b/libraries/technology/tse/tb_tech_tse_pkg.vhd
@@ -113,6 +113,10 @@ PACKAGE BODY tb_tech_tse_pkg IS
     RETURN pcs_addr * 2 + c_tech_tse_byte_addr_pcs_offset;
   END func_map_pcs_addr;
 
+  FUNCTION func_map_pcs_addr_arria10(pcs_addr : NATURAL) RETURN NATURAL IS
+  BEGIN
+    RETURN pcs_addr + c_tech_tse_reg_addr_pcs_offset;
+  END func_map_pcs_addr_arria10;
   
   ------------------------------------------------------------------------------
   -- GLOBAL ITEMS
@@ -252,7 +256,7 @@ PACKAGE BODY tb_tech_tse_pkg IS
     WAIT UNTIL rising_edge(mm_clk);
   END proc_tech_tse_setup_stratixiv;
   
-  -- It is noticed that the arria10 variant needs longer setup time.
+  -- It is noticed that the arria10 variant needs longer setup time and uses the mac register space with offset 0x80 to access the PCS registers.
   PROCEDURE proc_tech_tse_setup_arria10(CONSTANT c_promis_en         : IN  BOOLEAN;
                                         CONSTANT c_tse_tx_fifo_depth : IN  NATURAL;
                                         CONSTANT c_tse_rx_fifo_depth : IN  NATURAL;
@@ -262,8 +266,94 @@ PACKAGE BODY tb_tech_tse_pkg IS
                                         SIGNAL   mm_clk              : IN  STD_LOGIC;
                                         SIGNAL   mm_miso             : IN  t_mem_miso;
                                         SIGNAL   mm_mosi             : OUT t_mem_mosi) IS
-  BEGIN    
-    proc_tech_tse_setup_stratixiv(c_promis_en, c_tse_tx_fifo_depth, c_tse_rx_fifo_depth, c_tx_ready_latency, src_mac, psc_access, mm_clk, mm_miso, mm_mosi);
+    CONSTANT c_mac0       : INTEGER := TO_SINT(hton(src_mac(47 DOWNTO 16), 4));
+    CONSTANT c_mac1       : INTEGER := TO_SINT(hton(src_mac(15 DOWNTO  0), 2));
+  BEGIN
+    -- PSC control
+    psc_access <= '1';
+    proc_mem_mm_bus_rd(func_map_pcs_addr_arria10(16#11#),           mm_clk, mm_miso, mm_mosi);  -- REV --> 0x0901
+    proc_mem_mm_bus_wr(func_map_pcs_addr_arria10(16#14#), 16#0008#, mm_clk, mm_miso, mm_mosi);  -- IF_MODE <-- Force 1GbE, no autonegatiation
+    proc_mem_mm_bus_rd(func_map_pcs_addr_arria10(16#00#),           mm_clk, mm_miso, mm_mosi);  -- CONTROL --> 0x1140
+    proc_mem_mm_bus_rd(func_map_pcs_addr_arria10(16#01#),           mm_clk, mm_miso, mm_mosi);  -- STATUS --> 0x000D
+    proc_mem_mm_bus_wr(func_map_pcs_addr_arria10(16#00#), 16#0140#, mm_clk, mm_miso, mm_mosi);  -- CONTROL <-- Auto negotiate disable
+    psc_access <= '0';
+
+    -- MAC control
+    proc_mem_mm_bus_rd(16#000#, mm_clk, mm_miso, mm_mosi);  -- REV --> CUST_VERSION & 0x0901
+    IF c_promis_en=FALSE THEN
+      proc_mem_mm_bus_wr(16#002#, 16#0100004B#, mm_clk, mm_miso, mm_mosi);
+    ELSE
+      proc_mem_mm_bus_wr(16#002#, 16#0100005B#, mm_clk, mm_miso, mm_mosi);
+    END IF;
+      -- COMMAND_CONFIG <--
+      -- Only the bits relevant to UniBoard are explained here, others are 0
+      -- [    0] = TX_ENA             = 1, enable tx datapath
+      -- [    1] = RX_ENA             = 1, enable rx datapath
+      -- [    2] = XON_GEN            = 0
+      -- [    3] = ETH_SPEED          = 1, enable 1GbE operation
+      -- [    4] = PROMIS_EN          = 0, when 1 then receive all frames
+      -- [    5] = PAD_EN             = 0, when 1 enable receive padding removal (requires ethertype=payload length)
+      -- [    6] = CRC_FWD            = 1, enable receive CRC forward
+      -- [    7] = PAUSE_FWD          = 0
+      -- [    8] = PAUSE_IGNORE       = 0
+      -- [    9] = TX_ADDR_INS        = 0, when 1 then MAX overwrites tx SRC MAC with mac_0,1 or one of the supplemental mac
+      -- [   10] = HD_ENA             = 0
+      -- [   11] = EXCESS_COL         = 0
+      -- [   12] = LATE_COL           = 0
+      -- [   13] = SW_RESET           = 0, when 1 MAC disables tx and rx, clear statistics and flushes receive FIFO
+      -- [   14] = MHAS_SEL           = 0, select multicast address resolutions hash-code mode
+      -- [   15] = LOOP_ENA           = 0
+      -- [18-16] = TX_ADDR_SEL[2:0]   = 000, TX_ADDR_INS insert mac_0,1 or one of the supplemental mac
+      -- [   19] = MAGIC_EN           = 0
+      -- [   20] = SLEEP              = 0
+      -- [   21] = WAKEUP             = 0
+      -- [   22] = XOFF_GEN           = 0
+      -- [   23] = CNT_FRM_ENA        = 0
+      -- [   24] = NO_LGTH_CHECK      = 1, when 0 then check payload length of received frames (requires ethertype=payload length)
+      -- [   25] = ENA_10             = 0
+      -- [   26] = RX_ERR_DISC        = 0, when 1 then discard erroneous frames (requires store and forward mode, so rx_section_full=0)
+      --                                   when 0 then pass on with rx_err[0]=1
+      -- [   27] = DISABLE_RD_TIMEOUT = 0
+      -- [30-28] = RSVD               = 000
+      -- [   31] = CNT_RESET          = 0, when 1 clear statistics
+    proc_mem_mm_bus_wr(16#03#,       c_mac0, mm_clk, mm_miso, mm_mosi);  -- MAC_0
+    proc_mem_mm_bus_wr(16#04#,       c_mac1, mm_clk, mm_miso, mm_mosi);  -- MAC_1 <-- SRC_MAC = 12-34-56-78-9A-BC
+    proc_mem_mm_bus_wr(16#17#, 16#0000000C#, mm_clk, mm_miso, mm_mosi);  -- TX_IPG_LENGTH <-- interpacket gap = 12
+    --proc_mem_mm_bus_wr(16#05#, 16#000005EE#, mm_clk, mm_miso, mm_mosi);  -- FRM_LENGTH <-- receive max frame length = 1518
+    proc_mem_mm_bus_wr(16#05#, 16#0000233A#, mm_clk, mm_miso, mm_mosi);  -- FRM_LENGTH <-- receive max frame length = 9018
+
+    -- FIFO legenda:
+    -- . Tx section full  = There is enough data in the FIFO to start reading it, when 0 then store and forward.
+    -- . Rx section full  = There is enough data in the FIFO to start reading it, when 0 then store and forward.
+    -- . Tx section empty = There is not much empty space anymore in the FIFO, warn user via ff_tx_septy
+    -- . Rx section empty = There is not much empty space anymore in the FIFO, inform remote device via XOFF flow control
+    -- . Tx almost full   = Assert ff_tx_a_full and deassert ff_tx_rdy. Furthermore TX_ALMOST_FULL = c_tx_ready_latency+3,
+    --                      so choose 3 for zero tx ready latency
+    -- . Rx almost full   = Assert ff_rx_a_full and if the user is not ready ff_rx_rdy then:
+    --                      --> break off the reception with an error to avoid FIFO overflow
+    -- . Tx almost empty  = Assert ff_tx_a_empty and if the FIFO does not contain a eop yet then:
+    --                      --> break off the transmission with an error to avoid FIFO underflow
+    -- . Rx almost empty  = Assert ff_rx_a_empty
+    -- Typical FIFO values:
+    -- . TX_SECTION_FULL  = 16   > 8   = TX_ALMOST_EMPTY
+    -- . RX_SECTION_FULL  = 16   > 8   = RX_ALMOST_EMPTY
+    -- . TX_SECTION_EMPTY = D-16 < D-3 = Tx FIFO depth - TX_ALMOST_FULL
+    -- . RX_SECTION_EMPTY = D-16 < D-8 = Rx FIFO depth - RX_ALMOST_FULL
+    -- . c_tse_tx_fifo_depth = 1 M9K = 256*32b = 1k * 8b is sufficient when the Tx user respects ff_tx_rdy, to store a complete
+    --                         ETH packet would require 1518 byte, so 2 M9K = 2k * 8b
+    -- . c_tse_rx_fifo_depth = 1 M9K = 256*32b = 1k * 8b is sufficient when the Rx user ff_rx_rdy is sufficiently active
+    proc_mem_mm_bus_wr(16#07#, c_tse_rx_fifo_depth-16, mm_clk, mm_miso, mm_mosi);  -- RX_SECTION_EMPTY <-- default FIFO depth - 16, >3
+    proc_mem_mm_bus_wr(16#08#,                     16, mm_clk, mm_miso, mm_mosi);  -- RX_SECTION_FULL  <-- default 16
+    proc_mem_mm_bus_wr(16#09#, c_tse_tx_fifo_depth-16, mm_clk, mm_miso, mm_mosi);  -- TX_SECTION_EMPTY <-- default FIFO depth - 16, >3
+    proc_mem_mm_bus_wr(16#0A#,                     16, mm_clk, mm_miso, mm_mosi);  -- TX_SECTION_FULL  <-- default 16, >~ 8 otherwise no tx
+    proc_mem_mm_bus_wr(16#0B#,                      8, mm_clk, mm_miso, mm_mosi);  -- RX_ALMOST_EMPTY  <-- default 8
+    proc_mem_mm_bus_wr(16#0C#,                      8, mm_clk, mm_miso, mm_mosi);  -- RX_ALMOST_FULL   <-- default 8
+    proc_mem_mm_bus_wr(16#0D#,                      8, mm_clk, mm_miso, mm_mosi);  -- TX_ALMOST_EMPTY  <-- default 8
+    proc_mem_mm_bus_wr(16#0E#,   c_tx_ready_latency+3, mm_clk, mm_miso, mm_mosi);  -- TX_ALMOST_FULL   <-- default 3
+
+    proc_mem_mm_bus_rd(16#3A#, mm_clk, mm_miso, mm_mosi);  -- TX_CMD_STAT --> 0x00040000 : [18]=1 TX_SHIFT16, [17]=0 OMIT_CRC
+    proc_mem_mm_bus_rd(16#3B#, mm_clk, mm_miso, mm_mosi);  -- RX_CMD_STAT --> 0x02000000 : [25]=1 RX_SHIFT16
+
     WAIT FOR 10 us;
     WAIT UNTIL rising_edge(mm_clk);
   END proc_tech_tse_setup_arria10;
diff --git a/libraries/technology/tse/tech_tse_pkg.vhd b/libraries/technology/tse/tech_tse_pkg.vhd
index 603b85d225..2f4a8327c3 100644
--- a/libraries/technology/tse/tech_tse_pkg.vhd
+++ b/libraries/technology/tse/tech_tse_pkg.vhd
@@ -28,6 +28,7 @@ PACKAGE tech_tse_pkg IS
 
   CONSTANT c_tech_tse_reg_addr_w           : NATURAL := 8;         -- = max 256 MAC registers
   CONSTANT c_tech_tse_byte_addr_w          : NATURAL := c_tech_tse_reg_addr_w + 2;
+  CONSTANT c_tech_tse_reg_addr_pcs_offset  : NATURAL := 16#80#;   -- table 4.8, 4.9 in ug_ethernet.pdf
   CONSTANT c_tech_tse_byte_addr_pcs_offset : NATURAL := 16#200#;   -- table 4.8, 4.9 in ug_ethernet.pdf
   CONSTANT c_tech_tse_data_w               : NATURAL := c_word_w;  -- = 32
 
-- 
GitLab