]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
first scatter/gather modules
authorMichael Boehmer <mboehmer@ph.tum.de>
Fri, 8 Jul 2022 13:16:18 +0000 (15:16 +0200)
committerMichael Boehmer <mboehmer@ph.tum.de>
Fri, 8 Jul 2022 13:16:18 +0000 (15:16 +0200)
gbe_trb_ecp3/base/gather_ports.vhd [new file with mode: 0644]
gbe_trb_ecp3/base/rx_rb.vhd
gbe_trb_ecp3/base/scatter_ports.vhd [new file with mode: 0644]
gbe_trb_ecp3/base/tx_fifo.vhd

diff --git a/gbe_trb_ecp3/base/gather_ports.vhd b/gbe_trb_ecp3/base/gather_ports.vhd
new file mode 100644 (file)
index 0000000..18eedb6
--- /dev/null
@@ -0,0 +1,176 @@
+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
+    CLEAR               : 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);
+  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, CLEAR )\r
+    begin\r
+      if( CLEAR = '1' ) then\r
+        stored_ports(I) <= '0';\r
+      elsif( rising_edge(CLK) ) then\r
+        if( 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, CLEAR )\r
+  begin\r
+    if( CLEAR = '1' ) then\r
+      select_ports <= (others => '0');\r
+    elsif( rising_edge(CLK) ) then\r
+      select_ports <= next_port_x;\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
+      next_port_x <= x"0002";
+    elsif( stored_ports(2) = '1' ) then
+      next_port_x <= x"0004";
+    elsif( stored_ports(3) = '1' ) then
+      next_port_x <= x"0008";
+    elsif( stored_ports(4) = '1' ) then
+      next_port_x <= x"0010";
+    elsif( stored_ports(5) = '1' ) then
+      next_port_x <= x"0020";
+    elsif( stored_ports(6) = '1' ) then
+      next_port_x <= x"0040";
+    elsif( stored_ports(7) = '1' ) then
+      next_port_x <= x"0080";
+    elsif( stored_ports(8) = '1' ) then
+      next_port_x <= x"0100";
+    elsif( stored_ports(9) = '1' ) then
+      next_port_x <= x"0200";
+    elsif( stored_ports(10) = '1' ) then
+      next_port_x <= x"0400";
+    elsif( stored_ports(11) = '1' ) then
+      next_port_x <= x"0800";
+    elsif( stored_ports(12) = '1' ) then
+      next_port_x <= x"1000";
+    elsif( stored_ports(13) = '1' ) then
+      next_port_x <= x"2000";
+    elsif( stored_ports(14) = '1' ) then
+      next_port_x <= x"4000";
+    elsif( stored_ports(15) = '1' ) then
+      next_port_x <= x"8000";\r
+    else\r
+      next_port_x <= x"0000";
+    end if;
+  end process THE_NEXT_PORT_PROC;\r
+\r
+  -----------------------------------------------------------\r
+  -- statemachine: clocked process\r
+  -----------------------------------------------------------\r
+  THE_FSM: process( CLK, CLEAR )\r
+  begin\r
+    if   ( CLEAR = '1' ) then\r
+      STATE <= IDLE;\r
+    elsif( rising_edge(CLK) ) then\r
+      STATE <= NEXT_STATE;\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
+\r
+\r
+end architecture;\r
index 6d1763cf3d9800bba3328b21a0078a84b9b75e43..dd0a413dfeb6c8b051e3e0007c76ef0707f4d9a0 100644 (file)
@@ -22,6 +22,7 @@ entity rx_rb is
     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
@@ -67,7 +68,7 @@ architecture rx_rb_arch of rx_rb is
   signal fifo_wr_int     : std_logic;\r
   signal empty_read_ack  : std_logic;\r
   signal normal_read_ack : std_logic;\r
-  \r
+  signal sof_int         : std_logic;\r
   signal frames_avail    : unsigned(7 downto 0);\r
 \r
 \r
@@ -186,8 +187,12 @@ begin
   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
diff --git a/gbe_trb_ecp3/base/scatter_ports.vhd b/gbe_trb_ecp3/base/scatter_ports.vhd
new file mode 100644 (file)
index 0000000..181c201
--- /dev/null
@@ -0,0 +1,93 @@
+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
+    CLEAR               : in  std_logic;\r
+    RESET               : in  std_logic;\r
+    --\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
+  FRAME_REQ_OUT <= req_int;\r
+\r
+  -----------------------------------------------------------\r
+  -- statemachine: clocked process\r
+  -----------------------------------------------------------\r
+  THE_FSM: process( CLK, CLEAR )\r
+  begin\r
+    if   ( CLEAR = '1' ) then\r
+      STATE <= IDLE;\r
+      req_int <= '0';\r
+    elsif( rising_edge(CLK) ) then\r
+      STATE <= NEXT_STATE;\r
+      req_int <= req_x;\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
+\r
+\r
+end architecture;\r
index bcf8d7be45501286bc10f256f91fa209d7946b09..e406353f8ea460712796a9f4e36412f77f395b00 100644 (file)
@@ -20,6 +20,9 @@ entity tx_fifo is
     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
@@ -42,6 +45,23 @@ architecture tx_fifo_arch of tx_fifo is
   );\r
   end component fifo_4k_9;\r
 \r
+--  component fifo_4k_9\r
+--  port(\r
+--    DATA        : in  std_logic_vector(8 downto 0); \r
+--    WRCLOCK     : in  std_logic;\r
+--    RDCLOCK     : in  std_logic;\r
+--    WREN        : in  std_logic; \r
+--    RDEN        : in  std_logic;\r
+--    RESET       : in  std_logic;\r
+--    RPRESET     : in  std_logic; \r
+--    Q           : out std_logic_vector(8 downto 0);\r
+--    EMPTY       : out std_logic; \r
+--    FULL        : out std_logic;\r
+--    ALMOSTEMPTY : out std_logic; \r
+--    ALMOSTFULL  : out std_logic\r
+--  );\r
+--  end component fifo_4k_9;\r
+  \r
 -- state machine signals\r
 \r
 -- Signals\r
@@ -50,15 +70,33 @@ architecture tx_fifo_arch of tx_fifo is
   signal frame_read      : std_logic;\r
   signal mac_fifoeof     : std_logic;\r
   signal mac_tx_read     : std_logic;\r
-  \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, CLEAR )\r
+  begin\r
+    if( CLEAR = '1' ) then\r
+      frame_active <= '0';\r
+    elsif( rising_edge(CLK) ) then\r
+      if   ( 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_IN,\r
+    WREN          => fifo_wr, --FIFO_WR_IN,\r
     RDEN          => MAC_TX_READ_IN,\r
     RESET         => CLEAR,\r
     Q(8)          => mac_fifoeof,\r
@@ -67,13 +105,31 @@ begin
     FULL          => open,\r
     ALMOSTFULL    => FIFO_FULL_OUT\r
   );\r
-    \r
+\r
+--  -- TX FIFO storing full outgoing frames\r
+--  THE_TX_FIFO: fifo_4k_9\r
+--  port map(\r
+--    DATA          => FIFO_D_IN,\r
+--    WRCLOCK       => CLK,\r
+--    RDCLOCK       => CLK,\r
+--    WREN          => fifo_wr, --FIFO_WR_IN,\r
+--    RDEN          => MAC_TX_READ_IN,\r
+--    RESET         => CLEAR,\r
+--    RPRESET       => CLEAR, \r
+--    Q(8)          => mac_fifoeof,\r
+--    Q(7 downto 0) => MAC_TX_DATA_OUT,\r
+--    EMPTY         => MAC_FIFOEMPTY_OUT, \r
+--    FULL          => open,\r
+--    ALMOSTEMPTY   => 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') else '0';\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