筆記:從Aurora 8b/10b 到Aurora 64b/66b (三):自定義PHY層收發

NoNounknow發表於2024-08-07

相較於8/10來說沒那麼複雜,需要考慮的情況只有八種;

但是gearbox的控制需要額外的心思:每三十二週期所有操作都需要停止;

這一點在收發都需要注意;

RX:

核心思想是利用header做檢測,將夾雜在資料流中的控制包濾除掉;

筆記:從Aurora 8b/10b 到Aurora 64b/66b (三):自定義PHY層收發
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
View Code

TX:

只需要在gearbox需要暫停的時候停止即可;

筆記:從Aurora 8b/10b 到Aurora 64b/66b (三):自定義PHY層收發
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
View Code

相關文章