Here is my implementation of the idea described in that article. This is for USB polynomials. And this only generated the XOR block.
#!/usr/bin/env python
# Inspired by http://outputlogic.com/?p=158
# USB 5 : 0x105 - x^5 + x^2 + 1
# USB 16: 0x18005 - x^16 + x^15 + x^2 + 1
if 0:
N = 8 # Data width
M = 5 # CRC width
P = 0x05 # USB CRC5: x^5 + x^2 + 1
else:
N = 8 # Data width
M = 16 # CRC width
P = 0x8005 # USB CRC16: x^16 + x^15 + x^2 + 1
def crc_bit(crc, bit):
if ((crc >> (M-1)) ^ bit) & 1:
crc = (crc << 1) ^ P
else:
crc = (crc << 1)
return crc & ((1 << M) - 1)
def crc_par(crc, word):
crc_out = crc
for i in range(N):
crc_out = crc_bit(crc_out, (word >> i) & 1)
return crc_out
out_data = [[] for x in range(M)]
out_crc = [[] for x in range(M)]
c = 0
for i in range(N):
c = crc_par(0, 1 << i)
for j in range(M):
if (c & (1 << j)) and (i not in out_data[j]):
out_data[j] += [i]
for i in range(M):
c = crc_par(1 << i, 0)
for j in range(M):
if (c & (1 << j)) and (i not in out_crc[j]):
out_crc[j] += [i]
for j in range(M):
s = ' crc_out[%d] = ' % j
s += ' ^ '.join(['c[%d]' % v for v in out_crc[j]])
s += ' ^ '
s += ' ^ '.join(['d[%d]' % v for v in out_data[j]])
print s
Here is example of the use from the project:
reg [15:0] crc16_tx_r;
always @(posedge clk_i) begin
if (reset_i || ST_IDLE == state_r)
crc16_tx_r <= 16'hffff;
else if (ST_TX_DATA == state_r && pkt_tx_next_o)
crc16_tx_r <= usb_crc16(crc16_tx_r, pkt_tx_data_i);
end
function [15:0] usb_crc16(input [15:0] crc, input [7:0] data);
begin
usb_crc16[0] = crc[8] ^ crc[9] ^ crc[10] ^ crc[11] ^ crc[12] ^
crc[13] ^ crc[14] ^ crc[15] ^ data[0] ^ data[1] ^ data[2] ^
data[3] ^ data[4] ^ data[5] ^ data[6] ^ data[7];
..............................................
usb_crc16[15] = crc[7] ^ crc[8] ^ crc[9] ^ crc[10] ^ crc[11] ^
crc[12] ^ crc[13] ^ crc[14] ^ crc[15] ^ data[0] ^ data[1] ^
data[2] ^ data[3] ^ data[4] ^ data[5] ^ data[6] ^ data[7];
end
endfunction