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
+ FRAME_START_OUT : out std_logic -- StartOfFrame signal\r
);\r
end entity rx_rb;\r
\r
+-- This entity acts as receiv buffer for the new GbE media interface. It connects to the MAC RX ports,\r
+-- and is storing incoming Ethernet frames. \r
+-- Broken frames (indicated by MAC_RX_ERROR_IN) are dropped, and in addition, frames which can't be stored\r
+-- completely (due to potential ring buffer overflow) are also dropped.\r
+-- This entity can forward frames on request by doing "DMA":\r
+-- If a frame is requested by FRAME_REQ_IN, the entity decides if a full frame is available (as shown by\r
+-- FRAME_AVAIL_OUT), in case no data is present, a FRAME_ACK_OUT is generated to avoid deadlocks, but\r
+-- no data is transfered.\r
+-- If a frame can be transfered, FRAME_START_OUT is set for one cycle, and data is written out \r
+-- (handshaking with FIFO_FULL_IN) on FIFO_Q_OUT, with data validated by FIFO_WR_OUT.\r
+-- With the EOF signal (FIFO_Q_OUT(8)) set FRAME_ACK_OUT is also set and the transfer ends.\r
+\r
architecture rx_rb_arch of rx_rb is\r
\r
-- Components\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 rb_used_x : unsigned(11 downto 0);\r
+ signal rb_full_x : std_logic;\r
+ signal rb_empty_x : std_logic;\r
+ signal ce_wr_ptr_x : std_logic;\r
+ signal ld_wr_ptr_x : std_logic;\r
+ signal ce_rd_ptr_x : std_logic;\r
+ signal wr_ram_x : std_logic;\r
+ signal rd_ram_x : 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 frame_acknowledged : 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 normal_read_ack_x : std_logic;\r
signal sof_int : std_logic;\r
signal frames_avail : unsigned(7 downto 0);\r
-\r
-\r
+ signal frame_active : std_logic;\r
+ signal frame_error : std_logic;\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
+ -- when "buffer full" condition is deasserted.\r
+ -- Needs to be extra process, not inside the state machine!\r
THE_FRAME_ACTIVE_PROC: process( CLK )\r
begin\r
if( rising_edge(CLK) ) then\r
end if;\r
end process THE_FRAME_ACTIVE_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_x = '1' ) then\r
+ rd_ptr <= rd_ptr + 1;\r
+ end if;\r
+ end if;\r
+ end process THE_RD_PTR_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
+ elsif( ld_wr_ptr_x = '1' ) then\r
wr_ptr <= unsigned(last_wr_ptr);\r
- elsif( ce_wr_ptr = '1' ) then\r
+ elsif( ce_wr_ptr_x = '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
+ -- 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
- rd_ptr <= (others => '0');\r
- elsif( ce_rd_ptr = '1' ) then\r
- rd_ptr <= rd_ptr + 1;\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_RD_PTR_PROC;\r
+ end process THE_LAST_WR_PTR_PROC;\r
\r
-- ring buffer fill level\r
- rb_used <= wr_ptr - rd_ptr;\r
+ rb_used_x <= 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
+ rb_full_x <= '1' when (rb_used_x(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
+ -- ring buffer empty\r
+ rb_empty_x <= '1' when (rb_used_x(11 downto 0) = b"0000_0000_0000") else '0';\r
\r
- MAC_RX_FIFOFULL_OUT <= rb_full;\r
+ MAC_RX_FIFOFULL_OUT <= rb_full_x;\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
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
+ WE => wr_ram_x,\r
RDCLOCK => CLK,\r
RDCLOCKEN => '1',\r
RESET => RESET,\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
+ -- write signal \r
+ wr_ram_x <= '1' when ((STATE = RX_READY) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) or -- first byte of frame\r
+ ((STATE = RX_FRAME) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) -- all other bytes of frame\r
+ else '0';\r
+ ce_wr_ptr_x <= '1' when ((STATE = RX_READY) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) or\r
+ ((STATE = RX_FRAME) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) \r
+ else '0';\r
\r
+ -- FrameError: catches problem with FIFOFULL during a frame write.\r
+ THE_FRAME_ERROR_PROC: process( CLK )\r
+ begin\r
+ if( rising_edge(CLK) ) then\r
+ if ( RESET = '1' ) then\r
+ frame_error <= '0';\r
+ elsif( (frame_active = '1') and (rb_full_x = '1') and (MAC_RX_WR_IN = '1') ) then\r
+ frame_error <= '1';\r
+ elsif( (frame_active = '0') ) then -- could be better!\r
+ frame_error <= '0';\r
+ end if;\r
+ end if;\r
+ end process THE_FRAME_ERROR_PROC;\r
+ \r
-- FrameReq signal, one pulse only\r
THE_FRAME_REQ_PROC: process( CLK )\r
begin\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 when rising_edge(CLK); -- ADDED 2nd step\r
- normal_read_ack <= ram_q(8) and fifo_wr_int;\r
+ -- NormalReadAck signal: ends a normal data transfer by EOF\r
+ normal_read_ack_x <= 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 when rising_edge(CLK); -- ADDED\r
- \r
- FRAME_START_OUT <= sof_int when rising_edge(CLK); -- ADDED\r
- \r
- FIFO_Q_OUT <= ram_q when rising_edge(CLK); -- ADDED\r
- \r
- fifo_wr_int <= rd_ram when rising_edge(CLK);\r
- \r
- FIFO_WR_OUT <= fifo_wr_int when rising_edge(CLK); -- ADDED\r
+ rd_ram_x <= '1' when ((frame_requested = '1') and (ram_q(8) = '0') and (FIFO_FULL_IN = '0') and (rb_empty_x = '0')) else '0';\r
+ ce_rd_ptr_x <= '1' when ((frame_requested = '1') and (ram_q(8) = '0') and (FIFO_FULL_IN = '0') and (rb_empty_x = '0')) else '0';\r
+\r
+-- THE_SYNC_PROC: process( CLK )\r
+-- begin\r
+ empty_read_ack <= FRAME_REQ_IN and rb_empty_x when rising_edge(CLK);\r
+ sof_int <= FRAME_REQ_IN and not frame_requested when rising_edge(CLK); \r
+ FRAME_START_OUT <= sof_int when rising_edge(CLK);\r
+ fifo_wr_int <= rd_ram_x when rising_edge(CLK);\r
+ FIFO_WR_OUT <= fifo_wr_int when rising_edge(CLK);\r
+ FRAME_ACK_OUT <= normal_read_ack_x or empty_read_ack when rising_edge(CLK); \r
+ FIFO_Q_OUT <= ram_q when rising_edge(CLK);\r
+-- end process THE_SYNC_PROC;\r
\r
-- FramesAvailable counter\r
THE_FRAMES_AVAIL_PROC: process( CLK )\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
+ elsif( (STATE = FRAME_OK) and (normal_read_ack_x = '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
+ elsif( (STATE /= FRAME_OK) and (normal_read_ack_x = '1') ) then\r
-- one frame read successfully\r
frames_avail <= frames_avail - 1;\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
+ THE_STATE_TRANSITIONS: process( STATE, MAC_RX_WR_IN, MAC_RX_EOF_IN, MAC_RX_ERROR_IN, frame_active, rb_full_x )\r
begin\r
- ld_wr_ptr <= '0';\r
+ ld_wr_ptr_x <= '0';\r
\r
case STATE is\r
\r
when RX_DENY =>\r
- if( (frame_active = '0') and (rb_full = '0') ) then\r
+ if( (frame_active = '0') and (rb_full_x = '0') ) then\r
NEXT_STATE <= RX_READY;\r
else\r
NEXT_STATE <= RX_DENY;\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
+ if ( (MAC_RX_EOF_IN = '1') and (MAC_RX_ERROR_IN = '0') and (rb_full_x = '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
+ elsif( (MAC_RX_EOF_IN = '1') and ((MAC_RX_ERROR_IN = '1') or (rb_full_x = '1')) ) then\r
NEXT_STATE <= FRAME_BAD;\r
- ld_wr_ptr <= '1';\r
+ ld_wr_ptr_x <= '1';\r
else\r
NEXT_STATE <= RX_FRAME;\r
end if;\r
NEXT_STATE <= FORWARD;\r
\r
when FORWARD =>\r
- if( rb_full = '0' ) then\r
+ if( rb_full_x = '0' ) then\r
NEXT_STATE <= RX_READY;\r
else\r
NEXT_STATE <= RX_DENY;\r
NEXT_STATE <= SKIP;\r
\r
when SKIP =>\r
- if( rb_full = '0' ) then\r
+ if( rb_full_x = '0' ) then\r
NEXT_STATE <= RX_READY;\r
else\r
NEXT_STATE <= RX_DENY;\r
STATE_OUT => rx_bsm --open
);
- -- "Good" debugging pins
- debug(0) <= pll_lol;
- debug(1) <= rx_cdr_lol;
- debug(2) <= rx_los_low;
- debug(3) <= sd_rx_cv_error(0);
- debug(4) <= lsm_status;
- debug(5) <= tx_pcs_rst;
- debug(6) <= rx_serdes_rst;
- debug(7) <= rx_pcs_rst;
- debug(8) <= link_rx_ready;
- debug(9) <= link_tx_ready;
- debug(10) <= rx_bsm(0); --'0';
- debug(11) <= rx_bsm(1); --'0';
- debug(12) <= rx_bsm(2); --'0';
- debug(13) <= rx_bsm(3); --'0';
- debug(14) <= '0';
- debug(15) <= '0';
- debug(16) <= '0';
- debug(17) <= '0';
- debug(18) <= '0';
- debug(19) <= '0';
- -- "Bad" debugging pins
- debug(20) <= RESET;
- debug(21) <= CLEAR;
- debug(22) <= '0';
- debug(23) <= '0';
- debug(24) <= '0';
- debug(25) <= '0';
- debug(26) <= '0';
- debug(27) <= '0';
- debug(28) <= '0';
- debug(29) <= '0';
- debug(30) <= '0';
- debug(31) <= '0';
- debug(32) <= '0';
- debug(33) <= CLK_125;
-
-- 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 )
D_OUT(1) => rx_serdes_rst_q
);
+-- -- "Good" debugging pins
+ debug(7 downto 0) <= sd_tx_data;
+ debug(15 downto 8) <= sd_rx_data;
+ debug(16) <= sd_tx_kcntl(0);
+ debug(17) <= sd_rx_kcntl(0);
+ debug(18) <= sd_tx_correct_disp(0);
+ debug(19) <= sd_rx_disp_error(0);
+ -- "Bad" debugging pins
+ debug(20) <= pcs_tx_en;
+ debug(21) <= pcs_rx_en;
+ debug(22) <= '0';
+ debug(23) <= '0';
+ debug(24) <= '0';
+ debug(25) <= '0';
+ debug(26) <= '0';
+ debug(27) <= '0';
+ debug(28) <= '0';
+ debug(29) <= '0';
+ debug(30) <= '0';
+ debug(31) <= '0';
+ debug(32) <= sd_rx_clk;
+ debug(33) <= CLK_125;
+
-- SGMII core
SGMII_GBE_PCS : sgmii_gbe_core
port map(
FRAME_REQ_IN => FRAME_REQ_IN,
FRAME_ACK_OUT => FRAME_ACK_OUT,
FRAME_AVAIL_OUT => FRAME_AVAIL_OUT,
- FRAME_START_OUT => FRAME_START_OUT,
- --
- DEBUG => open
+ FRAME_START_OUT => FRAME_START_OUT
);
-- TX FIFO
FIFO_D_IN => FIFO_DATA_IN,
-- Link stuff
FRAME_START_IN => FRAME_START_IN,
- LINK_ACTIVE_IN => link_active,
- --
- DEBUG => open
+ LINK_ACTIVE_IN => link_active
);
FIFO_FULL_OUT <= fifo_full_i;
-- debug(32) <= '0';
-- debug(33) <= CLK_125;
+-- -- "Good" debugging pins
+-- debug(0) <= pll_lol;
+-- debug(1) <= rx_cdr_lol;
+-- debug(2) <= rx_los_low;
+-- debug(3) <= sd_rx_cv_error(0);
+-- debug(4) <= lsm_status;
+-- debug(5) <= tx_pcs_rst;
+-- debug(6) <= rx_serdes_rst;
+-- debug(7) <= rx_pcs_rst;
+-- debug(8) <= link_rx_ready;
+-- debug(9) <= link_tx_ready;
+-- debug(10) <= rx_bsm(0); --'0';
+-- debug(11) <= rx_bsm(1); --'0';
+-- debug(12) <= rx_bsm(2); --'0';
+-- debug(13) <= rx_bsm(3); --'0';
+-- debug(14) <= '0';
+-- debug(15) <= '0';
+-- debug(16) <= '0';
+-- debug(17) <= '0';
+-- debug(18) <= '0';
+-- debug(19) <= '0';
+-- -- "Bad" debugging pins
+-- debug(20) <= RESET;
+-- debug(21) <= CLEAR;
+-- debug(22) <= '0';
+-- debug(23) <= '0';
+-- debug(24) <= '0';
+-- debug(25) <= '0';
+-- debug(26) <= '0';
+-- debug(27) <= '0';
+-- debug(28) <= '0';
+-- debug(29) <= '0';
+-- debug(30) <= '0';
+-- debug(31) <= '0';
+-- debug(32) <= '0';
+-- debug(33) <= CLK_125;
+
-- -- "Good" debugging pins
-- debug(7 downto 0) <= pcs_txd;
-- debug(15 downto 8) <= pcs_rxd;