USB的CRC16理解

同crc5,附上verilog代码



// // 在线仿真工具:iverilog
// // https://hdlbits.01xz.net/wiki/Iverilog
// module top_module ();
//     reg clk = 0;
//     reg rst_n = 0;
//     reg start = 0;
//     reg [15:0] byte_cnt = 16'h0001;
//     reg [7:0] bytes = 8'h00;
//     wire [15:0] crc16;
//     wire cal_done;

//     crc5_d11 IP ( 
//         .clk(clk),
//         .rst_n(rst_n),
//         .byte_cnt(byte_cnt),
//         .bytes(bytes),
//         .start(start),
        
//         .crc16(crc16),
//         .cal_done(cal_done)
//     );
    
// 	always #1 clk = ~clk;
// 	initial `probe_start;
// 	initial begin
//         #0 rst_n <= 0;
//         start <= 0;
//         #2 rst_n <= 1;
        
//         #2 bytes <= 8'b0000_0000;
//         start <= 1;
//         #20 start <= 0;
        
//         #2 bytes <= 8'b0000_0000;
//         start <= 1;
//         #20 start <= 0;
        
//         #2 bytes <= 8'b0010_0000;
//         start <= 1;
//         #20 start <= 0;
        
//         #2 bytes <= 8'b1010_0000;
//         start <= 1;
//         #20 start <= 0;
        
//         #2 bytes <= 8'b0110_0000;
//         start <= 1;
//         #20 start <= 0;
        
//         #2 bytes <= 8'b1110_0000;
//         start <= 1;
//         #20 start <= 0;
        
//         #2 bytes <= 8'b0000_0000;
//         start <= 1;
//         #20 start <= 0;
        
//         #2 bytes <= 8'b0000_0000;
//         start <= 1;
//         #20 start <= 0;
        
// 		#20 $finish;
// 	end
// endmodule


// module crc5_d11 (
//     input wire clk,
//     input wire rst_n,
//     input wire [15:0]byte_cnt,//要发送n个bytes,byte_cnt从1~n
//     input wire [7:0]bytes,
//     input wire start,

//     output wire [15:0]crc16,
//     output wire cal_done//除法完成标志
// );

// reg [15:0]crc_temp;
// reg [3:0] crc_cnt;//计数器
// wire crc_need_xor = (crc_temp[0] & 1'b1) ? 1'b1 : 1'b0;
// wire [15:0] crc_xor_val = 16'hA001;
// always@(posedge clk or negedge rst_n) begin
//     if(!rst_n) begin
//         crc_cnt <= 4'd0;
//         crc_temp <= 16'hffff;
//     end
//     else begin
//         if(start) begin
//             if (crc_cnt < 4'd9) begin
//                 crc_cnt <= crc_cnt + 4'd1;
//             end
//             else begin
//                 crc_cnt <= crc_cnt;
//             end
//         end
//         else begin
//             crc_cnt <= 4'd0;
//         end
        
//         if(start) begin
//             if (crc_cnt == 4'd0) begin
//                 crc_temp <= crc_temp ^ {8'h00, bytes};
//             end
//             else if (crc_cnt < 4'd9) begin
//                 if (crc_need_xor) begin
//                     crc_temp <= (crc_temp >> 1) ^ crc_xor_val;
//                 end
//                 else begin
//                     crc_temp <= crc_temp >> 1;
//                 end
//             end
//             else begin
//                 crc_temp <= crc_temp;
//             end
//         end
//         else begin
//             crc_temp <= crc_temp;
//         end
//     end
// end

// assign cal_done = (crc_cnt == 4'd9) ? 1'b1 : 1'b0;
// assign crc16 = ~crc_temp;

//     `probe(clk);
//     `probe(rst_n);
//     `probe(start);
//     `probe(crc_temp);
//     `probe(crc16);
//     `probe(bytes);
//     `probe(crc_cnt);
//     `probe(cal_done);
// endmodule




// 亲测在线生成工具也可以用:http://www.easics.com
// 在线仿真工具:iverilog
// https://hdlbits.01xz.net/wiki/Iverilog
module top_module ();
    reg clk = 0;
    reg rst_n = 0;
    reg [15:0] byte_cnt = 16'h0000;
    reg [7:0] bytes = 8'hff;
    wire [15:0] crc16;
    wire [15:0] cal_done;
    
	`probe(clk);

    usb_crc16 IP ( 
        .clk(clk),
        .rst_n(rst_n),
        .byte_cnt(byte_cnt),
        .bytes(bytes),
        
        .crc16(crc16),
        .cal_done(cal_done)
    );
	always #1 clk = ~clk;
	initial `probe_start;
	initial begin
        #1 rst_n <= 1'b1;

        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0001;
        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0002;
        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0003;
        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0004;
        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0005;
        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0006;
        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0007;
        #2 bytes <= 8'h00;
        byte_cnt <= 16'h0008;

		#20 $finish;
	end
endmodule


module usb_crc16 (
    input wire clk,
    input wire rst_n,
    input wire [15:0]byte_cnt,//要发送n个bytes,byte_cnt从1~n
    input wire [7:0]bytes,

    output reg [15:0]crc16,
    output wire cal_done//除法完成标志
);

reg [15:0] byte_cnt_temp;
wire [15:0] crc16_new;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        byte_cnt_temp <= 16'h0000;
    end
    else begin
        if(byte_cnt == 16'h0000) begin
            byte_cnt_temp <= 16'h0000;
        end
        else if(byte_cnt_temp < byte_cnt) begin
            byte_cnt_temp <= byte_cnt_temp + 16'h0001;
        end
        else begin
            byte_cnt_temp <= byte_cnt_temp;
        end
    end
    
end
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        crc16 <= 16'hffff;
    end
    else begin
        if(byte_cnt == 16'h0000) begin
            crc16 <= 16'hffff;
        end
        else if(byte_cnt_temp < byte_cnt) begin
            crc16 <= crc16_new;
        end
        else begin
            crc16 <= crc16;
        end
    end
end
assign cal_done = (byte_cnt_temp == byte_cnt) ? 
    (byte_cnt_temp != 16'h0000) ? 
        1'b1 
        : 1'b0 
    : 1'b0;

usb_crc16_d8 usb_crc16_d8_u0 (
   .crc_old(crc16),
   .bytes(bytes),
   .crc_new(crc16_new)
);

`probe(rst_n);
`probe(byte_cnt);
`probe(byte_cnt_temp);
`probe(bytes);
`probe(crc16);
`probe(~crc16);
`probe(crc16_new);
`probe(cal_done);

endmodule


module usb_crc16_d8
(
    input wire [15:0] crc_old,
    input wire [7:0] bytes,

    output wire [15:0] crc_new
);
wire [15:0] crc_temp;
assign crc_temp[15] = bytes[0] ^ bytes[1] ^ bytes[2] ^ bytes[3] ^ bytes[4] ^ bytes[5] ^ bytes[6] ^ 
    bytes[7] ^ crc_old[7] ^ crc_old[6] ^ crc_old[5] ^ crc_old[4] ^ crc_old[3] ^ crc_old[2] ^ crc_old[1] ^ crc_old[0];
assign crc_temp[14] = bytes[0] ^ bytes[1] ^ bytes[2] ^ bytes[3] ^ bytes[4] ^ bytes[5] ^
    bytes[6] ^ crc_old[6] ^ crc_old[5] ^ crc_old[4] ^ crc_old[3] ^ crc_old[2] ^ crc_old[1] ^ crc_old[0];
assign crc_temp[13] = bytes[6] ^ bytes[7] ^ crc_old[7] ^ crc_old[6];
assign crc_temp[12] = bytes[5] ^ bytes[6] ^ crc_old[6] ^ crc_old[5];
assign crc_temp[11] = bytes[4] ^ bytes[5] ^ crc_old[5] ^ crc_old[4];
assign crc_temp[10] = bytes[3] ^ bytes[4] ^ crc_old[4] ^ crc_old[3];
assign crc_temp[9] = bytes[2] ^ bytes[3] ^ crc_old[3] ^ crc_old[2];
assign crc_temp[8] = bytes[1] ^ bytes[2] ^ crc_old[2] ^ crc_old[1];
assign crc_temp[7] = bytes[0] ^ bytes[1] ^ crc_old[15] ^ crc_old[1] ^ crc_old[0];
assign crc_temp[6] = bytes[0] ^ crc_old[14] ^ crc_old[0];
assign crc_temp[5] = crc_old[13];
assign crc_temp[4] = crc_old[12];
assign crc_temp[3] = crc_old[11];
assign crc_temp[2] = crc_old[10];
assign crc_temp[1] = crc_old[9];
assign crc_temp[0] = bytes[0] ^ bytes[1] ^ bytes[2] ^ bytes[3] ^ bytes[4] ^ bytes[5] ^ bytes[6] ^ bytes[7] ^ 
    crc_old[8] ^ crc_old[7] ^ crc_old[6] ^ crc_old[5] ^ crc_old[4] ^ crc_old[3] ^ crc_old[2] ^ crc_old[1] ^ crc_old[0];

assign crc_new = crc_temp;
endmodule
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值