高速收发器:PHY层代码(二)
TX:
总结:不难,只需要注意小端发送即可;
我选取的实现思路是使用VAILD信号计数,延迟几个周期之后启动发送计数器,发送计算器在其计数数值来到VAILD信号计数器的最大值-1后结束;
思路很简单,事实上这就是一个很常见的组帧模块,和其他的没有什么本质的差别;
always @(posedge i_sys_clk) begin if(i_sys_rst == 1'b1) begin r_o_gt_tx_data <= w_lfsr_data; r_o_gt_tx_char <= 4'b0000; end else if(r_st_current == P_ST_ICOMMOA) begin r_o_gt_tx_data <= {P_Sync_Code[07-:8],P_Sync_Code[15-:8],P_Sync_Code[23-:8],P_Sync_Code[31-:8]}; r_o_gt_tx_char <= 4'b0101; end else if(r_st_current == P_ST_COMMOA) begin r_o_gt_tx_data <= {P_Sync_Code[07-:8],P_Sync_Code[15-:8],P_Sync_Code[23-:8],P_Sync_Code[31-:8]}; r_o_gt_tx_char <= 4'b0101; end else if(r_st_current == P_ST_SOF) begin r_o_gt_tx_data <= {w_Gt_tx_fifo_dout[15-:8],w_Gt_tx_fifo_dout[23-:8],w_Gt_tx_fifo_dout[31-:8],P_SoT_Code[07-:8]}; r_o_gt_tx_char <= 4'b0001; end else if(r_st_current == P_ST_DATA) begin r_o_gt_tx_data <= {w_Gt_tx_fifo_dout[15-:8],w_Gt_tx_fifo_dout[23-:8],w_Gt_tx_fifo_dout[31-:8],r_Gt_tx_fifo_dout[07-:8]}; r_o_gt_tx_char <= 4'b0000; end else if(r_st_current == P_ST_EOF1) begin if(r_i_axi_s_keep == 4'b1000) begin r_o_gt_tx_data <= {w_lfsr_data[07:00],P_EoT_Code[07:00],w_Gt_tx_fifo_dout[31-:8],r_Gt_tx_fifo_dout[07-:8]}; r_o_gt_tx_char <= 4'b0100; end else if(r_i_axi_s_keep == 4'b1100) begin r_o_gt_tx_data <= {P_EoT_Code[07:00],w_Gt_tx_fifo_dout[23-:8],w_Gt_tx_fifo_dout[31-:8],r_Gt_tx_fifo_dout[07-:8]}; r_o_gt_tx_char <= 4'b1000; end else if(r_i_axi_s_keep == 4'b1110) begin r_o_gt_tx_data <= {w_Gt_tx_fifo_dout[15-:8],w_Gt_tx_fifo_dout[23-:8],w_Gt_tx_fifo_dout[31-:8],r_Gt_tx_fifo_dout[07-:8]}; r_o_gt_tx_char <= 4'b0000; end else if(r_i_axi_s_keep == 4'b1111) begin r_o_gt_tx_data <= {w_Gt_tx_fifo_dout[15-:8],w_Gt_tx_fifo_dout[23-:8],w_Gt_tx_fifo_dout[31-:8],r_Gt_tx_fifo_dout[07-:8]}; r_o_gt_tx_char <= 4'b0000; end else begin r_o_gt_tx_data <= 32'h0000; r_o_gt_tx_char <= 4'b0000; end end else if(r_st_current == P_ST_EOF2) begin if(r_i_axi_s_keep == 4'b1110) begin r_o_gt_tx_data <= {w_lfsr_data[23-:24],P_EoT_Code[07:00]}; r_o_gt_tx_char <= 4'b0001; end else if(r_i_axi_s_keep == 4'b1111) begin r_o_gt_tx_data <= {w_lfsr_data[15-:16],P_EoT_Code[07:00],r_Gt_tx_fifo_dout[07-:8]}; r_o_gt_tx_char <= 4'b0010; end else begin r_o_gt_tx_data <= w_lfsr_data; r_o_gt_tx_char <= 4'b0000; end end else begin r_o_gt_tx_data <= w_lfsr_data; r_o_gt_tx_char <= 4'b0000; end end
RX:
总结:默认小端存储需要转大端,对齐很麻烦,准确的筛选所需的字节也很麻烦;
推荐画图来理解;
我个人的总结规律是:
0.SOF的标志作为VAILD的起始信号;
1.SOF和EOF处字节相加大于用户数据位宽的时候,需要将EOF的标志延迟两拍作为VAILD的结束信号;
2.SOF和EOF处字节小于等于用户数据位宽的时候,需要将EOF的标志延迟一拍作为VAILD的结束信号;
3.如果相加为零,则选择EOF的标志作为VAILD的结束信号;
当然,这只是一个思路,这个延迟是相对来说的,如果你用其他方式来判断SOF或者EOF,只需要按我这个相对的概念修改即可;
always @(posedge i_sys_clk) begin if(i_sys_rst == 1'b1) begin r_o_axi_s_vaild <= 1'b0; end else if((r_sof_mark == 4'b0001) && (r_eof_mark == 4'b0001 || r_eof_mark == 4'b0010) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_vaild <= 1'b0; end else if((r_sof_mark == 4'b0001) && (r_eof_mark == 4'b0100 || r_eof_mark == 4'b1000) && (r_d2_eof_check == 1'b1)) begin r_o_axi_s_vaild <= 1'b0; end else if((r_sof_mark == 4'b0010) && (r_eof_mark == 4'b0001 || r_eof_mark == 4'b0010 || r_eof_mark == 4'b0100) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_vaild <= 1'b0; end else if((r_sof_mark == 4'b0010) && (r_eof_mark == 4'b1000) && (r_d2_eof_check == 1'b1)) begin r_o_axi_s_vaild <= 1'b0; end else if((r_sof_mark == 4'b0100) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_vaild <= 1'b0; end else if((r_sof_mark == 4'b1000) && (r_eof_mark == 4'b0001) && (r_eof_check == 1'b1)) begin r_o_axi_s_vaild <= 1'b0; end else if((r_sof_mark == 4'b1000) && (r_eof_mark == 4'b0010 || r_eof_mark == 4'b0100 || r_eof_mark == 4'b1000) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_vaild <= 1'b0; end else if(r_sof_check == 1'b1) begin r_o_axi_s_vaild <= 1'b1; end end always @(*) begin if((r_sof_mark == 4'b0001) && (r_eof_mark == 4'b0001 || r_eof_mark == 4'b0010) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_last <= 1'b1; end else if((r_sof_mark == 4'b0001) && (r_eof_mark == 4'b0100 || r_eof_mark == 4'b1000) && (r_d2_eof_check == 1'b1)) begin r_o_axi_s_last <= 1'b1; end else if((r_sof_mark == 4'b0010) && (r_eof_mark == 4'b0001 || r_eof_mark == 4'b0010 || r_eof_mark == 4'b0100) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_last <= 1'b1; end else if((r_sof_mark == 4'b0010) && (r_eof_mark == 4'b1000) && (r_d2_eof_check == 1'b1)) begin r_o_axi_s_last <= 1'b1; end else if((r_sof_mark == 4'b0100) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_last <= 1'b1; end else if((r_sof_mark == 4'b1000) && (r_eof_mark == 4'b0001) && (r_eof_check == 1'b1)) begin r_o_axi_s_last <= 1'b1; end else if((r_sof_mark == 4'b1000) && (r_eof_mark == 4'b0010 || r_eof_mark == 4'b0100 || r_eof_mark == 4'b1000) && (r_d1_eof_check == 1'b1)) begin r_o_axi_s_last <= 1'b1; end else begin r_o_axi_s_last <= 0; end end always @(posedge i_sys_clk) begin if(i_sys_rst == 1'b1) begin r_o_axi_s_data <= 32'h0000; end else if((r_sof_check == 1'b1)||(r_data_process == 1'b1)) begin if(r_sof_mark == 4'b0001) begin r_o_axi_s_data <= {r_2d_i_gt_rx_data[07-:08],r_3d_i_gt_rx_data[31-:24]}; end else if(r_sof_mark == 4'b0010) begin r_o_axi_s_data <= {r_2d_i_gt_rx_data[15-:16],r_3d_i_gt_rx_data[31-:16]}; end else if(r_sof_mark == 4'b0100) begin r_o_axi_s_data <= {r_2d_i_gt_rx_data[23-:24],r_3d_i_gt_rx_data[31-:08]}; end else if(r_sof_mark == 4'b1000) begin r_o_axi_s_data <= {r_2d_i_gt_rx_data[31-:32]}; end else begin r_o_axi_s_data <= 32'h0000; end end else begin r_o_axi_s_data <= 32'h0000; end end always @(posedge i_sys_clk) begin if(i_sys_rst == 1'b1) begin r_o_axi_s_keep <= 4'b0000; end else if((r_sof_check == 1'b1)||(r_data_process == 1'b1)) begin if(r_sof_mark == 4'b0001) begin if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1110; end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1111; end else if(r_eof_mark == 4'b0100 && r_d1_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1000; end else if(r_eof_mark == 4'b1000 && r_d1_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1100; end else begin r_o_axi_s_keep <= 4'b1111; end end else if(r_sof_mark == 4'b0010) begin if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1100; end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1110; end else if(r_eof_mark == 4'b0100 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1111; end else if(r_eof_mark == 4'b1000 && r_d1_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1000; end else begin r_o_axi_s_keep <= 4'b1111; end end else if(r_sof_mark == 4'b0100) begin if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1000; end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1100; end else if(r_eof_mark == 4'b0100 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1110; end else if(r_eof_mark == 4'b1000 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1111; end else begin r_o_axi_s_keep <= 4'b1111; end end else if(r_sof_mark == 4'b1000) begin if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b0000; end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1000; end else if(r_eof_mark == 4'b0100 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1100; end else if(r_eof_mark == 4'b1000 && r_eof_check == 1'b1) begin r_o_axi_s_keep <= 4'b1110; end else begin r_o_axi_s_keep <= 4'b1111; end end end else begin r_o_axi_s_keep <= 4'b0000; end end