I take this back a little ...I see absolutely no reason to use anything else than the "standard" serial CRC implementation, and the parallel version of it.
For checking the CRC of a received message, the long division implementation can be better.
You can't do this with the "optimized" serial/parallel CRC generator, since it always assumes M appended zeros after the input message/bits, which is what you want for generating the CRC. The "long division" implementation is the way to go for this type of CRC check.
module serial1(crc, data);
/=============================================================
// Verilog function that implements serial USB CRC5
//=============================================================
input [4:0] crc;
input data;
always @(*)
begin
crc5_serial[0] = crc[4] ^ data;
crc5_serial[1] = crc[0];
crc5_serial[2] = crc[1] ^ crc[4] ^ data;
crc5_serial[3] = crc[2];
crc5_serial[4] = crc[3];
end
//============================================================
endmodule
module serial2 (
input clock,
input enable,
input reset,
input data,
input input_strobe,
output [7:0] crc
);
reg [7:0] C;
genvar i;
generate
for (i = 0; i < 8; i=i+1) begin: reverse
assign crc[i] = ~C[7-i];
end
endgenerate
always @(posedge clock) begin
if (reset) begin
C <= 8'hff;
end else if (enable) begin
if (input_strobe) begin
C[0] <= data ^ C[7];
C[1] <= data ^ C[7] ^ C[0];
C[2] <= data ^ C[7] ^ C[1];
C[7:3] <= C[6:2];
end
end
end
endmodule
The schematic diagrams in your links may confuse you because the layout and the polynomial are different, but both are the same type (the "optimized" CRC generator).
module crc_serial_optimized(clk, reset, data, crc);
//=============================================================
// Verilog function that implements serial USB CRC5
//=============================================================
input clk, reset;
input data;
output reg [4:0] crc;
always @(posedge clk)
begin
if(reset) crc <= 0;
else begin
crc[0] <= crc[4] ^ data;
crc[1] <= crc[0];
crc[2] <= crc[1] ^ crc[4] ^ data;
crc[3] <= crc[2];
crc[4] <= crc[3];
end
end
//============================================================
endmodule
module crc_serial_optmized_tb();
reg clk;
reg reset;
reg data;
wire [4:0] crc;
wire new_data;
crc_serial_optimized crc5(.clk(clk), .reset(reset), .data(data), .crc(crc));
initial
begin
$dumpfile("crc_serial_optimized.vcd");
$dumpvars(1, crc5);
clk = 0;
reset = 1;
//new_data = 0;
data = 0;
@(posedge clk);
@(posedge clk);
reset = 0;
@(posedge clk);
@(posedge clk);
//data = 4'b1011;
//new_data = 1;
data = 1'b1;
@(posedge clk);
//new_data = 0;
data = 1'b1;
@(posedge clk);
data = 1'b0;
@(posedge clk);
data = 1'b1;
@(posedge clk);
@(posedge clk);
// data = 4'b1010;
//new_data = 1;
data = 1'b0;
@(posedge clk);
//new_data = 0;
data = 1'b1;
@(posedge clk);
data = 1'b0;
@(posedge clk);
data = 1'b1;
#50 $finish;
end
always #5 clk = !clk;
endmodule
module crc_serial_optmized_tb();
reg clk;
reg reset;
reg data;
wire [4:0] crc;
wire new_data;
crc_serial_optimized crc5(.clk(clk), .reset(reset), .data(data), .crc(crc));
initial
begin
$dumpfile("crc_serial_optimized.vcd");
$dumpvars(1, crc5);
clk <= 0;
reset <= 1;
//new_data = 0;
data <= 0;
@(posedge clk);
@(posedge clk);
reset <= 0;
@(posedge clk);
@(posedge clk);
//data = 4'b1011;
//new_data = 1;
data <= 1'b1;
@(posedge clk);
//new_data = 0;
data <= 1'b1;
@(posedge clk);
data <= 1'b0;
@(posedge clk);
data <= 1'b1;
@(posedge clk);
@(posedge clk);
// data = 4'b1010;
//new_data = 1;
data <= 1'b0;
@(posedge clk);
//new_data = 0;
data <= 1'b1;
@(posedge clk);
data <= 1'b0;
@(posedge clk);
data <= 1'b1;
#50 $finish;
end
always #5 clk = !clk;
endmodule
module crc_serial_long_division(clk, reset, data, crc);
//=============================================================
// Verilog function that implements serial USB CRC5
//=============================================================
input clk, reset;
input data;
output reg [4:0] crc;
always @(posedge clk)
begin
if(reset) crc <= 0;
else begin
crc[0] <= crc[4] ^ data;
crc[1] <= crc[0];
crc[2] <= crc[1] ^ crc[4];
crc[3] <= crc[2];
crc[4] <= crc[3];
end
end
//============================================================
endmodule
module crc_serial_long_division_tb();
reg clk;
reg reset;
reg data;
wire [4:0] crc;
wire new_data;
crc_serial_long_division crc5(.clk(clk), .reset(reset), .data(data), .crc(crc));
initial
begin
$dumpfile("crc_serial_long_division.vcd");
$dumpvars(1, crc5);
clk <= 0;
reset <= 1;
data <= 0;
@(posedge clk);
@(posedge clk);
reset <= 0;
@(posedge clk);
@(posedge clk);
// appends 5 zeroes
data <= 1'b0;
@(posedge clk);
data <= 1'b0;
@(posedge clk);
data <= 1'b0;
@(posedge clk);
data <= 1'b0;
@(posedge clk);
data <= 1'b0;
//data = 4'b1101; "0xD"
data <= 1'b1;
@(posedge clk);
data <= 1'b1;
@(posedge clk);
data <= 1'b0;
@(posedge clk);
data <= 1'b1;
@(posedge clk);
// data = 4'b1010; "0xA"
data <= 1'b1;
@(posedge clk);
data <= 1'b0;
@(posedge clk);
data <= 1'b1;
@(posedge clk);
data <= 1'b0;
#100 $finish;
end
always #5 clk = !clk;
endmodule
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?