I am trying to simulate a code in ModelSim for 16-bit CRC generator of 8 bit data. The logic for generating CRC byte is below, 1. Create a 16 bit crc register and initialize it to all zero's. 2. Now compare each bit of the data byte with the bit 0 of crc register i.e. (data[counter] == crc[0]) 3. If the compare is true, then shift right crc register i.e. crc >> 1 and save it to crc register. 4. If the compare is false, then shift right crc register and xor the result with 16'h1021 (polynomial generator).
Now i am not sure if my implementation of iterating across the data byte through FOR loop inside the always block is correct; in my simulation, the for loop iterates through the data byte on the first positive edge of the clock as seen in the simulation block.
My results is also wrong for the CRC generation.
i.e. Data = 0xF881 Correct CRC = 0x1CED
Below is the Verilog Code (Serial_CRC) with test bench and the simulation results.
//http://www.asic-world.com/examples/verilog/serial_crc.html#Serial_CRC
`timescale 1ns/1ns
`define WIDTH 16
//**************************************************************************
module Serial_CRC_wTB();
//**************************************************************************
reg in_enable;
reg in_clk;
reg in_rst_n;
reg [`WIDTH-9:0] in_data;
wire [`WIDTH-1:0] out_crcOutput;
Serial_CRC TS (.i_data(in_data), .o_crcOutput(out_crcOutput), .i_clk(in_clk), .i_rst_n(in_rst_n), .i_enable(in_enable));
initial
begin
in_clk = 1'b0 ;in_enable = 1'b0; in_rst_n = 1'b1;
#1 in_rst_n = 1'b0;
#2 in_rst_n = 1'b1; in_enable = 1'b1;
@(negedge in_clk) in_data = 8'hF8;
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(negedge in_clk) in_data = 8'h81;
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
#20 $finish;
end
always
#1 in_clk = ~in_clk;
endmodule // Serial_CRC_wTB
//**************************************************************************
module Serial_CRC (input [`WIDTH-9:0] i_data,input i_clk,input i_rst_n,input i_enable, output [`WIDTH-1:0] o_crcOutput);
//**************************************************************************
reg [`WIDTH-1:0] crc;
reg [`WIDTH-9:0] d;
integer counter;
always @ (posedge i_clk) begin
if (~i_rst_n) begin
crc <= {16{1'b0}};
d <= {8{1'b0}};
end
else if (i_rst_n && i_enable) begin
d <= i_data;
for (counter = 0 ; counter <= `WIDTH-9 ; counter = counter + 1) begin
if (d[counter] == crc[0])
crc <= crc >> 1;
else if (d[counter] != crc[0]) begin
crc <= crc >> 1;
crc <= crc ^ 16'h1021;
end // else if block
end // for loop block
end // else if block
end // always block
assign o_crcOutput = crc;
endmodule // Serial_CRC