]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
changes to sync reset
authorMichael Boehmer <mboehmer@ph.tum.de>
Sat, 9 Jul 2022 22:30:23 +0000 (00:30 +0200)
committerMichael Boehmer <mboehmer@ph.tum.de>
Sat, 9 Jul 2022 22:30:23 +0000 (00:30 +0200)
gbe_trb/base/gather_ports.vhd [new file with mode: 0644]
gbe_trb/base/gbe_lsm.vhd [new file with mode: 0644]
gbe_trb/base/rx_rb.vhd [new file with mode: 0644]
gbe_trb/base/scatter_ports.vhd [new file with mode: 0644]
gbe_trb/base/tx_fifo.vhd [new file with mode: 0644]

diff --git a/gbe_trb/base/gather_ports.vhd b/gbe_trb/base/gather_ports.vhd
new file mode 100644 (file)
index 0000000..9ee21b7
--- /dev/null
@@ -0,0 +1,177 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+\r
+entity gather_ports is\r
+  port(\r
+    CLK                 : in  std_logic;\r
+    RESET               : in  std_logic;\r
+    --\r
+    FRAME_AVAIL_IN      : in  std_logic_vector(15 downto 0) := (others => '0');\r
+    FRAME_REQ_OUT       : out std_logic_vector(15 downto 0);\r
+    FRAME_ACK_IN        : in  std_logic_vector(15 downto 0) := (others => '0');\r
+    PORT_SELECT_OUT     : out std_logic_vector(15 downto 0);\r
+    CYCLE_DONE_OUT      : out std_logic;\r
+    --\r
+    DEBUG               : out std_logic_vector(15 downto 0)\r
+  );\r
+end entity gather_ports;\r
+\r
+architecture gather_ports_arch of gather_ports is\r
+\r
+-- Components\r
+\r
+-- state machine signals\r
+  type state_t is (IDLE, STORE, DO_PORTS, DELAY, CLEANUP);\r
+  signal STATE, NEXT_STATE    : state_t;\r
+\r
+-- Signals\r
+  signal gather_needed_x        : std_logic;\r
+  signal store_ports_x          : std_logic;\r
+  signal all_ports_done_x       : std_logic;\r
+  signal stored_ports           : std_logic_vector(15 downto 0);\r
+  signal next_port_x            : std_logic_vector(15 downto 0);\r
+  signal select_ports           : std_logic_vector(15 downto 0);\r
+  signal req_ports              : std_logic_vector(15 downto 0);\r
+\r
+begin\r
+\r
+  -- we need to start a gather cycle if any src port has frames available\r
+  gather_needed_x <= '1' when FRAME_AVAIL_IN /= x"0000" else '0';\r
+\r
+  -- store the src port status\r
+  GEN_REGS: for I in 0 to 15 generate\r
+    THE_SRC_STORE_PROC: process( CLK )\r
+    begin\r
+      if( rising_edge(CLK) ) then\r
+        if   ( RESET = '1' ) then\r
+          stored_ports(I) <= '0';\r
+        elsif( store_ports_x = '1' ) then\r
+          stored_ports(I) <= FRAME_AVAIL_IN(I);\r
+        elsif( FRAME_ACK_IN(I) = '1' ) then\r
+          stored_ports(I) <= '0';\r
+        end if;\r
+      end if;\r
+    end process THE_SRC_STORE_PROC;\r
+  end generate;\r
+\r
+  all_ports_done_x <= '1' when stored_ports = x"0000" else '0';\r
+\r
+  -- select the port data\r
+  THE_SELECT_PORT_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if( RESET = '1' ) then\r
+        select_ports <= (others => '0');\r
+      else\r
+        select_ports <= next_port_x;\r
+      end if;\r
+    end if;\r
+  end process THE_SELECT_PORT_PROC;\r
+\r
+  PORT_SELECT_OUT <= select_ports;\r
+\r
+  -- port frame request, one clock cycle pulse\r
+  req_ports <= not select_ports and next_port_x when rising_edge(CLK);\r
+\r
+  FRAME_REQ_OUT <= req_ports;\r
+\r
+  CYCLE_DONE_OUT <= '1' when STATE = CLEANUP else '0';\r
+\r
+  -- priority decoced "next port to serve" signals\r
+  THE_NEXT_PORT_PROC: process( stored_ports )\r
+  begin\r
+    if   ( stored_ports(0) = '1' ) then\r
+      next_port_x <= x"0001";\r
+    elsif( stored_ports(1) = '1' ) then\r
+      next_port_x <= x"0002";\r
+    elsif( stored_ports(2) = '1' ) then\r
+      next_port_x <= x"0004";\r
+    elsif( stored_ports(3) = '1' ) then\r
+      next_port_x <= x"0008";\r
+    elsif( stored_ports(4) = '1' ) then\r
+      next_port_x <= x"0010";\r
+    elsif( stored_ports(5) = '1' ) then\r
+      next_port_x <= x"0020";\r
+    elsif( stored_ports(6) = '1' ) then\r
+      next_port_x <= x"0040";\r
+    elsif( stored_ports(7) = '1' ) then\r
+      next_port_x <= x"0080";\r
+    elsif( stored_ports(8) = '1' ) then\r
+      next_port_x <= x"0100";\r
+    elsif( stored_ports(9) = '1' ) then\r
+      next_port_x <= x"0200";\r
+    elsif( stored_ports(10) = '1' ) then\r
+      next_port_x <= x"0400";\r
+    elsif( stored_ports(11) = '1' ) then\r
+      next_port_x <= x"0800";\r
+    elsif( stored_ports(12) = '1' ) then\r
+      next_port_x <= x"1000";\r
+    elsif( stored_ports(13) = '1' ) then\r
+      next_port_x <= x"2000";\r
+    elsif( stored_ports(14) = '1' ) then\r
+      next_port_x <= x"4000";\r
+    elsif( stored_ports(15) = '1' ) then\r
+      next_port_x <= x"8000";\r
+    else\r
+      next_port_x <= x"0000";\r
+    end if;\r
+  end process THE_NEXT_PORT_PROC;\r
+\r
+  -----------------------------------------------------------\r
+  -- statemachine: clocked process\r
+  -----------------------------------------------------------\r
+  THE_FSM: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if( RESET = '1' ) then\r
+        STATE <= IDLE;\r
+      else\r
+        STATE <= NEXT_STATE;\r
+      end if;\r
+    end if;\r
+  end process THE_FSM;\r
+\r
+  THE_STATE_TRANSITIONS: process( STATE, gather_needed_x, all_ports_done_x )\r
+  begin\r
+    store_ports_x <= '0';\r
+\r
+    case STATE is\r
+\r
+      when IDLE =>\r
+        if( gather_needed_x = '1' ) then\r
+          NEXT_STATE <= STORE;\r
+          store_ports_x <= '1';\r
+        else\r
+          NEXT_STATE <= IDLE;\r
+        end if;\r
+\r
+      when STORE =>\r
+        NEXT_STATE <= DO_PORTS;\r
+\r
+      when DO_PORTS =>\r
+        if( all_ports_done_x = '1' ) then\r
+          NEXT_STATE <= DELAY;\r
+        else\r
+          NEXT_STATE <= DO_PORTS;\r
+        end if;\r
+\r
+      when DELAY =>\r
+        NEXT_STATE <= CLEANUP;\r
+\r
+      when CLEANUP =>\r
+        if( gather_needed_x = '1' ) then\r
+          NEXT_STATE <= STORE;\r
+          store_ports_x <= '1';\r
+        else\r
+          NEXT_STATE <= IDLE;\r
+        end if;\r
+\r
+      when others  =>\r
+        NEXT_STATE <= IDLE;\r
+    end case;\r
+  end process THE_STATE_TRANSITIONS;\r
+\r
+end architecture;\r
diff --git a/gbe_trb/base/gbe_lsm.vhd b/gbe_trb/base/gbe_lsm.vhd
new file mode 100644 (file)
index 0000000..1c9dead
--- /dev/null
@@ -0,0 +1,138 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+\r
+entity gbe_lsm is\r
+  port(\r
+    CLK                  : in  std_logic;\r
+    RESET                : in  std_logic;\r
+    -- \r
+    MAC_AN_COMPLETE_IN   : in  std_logic; -- PCS Autonegotiation completed\r
+    MAC_READY_CONF_IN    : in  std_logic; -- MAC configuration completed\r
+    MAC_RECONF_OUT       : out std_logic; -- start MAC configuration\r
+    --\r
+    LINK_ACTIVE_OUT      : out std_logic;\r
+    --\r
+    DEBUG                : out std_logic_vector(15 downto 0)\r
+  );\r
+end entity gbe_lsm;\r
+\r
+architecture gbe_lsm_arch of gbe_lsm is\r
+\r
+-- Components\r
+\r
+-- state machine signals\r
+  type state_t is (INACTIVE,WAIT_PCS,ENABLE_MAC,DELAY,ACTIVATED);\r
+  signal STATE, NEXT_STATE    : state_t;\r
+\r
+-- Signals\r
+  signal dly_ctr       : unsigned(15 downto 0);\r
+  signal ce_dly_ctr    : std_logic;\r
+  signal rst_dly_ctr   : std_logic;\r
+  signal dly_ctr_done  : std_logic;\r
+  signal reconf_mac    : std_logic;\r
+\r
+begin\r
+\r
+  MAC_RECONF_OUT <= reconf_mac;\r
+\r
+  LINK_ACTIVE_OUT <= '1' when (STATE = ACTIVATED) else '0';\r
+  \r
+  THE_DLY_CTR: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        dly_ctr <= (others => '0');\r
+      elsif( rst_dly_ctr = '1' ) then\r
+        dly_ctr <= (others => '0');\r
+      elsif( ce_dly_ctr = '1' ) then\r
+        dly_ctr <= dly_ctr + 1;\r
+      end if;\r
+    end if;\r
+  end process THE_DLY_CTR;\r
+  \r
+  dly_ctr_done <= '1' when dly_ctr = x"ffff" else '0';\r
+\r
+  -----------------------------------------------------------\r
+  -- statemachine: clocked process\r
+  -----------------------------------------------------------\r
+  THE_FSM: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if( RESET = '1' ) then\r
+        STATE <= INACTIVE;\r
+      else\r
+        STATE <= NEXT_STATE;\r
+      end if;\r
+    end if;\r
+  end process THE_FSM;\r
+\r
+  THE_STATE_TRANSITIONS: process( STATE, MAC_AN_COMPLETE_IN, MAC_READY_CONF_IN, dly_ctr_done )\r
+  begin\r
+    reconf_mac <= '0';\r
+    ce_dly_ctr <= '0';\r
+    rst_dly_ctr <= '0';\r
+    \r
+    case STATE is\r
+\r
+      when INACTIVE =>\r
+        rst_dly_ctr <= '1';\r
+        if( MAC_AN_COMPLETE_IN = '1' ) then\r
+          NEXT_STATE <= WAIT_PCS;\r
+        else\r
+          NEXT_STATE <= INACTIVE;\r
+        end if;\r
+\r
+      when WAIT_PCS =>\r
+        ce_dly_ctr <= '1';\r
+        if( MAC_AN_COMPLETE_IN = '0' ) then\r
+          NEXT_STATE <= INACTIVE;\r
+        else\r
+          if( dly_ctr_done = '1' ) then \r
+            NEXT_STATE <= ENABLE_MAC;\r
+            reconf_mac <= '1';\r
+          else\r
+            NEXT_STATE <= WAIT_PCS;\r
+          end if;\r
+        end if;\r
+\r
+      when ENABLE_MAC =>\r
+        rst_dly_ctr <= '1';\r
+        if( MAC_AN_COMPLETE_IN = '0' ) then\r
+          NEXT_STATE <= INACTIVE;\r
+        else\r
+          if( MAC_READY_CONF_IN = '1' ) then\r
+            NEXT_STATE <= DELAY;\r
+          else \r
+            NEXT_STATE <= ENABLE_MAC;\r
+          end if;\r
+        end if;\r
+\r
+      when DELAY =>\r
+        ce_dly_ctr <= '1';\r
+        if( MAC_AN_COMPLETE_IN = '0' ) then\r
+          NEXT_STATE <= INACTIVE;\r
+        else\r
+          if( dly_ctr_done = '1' ) then\r
+            NEXT_STATE <= ACTIVATED;\r
+          else \r
+            NEXT_STATE <= DELAY;\r
+          end if;\r
+        end if;\r
+        \r
+      when ACTIVATED =>\r
+        rst_dly_ctr <= '1';\r
+        if( MAC_AN_COMPLETE_IN = '0' ) then\r
+          NEXT_STATE <= INACTIVE;\r
+        else\r
+          NEXT_STATE <= ACTIVATED;\r
+        end if;\r
+\r
+      when others  =>\r
+        NEXT_STATE <= INACTIVE;\r
+    end case;\r
+  end process THE_STATE_TRANSITIONS;\r
+\r
+end architecture;\r
diff --git a/gbe_trb/base/rx_rb.vhd b/gbe_trb/base/rx_rb.vhd
new file mode 100644 (file)
index 0000000..0c57f46
--- /dev/null
@@ -0,0 +1,288 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+\r
+entity rx_rb is\r
+  port(\r
+    CLK                 : in  std_logic;\r
+    RESET               : in  std_logic;\r
+    -- MAC interface (RX)\r
+    MAC_RX_DATA_IN      : in  std_logic_vector(7 downto 0); -- RX data from TSMAC\r
+    MAC_RX_WR_IN        : in  std_logic; -- RX data write from TSMAC\r
+    MAC_RX_EOF_IN       : in  std_logic; -- RX EndOfFrame from TSMAC\r
+    MAC_RX_ERROR_IN     : in  std_logic; -- RX Error from TSMAC\r
+    MAC_RX_FIFOFULL_OUT : out std_logic;\r
+    -- FIFO interface (TX)\r
+    FIFO_FULL_IN        : in  std_logic; -- TX fifo full, delay read from ring buffer\r
+    FIFO_WR_OUT         : out std_logic; -- TX fifo write\r
+    FIFO_Q_OUT          : out std_logic_vector(8 downto 0); -- TX data\r
+    FRAME_REQ_IN        : in  std_logic; -- one pulse starts readout of frame stored in ring buffer\r
+    FRAME_ACK_OUT       : out std_logic; -- one pulse for "end of frame"\r
+    FRAME_AVAIL_OUT     : out std_logic; -- number of frames stored in ring buffer\r
+    FRAME_START_OUT     : out std_logic; -- StartOfFrame signal\r
+    --\r
+    DEBUG               : out std_logic_vector(15 downto 0)\r
+  );\r
+end entity rx_rb;\r
+\r
+architecture rx_rb_arch of rx_rb is\r
+\r
+-- Components\r
+  component rb_4k_9\r
+  port(\r
+    WRADDRESS : in  std_logic_vector(11 downto 0); \r
+    RDADDRESS : in  std_logic_vector(11 downto 0); \r
+    DATA      : in  std_logic_vector(8 downto 0); \r
+    WE        : in  std_logic; \r
+    RDCLOCK   : in  std_logic; \r
+    RDCLOCKEN : in  std_logic; \r
+    RESET     : in  std_logic; \r
+    WRCLOCK   : in  std_logic; \r
+    WRCLOCKEN : in  std_logic; \r
+    Q         : out std_logic_vector(8 downto 0)\r
+  );\r
+  end component rb_4k_9;\r
+\r
+-- state machine signals\r
+  type state_t is (RX_DENY,RX_READY,RX_FRAME,FRAME_OK,FRAME_BAD,FORWARD,SKIP);\r
+  signal STATE, NEXT_STATE    : state_t;\r
+\r
+-- Signals\r
+  signal rd_ptr          : unsigned(11 downto 0);\r
+  signal wr_ptr          : unsigned(11 downto 0);\r
+  signal last_wr_ptr     : std_logic_vector(11 downto 0);\r
+  signal rb_used         : unsigned(11 downto 0);\r
+  signal rb_full         : std_logic;\r
+  signal rb_empty        : std_logic;\r
+  signal ce_wr_ptr       : std_logic;\r
+  signal ld_wr_ptr       : std_logic;\r
+  signal ce_rd_ptr       : std_logic;\r
+  signal wr_ram          : std_logic;\r
+  signal rd_ram          : std_logic;\r
+  signal ram_q           : std_logic_vector(8 downto 0);\r
+  signal frame_active    : std_logic;\r
+  signal frame_requested : std_logic;\r
+  signal fifo_wr_int     : std_logic;\r
+  signal empty_read_ack  : std_logic;\r
+  signal normal_read_ack : std_logic;\r
+  signal sof_int         : std_logic;\r
+  signal frames_avail    : unsigned(7 downto 0);\r
+\r
+\r
+begin\r
+\r
+  -- FrameActive: we must not change to "receive" in the middle of a frame\r
+  -- when "buffer full" condition is deasserted\r
+  THE_FRAME_ACTIVE_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        frame_active <= '0';\r
+      elsif( (MAC_RX_WR_IN = '1') and (frame_active = '0') ) then\r
+        frame_active <= '1';\r
+      elsif( (MAC_RX_EOF_IN = '1') and (frame_active = '1') ) then\r
+        frame_active <= '0';\r
+      end if;\r
+    end if;\r
+  end process THE_FRAME_ACTIVE_PROC;\r
+\r
+  -- Write pointer for ring buffer\r
+  THE_WR_PTR_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        wr_ptr <= (others => '0');\r
+      elsif( ld_wr_ptr = '1' ) then\r
+        wr_ptr <= unsigned(last_wr_ptr);\r
+      elsif( ce_wr_ptr = '1' ) then\r
+        wr_ptr <= wr_ptr + 1;\r
+      end if;\r
+    end if;\r
+  end process THE_WR_PTR_PROC;\r
+\r
+  -- Read pointer for ring buffer\r
+  THE_RD_PTR_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        rd_ptr <= (others => '0');\r
+      elsif( ce_rd_ptr = '1' ) then\r
+        rd_ptr <= rd_ptr + 1;\r
+      end if;\r
+    end if;\r
+  end process THE_RD_PTR_PROC;\r
+\r
+  -- ring buffer fill level\r
+  rb_used <= wr_ptr - rd_ptr;\r
+  \r
+  -- ring buffer full \r
+  -- TAKE CARE: the last byte of a frame is taken into account\r
+  --            by "one less" for the full condition\r
+  rb_full  <= '1' when (rb_used(11 downto 1) = b"1111_1111_111") else '0';\r
+\r
+  rb_empty <= '1' when (rb_used(11 downto 0) = b"0000_0000_0000") else '0';\r
+\r
+  MAC_RX_FIFOFULL_OUT <= rb_full;\r
+  \r
+  -- last write pointer: used to drop a broken frame, in case\r
+  THE_LAST_WR_PTR_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        last_wr_ptr <= (others => '0');\r
+      elsif( (STATE = RX_READY) and (MAC_RX_WR_IN = '1') ) then\r
+        last_wr_ptr <= std_logic_vector(wr_ptr);\r
+      end if;\r
+    end if;\r
+  end process THE_LAST_WR_PTR_PROC;\r
+\r
+  -- DPRAM as ring buffer\r
+  THE_DP_RAM: rb_4k_9\r
+  port map(\r
+    WRADDRESS         => std_logic_vector(wr_ptr),\r
+    RDADDRESS         => std_logic_vector(rd_ptr),\r
+    DATA(8)           => MAC_RX_EOF_IN,\r
+    DATA(7 downto 0)  => MAC_RX_DATA_IN,\r
+    WE                => wr_ram,\r
+    RDCLOCK           => CLK,\r
+    RDCLOCKEN         => '1',\r
+    RESET             => RESET,\r
+    WRCLOCK           => CLK,\r
+    WRCLOCKEN         => '1',\r
+    Q                 => ram_q\r
+  );\r
+\r
+  -- write signal\r
+  wr_ram    <= '1' when ((STATE = RX_READY) and (MAC_RX_WR_IN = '1') and (rb_full = '0')) or\r
+                        ((STATE = RX_FRAME) and (MAC_RX_WR_IN = '1') and (rb_full = '0'))  \r
+                    else '0';\r
+  ce_wr_ptr <= '1' when ((STATE = RX_READY) and (MAC_RX_WR_IN = '1') and (rb_full = '0')) or\r
+                        ((STATE = RX_FRAME) and (MAC_RX_WR_IN = '1') and (rb_full = '0'))  \r
+                    else '0';\r
+\r
+  -- FrameReq signal, one pulse only\r
+  THE_FRAME_REQ_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        frame_requested <= '0';\r
+      elsif( (FRAME_REQ_IN = '1') and (frame_requested = '0') ) then\r
+        frame_requested <= '1';\r
+      elsif( ((ram_q(8) = '1') and (frame_requested = '1')) or (empty_read_ack = '1') ) then\r
+        frame_requested <= '0';\r
+      end if;\r
+    end if;\r
+  end process THE_FRAME_REQ_PROC;\r
+\r
+  -- EmptyReadAck signal, used to handle a request to RX_RB with no frame to send\r
+  empty_read_ack <= FRAME_REQ_IN and rb_empty when rising_edge(CLK);\r
+  \r
+  -- NormalReadAck signal\r
+  normal_read_ack <= ram_q(8) and fifo_wr_int;\r
+  \r
+  -- read signal\r
+  rd_ram    <= '1' when ((frame_requested = '1') and (ram_q(8) = '0') and (FIFO_FULL_IN = '0') and (rb_empty = '0')) else '0';\r
+  ce_rd_ptr <= '1' when ((frame_requested = '1') and (ram_q(8) = '0') and (FIFO_FULL_IN = '0') and (rb_empty = '0')) else '0';\r
+  \r
+  sof_int <= FRAME_REQ_IN and not frame_requested when rising_edge(CLK);\r
+  \r
+  FRAME_ACK_OUT <= normal_read_ack or empty_read_ack;\r
+  \r
+  FRAME_START_OUT <= sof_int;\r
+  \r
+  FIFO_Q_OUT <= ram_q;\r
+  \r
+  fifo_wr_int <= rd_ram when rising_edge(CLK);\r
+   \r
+  FIFO_WR_OUT <= fifo_wr_int;\r
+  \r
+  -- FramesAvailable counter\r
+  THE_FRAMES_AVAIL_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        frames_avail <= (others => '0');\r
+      elsif( (STATE = FRAME_OK) and (normal_read_ack = '0') ) then\r
+        -- one frame written successfully\r
+        frames_avail <= frames_avail + 1;\r
+      elsif( (STATE /= FRAME_OK) and (normal_read_ack = '1') ) then\r
+        -- one frame read successfully\r
+        frames_avail <= frames_avail - 1;\r
+      end if;\r
+    end if;\r
+  end process THE_FRAMES_AVAIL_PROC;\r
+  \r
+  FRAME_AVAIL_OUT <= '1' when (frames_avail /= x"00") else '0';\r
+\r
+  -----------------------------------------------------------\r
+  -- statemachine: clocked process\r
+  -----------------------------------------------------------\r
+  THE_FSM: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if( RESET = '1' ) then\r
+        STATE <= RX_DENY;\r
+      else\r
+        STATE <= NEXT_STATE;\r
+      end if;\r
+    end if;\r
+  end process THE_FSM;\r
+\r
+  THE_STATE_TRANSITIONS: process( STATE, MAC_RX_WR_IN, MAC_RX_EOF_IN, MAC_RX_ERROR_IN, frame_active, rb_full )\r
+  begin\r
+    ld_wr_ptr <= '0';\r
+    \r
+    case STATE is\r
+\r
+      when RX_DENY =>\r
+        if( (frame_active = '0') and (rb_full = '0') ) then\r
+          NEXT_STATE <= RX_READY;\r
+        else\r
+          NEXT_STATE <= RX_DENY;\r
+        end if;\r
+      \r
+      when RX_READY =>\r
+        if( MAC_RX_WR_IN = '1' ) then\r
+          NEXT_STATE <= RX_FRAME;\r
+        else\r
+          NEXT_STATE <= RX_READY;\r
+        end if;\r
+        \r
+      when RX_FRAME =>\r
+        if   ( (MAC_RX_EOF_IN = '1') and (MAC_RX_ERROR_IN = '0') and (rb_full = '0') ) then\r
+          NEXT_STATE <= FRAME_OK;\r
+        elsif( (MAC_RX_EOF_IN = '1') and ((MAC_RX_ERROR_IN = '1') or (rb_full = '1')) ) then\r
+          NEXT_STATE <= FRAME_BAD;\r
+          ld_wr_ptr <= '1';\r
+        else\r
+          NEXT_STATE <= RX_FRAME;\r
+        end if;\r
+      \r
+      when FRAME_OK =>\r
+        NEXT_STATE <= FORWARD;\r
+        \r
+      when FORWARD =>\r
+        if( rb_full = '0' ) then\r
+          NEXT_STATE <= RX_READY;\r
+        else\r
+          NEXT_STATE <= RX_DENY;\r
+        end if;\r
+\r
+      when FRAME_BAD =>\r
+        NEXT_STATE <= SKIP;\r
+        \r
+      when SKIP =>\r
+        if( rb_full = '0' ) then\r
+          NEXT_STATE <= RX_READY;\r
+        else\r
+          NEXT_STATE <= RX_DENY;\r
+        end if;\r
+\r
+      when others  =>\r
+        NEXT_STATE <= RX_DENY;\r
+    end case;\r
+  end process THE_STATE_TRANSITIONS;\r
+\r
+end architecture;\r
diff --git a/gbe_trb/base/scatter_ports.vhd b/gbe_trb/base/scatter_ports.vhd
new file mode 100644 (file)
index 0000000..9e9c24b
--- /dev/null
@@ -0,0 +1,96 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+\r
+entity scatter_ports is\r
+  port(\r
+    CLK                 : in  std_logic;\r
+    RESET               : in  std_logic;\r
+    --\r
+    FIFO_FULL_IN        : in  std_logic_vector(15 downto 0) := (others => '0');\r
+    FIFO_FULL_OUT       : out std_logic;\r
+    FRAME_AVAIL_IN      : in  std_logic := '0';\r
+    FRAME_REQ_OUT       : out std_logic;\r
+    FRAME_ACK_IN        : in  std_logic := '0';\r
+    CYCLE_DONE_OUT      : out std_logic;\r
+    --\r
+    DEBUG               : out std_logic_vector(15 downto 0)\r
+  );\r
+end entity scatter_ports;\r
+\r
+architecture scatter_ports_arch of scatter_ports is\r
+\r
+-- Components\r
+\r
+-- state machine signals\r
+  type state_t is (IDLE, DO_PORT, DELAY, CLEANUP);\r
+  signal STATE, NEXT_STATE    : state_t;\r
+\r
+-- Signals\r
+  signal req_int                : std_logic;\r
+  signal req_x                  : std_logic;\r
+\r
+begin\r
+\r
+  CYCLE_DONE_OUT <= '1' when STATE = CLEANUP else '0';\r
+\r
+  FRAME_REQ_OUT <= req_int;\r
+\r
+  FIFO_FULL_OUT <= '0' when FIFO_FULL_IN = x"0000" else '1';\r
+  \r
+  -----------------------------------------------------------\r
+  -- statemachine: clocked process\r
+  -----------------------------------------------------------\r
+  THE_FSM: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if( RESET = '1' ) then\r
+        STATE <= IDLE;\r
+        req_int <= '0';\r
+      else\r
+        STATE <= NEXT_STATE;\r
+        req_int <= req_x;\r
+      end if;\r
+    end if;\r
+  end process THE_FSM;\r
+\r
+  THE_STATE_TRANSITIONS: process( STATE, FRAME_AVAIL_IN, FRAME_ACK_IN )\r
+  begin\r
+    req_x <= '0';\r
+\r
+    case STATE is\r
+\r
+      when IDLE =>\r
+        if( FRAME_AVAIL_IN = '1' ) then\r
+          NEXT_STATE <= DO_PORT;\r
+          req_x <= '1';\r
+        else\r
+          NEXT_STATE <= IDLE;\r
+        end if;\r
+\r
+      when DO_PORT =>\r
+        if( FRAME_ACK_IN = '1' ) then\r
+          NEXT_STATE <= DELAY;\r
+        else\r
+          NEXT_STATE <= DO_PORT;\r
+        end if;\r
+\r
+      when DELAY =>\r
+        NEXT_STATE <= CLEANUP;\r
+\r
+      when CLEANUP =>\r
+        if( FRAME_AVAIL_IN = '1' ) then\r
+          NEXT_STATE <= DO_PORT;\r
+          req_x <= '1';\r
+        else\r
+          NEXT_STATE <= IDLE;\r
+        end if;\r
+\r
+      when others  =>\r
+        NEXT_STATE <= IDLE;\r
+    end case;\r
+  end process THE_STATE_TRANSITIONS;\r
+  \r
+end architecture;\r
diff --git a/gbe_trb/base/tx_fifo.vhd b/gbe_trb/base/tx_fifo.vhd
new file mode 100644 (file)
index 0000000..678143b
--- /dev/null
@@ -0,0 +1,119 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+\r
+entity tx_fifo is\r
+  port(\r
+    CLK               : in  std_logic;\r
+    RESET             : in  std_logic;\r
+    -- MAC interface\r
+    MAC_TX_DATA_OUT   : out std_logic_vector(7 downto 0);\r
+    MAC_TX_READ_IN    : in  std_logic;\r
+    MAC_FIFOEOF_OUT   : out std_logic; -- end of frame marker\r
+    MAC_FIFOEMPTY_OUT : out std_logic; -- must never happen during TX\r
+    MAC_FIFOAVAIL_OUT : out std_logic; -- starts TX process in MAC\r
+    MAC_TX_DONE_IN    : in  std_logic; -- frame sent\r
+    -- FIFO interface\r
+    FIFO_FULL_OUT     : out std_logic;\r
+    FIFO_WR_IN        : in  std_logic;\r
+    FIFO_D_IN         : in  std_logic_vector(8 downto 0);\r
+    -- Link stuff\r
+    FRAME_START_IN    : in  std_logic;\r
+    LINK_ACTIVE_IN    : in  std_logic;\r
+    --\r
+    DEBUG             : out std_logic_vector(15 downto 0)\r
+  );\r
+end entity tx_fifo;\r
+\r
+architecture tx_fifo_arch of tx_fifo is\r
+\r
+-- Components\r
+  component fifo_4k_9\r
+  port(\r
+    DATA        : in  std_logic_vector(8 downto 0); \r
+    CLOCK       : in  std_logic;\r
+    WREN        : in  std_logic; \r
+    RDEN        : in  std_logic;\r
+    RESET       : in  std_logic;\r
+    Q           : out std_logic_vector(8 downto 0);\r
+    EMPTY       : out std_logic; \r
+    FULL        : out std_logic;\r
+    ALMOSTFULL  : out std_logic\r
+  );\r
+  end component fifo_4k_9;\r
+  \r
+-- state machine signals\r
+\r
+-- Signals\r
+  signal frames_avail    : unsigned(7 downto 0);\r
+  signal frame_written   : std_logic;\r
+  signal frame_read      : std_logic;\r
+  signal mac_fifoeof     : std_logic;\r
+  signal mac_tx_read     : std_logic;\r
+  signal frame_active    : std_logic;\r
+  signal fifo_wr         : std_logic;\r
+\r
+begin\r
+\r
+  -- FrameActice signal - used to inhibt acceptance of runt frames\r
+  THE_FRAME_ACTIVE_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        frame_active <= '0';\r
+      elsif( FRAME_START_IN = '1' ) then\r
+        frame_active <= LINK_ACTIVE_IN;\r
+      elsif( frame_written = '1' ) then\r
+        frame_active <= '0';\r
+      end if;\r
+    end if;\r
+  end process THE_FRAME_ACTIVE_PROC;\r
+\r
+  fifo_wr <= FIFO_WR_IN and frame_active;\r
+\r
+  -- TX FIFO storing full outgoing frames\r
+  THE_TX_FIFO: fifo_4k_9\r
+  port map(\r
+    DATA          => FIFO_D_IN,\r
+    CLOCK         => CLK,\r
+    WREN          => fifo_wr,\r
+    RDEN          => MAC_TX_READ_IN,\r
+    RESET         => RESET,\r
+    Q(8)          => mac_fifoeof,\r
+    Q(7 downto 0) => MAC_TX_DATA_OUT,\r
+    EMPTY         => MAC_FIFOEMPTY_OUT, \r
+    FULL          => open,\r
+    ALMOSTFULL    => FIFO_FULL_OUT\r
+  );\r
+  \r
+  MAC_FIFOEOF_OUT <= mac_fifoeof;\r
+\r
+  mac_tx_read <= MAC_TX_READ_IN when rising_edge(CLK);\r
+\r
+  -- one frame written to FIFO\r
+  frame_written <= '1' when (FIFO_D_IN(8) = '1') and (FIFO_WR_IN = '1') and (frame_active = '1') else '0';\r
+\r
+  -- one frame read from FIFO\r
+  frame_read <= '1' when (mac_fifoeof = '1') and (mac_tx_read = '1') else '0';\r
+\r
+  -- FramesAvailable counter\r
+  THE_FRAMES_AVAIL_PROC: process( CLK )\r
+  begin\r
+    if( rising_edge(CLK) ) then\r
+      if   ( RESET = '1' ) then\r
+        frames_avail <= (others => '0');\r
+      elsif( (frame_written = '1') and (frame_read = '0') ) then\r
+        -- one frame written successfully\r
+        frames_avail <= frames_avail + 1;\r
+      elsif( (frame_written = '0') and (frame_read = '1') ) then\r
+        -- one frame read successfully\r
+        frames_avail <= frames_avail - 1;\r
+      end if;\r
+    end if;\r
+  end process THE_FRAMES_AVAIL_PROC;\r
+\r
+  MAC_FIFOAVAIL_OUT <= '1' when (frames_avail /= x"00") else '0';\r
+\r
+end architecture;\r