]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
New entity for forwarding only full packets from SerDes to media interface.
authorhadaq <hadaq>
Fri, 9 Jul 2010 07:51:59 +0000 (07:51 +0000)
committerhadaq <hadaq>
Fri, 9 Jul 2010 07:51:59 +0000 (07:51 +0000)
Written to workaround the "MDC I sparking kills da optical link" problem.
Not suitable for real fibre links (2GB), as it also does 25MHz/100MHz conversion
as well as 8b/16b by FIFO.

trb_net16_rx_packets.vhd [new file with mode: 0755]

diff --git a/trb_net16_rx_packets.vhd b/trb_net16_rx_packets.vhd
new file mode 100755 (executable)
index 0000000..d60aa37
--- /dev/null
@@ -0,0 +1,456 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+use work.trb_net_std.all;\r
+--use work.trb_net_components.all;\r
+\r
+entity trb_net16_rx_packets is\r
+port(\r
+       -- Resets\r
+       RESET_IN              : in  std_logic;\r
+       QUAD_RST_IN           : in  std_logic;\r
+       -- data stream from SerDes\r
+       CLK_IN                : in  std_logic; -- SerDes RX clock\r
+       RX_ALLOW_IN           : in  std_logic;\r
+       RX_DATA_IN            : in  std_logic_vector(7 downto 0);\r
+       RX_K_IN               : in  std_logic;\r
+       -- media interface\r
+       SYSCLK_IN             : in  std_logic; -- 100MHz master clock\r
+       MED_DATA_OUT          : out std_logic_vector(15 downto 0);\r
+       MED_DATAREADY_OUT     : out std_logic;\r
+       MED_READ_IN           : in  std_logic;\r
+       MED_PACKET_NUM_OUT    : out std_logic_vector(2 downto 0);\r
+       -- reset handling\r
+       SEND_RESET_WORDS_OUT  : out std_logic;\r
+       MAKE_TRBNET_RESET_OUT : out std_logic;\r
+       -- Status signals\r
+       LINK_BROKEN_OUT       : out std_logic;\r
+       CLEAR_STATUS_IN       : in  std_logic;\r
+       -- Debug signals\r
+       BSM_OUT               : out std_logic_vector(3 downto 0);\r
+       DBG_OUT               : out std_logic_vector(15 downto 0)\r
+);\r
+end entity trb_net16_rx_packets;\r
+\r
+\r
+architecture behavioral of trb_net16_rx_packets is\r
+\r
+-- components\r
+component trb_net_fifo_8bit_16bit_bram_dualport is\r
+port(\r
+       READ_CLOCK_IN    : in  std_logic;\r
+       WRITE_CLOCK_IN   : in  std_logic;\r
+       READ_ENABLE_IN   : in  std_logic;\r
+       WRITE_ENABLE_IN  : in  std_logic;\r
+       FIFO_GSR_IN      : in  std_logic;\r
+       WRITE_DATA_IN    : in  std_logic_vector(7 downto 0);\r
+       READ_DATA_OUT    : out std_logic_vector(15 downto 0);\r
+       FULL_OUT         : out std_logic;\r
+       EMPTY_OUT        : out std_logic;\r
+       WCNT_OUT         : out std_logic_vector(9 downto 0);\r
+       RCNT_OUT         : out std_logic_vector(8 downto 0)\r
+);\r
+end component trb_net_fifo_8bit_16bit_bram_dualport;\r
+\r
+-- State description:\r
+--\r
+-- IDLE: wait for any data to be written into the FIFO\r
+-- RD1 : first word prefetch\r
+-- RD2 : first word output reg, second word prefetch, wait state for full packet in FIFO\r
+-- RDI : generates initial dataready_out, wait state for handshake of first data word\r
+-- RD3 : second word output reg, third word prefetch, wait state for handshake of second data word\r
+-- RD4 : third word output reg, fourth word prefetch, wait state for handshake of third data word\r
+-- RD5 : fourth word output reg, fifth word prefetch, wait state for handshake of forth data word\r
+--       => decision: continous data stream or stalling as FIFO runs empty!\r
+-- RDO : fifth word output reg, wait state for handshake of fifth data word, can also resume transmission \r
+--       if new data is available in FIFO\r
+-- RDW : fifth word output reg, first word prefetch, wait state for handshake of fifth data word, \r
+--       continue data stream or stall if for complete packet\r
+\r
+-- state declarations\r
+type STATES is (IDLE, RD1, RD2, RDI, RD3, RD4, RD5, RDO, RDW, TOC, CLEAN);\r
+signal CURRENT_STATE, NEXT_STATE: STATES;\r
+\r
+-- normal signals\r
+signal bsm_x                : std_logic_vector(3 downto 0);\r
+signal bsm                  : std_logic_vector(3 downto 0);\r
+signal update_x             : std_logic;\r
+signal med_dataready_x      : std_logic;\r
+signal med_dataready        : std_logic;\r
+signal med_data             : std_logic_vector(15 downto 0);\r
+\r
+signal buf_rx_data          : std_logic_vector(7 downto 0);\r
+signal buf_rx_k             : std_logic;\r
+\r
+signal fifo_wr_en           : std_logic;\r
+signal fifo_rd_en_x         : std_logic;\r
+signal fifo_wr_data         : std_logic_vector(7 downto 0);\r
+signal fifo_rd_data         : std_logic_vector(15 downto 0);\r
+signal fifo_reset           : std_logic;\r
+signal fifo_rcnt_stdlv      : std_logic_vector(8 downto 0);\r
+signal fifo_rcnt            : unsigned(8 downto 0);\r
+signal fifo_rst_x           : std_logic;\r
+signal fifo_rst             : std_logic;\r
+\r
+signal rx_counter           : unsigned(2 downto 0);\r
+\r
+signal is_idle_word         : std_logic;\r
+signal rx_starting          : std_logic;\r
+signal send_reset_words     : std_logic;\r
+signal make_trbnet_reset    : std_logic;\r
+signal reset_word_cnt       : unsigned(4 downto 0);\r
+\r
+signal timeout_ctr          : unsigned(9 downto 0);\r
+signal rst_toc_x            : std_logic;\r
+signal rst_toc              : std_logic;\r
+signal ce_toc_x             : std_logic;\r
+signal ce_toc               : std_logic;\r
+signal toc_done_x           : std_logic;\r
+signal toc_done             : std_logic;\r
+signal link_broken          : std_logic;\r
+\r
+signal debug                : std_logic_vector(15 downto 0);\r
+\r
+begin\r
+\r
+----------------------------------------------------------------------\r
+-- FIFO write process\r
+----------------------------------------------------------------------\r
+THE_WRITE_RX_FIFO_PROC: process( CLK_IN )\r
+begin\r
+       if( rising_edge(CLK_IN) ) then\r
+               buf_rx_data <= RX_DATA_IN;\r
+               buf_rx_k    <= RX_K_IN;\r
+               if( (RESET_IN = '1') or (RX_ALLOW_IN = '0') ) then\r
+                       fifo_wr_en    <= '0';\r
+                       is_idle_word  <= '1';\r
+                       rx_starting   <= '1';\r
+               else\r
+                       fifo_wr_data <= buf_rx_data;\r
+                       if( (buf_rx_k = '0') and (is_idle_word = '0') and (rx_starting = '0') ) then\r
+                               fifo_wr_en <= '1';\r
+                       else\r
+                               fifo_wr_en <= '0';\r
+                       end if;\r
+                       if   ( buf_rx_k = '1' ) then\r
+                               is_idle_word <= '1';\r
+                               rx_starting <= '0';\r
+                       elsif( (buf_rx_k = '0') and (is_idle_word = '1') ) then\r
+                               is_idle_word <= '0';\r
+                       end if;\r
+               end if;\r
+       end if;\r
+end process THE_WRITE_RX_FIFO_PROC;\r
+\r
+----------------------------------------------------------------------\r
+-- TRBnet reset handling\r
+----------------------------------------------------------------------\r
+THE_CNT_RESET_PROC: process( CLK_IN )\r
+begin\r
+       if( rising_edge(CLK_IN) ) then\r
+               if( RESET_IN = '1' ) then\r
+                       send_reset_words  <= '0';\r
+                       make_trbnet_reset <= '0';\r
+                       reset_word_cnt    <= (others => '0');\r
+               else\r
+                       send_reset_words  <= '0';\r
+                       make_trbnet_reset <= '0';\r
+                       if( (buf_rx_data = x"FE") and (buf_rx_k = '1') ) then\r
+                               if( reset_word_cnt(4) = '0' ) then\r
+                                       reset_word_cnt <= reset_word_cnt + 1;\r
+                               else\r
+                                       send_reset_words <= '1';\r
+                               end if;\r
+                       else\r
+                               reset_word_cnt    <= (others => '0');\r
+                               make_trbnet_reset <= reset_word_cnt(4);\r
+                       end if;\r
+               end if;\r
+       end if;\r
+end process;\r
+\r
+----------------------------------------------------------------------\r
+-- the RX FIFO itself\r
+----------------------------------------------------------------------\r
+THE_RX_FIFO: trb_net_fifo_8bit_16bit_bram_dualport\r
+port map(\r
+       READ_CLOCK_IN    => SYSCLK_IN,\r
+       WRITE_CLOCK_IN   => CLK_IN,\r
+       READ_ENABLE_IN   => fifo_rd_en_x,\r
+       WRITE_ENABLE_IN  => fifo_wr_en,\r
+       FIFO_GSR_IN      => fifo_reset,\r
+       WRITE_DATA_IN    => fifo_wr_data,\r
+       READ_DATA_OUT    => fifo_rd_data,\r
+       FULL_OUT         => open,\r
+       EMPTY_OUT        => open,\r
+       WCNT_OUT         => open, -- not needed\r
+       RCNT_OUT         => fifo_rcnt_stdlv\r
+);\r
+\r
+fifo_reset <= RESET_IN or QUAD_RST_IN or not RX_ALLOW_IN or fifo_rst;\r
+\r
+fifo_rcnt  <= unsigned(fifo_rcnt_stdlv);\r
+\r
+----------------------------------------------------------------------\r
+-- RX packet state machine\r
+----------------------------------------------------------------------\r
+-- state registers\r
+STATE_MEM: process( SYSCLK_IN )\r
+begin\r
+       if( rising_edge(SYSCLK_IN) ) then\r
+               if( RESET_IN = '1' ) then\r
+                       CURRENT_STATE <= IDLE;\r
+                       med_dataready <= '0';\r
+                       ce_toc        <= '0';\r
+                       rst_toc       <= '0';\r
+                       fifo_rst      <= '0';\r
+                       bsm           <= (others => '0');\r
+               else\r
+                       CURRENT_STATE <= NEXT_STATE;\r
+                       med_dataready <= med_dataready_x;\r
+                       ce_toc        <= ce_toc_x;\r
+                       rst_toc       <= rst_toc_x;\r
+                       fifo_rst      <= fifo_rst_x;\r
+                       bsm           <= bsm_x;\r
+               end if;\r
+       end if;\r
+end process STATE_MEM;\r
+\r
+-- state transitions\r
+STATE_TRANSFORM: process( CURRENT_STATE, fifo_rcnt, MED_READ_IN, med_dataready, toc_done )\r
+begin\r
+       NEXT_STATE      <= IDLE; -- avoid latches\r
+       fifo_rd_en_x    <= '0';\r
+       med_dataready_x <= '0';\r
+       update_x        <= '0';\r
+       ce_toc_x        <= '0';\r
+       rst_toc_x       <= '0';\r
+       fifo_rst_x      <= '0';\r
+       case CURRENT_STATE is\r
+               when IDLE   =>  if( fifo_rcnt > 0 ) then\r
+                                                       -- we have at least one data word in FIFO, so we prefetch it\r
+                                                       NEXT_STATE   <= RD1; \r
+                                                       fifo_rd_en_x <= '1';\r
+                                                       ce_toc_x     <= '1';\r
+                                               else\r
+                                                       NEXT_STATE   <= IDLE;\r
+                                               end if;\r
+               when RD1    =>  if   ( fifo_rcnt > 1 ) then -- was 0\r
+                                                       -- second data word is available in FIFO, so we prefetch it and \r
+                                                       -- forward the first word to the output register\r
+                                                       NEXT_STATE   <= RD2;\r
+                                                       fifo_rd_en_x <= '1';\r
+                                                       update_x     <= '1';\r
+                                                       ce_toc_x     <= '1';\r
+                                               elsif( toc_done = '1' ) then\r
+                                                       NEXT_STATE   <= TOC;\r
+                                                       rst_toc_x    <= '1';\r
+                                                       fifo_rst_x   <= '1';\r
+                                               else\r
+                                                       NEXT_STATE   <= RD1;\r
+                                                       ce_toc_x     <= '1';\r
+                                               end if;\r
+               when RD2    =>  if   ( fifo_rcnt > 2 ) then\r
+                                                       -- at least all three missing words in FIFO... so we go ahead and notify full packet availability\r
+                                                       NEXT_STATE      <= RDI;\r
+                                                       med_dataready_x <= '1';\r
+                                                       rst_toc_x       <= '1';\r
+                                               elsif( toc_done = '1' ) then\r
+                                                       NEXT_STATE   <= TOC;\r
+                                                       rst_toc_x    <= '1';\r
+                                                       fifo_rst_x   <= '1';\r
+                                               else\r
+                                                       NEXT_STATE      <= RD2;\r
+                                                       ce_toc_x     <= '1';\r
+                                               end if;\r
+               when RDI        =>  med_dataready_x <= '1';\r
+                                               if( MED_READ_IN = '1' ) then\r
+                                                       -- first word of packet has been transfered, update output register and prefetch next data word\r
+                                                       NEXT_STATE      <= RD3;\r
+                                                       fifo_rd_en_x    <= '1';\r
+                                                       update_x        <= '1';\r
+                                               else\r
+                                                       NEXT_STATE <= RDI;\r
+                                               end if;\r
+               when RD3    =>  med_dataready_x <= '1';\r
+                                               if( MED_READ_IN = '1' ) then\r
+                                                       -- second word of packet has been transfered, update output register and prefetch next data word\r
+                                                       NEXT_STATE      <= RD4;\r
+                                                       fifo_rd_en_x    <= '1';\r
+                                                       update_x        <= '1';\r
+                                               else\r
+                                                       NEXT_STATE      <= RD3;\r
+                                               end if;\r
+               when RD4    =>  med_dataready_x <= '1';\r
+                                                       -- third word of packet has been transfered, update output register and prefetch next data word\r
+                                               if( MED_READ_IN = '1' ) then\r
+                                                       NEXT_STATE      <= RD5;\r
+                                                       fifo_rd_en_x    <= '1';\r
+                                                       update_x        <= '1';\r
+                                               else\r
+                                                       NEXT_STATE      <= RD4;\r
+                                               end if;\r
+               when RD5    =>  med_dataready_x <= '1';\r
+                                               -- DANGER. This is the key state for decisions here. \r
+                                               -- There are many ways to do it the wrong way, depending on the FIFO fill level.\r
+                                               if   ( (MED_READ_IN = '1') and (fifo_rcnt < 3) ) then -- was 2, changed due to RCNT latency\r
+                                                       -- fourth word of packet has been transfered, and FIFO has not seen any new packet word.\r
+                                                       -- so we update output register only, no prefetch\r
+                                                       NEXT_STATE      <= RDO;\r
+                                                       update_x        <= '1';\r
+                                               elsif( (MED_READ_IN = '1') and (fifo_rcnt > 2) ) then -- was 1, changed due to RCNT latency\r
+                                                       -- fourth word of packet DONE, new packet data already in the FIFO\r
+                                                       -- so we can prefetch on data word already and update the output register\r
+                                                       NEXT_STATE      <= RDW;\r
+                                                       fifo_rd_en_x    <= '1';\r
+                                                       update_x        <= '1';\r
+                                               else\r
+                                                       NEXT_STATE      <= RD5;\r
+                                               end if;\r
+               when RDO    =>  if   ( (MED_READ_IN = '1') and (fifo_rcnt = 0) ) then\r
+                                                       -- last word of packet has been transfered, and no new data words to handle.\r
+                                                       -- we keep the last transfered word in the output register and wait for new packets to arrive.\r
+                                                       NEXT_STATE      <= IDLE;\r
+                                               elsif( (MED_READ_IN = '1') and (fifo_rcnt > 0) ) then\r
+                                                       -- last word of packet has been transfered, and a new packet data available.\r
+                                                       -- so we enter the prefetch phase again.\r
+                                                       NEXT_STATE      <= RD1;\r
+                                                       fifo_rd_en_x    <= '1';\r
+                                               else\r
+                                                       NEXT_STATE      <= RDO;\r
+                                                       med_dataready_x <= '1';\r
+                                               end if;\r
+               when RDW    =>  if   ( (MED_READ_IN = '1') and (fifo_rcnt > 3) ) then\r
+                                                       -- last word of packet has been transfered, complete packet in FIFO, so we can go ahead.\r
+                                                       NEXT_STATE      <= RDI;\r
+                                                       fifo_rd_en_x    <= '1';\r
+                                                       update_x        <= '1';\r
+                                                       med_dataready_x <= '1';\r
+                                               elsif( (MED_READ_IN = '1') and (fifo_rcnt < 4 ) ) then\r
+                                                       -- last word of packet has been transfered, but new packet not complete yet.\r
+                                                       NEXT_STATE      <= RD2;\r
+                                                       fifo_rd_en_x    <= '1';\r
+                                                       update_x        <= '1';\r
+                                               else\r
+                                                       NEXT_STATE      <= RDW;\r
+                                                       med_dataready_x <= '1'; \r
+                                               end if;\r
+               when TOC    =>  NEXT_STATE <= CLEAN;\r
+                                               fifo_rst_x   <= '1';\r
+               when CLEAN  =>  NEXT_STATE   <= IDLE;\r
+                                                                               \r
+               when others =>  NEXT_STATE <= IDLE;\r
+       end case;\r
+end process STATE_TRANSFORM;\r
+\r
+-- just for debugging\r
+THE_DECODE_PROC: process( NEXT_STATE )\r
+begin\r
+       case NEXT_STATE is\r
+               when IDLE   => bsm_x <= x"0";\r
+               when RD1    => bsm_x <= x"1";\r
+               when RD2    => bsm_x <= x"2";\r
+               when RDI    => bsm_x <= x"3";\r
+               when RD3    => bsm_x <= x"4";\r
+               when RD4    => bsm_x <= x"5";\r
+               when RD5    => bsm_x <= x"6";\r
+               when RDO    => bsm_x <= x"7";\r
+               when RDW    => bsm_x <= x"8";\r
+               when TOC    => bsm_x <= x"9";\r
+               when CLEAN  => bsm_x <= x"a";\r
+               when others => bsm_x <= x"f";\r
+       end case;\r
+end process THE_DECODE_PROC;\r
+\r
+THE_SYNC_PROC: process( SYSCLK_IN )\r
+begin\r
+       if( rising_edge(SYSCLK_IN) ) then\r
+               if( update_x = '1' ) then\r
+                       med_data <= fifo_rd_data;\r
+               end if;\r
+       end if;\r
+end process THE_SYNC_PROC;\r
+\r
+----------------------------------------------------------------------\r
+-- Status bit\r
+----------------------------------------------------------------------\r
+THE_STATUS_BIT_PROC: process( SYSCLK_IN )\r
+begin\r
+       if( rising_edge(SYSCLK_IN) ) then\r
+               if   ( CURRENT_STATE = CLEAN ) then\r
+                       link_broken <= '1';\r
+               elsif( CLEAR_STATUS_IN = '1' ) then\r
+                       link_broken <= '0';\r
+               end if;\r
+       end if;\r
+end process THE_STATUS_BIT_PROC;\r
+\r
+----------------------------------------------------------------------\r
+-- RX packet counter\r
+----------------------------------------------------------------------\r
+THE_RX_PACKETS_PROC: process( SYSCLK_IN )\r
+begin\r
+       if( rising_edge(SYSCLK_IN) ) then\r
+               if( (RESET_IN = '1') or (RX_ALLOW_IN = '0') ) then\r
+                       rx_counter <= unsigned(c_H0);\r
+               else\r
+                       if( (med_dataready = '1') and (MED_READ_IN = '1') ) then -- modified\r
+                               if( rx_counter = unsigned(c_max_word_number) ) then\r
+                                       rx_counter <= (others => '0');\r
+                               else\r
+                                       rx_counter <= rx_counter + 1;\r
+                               end if;\r
+                       end if;\r
+               end if;\r
+       end if;\r
+end process THE_RX_PACKETS_PROC;\r
+\r
+----------------------------------------------------------------------\r
+-- Timeout counter\r
+----------------------------------------------------------------------\r
+THE_TOC_PROC: process( SYSCLK_IN )\r
+begin\r
+       if( rising_edge(SYSCLK_IN) ) then\r
+               toc_done <= toc_done_x;\r
+               if   ( (RESET_IN = '1') or (rst_toc = '1') ) then\r
+                       timeout_ctr <= (others => '0');\r
+               elsif( (ce_toc = '1') and (toc_done = '0') ) then\r
+                       timeout_ctr <= timeout_ctr + 1;\r
+               end if;\r
+       end if;\r
+end process THE_TOC_PROC;\r
+\r
+toc_done_x <= '1' when ( timeout_ctr(9 downto 2) = b"11_1111_11" ) else '0';\r
+\r
+----------------------------------------------------------------------\r
+-- Debug signals\r
+----------------------------------------------------------------------\r
+debug(15)            <= toc_done;\r
+debug(14)            <= ce_toc;\r
+debug(13)            <= rst_toc;\r
+debug(12)            <= fifo_rst;\r
+debug(11 downto 9)   <= (others => '0');\r
+debug(8 downto 0)    <= fifo_rcnt_stdlv;\r
+\r
+--debug(15 downto 8)   <= fifo_rcnt_stdlv(7 downto 0);\r
+--debug(7 downto 2)    <= (others => '0');\r
+--debug(1)             <= update_x;\r
+--debug(0)             <= fifo_rd_en_x;\r
+\r
+----------------------------------------------------------------------\r
+-- Output signals\r
+----------------------------------------------------------------------\r
+SEND_RESET_WORDS_OUT  <= send_reset_words;\r
+MAKE_TRBNET_RESET_OUT <= make_trbnet_reset;\r
+LINK_BROKEN_OUT       <= link_broken;\r
+\r
+MED_DATAREADY_OUT     <= med_dataready;\r
+MED_DATA_OUT          <= med_data;\r
+MED_PACKET_NUM_OUT    <= std_logic_vector(rx_counter);\r
+\r
+BSM_OUT               <= bsm;\r
+DBG_OUT               <= debug;\r
+\r
+end behavioral;
\ No newline at end of file