同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