乙太網MAC層處理CRC的兩種方法

NoNounknow發表於2024-08-21

1.資源消耗少,但是處理慢的方法;

輸入資料存入FIFO1,校驗資料存入FIFO2,存FIFO的過程中校驗並將資料存入FIFO2,存完1以後讀出FIFO2的資料並且判斷,如果正確則輸出資料流,錯誤則不輸出;

這種方法只需要兩個FIFO,但是面臨一個問題是:FIFO的資料只能讀出,直接清空時序很難控制,也不利於資料流處理;

可參考程式碼:

乙太網MAC層處理CRC的兩種方法
module mac_rx #(
    parameter   Protocol_UDP          =  8'h11                               ,
    parameter   Protocol_ICMP         =  8'h01                               ,
    parameter   UDP_MAC_CODE          = {8'h08,8'h00}                        ,
    parameter   ARP_MAC_CODE          = {8'h08,8'h06}                        ,
    parameter   Packet_IP             = {8'h08,8'h00}                        ,
    parameter   Packet_ARP            = {8'h08,8'h06}                        ,
    parameter   default_rx_target_mac = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00},
    parameter   default_rx_source_mac = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00},
    parameter   RX_SOURCE_PORT        = 16'd0808                             ,
    parameter   RX_TARGET_PORT        = 16'd8080                             ,
    parameter   RX_Sync_Frame         = {8'hF0,8'h5A,8'hA5,8'h0F}           
)(
    input   wire            sys_rst_n           ,
    input   wire            eth_rx_clk          ,

    /*--------GMII port--------*/
    input   wire            eth_rx_vaild        ,
    input   wire  [7:0]     eth_rx_data         ,
    //ARP module
    input   wire            i_target_mac_vaild  ,
    input   wire  [47:0]    i_target_mac        ,
    input   wire            i_source_mac_vaild  ,
    input   wire  [47:0]    i_source_mac        ,
    //arp
    output  wire            rx_arp_vaild        ,
    output  wire  [7:0]     rx_arp_data         ,    
    //icmp
    output  wire            rx_icmp_vaild       ,
    output  wire  [7:0]     rx_icmp_data        ,
    //udp
    output  wire            rx_udp_vaild        ,
    output  wire  [7:0]     rx_udp_data         ,

    output  wire            rx_udp_sync  
);
///////////////////////////////////////////////////////////////////////////

        //rxfifo
            wire            rxfifo_wr_clk       ;
            wire            rxfifo_wr_en        ;
            wire  [7:0]     rxfifo_wr_data      ;
            wire            rxfifo_rd_clk       ;
            reg             rxfifo_rd_en        ;
            wire  [7:0]     rxfifo_rd_data      ;
            wire            rxfifo_full         ; 
            wire            rxfifo_empty        ;   
            reg   [15:0]    rxfifo_rd_cnt       ;  
        //crc       
            wire            crc_error           ; 
            wire            crc_end             ;
        //rx cnt        
            reg             r_rx_vaild          ;
            reg   [15:0]    rx_vaild_cnt        ;
            reg   [13:0]    packet_length       ;
        //check  
            reg             udp_check_define    ;
            reg             udp_check_ip        ;
            reg             arp_check_define    ;
            reg             icmp_check          ;
            reg             source_port_check   ;
            reg             target_port_check   ;
            reg             packet_vaild        ;
        //status fifo   
            wire            status_wr_en        ;
            wire  [18:0]    status_wr_data      ;
            reg             status_rd_en        ;
            wire  [18:0]    status_rd_data      ;
            reg   [18:0]    r1_status_rd_data   ;
            wire            status_full         ;
            wire            status_empty        ;

            reg             status_cycle        ;  
            reg             status_check_udp_ip ;   
            reg             status_check_arp    ;
            reg             status_check_icmp   ;

            reg             r1_rx_udp_vaild     ;  
        //sync head
            reg             frame_sync_check    ;
            reg             frame_sync_vaild    ;   
            reg  [7:0]      frame_sync_cnt      ;

        //mac
            reg  [47:0]     r1_target_mac       ;
            reg  [47:0]     r1_source_mac       ;
        //
            reg             r1_rx_arp_vaild     ;
            reg  [7:0]      r1_rx_arp_data      ;
            reg             r1_rx_icmp_vaild    ;
            reg  [7:0]      r1_rx_icmp_data     ;

///////////////////////////////////////////////////////////////////////////

    always @(posedge eth_rx_clk) begin
        r_rx_vaild <= eth_rx_vaild;
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_target_mac <= default_rx_target_mac;
        end else if(i_target_mac_vaild == 1'b1) begin
            r1_target_mac <= i_target_mac;
        end
    end    

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_source_mac <= default_rx_source_mac;
        end else if(i_source_mac_vaild == 1'b1) begin
            r1_source_mac <= i_source_mac;
        end
    end   

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            rx_vaild_cnt <= 16'b0;
        end else if(eth_rx_vaild == 1'b0 && r_rx_vaild == 1'b1) begin
            rx_vaild_cnt <= 16'b0;
        end else if(eth_rx_vaild == 1'b1) begin
            rx_vaild_cnt <= rx_vaild_cnt + 1'b1;
        end else begin
            rx_vaild_cnt <= rx_vaild_cnt;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            packet_length <= 'd0;
        end else if(eth_rx_vaild == 1'b0 && r_rx_vaild == 1'b1) begin
            packet_length <= rx_vaild_cnt;
        end else begin
            packet_length <= packet_length;
        end
    end

// rxfifo && CRC
//-------------------------------------------------------------------------------------------//
    //rxfifo wr
    assign  rxfifo_wr_clk  = eth_rx_clk;
    assign  rxfifo_wr_en   = eth_rx_vaild;
    assign  rxfifo_wr_data = eth_rx_data;
    //rxfifo rd
    assign  rxfifo_rd_clk  = eth_rx_clk;



    CRC32_D8  CRC32_D8_inst0 (
        .i_clk                   ( eth_rx_clk          ),
        .i_rst_n                 ( sys_rst_n           ),
        .i_vaild                 ( eth_rx_vaild        ),
        .i_data                  ( eth_rx_data         ),

        .o_crc_error             ( crc_error           ),
        .o_crc_end               ( crc_end             )
    );

    eth_rxfifo_w8d8192 eth_rxfifo (
    .rst        ( !sys_rst_n         ),  // input  wire rst
    .wr_clk     ( rxfifo_wr_clk      ),  // input  wire wr_clk
    .rd_clk     ( rxfifo_rd_clk      ),  // input  wire rd_clk
    .din        ( rxfifo_wr_data     ),  // input  wire [7 : 0] din
    .wr_en      ( rxfifo_wr_en       ),  // input  wire wr_en
    .rd_en      ( rxfifo_rd_en       ),  // input  wire rd_en
    .dout       ( rxfifo_rd_data     ),  // output wire [7 : 0] dout
    .full       ( rxfifo_full        ),  // output wire full
    .empty      ( rxfifo_empty       ),  // output wire empty
    .wr_rst_busy(  ),  // output wire wr_rst_busy
    .rd_rst_busy(  )   // output wire rd_rst_busy
    );
//-------------------------------------------------------------------------------------------//

//Port && UDP && Packet Check
//-------------------------------------------------------------------------------------------//

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            udp_check_define <= 1'b0;
        end else if(crc_end == 1'b1) begin
            udp_check_define <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd20 && eth_rx_data == UDP_MAC_CODE[15:8]) begin
            udp_check_define <= 1'b1;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd21 && eth_rx_data != UDP_MAC_CODE[07:0]) begin
            udp_check_define <= 1'b0;
        end else begin
            udp_check_define <= udp_check_define;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            arp_check_define <= 1'b0;
        end else if(crc_end == 1'b1) begin
            arp_check_define <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd20 && eth_rx_data == ARP_MAC_CODE[15:8]) begin
            arp_check_define <= 1'b1;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd21 && eth_rx_data != ARP_MAC_CODE[07:0]) begin
            arp_check_define <= 1'b0;
        end else begin
            arp_check_define <= arp_check_define;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            udp_check_ip <= 1'b0;
        end else if(eth_rx_vaild == 1'b0 && r_rx_vaild == 1'b1) begin
            udp_check_ip <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd31 && eth_rx_data == Protocol_UDP[7:0]) begin
            udp_check_ip <= 1'b1;
        end else begin
            udp_check_ip <= udp_check_ip;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            icmp_check <= 1'b0;
        end else if(crc_end == 1'b1) begin
            icmp_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd31 && eth_rx_data == Protocol_ICMP[7:0]) begin
            icmp_check <= 1'b1;
        end else begin
            icmp_check <= icmp_check;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            source_port_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b0 && r_rx_vaild == 1'b1) begin
            source_port_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd42 && eth_rx_data == RX_SOURCE_PORT[15:8]) begin
            source_port_check <= 1'b1;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd43 && eth_rx_data != RX_SOURCE_PORT[07:0]) begin
            source_port_check <= 1'b0;
        end else begin
            source_port_check <= source_port_check;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            target_port_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b0 && r_rx_vaild == 1'b1) begin
            target_port_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd44 && eth_rx_data == RX_TARGET_PORT[15:8]) begin
            target_port_check <= 1'b1;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd45 && eth_rx_data != RX_TARGET_PORT[07:0]) begin
            target_port_check <= 1'b0;
        end else begin
            target_port_check <= target_port_check;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            frame_sync_check <= 1'b0;
        end else if(crc_end == 1'b1) begin
            frame_sync_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd50 && eth_rx_data == RX_Sync_Frame[31:24]) begin
            frame_sync_check <= 1'b1;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd51 && eth_rx_data != RX_Sync_Frame[23:16]) begin
            frame_sync_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd52 && eth_rx_data != RX_Sync_Frame[15:08]) begin
            frame_sync_check <= 1'b0;
        end else if(eth_rx_vaild == 1'b1 && rx_vaild_cnt == 'd53 && eth_rx_data != RX_Sync_Frame[07:0]) begin
            frame_sync_check <= 1'b0;
        end else begin
            frame_sync_check <= frame_sync_check;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            packet_vaild <= 1'b0;
        end else if(crc_end == 1'b1) begin
            packet_vaild <= 1'b0;
        end else if(eth_rx_vaild == 1'b0 && r_rx_vaild == 1'b1 && udp_check_ip == 1'b1 
                                                               && udp_check_define  == 1'b1
                                                               && source_port_check == 1'b1 
                                                               && target_port_check == 1'b1) begin
            packet_vaild <= 1'b1;                                
        end else begin
            packet_vaild <= packet_vaild;                    
        end
    end

//-------------------------------------------------------------------------------------------//
    
    assign  status_wr_en   = crc_end;
    assign  status_wr_data = {arp_check_define, //18
                              icmp_check,       //17
                              frame_sync_check, //16
                              (!crc_error),     //15
                              (packet_vaild),   //14
                              packet_length};   //13:0

    as_rxfifo_w16d64 status_buffer_fifo (
    .wr_clk ( eth_rx_clk        ),  // input wire wr_clk
    .rd_clk ( eth_rx_clk        ),  // input wire rd_clk
    .din    ( status_wr_data    ),  // input wire [18 : 0] din
    .wr_en  ( status_wr_en      ),  // input wire wr_en
    .rd_en  ( status_rd_en      ),  // input wire rd_en
    .dout   ( status_rd_data    ),  // output wire [18 : 0] dout
    .full   ( status_full       ),  // output wire full
    .empty  ( status_empty      )   // output wire empty
    );

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_status_rd_data <= 16'd0;
        end else if(status_rd_en == 1'b1 && status_cycle == 1'b0) begin
            r1_status_rd_data <= status_rd_data;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            status_rd_en <= 1'b0;
        end else if(status_rd_en == 1'b1 || status_cycle == 1'b1) begin
            status_rd_en <= 1'b0;
        end else if(status_empty == 1'b0 && status_cycle == 1'b0) begin
            status_rd_en <= 1'b1;
        end else begin
            status_rd_en <= 1'b0;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            status_cycle <= 1'b0;
        end else if(rxfifo_rd_en == 1'b1 && rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
            status_cycle <= 1'b0;
        end else if(status_rd_en == 1'b1 && status_cycle == 1'b0) begin
            status_cycle <= 1'b1;
        end else begin
            status_cycle <= status_cycle;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            rxfifo_rd_en <= 1'b0;
        end else if(rxfifo_rd_en == 1'b1 && rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
            rxfifo_rd_en <= 1'b0;
        end else if(status_rd_en == 1'b1 && status_cycle == 1'b0) begin
            rxfifo_rd_en <= 1'b1;
        end else begin
            rxfifo_rd_en <= rxfifo_rd_en;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            rxfifo_rd_cnt <= 16'd0;
        end else if(rxfifo_rd_en == 1'b1) begin
            if(rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
                rxfifo_rd_cnt <= 16'd0; 
            end else begin
                rxfifo_rd_cnt <= rxfifo_rd_cnt + 1'b1;
            end 
        end else begin
            rxfifo_rd_cnt <= rxfifo_rd_cnt;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            status_check_udp_ip <= 1'b0;
        end else if(rxfifo_rd_en == 1'b1 && rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
            status_check_udp_ip <= 1'b0;
        end else if(status_rd_en == 1'b1 && status_cycle == 1'b0) begin
            if(status_rd_data[18] == 1'b0 && status_rd_data[17] == 1'b0 &&
               status_rd_data[16] == 1'b0 && status_rd_data[15] == 1'b1 && status_rd_data[14] == 1'b1) begin
               status_check_udp_ip <= 1'b1;
            end else begin
                status_check_udp_ip <= 1'b0;
            end
        end else begin
            status_check_udp_ip <= status_check_udp_ip;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_rx_udp_vaild <= 1'b0;
        end else if(status_cycle == 1'b1 && status_check_udp_ip == 1'b1 && rxfifo_rd_en == 1'b1) begin
            if(rxfifo_rd_cnt >= 'd49 && rxfifo_rd_cnt < r1_status_rd_data[13:0] - 1'b1 - 3'd4) begin
                r1_rx_udp_vaild <= 1'b1;
            end else begin
                r1_rx_udp_vaild <= 1'b0;
            end
        end else begin
            r1_rx_udp_vaild <= 1'b0;
        end
    end

    assign  rx_udp_vaild    =  r1_rx_udp_vaild;
    assign  rx_udp_data     = (rx_udp_vaild == 1'b1)?(rxfifo_rd_data):(0);

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            frame_sync_vaild <= 1'b0;
        end else if(rxfifo_rd_en == 1'b1 && rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
            frame_sync_vaild <= 1'b0;
        end else if(frame_sync_vaild == 1'b1 && frame_sync_cnt == 'd15) begin
            frame_sync_vaild <= 1'b0;
        end else if(status_rd_en == 1'b1 && status_cycle == 1'b0) begin
            if(status_rd_data[18] == 1'b0 && 
               status_rd_data[17] == 1'b0 && status_rd_data[16] == 1'b1 && 
               status_rd_data[15] == 1'b1 && status_rd_data[14] == 1'b1) begin
                frame_sync_vaild <= 1'b1;
            end else begin
                frame_sync_vaild <= 1'b0;
            end
        end else begin
            frame_sync_vaild <= frame_sync_vaild;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            frame_sync_cnt <= 'd0;
        end else if(rxfifo_rd_en == 1'b1 && rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
            frame_sync_cnt <= 'd0;
        end else if(frame_sync_vaild == 1'b1) begin
            if(frame_sync_cnt == 'd15) begin
                frame_sync_cnt <= 'd0;
            end else begin
                frame_sync_cnt <= frame_sync_cnt + 1'b1;
            end
        end
    end

    assign  rx_udp_sync =  frame_sync_vaild;

    //arp
    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            status_check_arp <= 1'b0;
        end else if(rxfifo_rd_en == 1'b1 && rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
            status_check_arp <= 1'b0;
        end else if(status_rd_en == 1'b1 && status_cycle == 1'b0) begin
            if(status_rd_data[18] == 1'b1 && 
               status_rd_data[17] == 1'b0 && status_rd_data[16] == 1'b0 && 
               status_rd_data[15] == 1'b1 && status_rd_data[14] == 1'b0) begin
                status_check_arp <= 1'b1;
            end else begin
                status_check_arp <= 1'b0;
            end
        end else begin
            status_check_arp <= status_check_arp;
        end
    end

    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_rx_arp_vaild <= 1'b0;
        end else if(status_cycle == 1'b1 && status_check_arp == 1'b1 && rxfifo_rd_en == 1'b1) begin
            if(rxfifo_rd_cnt >= 'd7 && rxfifo_rd_cnt < r1_status_rd_data[13:0] - 1'b1 - 3'd4) begin
                r1_rx_arp_vaild <= 1'b1;
            end else begin
                r1_rx_arp_vaild <= 1'b0;
            end
        end else begin
            r1_rx_arp_vaild <= 1'b0;
        end
    end

    assign rx_arp_vaild = r1_rx_arp_vaild;
    assign rx_arp_data  = (rx_arp_vaild == 1'b1)?(rxfifo_rd_data):(0);

    //icmp
    always @(posedge eth_rx_clk) begin
        if(sys_rst_n == 1'b0) begin
            status_check_icmp <= 1'b0;
        end else if(rxfifo_rd_en == 1'b1 && rxfifo_rd_cnt == r1_status_rd_data[13:0] - 1'b1) begin
            status_check_icmp <= 1'b0;
        end else if(status_rd_en == 1'b1 && status_cycle == 1'b0) begin
            if(status_rd_data[18] == 1'b0 && 
               status_rd_data[17] == 1'b1 && status_rd_data[16] == 1'b0 && 
               status_rd_data[15] == 1'b1 && status_rd_data[14] == 1'b0) begin
                status_check_icmp <= 1'b1;
            end else begin
                status_check_icmp <= 1'b0;
            end
        end else begin
            status_check_icmp <= status_check_icmp;
        end
    end             
endmodule
View Code

1.資源消耗多,但是處理快的方法;

輸入資料存入雙口RAM1,校驗資料存入RAM2,同時把RAM的讀起始地址存入FIFO1,存完資料以後校驗,如果正確則從約定地址開始讀取資料,如果不正確則直接重置RAM1,RAM2的初始地址;

這個方法可以更快的處理這個資料流,但是需要更多的RAM資源。

乙太網MAC層處理CRC的兩種方法
    assign  o_m_axis_data   = r_o_m_axis_data ;
    assign  o_m_axis_user   = r_o_m_axis_user ;
    assign  o_m_axis_keep   = (r_o_m_axis_valid)?(r_o_m_axis_keep):0;
    assign  o_m_axis_last   = r_o_m_axis_last ;
    assign  o_m_axis_valid  = r_o_m_axis_valid;

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_s_axis_data            <= 0;
            r_s_axis_user            <= 0;
            r_s_axis_keep            <= 0;
            r_s_axis_last            <= 0;
            r_s_axis_valid           <= 0;
            r_1d_s_axis_data         <= 0;
            r_1d_s_axis_user         <= 0;
            r_1d_s_axis_keep         <= 0;
            r_1d_s_axis_last         <= 0;
            r_1d_s_axis_valid        <= 0;
            r_1d_bram_data_inst0_enb <= 0;
            r_1d_fifo_crc_rd_en      <= 0;
        end else begin
            r_s_axis_data            <= i_s_axis_data  ;
            r_s_axis_user            <= i_s_axis_user  ;
            r_s_axis_keep            <= i_s_axis_keep  ;
            r_s_axis_last            <= i_s_axis_last  ;
            r_s_axis_valid           <= i_s_axis_valid ;
            r_1d_s_axis_data         <= r_s_axis_data  ;
            r_1d_s_axis_user         <= r_s_axis_user  ;
            r_1d_s_axis_keep         <= r_s_axis_keep  ;
            r_1d_s_axis_last         <= r_s_axis_last  ;
            r_1d_s_axis_valid        <= r_s_axis_valid ;
            r_1d_bram_data_inst0_enb <= r_bram_data_inst0_enb;
            r_1d_fifo_crc_rd_en      <= r_fifo_crc_rd_en     ;
        end
    end

    BRAM_64x256_SD BRAM_64x256_SD_inst0 (
    .clka   ( i_xgmii_clk             ), // input  wire clka
    .ena    ( r_s_axis_valid          ), // input  wire ena
    .wea    ( r_s_axis_valid          ), // input  wire [0 : 0] wea
    .addra  ( r_bram_data_inst0_addra ), // input  wire [7 : 0] addra
    .dina   ( r_s_axis_data           ), // input  wire [63 : 0] dina
    .clkb   ( i_xgmii_clk             ), // input  wire clkb
    .enb    ( r_bram_data_inst0_enb   ), // input  wire enb
    .addrb  ( r_bram_data_inst0_addrb ), // input  wire [7 : 0] addrb
    .doutb  ( w_bram_data_inst0_data  )  // output wire [63 : 0] doutb
    );

    BRAM_16x32_SD BRAM_16x32_SD_inst0 (
    .clka   ( i_xgmii_clk             ), // input  wire clka
    .ena    ( r_s_axis_last           ), // input  wire ena
    .wea    ( r_s_axis_last           ), // input  wire [0 : 0] wea
    .addra  ( r_bram_lens_inst0_addra ), // input  wire [4 : 0] addra
    .dina   ( r_s_axis_user[64+:16]   ), // input  wire [15 : 0] dina
    .clkb   ( i_xgmii_clk             ), // input  wire clkb
    .enb    ( r_bram_lens_inst0_enb   ), // input  wire enb
    .addrb  ( r_bram_lens_inst0_addrb ), // input  wire [4 : 0] addrb
    .doutb  ( w_bram_lens_inst0_data  )  // output wire [15 : 0] doutb
    );

    BRAM_8x32 BRAM_8x32_SD_inst0 (
    .clka   ( i_xgmii_clk             ), // input  wire clka
    .ena    ( r_s_axis_last           ), // input  wire ena
    .wea    ( r_s_axis_last           ), // input  wire [0 : 0] wea
    .addra  ( r_bram_keep_inst0_addra ), // input  wire [4 : 0] addra
    .dina   ( r_s_axis_keep           ), // input  wire [7 : 0] dina
    .clkb   ( i_xgmii_clk             ), // input  wire clkb
    .enb    ( r_bram_keep_inst0_enb   ), // input  wire enb
    .addrb  ( r_bram_keep_inst0_addrb ), // input  wire [4 : 0] addrb
    .doutb  ( w_bram_keep_inst0_data  )  // output wire [7 : 0] doutb
    );

    BRAM_64x32 BRAM_64x32_SD_inst0 (
    .clka   ( i_xgmii_clk             ),// input wire clka
    .ena    ( r_s_axis_last           ),// input wire ena
    .wea    ( r_s_axis_last           ),// input wire [0 : 0] wea
    .addra  ( r_bram_user_inst0_addra ),// input wire [4 : 0] addra
    .dina   ( r_s_axis_user[63:00]    ),// input wire [63 : 0] dina
    .clkb   ( i_xgmii_clk             ),// input wire clkb
    .enb    ( r_bram_user_inst0_enb   ),// input wire enb
    .addrb  ( r_bram_user_inst0_addrb ),// input wire [4 : 0] addrb
    .doutb  ( w_bram_user_inst0_data  ) // output wire [63 : 0] doutb
    );

    FIFO_1x32 FIFO_1x32_inst0 (
    .clk    ( i_xgmii_clk                          ), // input  wire clk
    .din    ( i_crc_error                          ), // input  wire [0 : 0] din
    .wr_en  ( i_crc_out                            ), // input  wire wr_en
    .rd_en  ( r_fifo_crc_rd_en                     ), // input  wire rd_en
    .dout   ( w_fifo_crc_dout                      ), // output wire [0 : 0] dout
    .full   ( w_fifo_crc_full                      ), // output wire full
    .empty  ( w_fifo_crc_empty                     )  // output wire empty
    );

    FIFO_8x32 FIFO_8x32_inst0 (
    .clk    ( i_xgmii_clk                          ), // input  wire clk
    .din    ( r_bram_data_inst0_addra              ), // input  wire [7 : 0] din
    .wr_en  ( r_s_axis_valid && !r_1d_s_axis_valid ), // input  wire wr_en
    .rd_en  ( r_fifo_init_rden                     ), // input  wire rd_en
    .dout   ( w_fifo_data_init_addra               ), // output wire [7 : 0] dout
    .full   ( w_FIFO_8x32_inst0_full               ), // output wire full
    .empty  ( w_FIFO_8x32_inst0_empty              )  // output wire empty
    );

    FIFO_8x32 FIFO_8x32_inst1 (
    .clk    ( i_xgmii_clk                          ), // input  wire clk
    .din    ( {3'b0,r_bram_lens_inst0_addra}       ), // input  wire [7 : 0] din
    .wr_en  ( r_s_axis_last && !r_1d_s_axis_last   ), // input  wire wr_en
    .rd_en  ( r_fifo_init_rden                     ), // input  wire rd_en
    .dout   ( w_bram_lens_init_addra               ), // output wire [7 : 0] dout
    .full   ( w_FIFO_8x32_inst1_full               ), // output wire full
    .empty  ( w_FIFO_8x32_inst1_empty              )  // output wire empty
    );

    FIFO_8x32 FIFO_8x32_inst2 (
    .clk    ( i_xgmii_clk                          ), // input  wire clk
    .din    ( {3'b0,r_bram_keep_inst0_addra}       ), // input  wire [7 : 0] din
    .wr_en  ( r_s_axis_last && !r_1d_s_axis_last   ), // input  wire wr_en
    .rd_en  ( r_fifo_init_rden                     ), // input  wire rd_en
    .dout   ( w_bram_keep_init_addra               ), // output wire [7 : 0] dout
    .full   ( w_FIFO_8x32_inst2_full               ), // output wire full
    .empty  ( w_FIFO_8x32_inst2_empty              )  // output wire empty
    );

    FIFO_8x32 FIFO_8x32_inst3 (
    .clk    ( i_xgmii_clk                          ), // input  wire clk
    .din    ( {3'b0,r_bram_user_inst0_addra}       ), // input  wire [7 : 0] din
    .wr_en  ( r_s_axis_last && !r_1d_s_axis_last   ), // input  wire wr_en
    .rd_en  ( r_fifo_init_rden                     ), // input  wire rd_en
    .dout   ( w_bram_user_init_addra               ), // output wire [7 : 0] dout
    .full   ( w_FIFO_8x32_inst3_full               ), // output wire full
    .empty  ( w_FIFO_8x32_inst3_empty              )  // output wire empty
    );

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_fifo_crc_rd_en <= 1'b0;
        end else if(!w_fifo_crc_empty && !r_fifo_crc_rd_en && !r_fifo_crc_lock) begin
            r_fifo_crc_rd_en <= 1'b1;
        end else begin
            r_fifo_crc_rd_en <= 1'b0;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_fifo_init_rden <= 1'b0;
        end else if(!w_fifo_crc_empty && !r_fifo_crc_rd_en && !r_fifo_crc_lock) begin
            r_fifo_init_rden <= 1'b1;
        end else begin
            r_fifo_init_rden <= 1'b0;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_fifo_crc_lock <= 1'b0;
        end else if(r_bram_data_inst0_enb && r_data_cnt == r_out_lens - 1) begin
            r_fifo_crc_lock <= 1'b0;
        end else if(!w_fifo_crc_empty && !r_fifo_crc_rd_en && !r_fifo_crc_lock) begin
            r_fifo_crc_lock <= 1'b1;
        end else begin
            r_fifo_crc_lock <= r_fifo_crc_lock;
        end
    end

    //bram data
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_data_inst0_addra <= 'd0;
        end else if(r_1d_fifo_crc_rd_en && w_fifo_crc_dout) begin
            r_bram_data_inst0_addra <= w_fifo_data_init_addra;
        end else if(r_s_axis_valid) begin
            r_bram_data_inst0_addra <= r_bram_data_inst0_addra + 1;
        end else begin
            r_bram_data_inst0_addra <= r_bram_data_inst0_addra;
        end
    end

    //bram lens
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_lens_inst0_addra <= 'd0;
        end else if(r_1d_fifo_crc_rd_en && w_fifo_crc_dout) begin
            r_bram_lens_inst0_addra <= w_bram_lens_init_addra;
        end else if(r_s_axis_last) begin
            r_bram_lens_inst0_addra <= r_bram_lens_inst0_addra + 1;
        end else begin
            r_bram_lens_inst0_addra <= r_bram_lens_inst0_addra;
        end
    end

    //bram keep
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_keep_inst0_addra <= 'd0;
        end else if(r_1d_fifo_crc_rd_en && w_fifo_crc_dout) begin
            r_bram_keep_inst0_addra <= w_bram_keep_init_addra;
        end else if(r_s_axis_last) begin
            r_bram_keep_inst0_addra <= r_bram_keep_inst0_addra + 1;
        end else begin
            r_bram_keep_inst0_addra <= r_bram_keep_inst0_addra;
        end
    end

    //bram user
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_user_inst0_addra <= 'd0;
        end else if(r_1d_fifo_crc_rd_en && w_fifo_crc_dout) begin
            r_bram_user_inst0_addra <= w_bram_user_init_addra;
        end else if(r_s_axis_last) begin
            r_bram_user_inst0_addra <= r_bram_user_inst0_addra + 1;
        end else begin
            r_bram_user_inst0_addra <= r_bram_user_inst0_addra;
        end
    end

    /*當CRC校驗正確,為RAM的讀出地址賦予他們RAM當初的寫入地址,取出lens,keep,user等資料*/
    /*當CRC校驗錯誤,他們的寫入地址將被重置,由下一輪資料覆蓋                         */

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_out_run <= 1'd0;
        end else if(r_bram_data_inst0_enb && r_data_cnt == r_out_lens - 1) begin
            r_out_run <= 1'd0;
        end else if(r_1d_fifo_crc_rd_en && !w_fifo_crc_dout) begin
            r_out_run <= 1'd1;
        end else begin
            r_out_run <= r_out_run;
        end
    end

    //lens
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_lens_inst0_enb <= 1'b0;
        end else if(r_1d_fifo_crc_rd_en && !w_fifo_crc_dout) begin
            r_bram_lens_inst0_enb <= 1'b1;
        end else begin
            r_bram_lens_inst0_enb <= 1'b0;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_lens_valid <= 1'b0;
        end else begin
            r_lens_valid <= r_bram_lens_inst0_enb;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_out_lens <= 16'h0;
        end else if(r_lens_valid) begin
            r_out_lens <= w_bram_lens_inst0_data;
        end else begin
            r_out_lens <= r_out_lens;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_lens_inst0_addrb <= 0;
        end else if(r_1d_fifo_crc_rd_en && !w_fifo_crc_dout) begin
            r_bram_lens_inst0_addrb <= w_bram_lens_init_addra;
        end else begin
            r_bram_lens_inst0_addrb <= r_bram_lens_inst0_addrb;
        end
    end

    //keep
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_keep_inst0_enb <= 1'b0;
        end else if(r_1d_fifo_crc_rd_en && !w_fifo_crc_dout) begin
            r_bram_keep_inst0_enb <= 1'b1;
        end else begin
            r_bram_keep_inst0_enb <= 1'b0;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_keep_inst0_addrb <= 0;
        end else if(r_1d_fifo_crc_rd_en && !w_fifo_crc_dout) begin
            r_bram_keep_inst0_addrb <= w_bram_keep_init_addra;
        end else begin
            r_bram_keep_inst0_addrb <= r_bram_keep_inst0_addrb;
        end
    end

    //user
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_user_inst0_enb <= 1'b0;
        end else if(r_1d_fifo_crc_rd_en && !w_fifo_crc_dout) begin
            r_bram_user_inst0_enb <= 1'b1;
        end else begin
            r_bram_user_inst0_enb <= 1'b0;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_user_inst0_addrb <= 0;
        end else if(r_1d_fifo_crc_rd_en && !w_fifo_crc_dout) begin
            r_bram_user_inst0_addrb <= w_bram_user_init_addra;
        end else begin
            r_bram_user_inst0_addrb <= r_bram_user_inst0_addrb;
        end
    end
    //data
    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_data_inst0_enb <= 1'b0;
        end else if(r_bram_data_inst0_enb && r_data_cnt == r_out_lens - 1) begin
            r_bram_data_inst0_enb <= 1'b0;
        end else if(r_lens_valid) begin
            r_bram_data_inst0_enb <= 1'b1;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_data_cnt <= 0;
        end else if(r_bram_data_inst0_enb && r_data_cnt == r_out_lens - 1) begin
            r_data_cnt <= 0;
        end else if(r_bram_data_inst0_enb) begin
            r_data_cnt <= r_data_cnt + 1;
        end else begin
            r_data_cnt <= r_data_cnt;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_bram_data_inst0_addrb <= 0;
        end else if(r_lens_valid) begin
            r_bram_data_inst0_addrb <= w_fifo_data_init_addra;
        end else if(r_bram_data_inst0_enb) begin
            r_bram_data_inst0_addrb <= r_bram_data_inst0_addrb + 1'b1;
        end else begin
            r_bram_data_inst0_addrb <= r_bram_data_inst0_addrb;
        end
         
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_o_m_axis_data <= 0;
        end else begin
            r_o_m_axis_data <= w_bram_data_inst0_data;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_o_m_axis_keep <= 8'b0000_0000;
        end else if(!r_bram_data_inst0_enb && r_1d_bram_data_inst0_enb) begin
            r_o_m_axis_keep <= w_bram_keep_inst0_data;
        end else begin
            r_o_m_axis_keep <= 8'hff;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_o_m_axis_last <= 1'b0;
        end else if(!r_bram_data_inst0_enb && r_1d_bram_data_inst0_enb) begin
            r_o_m_axis_last <= 1'b1;
        end else begin
            r_o_m_axis_last <= 1'b0;
        end
    end

    always @(posedge i_xgmii_clk) begin
        if(i_xgmii_rst) begin
            r_o_m_axis_valid <= 1'b0;
        end else if(r_1d_bram_data_inst0_enb) begin
            r_o_m_axis_valid <= 1'b1;
        end else begin
            r_o_m_axis_valid <= 0;
        end
    end
View Code

需要注意:

1.CRC資料在接受完整幀資料才能校驗完成,所以校驗環節要在一幀完成以後;

2.當CRC校驗正確,輸出資料的過程中要給一個LOCK訊號;

相關文章