From: Michael Boehmer Date: Fri, 8 Jul 2022 13:16:18 +0000 (+0200) Subject: first scatter/gather modules X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=1221df166bf65229489762d16ce823d04e73742d;p=trbnet.git first scatter/gather modules --- diff --git a/gbe_trb_ecp3/base/gather_ports.vhd b/gbe_trb_ecp3/base/gather_ports.vhd new file mode 100644 index 0000000..18eedb6 --- /dev/null +++ b/gbe_trb_ecp3/base/gather_ports.vhd @@ -0,0 +1,176 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; + +entity gather_ports is + port( + CLK : in std_logic; + CLEAR : in std_logic; + RESET : in std_logic; + -- + FRAME_AVAIL_IN : in std_logic_vector(15 downto 0) := (others => '0'); + FRAME_REQ_OUT : out std_logic_vector(15 downto 0); + FRAME_ACK_IN : in std_logic_vector(15 downto 0) := (others => '0'); + PORT_SELECT_OUT : out std_logic_vector(15 downto 0); + CYCLE_DONE_OUT : out std_logic; + -- + DEBUG : out std_logic_vector(15 downto 0) + ); +end entity gather_ports; + +architecture gather_ports_arch of gather_ports is + +-- Components + +-- state machine signals + type state_t is (IDLE, STORE, DO_PORTS, DELAY, CLEANUP); + signal STATE, NEXT_STATE : state_t; + +-- Signals + signal gather_needed_x : std_logic; + signal store_ports_x : std_logic; + signal all_ports_done_x : std_logic; + signal stored_ports : std_logic_vector(15 downto 0); + signal next_port_x : std_logic_vector(15 downto 0); + signal select_ports : std_logic_vector(15 downto 0); + signal req_ports : std_logic_vector(15 downto 0); + +begin + + -- we need to start a gather cycle if any src port has frames available + gather_needed_x <= '1' when FRAME_AVAIL_IN /= x"0000" else '0'; + + -- store the src port status + GEN_REGS: for I in 0 to 15 generate + THE_SRC_STORE_PROC: process( CLK, CLEAR ) + begin + if( CLEAR = '1' ) then + stored_ports(I) <= '0'; + elsif( rising_edge(CLK) ) then + if( store_ports_x = '1' ) then + stored_ports(I) <= FRAME_AVAIL_IN(I); + elsif( FRAME_ACK_IN(I) = '1' ) then + stored_ports(I) <= '0'; + end if; + end if; + end process THE_SRC_STORE_PROC; + end generate; + + all_ports_done_x <= '1' when stored_ports = x"0000" else '0'; + + -- select the port data + THE_SELECT_PORT_PROC: process( CLK, CLEAR ) + begin + if( CLEAR = '1' ) then + select_ports <= (others => '0'); + elsif( rising_edge(CLK) ) then + select_ports <= next_port_x; + end if; + end process THE_SELECT_PORT_PROC; + + PORT_SELECT_OUT <= select_ports; + + -- port frame request, one clock cycle pulse + req_ports <= not select_ports and next_port_x when rising_edge(CLK); + + FRAME_REQ_OUT <= req_ports; + + CYCLE_DONE_OUT <= '1' when STATE = CLEANUP else '0'; + + -- priority decoced "next port to serve" signals + THE_NEXT_PORT_PROC: process( stored_ports ) + begin + if ( stored_ports(0) = '1' ) then + next_port_x <= x"0001"; + 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"; + else + next_port_x <= x"0000"; + end if; + end process THE_NEXT_PORT_PROC; + + ----------------------------------------------------------- + -- statemachine: clocked process + ----------------------------------------------------------- + THE_FSM: process( CLK, CLEAR ) + begin + if ( CLEAR = '1' ) then + STATE <= IDLE; + elsif( rising_edge(CLK) ) then + STATE <= NEXT_STATE; + end if; + end process THE_FSM; + + THE_STATE_TRANSITIONS: process( STATE, gather_needed_x, all_ports_done_x ) + begin + store_ports_x <= '0'; + + case STATE is + + when IDLE => + if( gather_needed_x = '1' ) then + NEXT_STATE <= STORE; + store_ports_x <= '1'; + else + NEXT_STATE <= IDLE; + end if; + + when STORE => + NEXT_STATE <= DO_PORTS; + + when DO_PORTS => + if( all_ports_done_x = '1' ) then + NEXT_STATE <= DELAY; + else + NEXT_STATE <= DO_PORTS; + end if; + + when DELAY => + NEXT_STATE <= CLEANUP; + + when CLEANUP => + if( gather_needed_x = '1' ) then + NEXT_STATE <= STORE; + store_ports_x <= '1'; + else + NEXT_STATE <= IDLE; + end if; + + when others => + NEXT_STATE <= IDLE; + end case; + end process THE_STATE_TRANSITIONS; + + + +end architecture; diff --git a/gbe_trb_ecp3/base/rx_rb.vhd b/gbe_trb_ecp3/base/rx_rb.vhd index 6d1763c..dd0a413 100644 --- a/gbe_trb_ecp3/base/rx_rb.vhd +++ b/gbe_trb_ecp3/base/rx_rb.vhd @@ -22,6 +22,7 @@ entity rx_rb is FRAME_REQ_IN : in std_logic; -- one pulse starts readout of frame stored in ring buffer FRAME_ACK_OUT : out std_logic; -- one pulse for "end of frame" FRAME_AVAIL_OUT : out std_logic; -- number of frames stored in ring buffer + FRAME_START_OUT : out std_logic; -- StartOfFrame signal -- DEBUG : out std_logic_vector(15 downto 0) ); @@ -67,7 +68,7 @@ architecture rx_rb_arch of rx_rb is signal fifo_wr_int : std_logic; signal empty_read_ack : std_logic; signal normal_read_ack : std_logic; - + signal sof_int : std_logic; signal frames_avail : unsigned(7 downto 0); @@ -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'; ce_rd_ptr <= '1' when ((frame_requested = '1') and (ram_q(8) = '0') and (FIFO_FULL_IN = '0') and (rb_empty = '0')) else '0'; + sof_int <= FRAME_REQ_IN and not frame_requested when rising_edge(CLK); + FRAME_ACK_OUT <= normal_read_ack or empty_read_ack; + FRAME_START_OUT <= sof_int; + FIFO_Q_OUT <= ram_q; fifo_wr_int <= rd_ram when rising_edge(CLK); diff --git a/gbe_trb_ecp3/base/scatter_ports.vhd b/gbe_trb_ecp3/base/scatter_ports.vhd new file mode 100644 index 0000000..181c201 --- /dev/null +++ b/gbe_trb_ecp3/base/scatter_ports.vhd @@ -0,0 +1,93 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; + +entity scatter_ports is + port( + CLK : in std_logic; + CLEAR : in std_logic; + RESET : in std_logic; + -- + FRAME_AVAIL_IN : in std_logic := '0'; + FRAME_REQ_OUT : out std_logic; + FRAME_ACK_IN : in std_logic := '0'; + CYCLE_DONE_OUT : out std_logic; + -- + DEBUG : out std_logic_vector(15 downto 0) + ); +end entity scatter_ports; + +architecture scatter_ports_arch of scatter_ports is + +-- Components + +-- state machine signals + type state_t is (IDLE, DO_PORT, DELAY, CLEANUP); + signal STATE, NEXT_STATE : state_t; + +-- Signals + signal req_int : std_logic; + signal req_x : std_logic; + +begin + + CYCLE_DONE_OUT <= '1' when STATE = CLEANUP else '0'; + + FRAME_REQ_OUT <= req_int; + + ----------------------------------------------------------- + -- statemachine: clocked process + ----------------------------------------------------------- + THE_FSM: process( CLK, CLEAR ) + begin + if ( CLEAR = '1' ) then + STATE <= IDLE; + req_int <= '0'; + elsif( rising_edge(CLK) ) then + STATE <= NEXT_STATE; + req_int <= req_x; + end if; + end process THE_FSM; + + THE_STATE_TRANSITIONS: process( STATE, FRAME_AVAIL_IN, FRAME_ACK_IN ) + begin + req_x <= '0'; + + case STATE is + + when IDLE => + if( FRAME_AVAIL_IN = '1' ) then + NEXT_STATE <= DO_PORT; + req_x <= '1'; + else + NEXT_STATE <= IDLE; + end if; + + when DO_PORT => + if( FRAME_ACK_IN = '1' ) then + NEXT_STATE <= DELAY; + else + NEXT_STATE <= DO_PORT; + end if; + + when DELAY => + NEXT_STATE <= CLEANUP; + + when CLEANUP => + if( FRAME_AVAIL_IN = '1' ) then + NEXT_STATE <= DO_PORT; + req_x <= '1'; + else + NEXT_STATE <= IDLE; + end if; + + when others => + NEXT_STATE <= IDLE; + end case; + end process THE_STATE_TRANSITIONS; + + + +end architecture; diff --git a/gbe_trb_ecp3/base/tx_fifo.vhd b/gbe_trb_ecp3/base/tx_fifo.vhd index bcf8d7b..e406353 100644 --- a/gbe_trb_ecp3/base/tx_fifo.vhd +++ b/gbe_trb_ecp3/base/tx_fifo.vhd @@ -20,6 +20,9 @@ entity tx_fifo is FIFO_FULL_OUT : out std_logic; FIFO_WR_IN : in std_logic; FIFO_D_IN : in std_logic_vector(8 downto 0); + -- Link stuff + FRAME_START_IN : in std_logic; + LINK_ACTIVE_IN : in std_logic; -- DEBUG : out std_logic_vector(15 downto 0) ); @@ -42,6 +45,23 @@ architecture tx_fifo_arch of tx_fifo is ); end component fifo_4k_9; +-- component fifo_4k_9 +-- port( +-- DATA : in std_logic_vector(8 downto 0); +-- WRCLOCK : in std_logic; +-- RDCLOCK : in std_logic; +-- WREN : in std_logic; +-- RDEN : in std_logic; +-- RESET : in std_logic; +-- RPRESET : in std_logic; +-- Q : out std_logic_vector(8 downto 0); +-- EMPTY : out std_logic; +-- FULL : out std_logic; +-- ALMOSTEMPTY : out std_logic; +-- ALMOSTFULL : out std_logic +-- ); +-- end component fifo_4k_9; + -- state machine signals -- Signals @@ -50,15 +70,33 @@ architecture tx_fifo_arch of tx_fifo is signal frame_read : std_logic; signal mac_fifoeof : std_logic; signal mac_tx_read : std_logic; - + signal frame_active : std_logic; + signal fifo_wr : std_logic; + begin + -- FrameActice signal - used to inhibt acceptance of runt frames + THE_FRAME_ACTIVE_PROC: process( CLK, CLEAR ) + begin + if( CLEAR = '1' ) then + frame_active <= '0'; + elsif( rising_edge(CLK) ) then + if ( FRAME_START_IN = '1' ) then + frame_active <= LINK_ACTIVE_IN; + elsif( frame_written = '1' ) then + frame_active <= '0'; + end if; + end if; + end process THE_FRAME_ACTIVE_PROC; + + fifo_wr <= FIFO_WR_IN and frame_active; + -- TX FIFO storing full outgoing frames THE_TX_FIFO: fifo_4k_9 port map( DATA => FIFO_D_IN, CLOCK => CLK, - WREN => FIFO_WR_IN, + WREN => fifo_wr, --FIFO_WR_IN, RDEN => MAC_TX_READ_IN, RESET => CLEAR, Q(8) => mac_fifoeof, @@ -67,13 +105,31 @@ begin FULL => open, ALMOSTFULL => FIFO_FULL_OUT ); - + +-- -- TX FIFO storing full outgoing frames +-- THE_TX_FIFO: fifo_4k_9 +-- port map( +-- DATA => FIFO_D_IN, +-- WRCLOCK => CLK, +-- RDCLOCK => CLK, +-- WREN => fifo_wr, --FIFO_WR_IN, +-- RDEN => MAC_TX_READ_IN, +-- RESET => CLEAR, +-- RPRESET => CLEAR, +-- Q(8) => mac_fifoeof, +-- Q(7 downto 0) => MAC_TX_DATA_OUT, +-- EMPTY => MAC_FIFOEMPTY_OUT, +-- FULL => open, +-- ALMOSTEMPTY => open, +-- ALMOSTFULL => FIFO_FULL_OUT +-- ); + MAC_FIFOEOF_OUT <= mac_fifoeof; mac_tx_read <= MAC_TX_READ_IN when rising_edge(CLK); -- one frame written to FIFO - frame_written <= '1' when (FIFO_D_IN(8) = '1') and (FIFO_WR_IN = '1') else '0'; + frame_written <= '1' when (FIFO_D_IN(8) = '1') and (FIFO_WR_IN = '1') and (frame_active = '1') else '0'; -- one frame read from FIFO frame_read <= '1' when (mac_fifoeof = '1') and (mac_tx_read = '1') else '0';