06-16-2017 08:14 AM
is there some Xilinx IP or tool available to generate code for a (preferably parallel) CRC calculator?
06-18-2017 06:21 PM
@ronnywebers what about this: http://outputlogic.com/?page_id=321 ? Obviously it's not from Xilinx but it was the top pick of https://www.google.com/search?q=crc+generator+verilog
06-18-2017 11:55 PM
thanks @muzaffer, I discovered it also and I'm currently testing it for my CRC case.
But I was wondering, since this is a very common operation that needs to be performed, and the parallel CRC method is not that simple to grasp (at least not at first sight :-), that Xilinx would have built some similar configurable IP. Also I found some CRC wizard for Virtex 5
So I was wondering if Vivado would have something similar. Otherwise I'll have to thrust the code at opencores, and try to understand the conversion from a 'classic LFSR' to parallel CRC. If I understand it correctly, the parallel CRC method allows for a CRC calculation in a single clock cycle? (if word-lenth allows it, otherwise I guess some pipelines need to be added, but I don't think the code generator does that?)
06-19-2017 10:42 AM
I've created the tool mentioned above.
I frequently needed to implement parallel CRC generators and checkers for different protocols, data widths, and FPGA vendors, and had the same question: why there wasn't a simple configurable IP. So a few years ago I put together this tool for other developers to benefit.
06-21-2017 03:15 AM - edited 06-21-2017 08:16 AM
thanks @evgenis1 for creating this tool, I also own your book '100 power tips for FPGA designers', and I'm trying to understand the way your tool works as explained in tip 71, where you show the CRC5 example). This whole 'matrix' magic is not yet clear to me, but I'd like to understand it. Great job, and thanks for writing the book!
I was totally unfamiliar with CRC's so far, so to see if I was correctly using your online tool for my CRC case (88 bit of data with 24 bit CRC), I started with a well-known CRC32, as I did find some VHDL code example here. The example also gave a few test vectors. So I took the VHDL code that I found, and created a testbench for it using the testvectors that were given. The results matched with the code example.
Then I generated a parallel version using your online tool, and created a testbench as well (it was more or less copy/paste of the previous one). However the CRC results were not the same, so I was puzzled. After googling around, I came across this post of some guy having the same 'issues' (?) with your generated code as I did, which gave me a hint :
I wanna complete this thread with the answer. I used the code of http://outputlogic.com/ for Ethernet (802.3) with 4-bits input data width. There are some points to get the correct result. 1. You have to reverse your input nibble(e.g., "1011" -> "1101") 2. You have to xor and reverse the final result (crc_out in this code). (e.g., crc_out(31 downto 0) -> not(crc_out(0 to 31))
So I did these same modifications in your generated template, and reversed my input data, and then the results matched with the VHDL example.
I've attached the generated code and the one that I modified to get results matching the VHDL example that I found. The modifications are like this :
-- bit reverse the vector and one's complement result <= not(reverse_any_vector(crc_out));
the bit reverse was performed like this :
function reverse_any_vector (a: in std_logic_vector) return std_logic_vector is variable result: std_logic_vector(a'RANGE); alias aa: std_logic_vector(a'REVERSE_RANGE) is a; begin for i in aa'RANGE loop result(i) := aa(i); end loop; return result; end; -- function reverse_any_vector
it looks like this cause by is a different convention in what is MSB / LSB of the polynomial? If I look at your polynomial, you start with 1 + x ..., while the VHDL example that I found starts with X^32 + x^26, ... so has this something to do with the different results that I get?
Here's a screenshot of the (correct) results after the modifications and bit reversal of the input data (correct crc is in the output 'result') :
06-21-2017 06:12 AM - edited 06-21-2017 08:17 AM
@evgenis1. I've also attached the a reworked version of the example VHDL code that I found on the web, + the test bench that I wrote for it. So again, after modifying your source file and bit reverting the input data, both give the same results.
02-13-2018 03:28 AM - edited 02-13-2018 03:31 AM
Thanks for creating this tool and making it public!
I just want to check if I understood it right:
I have a 8 bit (byte) data input from GMII interface and want to manipulate the Ethernet Frame so that at the end need a new CRC code. Ethernet Frames will need 4 byte FCS at the end of the frame, frame that can be any length(measured by byte count).
Question: To use this tool correct. I need to choose:
1. Data width=8 bit
2. Polynomial width = 32
Is this correct?
After the complete Ethernet Packet (sequence of random Bytes) passes through this I will have the correct FCS at the end?
12-16-2019 02:24 PM - edited 12-16-2019 02:28 PM
12-16-2019 02:50 PM
Are you asking how to do the parallelization, or are you offering up an example?
As to how to do the parallelization - in it's most simple form - not optimized for performance, but usually sufficient for most designs, the details are NOT much more complicated that putting a "for" loop around a shift of one length, to make the shift and "N" length shift. It really is that easy, to do directly in Verilog/VHDL, and get highly optimal results in just a few lines of code.i.e.
bit [ POLY_LENGTH - 1 : 0 ] lfsr; bit [ N - 1 : 0 ] parallel_lfsr; always_comb begin for( int i = 0; i< N; i++) begin lfsr = do_one_shift_of_lfsr(); parallel_lfsr[ i ] = lfsr[ N - 1 ]; // or index 0 depending on the way you're shifting end end