]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
FIFO on da way
authorMichael Boehmer <mboehmer@ph.tum.de>
Fri, 8 Jul 2022 14:34:55 +0000 (16:34 +0200)
committerMichael Boehmer <mboehmer@ph.tum.de>
Fri, 8 Jul 2022 14:34:55 +0000 (16:34 +0200)
gbe_trb_ecp3/base/gbe_med_fifo.vhd [new file with mode: 0644]

diff --git a/gbe_trb_ecp3/base/gbe_med_fifo.vhd b/gbe_trb_ecp3/base/gbe_med_fifo.vhd
new file mode 100644 (file)
index 0000000..cca5336
--- /dev/null
@@ -0,0 +1,688 @@
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.std_logic_ARITH.ALL;
+USE IEEE.std_logic_UNSIGNED.ALL;
+
+library work;
+use work.trb_net_std.all;
+use work.trb_net_components.all;
+use work.trb_net_gbe_components.all;
+use work.med_sync_define_RS.all;
+
+entity gbe_med_fifo is
+  generic(
+    LINKS_ACTIVE          : std_logic_vector(3 downto 0) := "1111"
+  );
+  port(
+    RESET                 : in  std_logic;
+    GSR_N                 : in  std_logic;
+    CLK_SYS               : in  std_logic;
+    CLK_125               : in  std_logic;
+    CLK_125_RX            : out std_logic_vector(3 downto 0);
+    -- FIFO interface RX
+    FIFO_DATA_OUT         : out std_logic_vector(4 * 8 - 1 downto 0);
+    FIFO_FULL_IN          : in  std_logic_vector(3 downto 0);
+    FIFO_WR_OUT           : out std_logic_vector(3 downto 0);
+    FRAME_REQ_IN          : in  std_logic_vector(3 downto 0);
+    FRAME_ACK_OUT         : out std_logic_vector(3 downto 0);
+    FRAME_AVAIL_OUT       : out std_logic_vector(3 downto 0);
+    FRAME_START_OUT       : out std_logic_vector(3 downto 0);
+    -- FIFO interface TX
+    FIFO_FULL_OUT         : out std_logic_vector(3 downto 0);
+    FIFO_WR_IN            : in  std_logic_vector(3 downto 0);
+    FIFO_DATA_IN          : in  std_logic_vector(4 * 8 - 1 downto 0);
+    FRAME_START_IN        : in  std_logic_vector(3 downto 0);
+    -- SFP Connection
+    SD_PRSNT_N_IN         : in  std_logic_vector(3 downto 0)          := (others => '0');
+    SD_LOS_IN             : in  std_logic_vector(3 downto 0)          := (others => '0');
+    SD_TXDIS_OUT          : out std_logic_vector(3 downto 0);
+    -- SerDes control
+    TX_PLOL_LOL_OUT       : out std_logic;
+    TX_PCS_RST_IN         : in  std_logic;
+    RX_LINK_READY_OUT     : out std_logic_vector(3 downto 0);
+    TX_LINK_READY_IN      : in  std_logic;
+    -- Debug
+    STATUS_OUT            : out std_logic_vector(4 * 8 - 1 downto 0);
+    DEBUG_OUT             : out std_logic_vector(63 downto 0)
+  );
+end entity gbe_med_fifo;
+
+architecture RTL of gbe_med_fifo is
+  
+  component sgmii_gbe_pcs42
+  port( 
+    rst_n                  : in  std_logic;
+    signal_detect          : in  std_logic;
+    gbe_mode               : in  std_logic;
+    sgmii_mode             : in  std_logic;
+    operational_rate       : in  std_logic_vector(1 downto 0);
+    debug_link_timer_short : in  std_logic;
+
+    force_isolate          : in  std_logic;
+    force_loopback         : in  std_logic;
+    force_unidir           : in  std_logic;
+
+    rx_compensation_err    : out std_logic;
+
+    ctc_drop_flag          : out std_logic;
+    ctc_add_flag           : out std_logic;
+    an_link_ok             : out std_logic;
+
+    tx_clk_125             : in  std_logic;                    
+    tx_clock_enable_source : out std_logic;
+    tx_clock_enable_sink   : in  std_logic;          
+    tx_d                   : in  std_logic_vector(7 downto 0); 
+    tx_en                  : in  std_logic;       
+    tx_er                  : in  std_logic;       
+    rx_clk_125             : in  std_logic; 
+    rx_clock_enable_source : out std_logic;
+    rx_clock_enable_sink   : in  std_logic;          
+    rx_d                   : out std_logic_vector(7 downto 0);       
+    rx_dv                  : out std_logic;  
+    rx_er                  : out std_logic; 
+    col                    : out std_logic;  
+    crs                    : out std_logic;  
+    tx_data                : out std_logic_vector(7 downto 0);  
+    tx_kcntl               : out std_logic; 
+    tx_disparity_cntl      : out std_logic; 
+
+    xmit_autoneg           : out std_logic;
+
+    serdes_recovered_clk   : in  std_logic; 
+    rx_data                : in  std_logic_vector(7 downto 0);  
+    rx_even                : in  std_logic;  
+    rx_kcntl               : in  std_logic; 
+    rx_disp_err            : in  std_logic; 
+    rx_cv_err              : in  std_logic; 
+    rx_err_decode_mode     : in  std_logic; 
+    mr_an_complete         : out std_logic; 
+    mr_page_rx             : out std_logic; 
+    mr_lp_adv_ability      : out std_logic_vector(15 downto 0); 
+    mr_main_reset          : in  std_logic; 
+    mr_an_enable           : in  std_logic; 
+    mr_restart_an          : in  std_logic; 
+    mr_adv_ability         : in  std_logic_vector(15 downto 0)  
+  );
+  end component;
+
+  component tsmac41
+  port(
+    --------------- clock and reset port declarations ------------------
+    hclk            : in  std_logic;
+    txmac_clk       : in  std_logic;
+    rxmac_clk       : in  std_logic;
+    reset_n         : in  std_logic;
+    ------------------- Input signals to the GMII ----------------
+    rxd             : in  std_logic_vector(7 downto 0);
+    rx_dv           : in  std_logic;
+    rx_er           : in  std_logic;
+    -------------------- Input signals to the CPU I/F -------------------
+    haddr           : in  std_logic_vector(7 downto 0);
+    hdatain         : in  std_logic_vector(7 downto 0);
+    hcs_n           : in  std_logic;
+    hwrite_n        : in  std_logic;
+    hread_n         : in  std_logic;
+    ---------------- Input signals to the Tx MAC FIFO I/F ---------------
+    tx_fifodata     : in  std_logic_vector(7 downto 0);
+    tx_fifoavail    : in  std_logic;
+    tx_fifoeof      : in  std_logic;
+    tx_fifoempty    : in  std_logic;
+    tx_sndpaustim   : in  std_logic_vector(15 downto 0);
+    tx_sndpausreq   : in  std_logic;
+    tx_fifoctrl     : in  std_logic;
+    ---------------- Input signals to the Rx MAC FIFO I/F --------------- 
+    rx_fifo_full    : in  std_logic;
+    ignore_pkt      : in  std_logic;
+    -------------------- Output signals from the GMII -----------------------
+    txd             : out std_logic_vector(7 downto 0);  
+    tx_en           : out std_logic;
+    tx_er           : out std_logic;
+    -------------------- Output signals from the CPU I/F -------------------
+    hdataout        : out std_logic_vector(7 downto 0);
+    hdataout_en_n   : out std_logic;
+    hready_n        : out std_logic;
+    cpu_if_gbit_en  : out std_logic;
+    ---------------- Output signals from the Tx MAC FIFO I/F --------------- 
+    tx_macread      : out std_logic;
+    tx_discfrm      : out std_logic;
+    tx_staten       : out std_logic;
+    tx_done         : out std_logic;
+    tx_statvec      : out std_logic_vector(30 downto 0);
+    ---------------- Output signals from the Rx MAC FIFO I/F ---------------   
+    rx_fifo_error   : out std_logic;
+    rx_stat_vector  : out std_logic_vector(31 downto 0);
+    rx_dbout        : out std_logic_vector(7 downto 0);
+    rx_write        : out std_logic;
+    rx_stat_en      : out std_logic;
+    rx_eof          : out std_logic;
+    rx_error        : out std_logic
+  );
+  end component; 
+
+  signal sd_rx_clk                                : std_logic_vector(3 downto 0);
+  signal sd_tx_kcntl                              : std_logic_vector(3 downto 0);
+  signal sd_tx_data                               : std_logic_vector(4 * 8 - 1 downto 0);
+  signal xmit                                     : std_logic_vector(3 downto 0);
+  signal sd_tx_correct_disp                       : std_logic_vector(3 downto 0);
+  signal sd_rx_data                               : std_logic_vector(4 * 8 - 1 downto 0);
+  signal sd_rx_kcntl                              : std_logic_vector(3 downto 0);
+  signal sd_rx_disp_error                         : std_logic_vector(3 downto 0);
+  signal sd_rx_cv_error                           : std_logic_vector(3 downto 0); 
+  signal lsm_status                               : std_logic_vector(3 downto 0);
+  signal rx_clk_en                                : std_logic_vector(3 downto 0);
+  signal tx_clk_en                                : std_logic_vector(3 downto 0);
+  signal operational_rate                         : std_logic_vector(4 * 2 - 1 downto 0);
+  signal an_complete                              : std_logic_vector(3 downto 0);
+  signal mr_page_rx                               : std_logic_vector(3 downto 0);
+  signal mr_lp_adv_ability                        : std_logic_vector(4 * 16 - 1 downto 0);
+  signal mr_main_reset                            : std_logic_vector(3 downto 0);
+  signal mr_restart_an                            : std_logic_vector(3 downto 0);
+  signal mr_adv_ability                           : std_logic_vector(4 * 16 - 1 downto 0);
+  signal mr_an_enable                             : std_logic_vector(3 downto 0);
+  signal an_link_ok                               : std_logic_vector(3 downto 0);
+  signal pcs_rxd                                  : std_logic_vector(4 * 8 - 1 downto 0);
+  signal pcs_rx_en                                : std_logic_vector(3 downto 0);
+  signal pcs_rx_er                                : std_logic_vector(3 downto 0);
+  signal pcs_txd                                  : std_logic_vector(4 * 8 - 1 downto 0);
+  signal pcs_tx_en                                : std_logic_vector(3 downto 0);
+  signal pcs_tx_er                                : std_logic_vector(3 downto 0);
+  signal tsm_hdataout_en_n                        : std_logic_vector(3 downto 0);
+  signal tsm_hready_n                             : std_logic_vector(3 downto 0);
+  signal tsm_hread_n                              : std_logic_vector(3 downto 0);
+  signal tsm_hwrite_n                             : std_logic_vector(3 downto 0);
+  signal tsm_hcs_n                                : std_logic_vector(3 downto 0);
+  signal tsm_hdata                                : std_logic_vector(4 * 8 - 1 downto 0);
+  signal tsm_haddr                                : std_logic_vector(4 * 8 - 1 downto 0);
+  
+  signal synced_rst                               : std_logic;
+  
+  signal powerup_ch                               : std_logic_vector(3 downto 0);
+  signal link_rx_ready                            : std_logic_vector(3 downto 0);
+  signal rx_los_low                               : std_logic_vector(3 downto 0);
+  signal rx_cdr_lol                               : std_logic_vector(3 downto 0);
+  signal rx_pcs_rst                               : std_logic_vector(3 downto 0);
+  signal rx_pcs_rst_q                             : std_logic_vector(3 downto 0);
+  signal rx_serdes_rst                            : std_logic_vector(3 downto 0);
+  signal rx_serdes_rst_q                          : std_logic_vector(3 downto 0);
+  signal init_quad                                : std_logic;
+  signal tx_plol_lol                              : std_logic;
+  
+  signal debug                                    : std_logic_vector(63 downto 0);
+
+  -- for replacing register interface
+  signal delay_q                                  : std_logic_vector(4 * 8 - 1 downto 0);
+  signal pulse                                    : std_logic_vector(3 downto 0);
+
+  signal SD_RXD_P_IN, SD_RXD_N_IN, SD_TXD_P_OUT, SD_TXD_N_OUT : std_logic_vector(3 downto 0);
+
+  signal mac_tx_data                              : std_logic_vector(4 * 8 - 1 downto 0);
+  signal mac_tx_read                              : std_logic_vector(3 downto 0);
+  signal mac_tx_done                              : std_logic_vector(3 downto 0);
+  signal mac_fifoeof                              : std_logic_vector(3 downto 0);
+  signal mac_fifoavail                            : std_logic_vector(3 downto 0);
+  signal mac_fifoempty                            : std_logic_vector(3 downto 0);
+
+  signal mac_rx_data                              : std_logic_vector(4 * 8 - 1 downto 0);
+  signal mac_rx_wr                                : std_logic_vector(3 downto 0);
+  signal mac_rx_eof                               : std_logic_vector(3 downto 0);
+  signal mac_rx_err                               : std_logic_vector(3 downto 0);
+  signal mac_rx_fifofull                          : std_logic_vector(3 downto 0);
+  signal mac_ready_conf                           : std_logic_vector(3 downto 0);
+  signal mac_reconf                               : std_logic_vector(3 downto 0);
+  signal link_active                              : std_logic_vector(3 downto 0);
+
+  signal led_timer                                : unsigned(19 downto 0);
+  signal led_timer_done_x                         : std_logic;
+  signal led_timer_done                           : std_logic;
+  signal led_activity_x                           : std_logic_vector(3 downto 0);
+  signal led_activity                             : std_logic_vector(4 * 2 - 1 downto 0);
+  
+begin
+
+  init_quad <= not GSR_N;
+  
+  gbe_serdes: entity serdes_gbe_4ch_ds
+  port map(
+    -- CH0 --
+    hdinp_ch0           => SD_RXD_P_IN(0),
+    hdinn_ch0           => SD_RXD_N_IN(0),
+    hdoutp_ch0          => SD_TXD_P_OUT(0),
+    hdoutn_ch0          => SD_TXD_N_OUT(0),
+    rxiclk_ch0          => sd_rx_clk(0),
+    txiclk_ch0          => CLK_125,
+    rx_full_clk_ch0     => sd_rx_clk(0),
+    rx_half_clk_ch0     => open,
+    tx_full_clk_ch0     => open,
+    tx_half_clk_ch0     => open,
+    fpga_rxrefclk_ch0   => CLK_125,
+    txdata_ch0          => sd_tx_data(7 downto 0),
+    tx_k_ch0            => sd_tx_kcntl(0),
+    xmit_ch0            => xmit(0),
+    tx_disp_correct_ch0 => sd_tx_correct_disp(0),
+    rxdata_ch0          => sd_rx_data(7 downto 0),
+    rx_k_ch0            => sd_rx_kcntl(0),
+    rx_disp_err_ch0     => sd_rx_disp_error(0),
+    rx_cv_err_ch0       => sd_rx_cv_error(0),
+    rx_serdes_rst_ch0_c => rx_serdes_rst(0),
+    sb_felb_ch0_c       => '0',
+    sb_felb_rst_ch0_c   => '0',
+    tx_pcs_rst_ch0_c    => TX_PCS_RST_IN,
+    tx_pwrup_ch0_c      => powerup_ch(0),
+    rx_pcs_rst_ch0_c    => rx_pcs_rst(0),
+    rx_pwrup_ch0_c      => powerup_ch(0),
+    rx_los_low_ch0_s    => rx_los_low(0),
+    lsm_status_ch0_s    => lsm_status(0),
+    rx_cdr_lol_ch0_s    => rx_cdr_lol(0),
+    -- CH1 --
+    hdinp_ch1           => SD_RXD_P_IN(1),
+    hdinn_ch1           => SD_RXD_N_IN(1),
+    hdoutp_ch1          => SD_TXD_P_OUT(1),
+    hdoutn_ch1          => SD_TXD_N_OUT(1),
+    rxiclk_ch1          => sd_rx_clk(1),
+    txiclk_ch1          => CLK_125,
+    rx_full_clk_ch1     => sd_rx_clk(1),
+    rx_half_clk_ch1     => open,
+    tx_full_clk_ch1     => open,
+    tx_half_clk_ch1     => open,
+    fpga_rxrefclk_ch1   => CLK_125,
+    txdata_ch1          => sd_tx_data(15 downto 8),
+    tx_k_ch1            => sd_tx_kcntl(1),
+    xmit_ch1            => xmit(1),
+    tx_disp_correct_ch1 => sd_tx_correct_disp(1),
+    rxdata_ch1          => sd_rx_data(15 downto 8),
+    rx_k_ch1            => sd_rx_kcntl(1),
+    rx_disp_err_ch1     => sd_rx_disp_error(1),
+    rx_cv_err_ch1       => sd_rx_cv_error(1),
+    rx_serdes_rst_ch1_c => rx_serdes_rst(1),
+    sb_felb_ch1_c       => '0',
+    sb_felb_rst_ch1_c   => '0',
+    tx_pcs_rst_ch1_c    => TX_PCS_RST_IN,
+    tx_pwrup_ch1_c      => powerup_ch(1),
+    rx_pcs_rst_ch1_c    => rx_pcs_rst(1),
+    rx_pwrup_ch1_c      => powerup_ch(1),
+    rx_los_low_ch1_s    => rx_los_low(1),
+    lsm_status_ch1_s    => lsm_status(1),
+    rx_cdr_lol_ch1_s    => rx_cdr_lol(1),
+    -- CH2 --
+    hdinp_ch2           => SD_RXD_P_IN(2),
+    hdinn_ch2           => SD_RXD_N_IN(2),
+    hdoutp_ch2          => SD_TXD_P_OUT(2),
+    hdoutn_ch2          => SD_TXD_N_OUT(2),
+    rxiclk_ch2          => sd_rx_clk(2),
+    txiclk_ch2          => CLK_125,
+    rx_full_clk_ch2     => sd_rx_clk(2),
+    rx_half_clk_ch2     => open,
+    tx_full_clk_ch2     => open,
+    tx_half_clk_ch2     => open,
+    fpga_rxrefclk_ch2   => CLK_125,
+    txdata_ch2          => sd_tx_data(23 downto 16),
+    tx_k_ch2            => sd_tx_kcntl(2),
+    xmit_ch2            => xmit(2),
+    tx_disp_correct_ch2 => sd_tx_correct_disp(2),
+    rxdata_ch2          => sd_rx_data(23 downto 16),
+    rx_k_ch2            => sd_rx_kcntl(2),
+    rx_disp_err_ch2     => sd_rx_disp_error(2),
+    rx_cv_err_ch2       => sd_rx_cv_error(2),
+    rx_serdes_rst_ch2_c => rx_serdes_rst(2),
+    sb_felb_ch2_c       => '0',
+    sb_felb_rst_ch2_c   => '0',
+    tx_pcs_rst_ch2_c    => TX_PCS_RST_IN,
+    tx_pwrup_ch2_c      => powerup_ch(2),
+    rx_pcs_rst_ch2_c    => rx_pcs_rst(2),
+    rx_pwrup_ch2_c      => powerup_ch(2),
+    rx_los_low_ch2_s    => rx_los_low(2),
+    lsm_status_ch2_s    => lsm_status(2),
+    rx_cdr_lol_ch2_s    => rx_cdr_lol(2),
+    -- CH3 --
+    hdinp_ch3           => SD_RXD_P_IN(3),
+    hdinn_ch3           => SD_RXD_N_IN(3),
+    hdoutp_ch3          => SD_TXD_P_OUT(3),
+    hdoutn_ch3          => SD_TXD_N_OUT(3),
+    rxiclk_ch3          => sd_rx_clk(3),
+    txiclk_ch3          => CLK_125,
+    rx_full_clk_ch3     => sd_rx_clk(3),
+    rx_half_clk_ch3     => open,
+    tx_full_clk_ch3     => open,
+    tx_half_clk_ch3     => open,
+    fpga_rxrefclk_ch3   => CLK_125,
+    txdata_ch3          => sd_tx_data(31 downto 24),
+    tx_k_ch3            => sd_tx_kcntl(3),
+    xmit_ch3            => xmit(3),
+    tx_disp_correct_ch3 => sd_tx_correct_disp(3),
+    rxdata_ch3          => sd_rx_data(31 downto 24),
+    rx_k_ch3            => sd_rx_kcntl(3),
+    rx_disp_err_ch3     => sd_rx_disp_error(3),
+    rx_cv_err_ch3       => sd_rx_cv_error(3),
+    rx_serdes_rst_ch3_c => rx_serdes_rst(3),
+    sb_felb_ch3_c       => '0',
+    sb_felb_rst_ch3_c   => '0',
+    tx_pcs_rst_ch3_c    => TX_PCS_RST_IN,
+    tx_pwrup_ch3_c      => powerup_ch(3),
+    rx_pcs_rst_ch3_c    => rx_pcs_rst(3),
+    rx_pwrup_ch3_c      => powerup_ch(3),
+    rx_los_low_ch3_s    => rx_los_low(3),
+    lsm_status_ch3_s    => lsm_status(3),
+    rx_cdr_lol_ch3_s    => rx_cdr_lol(3),
+    ---- Miscallaneous ports
+    fpga_txrefclk        => CLK_125,
+    tx_serdes_rst_c      => '0',
+    tx_pll_lol_qd_s      => tx_plol_lol,
+    rst_qd_c             => init_quad, 
+    serdes_rst_qd_c      => '0',
+    tx_sync_qd_c         => '0'
+  );
+
+  TX_PLOL_LOL_OUT <= tx_plol_lol;
+  
+  CHANNEL_GEN : for i in 0 to 3 generate
+    
+    CHANNEL_ACTIVE_GEN : if LINKS_ACTIVE(i) = '1' generate
+      
+      powerup_ch(i)      <= '1';
+      SD_TXDIS_OUT(i)    <= '0';
+    
+      -- RSL for RX of SerDes, based on extRSL logic
+      -- CAVEAT: reset signals MUST BE sync'ed to recovered RX clock!
+      THE_MAIN_RX_RST: main_rx_reset_RS 
+      port map(
+        CLEAR             => init_quad,
+        CLK_REF           => CLK_125,
+        CDR_LOL_IN        => rx_cdr_lol(i),
+        CV_IN             => sd_rx_cv_error(i),
+        LSM_IN            => lsm_status(i),
+        LOS_IN            => rx_los_low(i),
+        WAP_ZERO_IN       => '1', -- not needed here
+        -- outputs
+        WAP_REQ_OUT       => open, -- not needed here
+        RX_SERDES_RST_OUT => rx_serdes_rst(i), -- CLK_REF based
+        RX_PCS_RST_OUT    => rx_pcs_rst(i), -- CLK_REF based
+        LINK_RX_READY_OUT => link_rx_ready(i), -- CLK_REF based
+        STATE_OUT         => open
+      );
+
+      -- reset signals for RX SerDes need to be sync'ed to real RX clock for ECP5
+      SYNC_RST_SIGS: entity work.signal_sync 
+      generic map( WIDTH => 2 )
+      port map(
+        RESET    => '0',
+        CLK0     => sd_rx_clk(i), 
+        CLK1     => sd_rx_clk(i),
+        D_IN(0)  => rx_pcs_rst(i),
+        D_IN(1)  => rx_serdes_rst(i),
+        D_OUT(0) => rx_pcs_rst_q(i),
+        D_OUT(1) => rx_serdes_rst_q(i)
+      );
+
+      CLK_125_RX(i) <= sd_rx_clk(i);
+      
+      -- SGMII core
+      SGMII_GBE_PCS : sgmii_gbe_pcs42
+      port map(
+        rst_n                   => GSR_N,
+        signal_detect           => link_rx_ready(i),
+        gbe_mode                => '1',
+        sgmii_mode              => '0',
+        operational_rate        => operational_rate((i + 1) * 2 - 1 downto i * 2),
+        debug_link_timer_short  => '0',
+        force_isolate           => '0',
+        force_loopback          => '0',
+        force_unidir            => '0',
+        rx_compensation_err     => open,
+        ctc_drop_flag           => open,
+        ctc_add_flag            => open,
+        an_link_ok              => open,
+      -- MAC interface
+        tx_clk_125              => CLK_125,
+        tx_clock_enable_source  => tx_clk_en(i),
+        tx_clock_enable_sink    => tx_clk_en(i),
+        tx_d                    => pcs_txd((i + 1) * 8 - 1 downto i * 8), -- TX data from MAC
+        tx_en                   => pcs_tx_en(i), -- TX data enable from MAC
+        tx_er                   => pcs_tx_er(i), -- TX error from MAC
+        rx_clk_125              => CLK_125,
+        rx_clock_enable_source  => rx_clk_en(i),
+        rx_clock_enable_sink    => rx_clk_en(i),
+        rx_d                    => pcs_rxd((i + 1 ) * 8 - 1 downto i * 8), -- RX data to MAC
+        rx_dv                   => pcs_rx_en(i), -- RX data enable to MAC
+        rx_er                   => pcs_rx_er(i), -- RX error to MAC
+        col                     => open,
+        crs                     => open,
+        -- SerDes interface
+        tx_data                 => sd_tx_data((i + 1) * 8 - 1 downto i * 8), -- TX data to SerDes
+        tx_kcntl                => sd_tx_kcntl(i), -- TX komma control to SerDes
+        tx_disparity_cntl       => sd_tx_correct_disp(i), -- idle parity state control in IPG (to SerDes)
+        xmit_autoneg            => xmit(i),
+        serdes_recovered_clk    => sd_rx_clk(i), -- 125MHz recovered from receive bit stream
+        rx_data                 => sd_rx_data((i + 1) * 8 - 1 downto i * 8), -- RX data from SerDes
+        rx_kcntl                => sd_rx_kcntl(i), -- RX komma control from SerDes
+        rx_err_decode_mode      => '0', -- receive error control mode fixed to normal
+        rx_even                 => '0', -- unused (receive error control mode = normal, tie to GND)
+        rx_disp_err             => sd_rx_disp_error(i), -- RX disparity error from SerDes
+        rx_cv_err               => sd_rx_cv_error(i), -- RX code violation error from SerDes
+        -- Autonegotiation stuff
+        mr_an_complete          => an_complete(i),
+        mr_page_rx              => mr_page_rx(i),
+        mr_lp_adv_ability       => mr_lp_adv_ability((i + 1) * 16 - 1 downto i * 16),
+        mr_main_reset           => mr_main_reset(i),
+        mr_an_enable            => mr_an_enable(i),
+        mr_restart_an           => mr_restart_an(i),
+        mr_adv_ability          => mr_adv_ability((i + 1) * 16 - 1 downto i * 16)
+      );
+      
+      operational_rate((i + 1) * 2 - 1 downto i * 2) <= b"10";
+    
+      mr_main_reset(i)                               <= init_quad;
+      mr_restart_an(i)                               <= pulse(i);
+      mr_an_enable(i)                                <= link_rx_ready(i);
+      mr_adv_ability((i + 1) * 16 - 1 downto i * 16) <= x"0020";
+    
+      SYNC_PROC: process( CLK_125 ) 
+      begin
+        if( rising_edge(CLK_125) ) then
+          delay_q((i + 1) * 8 - 1 downto i * 8) <= delay_q((i + 1) * 8 - 2 downto i * 8) & link_rx_ready(i);
+        end if;
+      end process SYNC_PROC;
+      
+      pulse(i)  <= not delay_q((i + 1) * 8 - 1) and delay_q((i + 1) * 8 - 2);
+
+      -- TSMAC core
+      MAC: tsmac41
+      port map(
+      ----------------- clock and reset port declarations ------------------
+        hclk            => CLK_125, -- BUG: can be CLK_125
+        txmac_clk       => CLK_125,
+        rxmac_clk       => CLK_125,
+        reset_n         => GSR_N,
+      ------------------- Input signals to the GMII ----------------
+        rxd             => pcs_rxd((i + 1) * 8 - 1 downto i * 8),
+        rx_dv           => pcs_rx_en(i),
+        rx_er           => pcs_rx_er(i),
+      -------------------- Input signals to the CPU I/F -------------------
+        haddr           => tsm_haddr((i + 1) * 8 - 1 downto i * 8),
+        hdatain         => tsm_hdata((i + 1) * 8 - 1 downto i * 8),
+        hcs_n           => tsm_hcs_n(i),
+        hwrite_n        => tsm_hwrite_n(i),
+        hread_n         => tsm_hread_n(i),
+      ---------------- Input signals to the Tx MAC FIFO I/F ---------------
+        tx_fifodata     => mac_tx_data((i + 1) * 8 - 1 downto i * 8),
+        tx_fifoavail    => mac_fifoavail(i),
+        tx_fifoeof      => mac_fifoeof(i),
+        tx_fifoempty    => mac_fifoempty(i),
+        tx_sndpaustim   => x"0000",
+        tx_sndpausreq   => '0',
+        tx_fifoctrl     => '0',  -- always data frame
+      ---------------- Input signals to the Rx MAC FIFO I/F --------------- 
+        rx_fifo_full    => mac_rx_fifofull(i),
+        ignore_pkt      => '0',
+      ---------------- Output signals from the GMII -----------------------
+        txd             => pcs_txd((i + 1) * 8 - 1 downto i * 8),
+        tx_en           => pcs_tx_en(i),
+        tx_er           => pcs_tx_er(i),
+      ----------------- Output signals from the CPU I/F -------------------
+        hdataout        => open,
+        hdataout_en_n   => tsm_hdataout_en_n(i),
+        hready_n        => tsm_hready_n(i),
+        cpu_if_gbit_en  => open,
+      ------------- Output signals from the Tx MAC FIFO I/F --------------- 
+        tx_macread      => mac_tx_read(i),
+        tx_discfrm      => open,
+        tx_staten       => open,
+        tx_statvec      => open,
+        tx_done         => mac_tx_done(i),
+      ------------- Output signals from the Rx MAC FIFO I/F ---------------   
+        rx_fifo_error   => open,
+        rx_stat_vector  => open,
+        rx_dbout        => mac_rx_data((i + 1) * 8 - 1 downto i * 8),
+        rx_write        => mac_rx_wr(i),
+        rx_stat_en      => open,
+        rx_eof          => mac_rx_eof(i),
+        rx_error        => mac_rx_err(i)
+      );
+      
+      -- responsible for loading the TSMAC registers
+      -- CAN BE OPTIMIZED
+      TSMAC_CONTROLLER : trb_net16_gbe_mac_control
+      port map(
+        CLK                 => CLK_125, -- BUG: can be CLK_125
+        RESET               => RESET, 
+      -- signals to/from main controller
+        MC_TSMAC_READY_OUT  => mac_ready_conf(i),
+        MC_RECONF_IN        => mac_reconf(i),
+        MC_GBE_EN_IN        => '1',
+        MC_RX_DISCARD_FCS   => '0',
+        MC_PROMISC_IN       => '1',
+        MC_MAC_ADDR_IN      => (others => '0'),
+      -- signal to/from Host interface of TriSpeed MAC
+        TSM_HADDR_OUT       => tsm_haddr((i + 1) * 8 - 1 downto i * 8),
+        TSM_HDATA_OUT       => tsm_hdata((i + 1) * 8 - 1 downto i * 8),
+        TSM_HCS_N_OUT       => tsm_hcs_n(i),
+        TSM_HWRITE_N_OUT    => tsm_hwrite_n(i),
+        TSM_HREAD_N_OUT     => tsm_hread_n(i),
+        TSM_HREADY_N_IN     => tsm_hready_n(i),
+        TSM_HDATA_EN_N_IN   => tsm_hdataout_en_n(i),
+      -- Debug
+        DEBUG_OUT           => open
+      );
+
+      -- initializes MAC after AN is complete 
+      THE_FW_GBE_LSM: entity gbe_lsm
+      port map(
+        CLK                  => CLK_125, -- BUG: can be CLK_125
+        CLEAR                => init_quad,
+        RESET                => RESET,
+        -- 
+        MAC_AN_COMPLETE_IN   => an_complete(i),
+        MAC_READY_CONF_IN    => mac_ready_conf(i),
+        MAC_RECONF_OUT       => mac_reconf(i),
+        --
+        LINK_ACTIVE_OUT      => link_active(i),
+        --
+        DEBUG                => open
+      );
+
+      -- RX ringbuffer
+      THE_FW_RB: entity rx_rb 
+      port map(
+        CLK                 => CLK_125,
+        CLEAR               => init_quad,
+        RESET               => RESET,
+        -- MAC interface (RX)
+        MAC_RX_DATA_IN      => mac_rx_data((i + 1) * 8 - 1 downto i * 8),
+        MAC_RX_WR_IN        => mac_rx_wr(i),
+        MAC_RX_EOF_IN       => mac_rx_eof(i),
+        MAC_RX_ERROR_IN     => mac_rx_err(i),
+        MAC_RX_FIFOFULL_OUT => mac_rx_fifofull(i),
+        -- FIFO interface (TX)
+        FIFO_FULL_IN        => FIFO_FULL_IN(i),
+        FIFO_WR_OUT         => FIFO_WR_OUT(i),
+        FIFO_Q_OUT          => FIFO_DATA_OUT((i + 1) * 8 - 1 downto i * 8),
+        FRAME_REQ_IN        => FRAME_REQ_IN(i),
+        FRAME_ACK_OUT       => FRAME_ACK_OUT(i),
+        FRAME_AVAIL_OUT     => FRAME_AVAIL_OUT(i),
+        FRAME_START_OUT     => FRAME_START_OUT(i),
+        --
+        DEBUG               => open
+      );
+      
+      -- TX FIFO
+      THE_FW_FIFO: entity tx_fifo
+      port map(
+        CLK               => CLK_125,
+        CLEAR             => init_quad,
+        RESET             => RESET,
+        -- MAC interface
+        MAC_TX_DATA_OUT   => mac_tx_data((i + 1) * 8 - 1 downto i * 8),
+        MAC_TX_READ_IN    => mac_tx_read(i),
+        MAC_FIFOEOF_OUT   => mac_fifoeof(i),
+        MAC_FIFOEMPTY_OUT => mac_fifoempty(i),
+        MAC_FIFOAVAIL_OUT => mac_fifoavail(i),
+        MAC_TX_DONE_IN    => mac_tx_done(i), -- not used
+        -- FIFO interface
+        FIFO_FULL_OUT     => FIFO_FULL_OUT(i),
+        FIFO_WR_IN        => FIFO_WR_IN(i),
+        FIFO_D_IN         => FIFO_DATA_IN((i + 1) * 8 - 1 downto i * 8),
+        -- Link stuff
+        FRAME_START_IN    => FRAME_START_IN(i),
+        LINK_ACTIVE_IN    => an_complete(i),
+        --
+        DEBUG             => open
+      );
+          
+      -- LED connections, can be simplified by CE signal, to get rid of local counter instances
+      led_activity_x(i)  <= pcs_rx_en(i) or pcs_tx_en(i);
+
+      THE_LED_ACT_PROC: process( CLK_125 )
+      begin
+        if( rising_edge(CLK_125) ) then
+          if( led_activity_x(i) = '1' ) then
+            led_activity((i + 1) * 2 - 2) <= '1';
+          end if;
+          if( led_timer_done = '1' ) then
+            led_activity((i + 1) * 2 - 1 downto (i + 1) * 2 - 2) <= led_activity((i + 1) * 2 - 2) & '0';
+          end if;
+        end if;
+      end process THE_LED_ACT_PROC;
+
+      -- Status signals
+      STATUS_OUT(i * 8 + 7) <= '0';                            -- unused
+      STATUS_OUT(i * 8 + 6) <= link_active(i);                 -- link is active
+      STATUS_OUT(i * 8 + 5) <= led_activity((i + 1) * 2 - 1);  -- long LED signal for activity
+      STATUS_OUT(i * 8 + 4) <= pcs_rx_en(i);                   -- SerDes RX activity
+      STATUS_OUT(i * 8 + 3) <= pcs_tx_en(i);                   -- SerDes TX activity
+      STATUS_OUT(i * 8 + 2) <= an_complete(i);                 -- GbE Autonegotiation completed
+      STATUS_OUT(i * 8 + 1) <= link_rx_ready(i);               -- SerDes Rx channel operational
+      STATUS_OUT(i * 8 + 0) <= TX_LINK_READY_IN;               -- SerDes Tx channel operational
+
+    end generate CHANNEL_ACTIVE_GEN;
+
+    CHANNEL_INACTIVE_GEN : if LINKS_ACTIVE(i) = '0' generate
+      
+      powerup_ch(i)      <= '0';
+      SD_TXDIS_OUT(i)    <= '1';
+      rx_pcs_rst_q(i)    <= '1';
+      rx_serdes_rst_q(i) <= '1';
+
+      -- Status signals
+      STATUS_OUT(i * 8 + 7) <= '0';                            -- unused
+      STATUS_OUT(i * 8 + 6) <= '0';                            -- link is active
+      STATUS_OUT(i * 8 + 5) <= '0';                            -- long LED signal for activity
+      STATUS_OUT(i * 8 + 4) <= '0';                            -- SerDes RX activity
+      STATUS_OUT(i * 8 + 3) <= '0';                            -- SerDes TX activity
+      STATUS_OUT(i * 8 + 2) <= '0';                            -- GbE Autonegotiation completed
+      STATUS_OUT(i * 8 + 1) <= '0';                            -- SerDes Rx channel operational
+      STATUS_OUT(i * 8 + 0) <= '0';                            -- SerDes Tx channel operational
+
+    end generate CHANNEL_INACTIVE_GEN;
+    
+  end generate CHANNEL_GEN;
+
+  THE_LED_TIMER_PROC: process( CLK_125 )
+  begin
+    if( rising_edge(CLK_125) ) then
+      led_timer_done <= led_timer_done_x;
+      led_timer      <= led_timer + 1;
+    end if;
+  end process THE_LED_TIMER_PROC;
+
+  led_timer_done_x <= '1' when (std_logic_vector(led_timer) = x"fffff") else '0';
+  
+end architecture RTL;