1------------------------------------------------------------------------------- 2-- Title : Transmission Streamer 3-- Project : WR Streamers 4-- URL : http://www.ohwr.org/projects/wr-cores/wiki/WR_Streamers 5------------------------------------------------------------------------------- 6-- File : xrx_streamer.vhd 7-- Author : Tomasz Wlostowski 8-- Company : CERN BE-CO-HT 9-- Created : 2012-11-02 10-- Platform : FPGA-generic 11-- Standard : VHDL 12------------------------------------------------------------------------------- 13-- Description: A simple core demonstrating how to encapsulate a continuous 14-- stream of data words into Ethernet frames, in a format that is accepted by 15-- the White Rabbit PTP core. This core decodes Ethernet frames encoded by 16-- xtx_streamer. More info in the documentation. 17------------------------------------------------------------------------------- 18-- Copyright (c) 2012-2017 CERN/BE-CO-HT 19-- 20-- This source file is free software; you can redistribute it 21-- and/or modify it under the terms of the GNU Lesser General 22-- Public License as published by the Free Software Foundation; 23-- either version 2.1 of the License, or (at your option) any 24-- later version. 25-- 26-- This source is distributed in the hope that it will be 27-- useful, but WITHOUT ANY WARRANTY; without even the implied 28-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 29-- PURPOSE. See the GNU Lesser General Public License for more 30-- details. 31-- 32-- You should have received a copy of the GNU Lesser General 33-- Public License along with this source; if not, download it 34-- from http://www.gnu.org/licenses/lgpl-2.1.html 35------------------------------------------------------------------------------- 36 37library ieee; 38use ieee.std_logic_1164.all; 39use ieee.numeric_std.all; 40 41use work.wishbone_pkg.all; 42use work.wr_fabric_pkg.all; 43use work.gencores_pkg.all; 44use work.genram_pkg.all; 45use work.streamers_priv_pkg.all; 46use work.streamers_pkg.all; 47 48entity xrx_streamer is 49 50 generic ( 51 -- Width of the data words, must be multiple of 16 bits. This value set to this generic 52 -- on the receviving device must be the same as the value of g_tx_data_width set on the 53 -- transmitting node. The g_rx_data_width and g_tx_data_width can be set to different 54 -- values in the same device (i.e. instantiation of xwr_transmission entity). It is the 55 -- responsibility of a network designer to make sure these parameters are properly set 56 -- in the network. 57 g_data_width : integer := 32; 58 59 -- Size of RX buffer, in data words. 60 g_buffer_size : integer := 256; 61 62 -- DO NOT USE unless you know what you are doing 63 -- legacy: the streamers that were initially used in Btrain did not check/insert 64 -- the escape code. This is justified if only one block of a known number of words is 65 -- sent/expected. 66 g_escape_code_disable : boolean := FALSE; 67 68 -- DO NOT USE unless you know what you are doing 69 -- legacy: the streamers that were initially used in Btrain accepted only a fixed 70 -- number of words, regardless of the frame content. If this generic is set to number 71 -- other than zero, only a fixed number of words is accepted. 72 -- In combination with the g_escape_code_disable generic set to TRUE, the behaviour of 73 -- the "Btrain streamers" can be recreated. 74 g_expected_words_number : integer := 0 75 ); 76 77 port ( 78 clk_sys_i : in std_logic; 79 rst_n_i : in std_logic; 80 81 -- Endpoint/WRC interface 82 snk_i : in t_wrf_sink_in; 83 snk_o : out t_wrf_sink_out; 84 85 --------------------------------------------------------------------------- 86 -- WRC Timing interface, used for latency measurement 87 -- Caution: uses clk_ref_i clock domain! 88 --------------------------------------------------------------------------- 89 90 -- White Rabbit reference clock 91 clk_ref_i : in std_logic := '0'; 92 93 -- Time valid flag 94 tm_time_valid_i : in std_logic := '0'; 95 96 -- TAI seconds 97 tm_tai_i : in std_logic_vector(39 downto 0) := x"0000000000"; 98 99 -- Fractional part of the second (in clk_ref_i cycles) 100 tm_cycles_i : in std_logic_vector(27 downto 0) := x"0000000"; 101 102 --------------------------------------------------------------------------- 103 -- User interface 104 --------------------------------------------------------------------------- 105 106 -- 1 indicates the 1st word of the data block on rx_data_o. 107 rx_first_p1_o : out std_logic; 108 -- 1 indicates the last word of the data block on rx_data_o. 109 rx_last_p1_o : out std_logic; 110 -- Received data. 111 rx_data_o : out std_logic_vector(g_data_width-1 downto 0); 112 -- 1 indicted that rx_data_o is outputting a valid data word. 113 rx_valid_o : out std_logic; 114 -- Synchronous data request input: when 1, the streamer may output another 115 -- data word in the subsequent clock cycle. 116 rx_dreq_i : in std_logic; 117 -- Lost output: 1 indicates that one or more frames or blocks have been lost 118 -- (left for backward compatibility). 119 rx_lost_p1_o : out std_logic := '0'; 120 -- indicates that one or more blocks within frame are missing 121 rx_lost_blocks_p1_o : out std_logic := '0'; 122 -- indicates that one or more frames are missing, the number of frames is provied 123 rx_lost_frames_p1_o : out std_logic := '0'; 124 --number of lost frames, the 0xF...F means that counter overflew 125 rx_lost_frames_cnt_o : out std_logic_vector(14 downto 0); 126 -- Latency measurement output: indicates the transport latency (between the 127 -- TX streamer in remote device and this streamer), in clk_ref_i clock cycles. 128 rx_latency_o : out std_logic_vector(27 downto 0); 129 -- 1 when the latency on rx_latency_o is valid. 130 rx_latency_valid_o : out std_logic; 131 -- received streamer frame (counts all frames, corrupted and not) 132 rx_frame_p1_o : out std_logic; 133 -- configuration 134 rx_streamer_cfg_i : in t_rx_streamer_cfg := c_rx_streamer_cfg_default 135 ); 136 137end xrx_streamer; 138 139architecture rtl of xrx_streamer is 140 141 type t_rx_state is (IDLE, HEADER, FRAME_SEQ_ID, PAYLOAD, SUBFRAME_HEADER, EOF); 142 143 signal fab, fsm_in : t_pipe; 144 145 signal state : t_rx_state; 146 147 signal ser_count : unsigned(7 downto 0); 148 signal seq_no, seq_new,count : unsigned(14 downto 0); 149 150 signal crc_match, crc_en, crc_en_masked, crc_restart : std_logic; 151 152 signal detect_escapes, is_escape : std_logic; 153 signal rx_pending : std_logic; 154 155 signal pack_data, fifo_data : std_logic_vector(g_data_width-1 downto 0); 156 157 signal fifo_drop, fifo_accept, fifo_accept_d0, fifo_dvalid : std_logic; 158 signal fifo_sync, fifo_last, frames_lost, blocks_lost : std_logic; 159 signal fifo_dout, fifo_din : std_logic_vector(g_data_width + 1 downto 0); 160 161 signal pending_write, fab_dvalid_pre : std_logic; 162 163 164 signal tx_tag_cycles, rx_tag_cycles : std_logic_vector(27 downto 0); 165 signal tx_tag_valid, rx_tag_valid : std_logic; 166 167 signal got_next_subframe : std_logic; 168 signal is_frame_seq_id : std_logic; 169 signal word_count : unsigned(11 downto 0); 170 signal sync_seq_no : std_logic; 171 172 -- fixed latency signals 173 type t_rx_delay_state is (DISABLED, DELAY, ALLOW); 174 signal timestamped : std_logic; 175 signal delay_cnt : unsigned(27 downto 0); 176 signal rx_dreq_allow : std_logic; 177 signal rx_latency : unsigned(27 downto 0); 178 signal rx_latency_stored : unsigned(27 downto 0); 179 signal rx_latency_valid : std_logic; 180 signal delay_state : t_rx_delay_state; 181 signal rx_dreq : std_logic; 182 signal is_vlan : std_logic; 183 184 constant c_fixed_latency_zero : unsigned(27 downto 0) := (others => '0'); 185 constant c_timestamper_delay : unsigned(27 downto 0) := to_unsigned(12, 28); -- cycles 186 187begin -- rtl 188 189 U_rx_crc_generator : gc_crc_gen 190 generic map ( 191 g_polynomial => x"1021", 192 g_init_value => x"ffff", 193 g_residue => x"470f", 194 g_data_width => 16, 195 g_sync_reset => 1, 196 g_dual_width => 0, 197 g_registered_match_output => true) 198 port map ( 199 clk_i => clk_sys_i, 200 rst_i => '0', 201 restart_i => crc_restart, 202 en_i => crc_en_masked, 203 data_i => fsm_in.data, 204 half_i => '0', 205 match_o => crc_match); 206 207 crc_en_masked <= crc_en and fsm_in.dvalid; 208 209 U_Fabric_Sink : xwb_fabric_sink 210 port map ( 211 clk_i => clk_sys_i, 212 rst_n_i => rst_n_i, 213 snk_i => snk_i, 214 snk_o => snk_o, 215 addr_o => fab.addr, 216 data_o => fab.data, 217 dvalid_o => fab_dvalid_pre, 218 sof_o => fab.sof, 219 eof_o => fab.eof, 220 error_o => fab.error, 221 bytesel_o => fab.bytesel, 222 dreq_i => fab.dreq); 223 224 fab.dvalid <= '1' when fab_dvalid_pre = '1' and fab.addr = c_WRF_DATA and fab.bytesel = '0' else '0'; 225 gen_escape: if (g_escape_code_disable = FALSE) generate 226 U_Escape_Detect : escape_detector 227 generic map ( 228 g_data_width => 16, 229 g_escape_code => x"cafe") 230 port map ( 231 clk_i => clk_sys_i, 232 rst_n_i => rst_n_i, 233 d_i => fab.data, 234 d_detect_enable_i => detect_escapes, 235 d_valid_i => fab.dvalid, 236 d_req_o => fab.dreq, 237 d_o => fsm_in.data, 238 d_escape_o => is_escape, 239 d_valid_o => fsm_in.dvalid, 240 d_req_i => fsm_in.dreq); 241 end generate gen_escape; 242 gen_no_escape: if (g_escape_code_disable = TRUE) generate 243 fsm_in.dvalid <= fab.dvalid; 244 fsm_in.data <= fab.data; 245 fab.dreq <= fsm_in.dreq; 246 is_escape <= '0'; 247 end generate gen_no_escape; 248 fsm_in.eof <= fab.eof or fab.error; 249 fsm_in.sof <= fab.sof; 250 251 252 U_Output_FIFO : dropping_buffer 253 generic map ( 254 g_size => g_buffer_size, 255 g_data_width => g_data_width + 2) 256 port map ( 257 clk_i => clk_sys_i, 258 rst_n_i => rst_n_i, 259 d_i => fifo_din, 260 d_req_o => fsm_in.dreq, 261 d_drop_i => fifo_drop, 262 d_accept_i => fifo_accept_d0, 263 d_valid_i => fifo_dvalid, 264 d_o => fifo_dout, 265 d_valid_o => rx_valid_o, 266 d_req_i => rx_dreq); 267 268 fifo_din(g_data_width+1) <= fifo_sync; 269 fifo_din(g_data_width) <= fifo_last or 270 ((not pending_write) and is_escape); -- when word is 16 bits 271 fifo_din(g_data_width-1 downto 0) <= fifo_data; 272 273 rx_data_o <= fifo_dout(g_data_width-1 downto 0); 274 rx_first_p1_o <= fifo_dout(g_data_width+1); 275 rx_last_p1_o <= fifo_dout(g_data_width); 276 277 U_RX_Timestamper : pulse_stamper 278 port map ( 279 clk_ref_i => clk_ref_i, 280 clk_sys_i => clk_sys_i, 281 rst_n_i => rst_n_i, 282 pulse_a_i => fsm_in.sof, 283 tm_time_valid_i => tm_time_valid_i, 284 tm_tai_i => tm_tai_i, 285 tm_cycles_i => tm_cycles_i, 286 tag_cycles_o => rx_tag_cycles); 287 288 ------------------------------------------------------------------------------------------- 289 -- fixed latency implementation 290 ------------------------------------------------------------------------------------------- 291 292 -- mask rx_dreq to prevent reception 293 rx_dreq <= rx_dreq_i and rx_dreq_allow; 294 -- produce a pulse when SOF is timestamped, this pulse starts counter in clk_sys clock 295 -- domain 296 U_sync_with_clk : gc_sync_ffs 297 port map ( 298 clk_i => clk_sys_i, 299 rst_n_i => rst_n_i, 300 data_i => fsm_in.sof, 301 synced_o => timestamped); 302 303 -- introduce fixed latency, if configured to do so 304 p_fixed_latency_fsm : process(clk_sys_i) 305 begin 306 if rising_edge(clk_sys_i) then 307 if rst_n_i = '0' then 308 delay_state <= DISABLED; 309 rx_latency_stored <= (others=>'0'); 310 rx_dreq_allow <= '1'; 311 delay_cnt <= c_timestamper_delay; 312 else 313 case delay_state is 314 when DISABLED => 315 if unsigned(rx_streamer_cfg_i.fixed_latency) /= c_fixed_latency_zero then 316 delay_state <= ALLOW; 317 end if; 318 rx_latency_stored <= (others=>'0'); 319 delay_cnt <= c_timestamper_delay; 320 rx_dreq_allow <= '1'; 321 when ALLOW => 322 if unsigned(rx_streamer_cfg_i.fixed_latency) = c_fixed_latency_zero then 323 delay_state <= DISABLED; 324 elsif(rx_latency_valid ='1') then 325 rx_dreq_allow <= '0'; 326 rx_latency_stored <= rx_latency; 327 delay_state <= DELAY; 328 end if; 329 if(timestamped = '1') then 330 delay_cnt <= c_timestamper_delay; 331 else 332 delay_cnt <= delay_cnt + 2; 333 end if; 334 when DELAY => 335 if unsigned(rx_streamer_cfg_i.fixed_latency) <= delay_cnt + rx_latency_stored then 336 rx_latency_stored <= (others=>'0'); 337 rx_dreq_allow <= '1'; 338 delay_state <= ALLOW; 339 else 340 delay_cnt <= delay_cnt + 2; 341 end if; 342 end case; 343 end if; 344 end if; 345 end process; 346 347 ------------------------------------------------------------------------------------------- 348 -- end of fixed latency implementation 349 -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 350 351 p_fsm : process(clk_sys_i) 352 begin 353 if rising_edge(clk_sys_i) then 354 if rst_n_i = '0' then 355 state <= IDLE; 356 count <= (others => '0'); 357 seq_no <= (others => '1'); 358 detect_escapes <= '0'; 359 crc_en <= '0'; 360 fifo_accept <= '0'; 361 fifo_drop <= '0'; 362 fifo_dvalid <= '0'; 363 pending_write <= '0'; 364 got_next_subframe <= '0'; 365 fifo_sync <= '0'; 366 fifo_last <= '0'; 367 tx_tag_valid <= '0'; 368 ser_count <= (others => '0'); 369 word_count <= (others => '0'); 370 sync_seq_no <= '1'; 371 rx_frame_p1_o <= '0'; 372 rx_lost_frames_cnt_o <= (others => '0'); 373 frames_lost <= '0'; 374 rx_latency <= (others=>'0'); 375 rx_latency_valid <= '0'; 376 blocks_lost <= '0'; 377 pack_data <= (others=>'0'); 378 is_vlan <= '0'; 379 else 380 case state is 381 when IDLE => 382 detect_escapes <= '0'; 383 crc_en <= '0'; 384 count <= (others => '0'); 385 fifo_accept <= '0'; 386 fifo_drop <= '0'; 387 fifo_dvalid <= '0'; 388 pending_write <= '0'; 389 got_next_subframe <='0'; 390 ser_count <= (others => '0'); 391 fifo_sync <='0'; 392 fifo_last <= '0'; 393 word_count <= (others => '0'); 394 tx_tag_valid <= '0'; 395 rx_frame_p1_o <= '0'; 396 rx_lost_frames_cnt_o <= (others => '0'); 397 frames_lost <= '0'; 398 blocks_lost <= '0'; 399 rx_latency <= (others=>'0'); 400 rx_latency_valid <= '0'; 401 is_vlan <= '0'; 402 403 if(fsm_in.sof = '1') then 404 state <= HEADER; 405 end if; 406 407 when HEADER => 408 if(fsm_in.eof = '1') then 409 state <= IDLE; 410 elsif(fsm_in.dvalid = '1') then 411 case count(7 downto 0) is 412 when x"00" => 413 if(fsm_in.data /= rx_streamer_cfg_i.mac_local(47 downto 32) nor (rx_streamer_cfg_i.accept_broadcasts = '1' and fsm_in.data /= x"ffff")) then 414 state <= IDLE; 415 end if; 416 count <= count + 1; 417 when x"01" => 418 if(fsm_in.data /= rx_streamer_cfg_i.mac_local(31 downto 16) nor (rx_streamer_cfg_i.accept_broadcasts = '1' and fsm_in.data /= x"ffff")) then 419 state <= IDLE; 420 end if; 421 count <= count + 1; 422 when x"02" => 423 if(fsm_in.data /= rx_streamer_cfg_i.mac_local(15 downto 0) nor (rx_streamer_cfg_i.accept_broadcasts = '1' and fsm_in.data /= x"ffff")) then 424 state <= IDLE; 425 end if; 426 count <= count + 1; 427 when x"03" => 428 if(fsm_in.data /= rx_streamer_cfg_i.mac_remote(47 downto 32) and rx_streamer_cfg_i.filter_remote ='1') then 429 state <= IDLE; 430 end if; 431 count <= count + 1; 432 when x"04" => 433 if(fsm_in.data /= rx_streamer_cfg_i.mac_remote(31 downto 16) and rx_streamer_cfg_i.filter_remote ='1') then 434 state <= IDLE; 435 end if; 436 count <= count + 1; 437 when x"05" => 438 if(fsm_in.data /= rx_streamer_cfg_i.mac_remote(15 downto 0) and rx_streamer_cfg_i.filter_remote ='1') then 439 state <= IDLE; 440 end if; 441 count <= count + 1; 442 when x"06" => 443 if(fsm_in.data = x"8100") then 444 is_vlan <='1'; 445 elsif(fsm_in.data /= rx_streamer_cfg_i.ethertype) then 446 state <= IDLE; 447 is_vlan <='0'; 448 end if; 449 count <= count + 1; 450 when x"07" => 451 if(is_vlan = '0') then 452 tx_tag_valid <= fsm_in.data(15); 453 tx_tag_cycles(27 downto 16)<= fsm_in.data(11 downto 0); 454 end if; 455 count <= count + 1; 456 when x"08" => 457 if(is_vlan = '0') then 458 tx_tag_cycles(15 downto 0) <= fsm_in.data; 459 count <= count + 1; 460 crc_en <= '1'; 461 detect_escapes <= '1'; 462 state <= FRAME_SEQ_ID; 463 rx_frame_p1_o <= '1'; 464 elsif(fsm_in.data /= rx_streamer_cfg_i.ethertype) then 465 state <= IDLE; 466 end if; 467 count <= count + 1; 468 when x"09" => 469 tx_tag_valid <= fsm_in.data(15); 470 tx_tag_cycles(27 downto 16)<= fsm_in.data(11 downto 0); 471 count <= count + 1; 472 when x"0A" => 473 tx_tag_cycles(15 downto 0) <= fsm_in.data; 474 count <= count + 1; 475 crc_en <= '1'; 476 detect_escapes <= '1'; 477 state <= FRAME_SEQ_ID; 478 rx_frame_p1_o <= '1'; 479 count <= count + 1; 480 when others => null; 481 end case; 482 end if; 483 484 when FRAME_SEQ_ID => 485 rx_frame_p1_o <= '0'; 486 if(fsm_in.eof = '1') then 487 state <= IDLE; 488 elsif(fsm_in.dvalid = '1') then 489 count <= "000" & x"001"; -- use as subframe seq_no 490 state <= PAYLOAD; 491 fifo_drop <= '0'; 492 fifo_accept <= '0'; 493 ser_count <= (others => '0'); 494 word_count <= word_count + 1; -- count words, increment in advance 495 got_next_subframe <= '1'; 496 if(tx_tag_valid = '1') then 497 rx_latency_valid <= '1'; 498 if(unsigned(tx_tag_cycles) > unsigned(rx_tag_cycles)) then 499 rx_latency <= unsigned(rx_tag_cycles) - unsigned(tx_tag_cycles) + to_unsigned(125000000, 28); 500 else 501 rx_latency <= unsigned(rx_tag_cycles) - unsigned(tx_tag_cycles); 502 end if; 503 tx_tag_valid <= '0'; 504 else 505 rx_latency_valid <= '0'; 506 end if; 507 508 if(std_logic_vector(seq_no) /= fsm_in.data(14 downto 0)) then 509 seq_no <= unsigned(fsm_in.data(14 downto 0))+1; 510 if (sync_seq_no = '1') then -- sync to the first received seq_no 511 sync_seq_no <= '0'; 512 frames_lost <= '0'; 513 rx_lost_frames_cnt_o <= (others => '0'); 514 else 515 rx_lost_frames_cnt_o <= std_logic_vector(unsigned(fsm_in.data(14 downto 0)) - seq_no); 516 frames_lost <= '1'; 517 end if; 518 else 519 seq_no <= unsigned(seq_no + 1); 520 frames_lost <= '0'; 521 rx_lost_frames_cnt_o <= (others => '0'); 522 end if; 523 end if; 524 525 when SUBFRAME_HEADER => 526 fifo_drop <= '0'; 527 fifo_accept <= '0'; 528 ser_count <= (others => '0'); 529 530 if(fsm_in.eof = '1') then 531 state <= IDLE; 532 got_next_subframe <= '0'; 533 blocks_lost <= '0'; 534 elsif (fsm_in.dvalid = '1' and is_escape = '1') then 535 got_next_subframe <= '1'; 536 537 if(std_logic_vector(count) /= fsm_in.data(14 downto 0)) then 538 count <= unsigned(fsm_in.data(14 downto 0))+1; 539 blocks_lost <= '1'; 540 else 541 count <= count + 1; 542 blocks_lost <= '0'; 543 end if; 544 state <= PAYLOAD; 545 end if; 546 547 when PAYLOAD => 548 frames_lost <= '0'; 549 rx_lost_frames_cnt_o <= (others => '0'); 550 rx_latency_valid <= '0'; 551 fifo_sync <= got_next_subframe; 552 553 if(fsm_in.eof = '1') then 554 state <= IDLE; 555 fifo_drop <= '1'; 556 fifo_accept <= '0'; 557 got_next_subframe <= '0'; 558 559 elsif(fsm_in.dvalid = '1') then 560 561 562 563 if(is_escape = '1') then 564 ser_count <= (others => '0'); 565 fifo_last <= '1'; 566 567 got_next_subframe <= '1'; 568 569 if(fsm_in.data(15) = '1') then 570 571 if(std_logic_vector(count) /= fsm_in.data(14 downto 0)) then 572 count <= unsigned(fsm_in.data(14 downto 0)); 573 blocks_lost <= '1'; 574 else 575 count <= unsigned(count + 1); 576 blocks_lost <= '0'; 577 end if; 578 579 state <= PAYLOAD; 580 581 fifo_accept <= crc_match; --_latched; 582 fifo_drop <= not crc_match; --_latched; 583 fifo_dvalid <= pending_write and not fifo_dvalid; 584 pending_write <= '0'; 585 586 elsif fsm_in.data = x"0bad" then 587 blocks_lost <= '0'; 588 state <= EOF; 589 fifo_accept <= crc_match; --_latched; 590 fifo_drop <= not crc_match; --_latched; 591 fifo_dvalid <= pending_write and not fifo_dvalid; 592 else 593 blocks_lost <= '0'; 594 state <= EOF; 595 fifo_drop <= '1'; 596 fifo_accept <= '0'; 597 end if; 598 599 else --of: if(is_escape = '1' or word_count = g_expected_words_number) then 600 601 fifo_last <= '0'; 602 fifo_accept <= '0'; 603 fifo_drop <= '0'; 604 blocks_lost <= '0'; 605 606 pack_data(to_integer(ser_count) * 16 + 15 downto to_integer(ser_count) * 16) <= fsm_in.data; 607 608 if(ser_count = g_data_width/16 - 1) then 609 ser_count <= (others => '0'); 610 611 if (ser_count = x"00") then -- ML: the case when g_data_width == 16 612 fifo_sync <= got_next_subframe; 613 fifo_data(g_data_width-1 downto 0) <= pack_data(g_data_width-1 downto 0); 614 fifo_dvalid <= not is_escape; 615 pending_write <= '0'; 616 else 617 ser_count <= (others => '0'); 618 fifo_data(g_data_width-16-1 downto 0) <= pack_data(g_data_width-16-1 downto 0); 619 fifo_data(g_data_width-1 downto g_data_width-16) <= fsm_in.data; 620 fifo_dvalid <= '0'; 621 pending_write <= '1'; 622 end if; 623 if(word_count = g_expected_words_number) then 624 state <= EOF; 625 fifo_accept <= '1'; 626 fifo_drop <= '0'; 627 fifo_dvalid <= '1'; 628 else 629 word_count <= word_count + 1; 630 end if; 631 elsif(ser_count = g_data_width/16-2 and pending_write = '1') then 632 pending_write <= '0'; 633 ser_count <= ser_count + 1; 634 fifo_dvalid <= '1'; 635 fifo_sync <= got_next_subframe; 636 got_next_subframe <= '0'; 637 else 638 ser_count <= ser_count + 1; 639 fifo_dvalid <= '0'; 640 end if; 641 642 end if; 643 else --of: elsif(fsm_in.dvalid = '1') then 644 fifo_dvalid <= '0'; 645 end if; 646 647 if(fifo_dvalid = '1') then 648 fifo_sync <= '0'; 649 end if; 650 651 652 when EOF => 653 fifo_dvalid <= '0'; 654 fifo_drop <= '0'; 655 fifo_accept <= '0'; 656 state <= IDLE; 657 658 end case; 659 end if; 660 end if; 661 end process; 662 663 p_delay_fifo_accept : process(clk_sys_i) 664 begin 665 if rising_edge(clk_sys_i) then 666 fifo_accept_d0 <= fifo_accept; 667 end if; 668 end process; 669 670 rx_lost_p1_o <= frames_lost or blocks_lost; 671 rx_lost_blocks_p1_o <= blocks_lost; 672 rx_lost_frames_p1_o <= frames_lost; 673 rx_latency_o <= std_logic_vector(rx_latency); 674 rx_latency_valid_o <= rx_latency_valid; 675 crc_restart <= '1' when (state = FRAME_SEQ_ID or (is_escape = '1' and fsm_in.data(15) = '1')) else not rst_n_i; 676 677end rtl; 678