【CRC校驗方法】+【FPGA實現(傳送端)】

NoNounknow發表於2024-04-09

書接上回:

https://www.cnblogs.com/VerweileDoch/p/18105959

傳送端的邏輯和接收端類似,但是需要進行八位內的逆運算和取反:

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_crc_value <= 32'h0;
        end else if(crc_cycle == 1'b1 && crc_cnt == 'd3) begin
            r1_crc_value <= 32'h0;
        end else if(i_vaild == 1'b0 && r1_i_vaild == 1'b1) begin
            r1_crc_value <= crc_value;
        end
    end

    reg [7:0] inver_i;
    always @(*) begin
        for (inver_i = 0;inver_i < 8;inver_i = inver_i + 1'b1 ) begin
            r2_crc_value[31 - inver_i] <= r1_crc_value[24 + inver_i];
            r2_crc_value[23 - inver_i] <= r1_crc_value[16 + inver_i];
            r2_crc_value[15 - inver_i] <= r1_crc_value[08 + inver_i];
            r2_crc_value[07 - inver_i] <= r1_crc_value[0  + inver_i];
        end
    end 

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            r_o_data <= 8'hff;
        end else if(r1_i_vaild == 1'b1 && crc_cycle == 1'b0) begin
            r_o_data <= r1_i_data;
        end else if(crc_cycle == 1'b1) begin
            r_o_data <= ~(r2_crc_value[(31-(crc_cnt << 3))-:8]);
        end else begin
            r_o_data <= 8'hff;
        end
    end

完整程式碼:

module CRC_buffer #(
    parameter   UDP_CODE             =  8'h11                                           ,
    parameter   TX_TARGET_PORT       = 16'd808                                          ,
    parameter   TX_SOURCE_PORT       = 16'd8080                                         ,
    parameter   RX_Sync_Frame        = 32'hF05AA50F                                     ,
    parameter   TX_SOURCE_Addr       = {8'd192,8'd168,8'd0,8'd1}                        ,
    parameter   TX_TARGET_Addr       = {8'hFF,8'hFF,8'hFF,8'hFF}                        ,
    //Length
    parameter   TX_PREAMBLE          = {8'h55,8'h55,8'h55,8'h55,8'h55,8'h55,8'h55,8'hD5},
    parameter   TX_TARGET_MAC        = {8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF}            ,// broadcast packet
    parameter   TX_SOURECE_MAC       = {8'hA8,8'hB2,8'h3C,8'h7D,8'h97,8'hD7}            , 
    parameter   Length_HeartBeat     = 16'd92                                           ,
    parameter   Length_UDP           = 16'd72                                           ,
    parameter   Length_HeartBeat_all = 8'd114                                           ,
    parameter   Length_EnCODE_Packet = 8'd114 
)(
    input   wire            sys_clk            ,
    input   wire            sys_rst_n          ,
    input   wire            i_vaild            ,
    input   wire  [7:0]     i_data             ,
    output  wire            o_vaild            ,
    output  wire  [7:0]     o_data                   
);
            wire  [31:00]   crc_value          ;
             reg  [31:00]   r1_crc_value       ;
             reg  [31:00]   r2_crc_value       ;

            reg             r1_i_vaild         ;  
            reg             r2_i_vaild         ;
            reg   [7:0]     r1_i_data          ;              
            reg   [15:00]   i_vaild_cnt        ;

            reg             crc_cycle          ;
            reg             r_crc_cycle        ;
            reg   [03:00]   crc_cnt            ;

            reg   [07:00]   r_o_data           ;

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            i_vaild_cnt <= 16'd0;
        end else if(i_vaild == 1'b1) begin
            if(i_vaild_cnt == Length_EnCODE_Packet - 1'b1) begin
                i_vaild_cnt <= 16'd0;
            end else begin
                i_vaild_cnt <= i_vaild_cnt + 1'b1;
            end
        end
    end

    always @(posedge sys_clk) begin
        r1_i_vaild  <= i_vaild;  
        r2_i_vaild  <= r1_i_vaild;
        r1_i_data   <= i_data ; 
        r_crc_cycle <=  crc_cycle;
    end

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_crc_value <= 32'h0;
        end else if(crc_cycle == 1'b1 && crc_cnt == 'd3) begin
            r1_crc_value <= 32'h0;
        end else if(i_vaild == 1'b0 && r1_i_vaild == 1'b1) begin
            r1_crc_value <= crc_value;
        end
    end

    reg [7:0] inver_i;
    always @(*) begin
        for (inver_i = 0;inver_i < 8;inver_i = inver_i + 1'b1 ) begin
            r2_crc_value[31 - inver_i] <= r1_crc_value[24 + inver_i];
            r2_crc_value[23 - inver_i] <= r1_crc_value[16 + inver_i];
            r2_crc_value[15 - inver_i] <= r1_crc_value[08 + inver_i];
            r2_crc_value[07 - inver_i] <= r1_crc_value[0  + inver_i];
        end
    end 

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            crc_cycle <= 1'b0;
        end else if(crc_cycle == 1'b1 && crc_cnt == 'd3) begin
            crc_cycle <= 1'b0;
        end else if(i_vaild == 1'b0 && r1_i_vaild == 1'b1) begin
            crc_cycle <= 1'b1;
        end else begin
            crc_cycle <= crc_cycle;
        end
    end

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            crc_cnt <= 4'h0;
        end else if(crc_cycle == 1'b1) begin
            if(crc_cnt== 'd3) begin
                crc_cnt <= 4'h0;
            end else begin
                crc_cnt <= crc_cnt + 1'b1;
            end
        end else begin
            crc_cnt <= 4'h0;
        end
    end 

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            r_o_data <= 8'hff;
        end else if(r1_i_vaild == 1'b1 && crc_cycle == 1'b0) begin
            r_o_data <= r1_i_data;
        end else if(crc_cycle == 1'b1) begin
            r_o_data <= ~(r2_crc_value[(31-(crc_cnt << 3))-:8]);
        end else begin
            r_o_data <= 8'hff;
        end
    end

    assign  o_vaild = (r2_i_vaild)||(r_crc_cycle);
    assign  o_data = r_o_data;

CRC32_D8_Out  CRC32_D8_Out_inst0 (
    .i_clk                   ( sys_clk       ),
    .i_rst_n                 ( sys_rst_n     ),
    .i_data                  ( i_data        ),
    .i_vaild                 ( i_vaild       ),

    .o_crc_error             (               ),
    .o_crc_end               (               ),
    .o_crc_value             ( crc_value     )
);
    reg [07:00] test_cnt;
    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            test_cnt <= 8'd0;
        end else if(o_vaild == 1'b1) begin
            test_cnt <= test_cnt + 1'b1;
        end else begin
            test_cnt <= 8'd0;
        end
    end 
endmodule

相關文章