笔记:从Aurora 8b/10b 到Aurora 64b/66b (三):自定义PHY层收发
相较于8/10来说没那么复杂,需要考虑的情况只有八种;
但是gearbox的控制需要额外的心思:每三十二周期所有操作都需要停止;
这一点在收发都需要注意;
RX:
核心思想是利用header做检测,将夹杂在数据流中的控制包滤除掉;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
module gt_phy_rx ( input wire i_rx_clk , input wire i_rx_reset , input wire [63:00] i_rx_data , input wire i_rx_data_valid , input wire [01:00] i_rx_header , input wire i_rx_headervalid , output wire m_axis_valid , output wire m_axis_last , output wire [63:00] m_axis_data , output wire [07:00] m_axis_keep , input wire m_axis_ready ); localparam P_FrameHeader_CONTROL = 2'b10; localparam P_FrameHeader_DATA = 2'b01; localparam P_FLAG_START = 8'h71; localparam P_FLAG_END_0 = 8'h8E; localparam P_FLAG_END_1 = 8'h99; localparam P_FLAG_END_2 = 8'hA5; localparam P_FLAG_END_3 = 8'hB2; localparam P_FLAG_END_4 = 8'hC3; localparam P_FLAG_END_5 = 8'hD4; localparam P_FLAG_END_6 = 8'hE8; localparam P_FLAG_END_7 = 8'hFF; reg [63:00] r_i_rx_data ; reg r_i_rx_data_valid ; reg [01:00] r_i_rx_header ; reg r_i_rx_headervalid ; reg [63:00] r_d1_i_rx_data ; reg r_d1_i_rx_data_valid ; reg [01:00] r_d1_i_rx_header ; reg r_d1_i_rx_headervalid ; reg [63:00] r_d2_i_rx_data ; reg r_d2_i_rx_data_valid ; reg [01:00] r_d2_i_rx_header ; reg r_d2_i_rx_headervalid ; reg r_receiving ; reg r_m_axis_valid ; reg r_m_axis_last ; reg r_d1_m_axis_last ; reg [63:00] r_m_axis_data ; reg [07:00] r_m_axis_keep ; reg ro_m_axis_valid ; reg ro_m_axis_last ; reg [63:00] ro_m_axis_data ; reg [07:00] ro_m_axis_keep ; wire w_data_frame ; wire w_sof ; wire w_sof_pre ; wire w_eof ; wire w_eof_pre ; reg r_d1_eof ; reg [07:00] r_eof_local ; reg [07:00] r_eof_local_pre ; reg [07:00] r_d1_eof_local ; reg [07:00] r_d2_eof_local ; reg r_i_valid ; reg r_d1_i_valid ; assign m_axis_valid = ro_m_axis_valid; assign m_axis_last = ro_m_axis_last ; assign m_axis_data = ro_m_axis_data ; assign m_axis_keep = ro_m_axis_keep ; always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin ro_m_axis_data <= 0; ro_m_axis_keep <= 0; end else begin ro_m_axis_data <= (r_m_axis_valid)?{r_m_axis_data[07:00],r_m_axis_data[15:08],r_m_axis_data[23:16], r_m_axis_data[31:24],r_m_axis_data[39:32],r_m_axis_data[47:40], r_m_axis_data[55:48],r_m_axis_data[63:56]}:0; ro_m_axis_keep <= (r_m_axis_valid)?{r_m_axis_keep[0],r_m_axis_keep[1],r_m_axis_keep[2],r_m_axis_keep[3], r_m_axis_keep[4],r_m_axis_keep[5],r_m_axis_keep[6],r_m_axis_keep[7]}:0; end end always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin ro_m_axis_valid <= 0; end else if(m_axis_valid && m_axis_last) begin ro_m_axis_valid <= 0; end else if(r_m_axis_valid) begin ro_m_axis_valid <= 1'b1; end else begin ro_m_axis_valid <= 0; end end always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin ro_m_axis_last <= 0; end else if(m_axis_valid && m_axis_last) begin ro_m_axis_last <= 1'b0; end else if(r_m_axis_last == 1'b1) begin ro_m_axis_last <= 1'b1; end end always @(posedge i_rx_clk) begin r_d1_i_valid <= r_i_valid ; r_d1_eof_local <= r_eof_local ; r_d1_eof <= w_eof ; r_d1_m_axis_last <= r_m_axis_last ; end always @(*) begin if(w_sof_pre||w_eof_pre||w_data_frame) begin r_i_valid <= 1'b1; end else begin r_i_valid <= 1'b0; end end always @(*) begin if((r_d1_i_valid && r_receiving)||m_axis_last) begin r_m_axis_valid <= 1'b1; end else begin r_m_axis_valid <= 1'b0; end end always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin r_i_rx_data <= 0; r_i_rx_data_valid <= 0; r_i_rx_header <= 0; r_i_rx_headervalid <= 0; end else if(m_axis_last == 1'b1) begin r_i_rx_data <= 0; r_i_rx_data_valid <= 0; r_i_rx_header <= 0; r_i_rx_headervalid <= 0; end else if(r_i_valid) begin r_i_rx_data <= i_rx_data ; r_i_rx_data_valid <= i_rx_data_valid ; r_i_rx_header <= i_rx_header ; r_i_rx_headervalid <= i_rx_headervalid ; end else begin r_i_rx_data <= r_i_rx_data ; r_i_rx_data_valid <= r_i_rx_data_valid ; r_i_rx_header <= r_i_rx_header ; r_i_rx_headervalid <= r_i_rx_headervalid ; end end always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin r_d1_i_rx_data <= 0; r_d1_i_rx_data_valid <= 0; r_d1_i_rx_header <= 0; r_d1_i_rx_headervalid <= 0; end else if(m_axis_last) begin r_d1_i_rx_data <= 0; r_d1_i_rx_data_valid <= 0; r_d1_i_rx_header <= 0; r_d1_i_rx_headervalid <= 0; end else if(r_d1_i_valid) begin r_d1_i_rx_data <= r_i_rx_data ; r_d1_i_rx_data_valid <= r_i_rx_data_valid ; r_d1_i_rx_header <= r_i_rx_header ; r_d1_i_rx_headervalid <= r_i_rx_headervalid ; end else begin r_d1_i_rx_data <= r_d1_i_rx_data ; r_d1_i_rx_data_valid <= r_d1_i_rx_data_valid ; r_d1_i_rx_header <= r_d1_i_rx_header ; r_d1_i_rx_headervalid <= r_d1_i_rx_headervalid ; end end assign w_data_frame = (i_rx_header == P_FrameHeader_DATA)&&(i_rx_headervalid)&&(i_rx_data_valid); assign w_sof = (r_i_rx_header == P_FrameHeader_CONTROL)&&(r_i_rx_headervalid)&&(r_i_rx_data_valid)&&(r_i_rx_data[07:00] == P_FLAG_START); assign w_sof_pre = (i_rx_header == P_FrameHeader_CONTROL)&&(i_rx_headervalid)&&(i_rx_data_valid)&&(i_rx_data[07:00] == P_FLAG_START); assign w_eof = (r_i_rx_header == P_FrameHeader_CONTROL)&&(r_i_rx_headervalid)&&(r_i_rx_data_valid)&&((r_i_rx_data[07:00] == P_FLAG_END_0 )|| (r_i_rx_data[07:00] == P_FLAG_END_1 )|| (r_i_rx_data[07:00] == P_FLAG_END_2 )|| (r_i_rx_data[07:00] == P_FLAG_END_3 )|| (r_i_rx_data[07:00] == P_FLAG_END_4 )|| (r_i_rx_data[07:00] == P_FLAG_END_5 )|| (r_i_rx_data[07:00] == P_FLAG_END_6 )|| (r_i_rx_data[07:00] == P_FLAG_END_7 )); assign w_eof_pre = (i_rx_header == P_FrameHeader_CONTROL)&&(i_rx_headervalid)&&(i_rx_data_valid)&&((i_rx_data[07:00] == P_FLAG_END_0 )|| (i_rx_data[07:00] == P_FLAG_END_1 )|| (i_rx_data[07:00] == P_FLAG_END_2 )|| (i_rx_data[07:00] == P_FLAG_END_3 )|| (i_rx_data[07:00] == P_FLAG_END_4 )|| (i_rx_data[07:00] == P_FLAG_END_5 )|| (i_rx_data[07:00] == P_FLAG_END_6 )|| (i_rx_data[07:00] == P_FLAG_END_7 )); always @(*) begin if((r_i_rx_header == P_FrameHeader_CONTROL)&&(r_i_rx_headervalid)&&(r_i_rx_data_valid)) begin case (r_i_rx_data[07:00]) P_FLAG_END_0:r_eof_local <= 8; P_FLAG_END_1:r_eof_local <= 1; P_FLAG_END_2:r_eof_local <= 2; P_FLAG_END_3:r_eof_local <= 3; P_FLAG_END_4:r_eof_local <= 4; P_FLAG_END_5:r_eof_local <= 5; P_FLAG_END_6:r_eof_local <= 6; P_FLAG_END_7:r_eof_local <= 7; default: r_eof_local <= 0; endcase end else begin r_eof_local <= 0; end end always @(*) begin if((i_rx_header == P_FrameHeader_CONTROL)&&(i_rx_headervalid)&&(i_rx_data_valid)) begin case (i_rx_data[07:00]) P_FLAG_END_0:r_eof_local_pre <= 8; P_FLAG_END_1:r_eof_local_pre <= 1; P_FLAG_END_2:r_eof_local_pre <= 2; P_FLAG_END_3:r_eof_local_pre <= 3; P_FLAG_END_4:r_eof_local_pre <= 4; P_FLAG_END_5:r_eof_local_pre <= 5; P_FLAG_END_6:r_eof_local_pre <= 6; P_FLAG_END_7:r_eof_local_pre <= 7; default: r_eof_local_pre <= 0; endcase end else begin r_eof_local_pre <= 0; end end always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin r_receiving <= 0; end else if(r_d1_eof_local == 7 && r_d1_eof == 1'b1) begin r_receiving <= 0; end else if(r_d1_eof_local == 6 && r_d1_eof == 1'b1) begin r_receiving <= 0; end else if(r_d1_eof_local == 5 && r_d1_eof == 1'b1) begin r_receiving <= 0; end else if(r_d1_eof_local == 4 && r_d1_eof == 1'b1) begin r_receiving <= 0; end else if(r_d1_eof_local == 3 && r_d1_eof == 1'b1) begin r_receiving <= 0; end else if(r_d1_eof_local == 2 && r_d1_eof == 1'b1) begin r_receiving <= 0; end else if(r_eof_local == 1 && w_eof == 1'b1) begin r_receiving <= 0; end else if(r_eof_local == 8 && w_eof == 1'b1) begin r_receiving <= 0; end else if(w_sof) begin r_receiving <= 1'b1; end else begin r_receiving <= r_receiving; end end always @(*) begin if(r_d1_eof_local == 7 && r_d1_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else if(r_d1_eof_local == 6 && r_d1_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else if(r_d1_eof_local == 5 && r_d1_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else if(r_d1_eof_local == 4 && r_d1_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else if(r_d1_eof_local == 3 && r_d1_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else if(r_d1_eof_local == 2 && r_d1_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else if(r_eof_local == 1 && w_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else if(r_eof_local == 8 && w_eof == 1'b1) begin r_m_axis_last <= 1'b1; end else begin r_m_axis_last <= 1'b0; end end always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin r_m_axis_data <= 0; end else if(r_eof_local == 7 && w_eof == 1'b1) begin r_m_axis_data <= {{2{8'h0}},r_i_rx_data[63-:48]}; end else if(r_eof_local_pre == 7 && w_eof_pre == 1'b1) begin r_m_axis_data <= {i_rx_data[15:08],r_i_rx_data[63-:56]}; end else if(r_eof_local == 6 && w_eof == 1'b1) begin r_m_axis_data <= {{3{8'h0}},r_i_rx_data[55-:40]}; end else if(r_eof_local_pre == 6 && w_eof_pre == 1'b1) begin r_m_axis_data <= {i_rx_data[15:08],r_i_rx_data[63-:56]}; end else if(r_eof_local == 5 && w_eof == 1'b1) begin r_m_axis_data <= {{4{8'h0}},r_i_rx_data[47-:32]}; end else if(r_eof_local_pre == 5 && w_eof_pre == 1'b1) begin r_m_axis_data <= {i_rx_data[15:08],r_i_rx_data[63-:56]}; end else if(r_eof_local == 4 && w_eof == 1'b1) begin r_m_axis_data <= {{5{8'h0}},r_i_rx_data[39-:24]}; end else if(r_eof_local_pre == 4 && w_eof_pre == 1'b1) begin r_m_axis_data <= {i_rx_data[15:08],r_i_rx_data[63-:56]}; end else if(r_eof_local == 3 && w_eof == 1'b1) begin r_m_axis_data <= {{6{8'h0}},r_i_rx_data[31-:16]}; end else if(r_eof_local_pre == 3 && w_eof_pre == 1'b1) begin r_m_axis_data <= {i_rx_data[15:08],r_i_rx_data[63-:56]}; end else if(r_eof_local == 2 && w_eof == 1'b1) begin r_m_axis_data <= {{7{8'h0}},r_i_rx_data[23-:08]}; end else if(r_eof_local_pre == 2 && w_eof_pre == 1'b1) begin r_m_axis_data <= {i_rx_data[15:08],r_i_rx_data[63-:56]}; end else if(r_eof_local_pre == 1 && w_eof_pre == 1'b1) begin r_m_axis_data <= {i_rx_data[15:08],r_i_rx_data[63-:56]}; end else if(r_eof_local_pre == 8 && w_eof_pre == 1'b1) begin r_m_axis_data <= {{8'h0},r_i_rx_data[63-:56]}; end else begin r_m_axis_data <= {i_rx_data[07:00],r_i_rx_data[63-:56]}; end end always @(posedge i_rx_clk) begin if(i_rx_reset == 1'b1) begin r_m_axis_keep <= 8'b0000_0000; end else if(r_eof_local == 7 && w_eof == 1'b1) begin r_m_axis_keep <= 8'b0011_1111; end else if(r_eof_local == 6 && w_eof == 1'b1) begin r_m_axis_keep <= 8'b0001_1111; end else if(r_eof_local == 5 && w_eof == 1'b1) begin r_m_axis_keep <= 8'b0000_1111; end else if(r_eof_local == 4 && w_eof == 1'b1) begin r_m_axis_keep <= 8'b0000_0111; end else if(r_eof_local == 3 && w_eof == 1'b1) begin r_m_axis_keep <= 8'b0000_0011; end else if(r_eof_local == 2 && w_eof == 1'b1) begin r_m_axis_keep <= 8'b0000_0001; end else if(r_eof_local_pre == 1 && w_eof_pre == 1'b1) begin r_m_axis_keep <= 8'b1111_1111; end else if(r_eof_local_pre == 8 && w_eof_pre == 1'b1) begin r_m_axis_keep <= 8'b0111_1111; end end endmodule
TX:
只需要在gearbox需要暂停的时候停止即可;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
module gt_phy_tx ( input wire i_tx_clk , input wire i_tx_reset , output wire [63:00] o_tx_data , output wire [01:00] o_tx_header , output wire [06:00] o_tx_sequence , input wire s_axis_valid , input wire s_axis_last , input wire [63:00] s_axis_data , input wire [07:00] s_axis_keep , output wire s_axis_ready ); localparam P_FrameHeader_CONTROL = 2'b10; localparam P_FrameHeader_DATA = 2'b01; localparam P_FLAG_IDLE = 8'h17; localparam P_FLAG_START = 8'h71; localparam P_FLAG_END_0 = 8'h8E; localparam P_FLAG_END_1 = 8'h99; localparam P_FLAG_END_2 = 8'hA5; localparam P_FLAG_END_3 = 8'hB2; localparam P_FLAG_END_4 = 8'hC3; localparam P_FLAG_END_5 = 8'hD4; localparam P_FLAG_END_6 = 8'hE8; localparam P_FLAG_END_7 = 8'hFF; localparam P_ST_INIT = 1; localparam P_ST_IDLE = 2; localparam P_ST_FRAMESTART = 3; localparam P_ST_DATALOADS = 4; localparam P_ST_END1 = 5; localparam P_ST_END2 = 6; reg r_s_axis_ready ; reg r_s_axis_valid ; reg [07:00] r_s_axis_keep ; reg [07:00] r_st_current ; reg [07:00] r_st_next ; reg r1_w_data_wr_en ; reg r2_w_data_wr_en ; reg r3_w_data_wr_en ; reg [15:00] r_valid_cnt ; wire w_data_wr_en ; wire [63:00] w_data_wr_data ; reg r_data_rd_en ; wire [63:00] w_data_rd_data ; wire [63:00] w_data_rd_data_conv ; reg [63:00] r1_data_rd_data ; reg [63:00] r2_data_rd_data ; wire w_full ; wire w_empty ; wire [09:00] w_data_count ; reg [05:00] r_o_tx_sequence ; wire w_sequence_check ; wire w_send_valid ; reg [15:00] r_send_cnt ; reg [01:00] r_o_tx_header ; reg [63:00] r_o_tx_data ; assign w_data_wr_data = s_axis_data; assign w_data_wr_en = (s_axis_valid)&&(s_axis_ready); assign w_data_rd_data_conv = {w_data_rd_data[07-:8],w_data_rd_data[15-:8],w_data_rd_data[23-:8], w_data_rd_data[31-:8],w_data_rd_data[39-:8],w_data_rd_data[47-:8], w_data_rd_data[55-:8],w_data_rd_data[63-:8]}; assign o_tx_sequence = {1'b0,r_o_tx_sequence[05:00]}; assign o_tx_header = r_o_tx_header; assign o_tx_data = r_o_tx_data; assign s_axis_ready = r_s_axis_ready; assign w_sequence_check = r_o_tx_sequence == 31; assign w_send_valid = (r_data_rd_en)&&(!w_sequence_check); always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_o_tx_sequence <= 0; end else if(r_o_tx_sequence == 'd32) begin r_o_tx_sequence <= 0; end else begin r_o_tx_sequence <= r_o_tx_sequence + 1'b1; end end Gt_txfifo Gt_txfifo ( .clk ( i_tx_clk ), // input wire clk .srst ( i_tx_reset ), // input wire srst .din ( w_data_wr_data ), // input wire [63 : 0] din .wr_en ( w_data_wr_en ), // input wire wr_en .rd_en ( w_send_valid ), // input wire rd_en .dout ( w_data_rd_data ), // output wire [63 : 0] dout .full ( w_full ), // output wire full .empty ( w_empty ), // output wire empty .data_count ( w_data_count ) // output wire [9 : 0] data_count ); always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_o_tx_header <= 2'b00; r_o_tx_data <= 0; end else if(r_st_current == P_ST_FRAMESTART && w_send_valid) begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {w_data_rd_data_conv[55:0],P_FLAG_START}; end else if(r_st_current == P_ST_DATALOADS && w_send_valid) begin r_o_tx_header <= P_FrameHeader_DATA; r_o_tx_data <= {w_data_rd_data_conv[55:0],r1_data_rd_data[63-:8]}; end else if(r_st_current == P_ST_END1 && w_send_valid) begin case (r_s_axis_keep) 8'b1111_1111:begin r_o_tx_header <= P_FrameHeader_DATA; r_o_tx_data <= {w_data_rd_data_conv[55:00],r1_data_rd_data[63-:8]}; end 8'b1111_1110:begin r_o_tx_header <= P_FrameHeader_DATA; r_o_tx_data <= {w_data_rd_data_conv[55:00],r1_data_rd_data[63-:8]}; end 8'b1111_1100:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {w_data_rd_data_conv[47:00],r1_data_rd_data[63-:8],P_FLAG_END_7}; end 8'b1111_1000:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{1{7'h16}},1'b0,w_data_rd_data_conv[39:00],r1_data_rd_data[63-:8],P_FLAG_END_6}; end 8'b1111_0000:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{2{7'h16}},2'b0,w_data_rd_data_conv[31:00],r1_data_rd_data[63-:8],P_FLAG_END_5}; end 8'b1110_0000:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{3{7'h16}},3'b0,w_data_rd_data_conv[23:00],r1_data_rd_data[63-:8],P_FLAG_END_4}; end 8'b1100_0000:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{4{7'h16}},4'b0,w_data_rd_data_conv[15:00],r1_data_rd_data[63-:8],P_FLAG_END_3}; end 8'b1000_0000:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{5{7'h16}},5'b0,w_data_rd_data_conv[07:00],r1_data_rd_data[63-:8],P_FLAG_END_2}; end default: begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{8{7'h16}},P_FLAG_IDLE}; end endcase end else if(r_st_current == P_ST_END2) begin case (r_s_axis_keep) 8'b1111_1111:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{6{7'h16}},6'b0,r1_data_rd_data[63-:8],P_FLAG_END_1}; end 8'b1111_1110:begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{7{7'h16}},7'b0,P_FLAG_END_0}; end default: begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{8{7'h16}},P_FLAG_IDLE}; end endcase end else begin r_o_tx_header <= P_FrameHeader_CONTROL; r_o_tx_data <= {{8{7'h16}},P_FLAG_IDLE}; end end always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r1_data_rd_data <= 0; end else if(w_send_valid) begin r1_data_rd_data <= w_data_rd_data_conv; end end always @(posedge i_tx_clk) begin r1_w_data_wr_en <= w_data_wr_en; r2_w_data_wr_en <= r1_w_data_wr_en; r3_w_data_wr_en <= r2_w_data_wr_en; r2_data_rd_data <= r1_data_rd_data; end always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_data_rd_en <= 1'b0; end else if(w_send_valid == 1'b1 && r_send_cnt == r_valid_cnt - 1'b1) begin r_data_rd_en <= 1'b0; end else if(r_st_current == P_ST_FRAMESTART) begin r_data_rd_en <= 1'b1; end else begin r_data_rd_en <= r_data_rd_en; end end always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_send_cnt <= 0; end else if(w_send_valid == 1'b1 && r_send_cnt == r_valid_cnt - 1'b1) begin r_send_cnt <= 0; end else if(w_send_valid == 1'b1) begin r_send_cnt <= r_send_cnt + 1'b1; end end always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_valid_cnt <= 0; end else if(w_send_valid == 1'b1 && r_send_cnt == r_valid_cnt - 1'b1) begin r_valid_cnt <= 0; end else if(w_data_wr_en == 1'b1) begin r_valid_cnt <= r_valid_cnt + 1'b1; end else begin r_valid_cnt <= r_valid_cnt; end end always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_st_current <= P_ST_INIT; end else begin r_st_current <= r_st_next; end end always @(*) begin case (r_st_current) P_ST_INIT:begin r_st_next <= P_ST_IDLE; end P_ST_IDLE:begin if(r3_w_data_wr_en == 1) begin r_st_next <= P_ST_FRAMESTART; end else begin r_st_next <= P_ST_IDLE; end end P_ST_FRAMESTART:begin if(w_send_valid) begin r_st_next <= P_ST_DATALOADS; end else begin r_st_next <= P_ST_FRAMESTART; end end P_ST_DATALOADS:begin if(w_send_valid == 1'b1 && r_send_cnt == r_valid_cnt - 2 ) begin r_st_next <= P_ST_END1; end else begin r_st_next <= P_ST_DATALOADS; end end P_ST_END1:begin if(w_send_valid) begin case (r_s_axis_keep) 8'b1111_1111: r_st_next <= P_ST_END2; 8'b1111_1110: r_st_next <= P_ST_END2; 8'b1111_1100: r_st_next <= P_ST_IDLE; 8'b1111_1000: r_st_next <= P_ST_IDLE; 8'b1111_0000: r_st_next <= P_ST_IDLE; 8'b1110_0000: r_st_next <= P_ST_IDLE; 8'b1100_0000: r_st_next <= P_ST_IDLE; 8'b1000_0000: r_st_next <= P_ST_IDLE; default: r_st_next <= P_ST_INIT; endcase end else begin r_st_next <= P_ST_END1; end end P_ST_END2:begin r_st_next <= P_ST_IDLE; end default:begin r_st_next <= P_ST_INIT; end endcase end always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_s_axis_keep <= 0; end else if(s_axis_last) begin r_s_axis_keep <= s_axis_keep; end end always @(posedge i_tx_clk) begin if(i_tx_reset == 1'b1) begin r_s_axis_ready <= 1'b1; end else if(s_axis_last) begin r_s_axis_ready <= 1'b0; end else if(r_st_current == P_ST_IDLE) begin r_s_axis_ready <= 1'b1; end else begin r_s_axis_ready <= r_s_axis_ready; end end endmodule