1 |
15 |
wzab |
#!/usr/bin/python
|
2 |
|
|
# This is the public domain code written by Wojciech M. Zabolotny
|
3 |
|
|
# ( wzab(at)ise.pw.edu.pl )
|
4 |
|
|
# The functionality has been inspired by the CRC Tool available
|
5 |
|
|
# at http://www.easics.com/webtools/crctool , however the code
|
6 |
|
|
# has been written independently.
|
7 |
|
|
# In fact I have decided to write this code, when I was not able to
|
8 |
|
|
# generate CRC with the crctool for a particular non-typical length
|
9 |
|
|
# of data word.
|
10 |
|
|
# The program crc_gen.py generates the VHDL code for CRC update for given
|
11 |
|
|
# length of the data vector.
|
12 |
|
|
# The length of the CRC results from the coefficient of the CRC polynomial.
|
13 |
|
|
# The arguments are as follows:
|
14 |
|
|
# 1st: Function name. The package name is created by prefixing it with
|
15 |
|
|
# pkg_
|
16 |
|
|
# 2nd: L - for data fed LSB first, M for data fed MSB first
|
17 |
|
|
# 3rd: the width of the data bus,
|
18 |
|
|
# 4th and next: the coefficients of the polynomial (the exponents in fact).
|
19 |
|
|
# For example, to generate the expression for CRC7 for 12bit data transmitted LSB first
|
20 |
|
|
# you should call:
|
21 |
|
|
# crc_gen.py crc7_d12 L 12 7 3 0
|
22 |
|
|
# To generate CRC-12 for 16 bit data transmitted MSB first, you should call:
|
23 |
|
|
# crc_gen.py crc12_d16 M 16 12 11 3 2 1 0
|
24 |
|
|
# The generated code implements a package with the function calculating
|
25 |
|
|
# the new value of the CRC from the previous value of the CRC and
|
26 |
|
|
# the data word.
|
27 |
|
|
import sys
|
28 |
|
|
fun_name=sys.argv[1]
|
29 |
|
|
pkg_name = "pkg_"+fun_name
|
30 |
|
|
data_order=sys.argv[2]
|
31 |
|
|
if data_order != 'L' and data_order != 'M':
|
32 |
|
|
print "The second argument must be 'L' or 'M', not the '"+data_order+"'"
|
33 |
|
|
sys.exit(1)
|
34 |
|
|
data_len=int(sys.argv[3])
|
35 |
|
|
poly=[]
|
36 |
|
|
for i in range(4,len(sys.argv)):
|
37 |
|
|
poly.append(int(sys.argv[i]))
|
38 |
|
|
crc_len=max(poly)
|
39 |
|
|
|
40 |
|
|
#The class "xor_result" implements result of xor-ing of multiple
|
41 |
|
|
# CRC and DATA bits
|
42 |
|
|
# dirty trick: the class relies on global variables crc_len and data_len
|
43 |
|
|
class xor_result:
|
44 |
|
|
def __init__(self,c=-1,d=-1):
|
45 |
|
|
self.c=crc_len*[0]
|
46 |
|
|
self.d=data_len*[0]
|
47 |
|
|
if(c>-1):
|
48 |
|
|
self.c[c]=1
|
49 |
|
|
if(d>-1):
|
50 |
|
|
self.d[d]=1
|
51 |
|
|
def copy(self):
|
52 |
|
|
res=xor_result()
|
53 |
|
|
for i in range(0,crc_len):
|
54 |
|
|
res.c[i]=self.c[i]
|
55 |
|
|
for i in range(0,data_len):
|
56 |
|
|
res.d[i]=self.d[i]
|
57 |
|
|
return res
|
58 |
|
|
# The new XOR operator
|
59 |
|
|
def __xor__(self,x):
|
60 |
|
|
res=xor_result()
|
61 |
|
|
for i in range(0,crc_len):
|
62 |
|
|
res.c[i]=self.c[i]^x.c[i]
|
63 |
|
|
for i in range(0,data_len):
|
64 |
|
|
res.d[i]=self.d[i]^x.d[i]
|
65 |
|
|
return res
|
66 |
|
|
def tostr(self):
|
67 |
|
|
res=""
|
68 |
|
|
for i in range(0,crc_len):
|
69 |
|
|
if self.c[i]==1:
|
70 |
|
|
if res=="":
|
71 |
|
|
res+="c("+str(i)+")"
|
72 |
|
|
else:
|
73 |
|
|
res+=" xor c("+str(i)+")"
|
74 |
|
|
for i in range(0,data_len):
|
75 |
|
|
if self.d[i]==1:
|
76 |
|
|
if res=="":
|
77 |
|
|
res+="d("+str(i)+")"
|
78 |
|
|
else:
|
79 |
|
|
res+=" xor d("+str(i)+")"
|
80 |
|
|
return res
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
#Now we create the CRC vector, which initially contains only the bits
|
84 |
|
|
#of the initial value of the CRC
|
85 |
|
|
CRC=[ xor_result(c=i) for i in range(0,crc_len) ]
|
86 |
|
|
#And the data vector
|
87 |
|
|
DATA=[ xor_result(d=i) for i in range(0,data_len) ]
|
88 |
|
|
#Now we pass the data through the CRC polynomial
|
89 |
|
|
if data_order == 'L':
|
90 |
|
|
d_range = range(0,data_len)
|
91 |
|
|
ord_name = "LSB"
|
92 |
|
|
elif data_order == 'M':
|
93 |
|
|
d_range = range(data_len-1,-1,-1)
|
94 |
|
|
ord_name = "MSB"
|
95 |
|
|
else:
|
96 |
|
|
print "Internal error"
|
97 |
|
|
sys.exit(1)
|
98 |
|
|
for i in d_range:
|
99 |
|
|
#We create the vector for the new CRC
|
100 |
|
|
NCRC = [ xor_result() for k in range(0,crc_len) ]
|
101 |
|
|
#First - the basic shift operation
|
102 |
|
|
for j in range(1,crc_len):
|
103 |
|
|
NCRC[j]=CRC[j-1].copy()
|
104 |
|
|
#Now we add the feedback
|
105 |
|
|
FB=DATA[i] ^ CRC[crc_len-1]
|
106 |
|
|
for j in poly:
|
107 |
|
|
if j == crc_len:
|
108 |
|
|
# This does not require any action
|
109 |
|
|
pass
|
110 |
|
|
else:
|
111 |
|
|
NCRC[j]=NCRC[j] ^ FB
|
112 |
|
|
CRC=NCRC
|
113 |
|
|
pkg_text = '''library ieee;
|
114 |
|
|
use ieee.std_logic_1164.all;
|
115 |
|
|
package ''' + pkg_name +" is\n"
|
116 |
|
|
pkg_text += " -- CRC update for "+str(crc_len)+"-bit CRC and "+\
|
117 |
|
|
str(data_len)+"-bit data ("+ord_name+" first)\n"
|
118 |
|
|
pkg_text += " -- The CRC polynomial exponents: "+str(poly)+"\n"
|
119 |
|
|
fun_decl = ' function ' + fun_name +"(\n" +\
|
120 |
|
|
' din : std_logic_vector('+str(data_len-1)+' downto 0);\n'+\
|
121 |
|
|
' crc : std_logic_vector('+str(crc_len-1)+' downto 0))\n'+\
|
122 |
|
|
' return std_logic_vector'
|
123 |
|
|
pkg_text += fun_decl+';\n'
|
124 |
|
|
pkg_text += 'end '+pkg_name+';\n\n'
|
125 |
|
|
pkg_text += "package body " + pkg_name +" is\n"
|
126 |
|
|
pkg_text += fun_decl + ' is \n'
|
127 |
|
|
pkg_text += ' variable c,n : std_logic_vector(' + str(crc_len-1)+' downto 0);\n'
|
128 |
|
|
pkg_text += ' variable d : std_logic_vector(' + str(data_len-1)+' downto 0);\n'
|
129 |
|
|
pkg_text += ' begin\n'
|
130 |
|
|
pkg_text += ' c := crc;\n d := din; \n'
|
131 |
|
|
for i in range(0,len(CRC)):
|
132 |
|
|
pkg_text += " n("+str(i)+") := "+CRC[i].tostr()+";\n"
|
133 |
|
|
pkg_text += ' return n;\n'
|
134 |
|
|
pkg_text += ' end '+fun_name+";\n"
|
135 |
|
|
pkg_text += 'end '+pkg_name+";\n"
|
136 |
|
|
print pkg_text
|