# fsic_io_serdes_rx.v ## w_ptr in RX ``` wire w_ptr_graycode_bit0; assign w_ptr_graycode_bit0 = w_ptr[1] ^ w_ptr[0]; always @(negedge rxclk or negedge axis_rst_n) begin if ( !axis_rst_n || !rxen ) begin w_ptr <= 0; end else begin if (w_ptr == 4) w_ptr <= 0; else w_ptr <= w_ptr+1; end end always @(posedge ioclk or negedge axis_rst_n) begin if ( !axis_rst_n ) begin w_ptr_pre <= 0; w_ptr_sync <= 0; end else begin w_ptr_pre <= w_ptr_graycode_bit0; //use gray code w_ptr_sync <= w_ptr_pre; //avoid metastable issue end end ``` ![](https://hackmd.io/_uploads/HJ8VyX6K2.png) ## RxFIFO ``` reg [pRxFIFO_DEPTH-1:0] RxFifo; always @(negedge rxclk or negedge axis_rst_n) begin if ( !axis_rst_n || !rxen ) begin RxFifo <= 0; end else begin RxFifo[w_ptr] <= Serial_Data_in; end end ``` - in yellow line get w_ptr=2 then write data to RxFifo[2] in rxclk negedge ![](https://hackmd.io/_uploads/Hkp1-Qpt2.png) ## rx_start ``` reg rx_start; always @(posedge ioclk or negedge axis_rst_n) begin if ( !axis_rst_n ) begin rx_start <= 0; end else begin if (w_ptr_sync != 0 ) rx_start <= 1; else rx_start <= rx_start; end end ``` ![](https://hackmd.io/_uploads/r1vRyQTKh.png) ## r_ptr ``` always @(posedge ioclk or negedge axis_rst_n) begin if ( !axis_rst_n ) begin r_ptr <= 0; end else begin if (rx_start) begin if ( r_ptr == 4 ) r_ptr <= 0; else r_ptr <= r_ptr + 1; end else r_ptr <= r_ptr; end end ``` ![](https://hackmd.io/_uploads/Hk41WLaF2.png) ## data move from RxFifo to rx_shift_reg ``` always @(posedge ioclk or negedge axis_rst_n) begin if ( !axis_rst_n ) begin rx_shift_reg <= 0; end else begin if (rx_start) begin rx_shift_reg[3] <= RxFifo[r_ptr]; //r_ptr get from LSB to MSB rx_shift_reg[2:0] <= rx_shift_reg[3:1]; end end end ``` - in yellow line, r_ptr = 2 then move RxFifo[2] to rx_shift_reg[3] - ![](https://hackmd.io/_uploads/HyJtGITF2.png) ## rx_shift_phase_cnt ``` always @(posedge ioclk or negedge axis_rst_n) begin if ( !axis_rst_n ) begin rx_shift_phase_cnt <= pCLK_RATIO-1; end else begin if (rx_start) rx_shift_phase_cnt <= rx_shift_phase_cnt+1; else rx_shift_phase_cnt <= rx_shift_phase_cnt; end end ``` ### soc and fpga coreclk is sync ![](https://hackmd.io/_uploads/rks_ISTt3.png) ### soc and fpga coreclk is not sync ![](https://hackmd.io/_uploads/Bk8MLrpth.png) ## rx_shift_reg_valid ``` always @(posedge ioclk or negedge axis_rst_n) begin if ( !axis_rst_n ) begin rx_start_delay <= 0; end else begin rx_start_delay[0] <= rx_start; rx_start_delay[2:1] <= rx_start_delay[1:0]; end end assign rx_shift_reg_valid = (rx_shift_phase_cnt == pCLK_RATIO-1) && rx_start_delay[2] ; //rx_shift_reg is ready to move. ``` ### rx_shift_reg_valid waveform ![](https://hackmd.io/_uploads/Sk-BWvTYh.png) ## data move from rx_shift_reg to rx_sync_fifo ``` //write by ioclk in negedge and read by coreclk in posedge then simulation result is ok. reg [pCLK_RATIO-1:0] rx_sync_fifo; reg rx_sync_fifo_valid; always @(posedge ioclk or negedge axis_rst_n) begin //use posedge, the simulation result is early 1T in rxdata // - This issue is fixed by use block assigment in clock divider to avoid race condition in simulation if ( !axis_rst_n ) begin rx_sync_fifo <= 0; rx_sync_fifo_valid <= 0; end else begin if (rx_start && rx_shift_reg_valid) begin rx_sync_fifo <= rx_shift_reg; rx_sync_fifo_valid <= 1; end else begin rx_sync_fifo <= rx_sync_fifo; rx_sync_fifo_valid <= rx_sync_fifo_valid; end end end ``` ### data move from rx_shift_reg to rx_sync_fifo waveform ![](https://hackmd.io/_uploads/ByJ1bDTFh.png)