N
Neil Steiner
Guest
I am unsuccessfully trying to update Spartan6 CRC checksums after I make
packet modifications. This is not a problem for Virtex/E/2/2P/4/5/6/7
or for Spartan3E, but Spartan6 is a different story altogether. I
posted this same question on Xilinx Forums, but there have been no
responses.
I know that Spartan6 packets consist of 16-bit words, unlike the 32-bit
words of the other architectures listed above. UG380 also states that
"The Cyclic Redundancy Check register utilizes a standard 32-bit CRC
checksum algorithm." My perhaps incorrect assumption is that the
polynomial is the same CRC-32C (Castagnoli) polynomial as for
Virtex4/5/6/7 families. I am also assuming that only "payload words"
(after the packet header) factor into the calculation, just as with the
other architectures, and UG380 explicitly shows the address length as 6
bits.
Does anybody know how to calculate this correctly for Spartan6? If
anyone cares to see the logic I'm trying to use, it's quite similar to
what works correctly for all the other Xilinx architectures:
// begin CRC calculation
uint32_t address = 0;
iterator p = begin();
iterator e = end();
// CRC-32C (Castagnoli) polynomial for Virtex4/5/6/7 families
boost::crc_basic<32> crc32(0x1edc6f41, 0, 0, false, true);
while(p < e) {
// look up the current packet
const Spartan6Packet& packet = *p++;
// only process write packets with non-zero payload length
if(!packet.isWrite()) continue;
address = packet.getAddress();
uint32_t wordCount = packet.getWordCount();
if(wordCount == 0) continue;
// CRC register write (this is what compares the expected and
supplied CRC values)
if(address == crcRegister) {
printf("Expected CRC32: %8.8x\n", (uint32_t(packet[1]) <<
16) | packet[2]);
printf("Calculated CRC32: %8.8x\n", crc32.checksum());
*(p-1) = Spartan6Packet::makeType1Write(crcRegister,
crc32.checksum());
crc32.reset();
// reset CRC command
} else if(address == cmdRegister && wordCount >= 1 && packet[1]
== rcrcCommand) {
crc32.reset();
// process packet contents
} else {
uint32_t j;
uint32_t mask;
for(uint32_t i = 1; i <= wordCount; i++) {
uint32_t word = packet;
//printf("Address: %4.4x\n", address);
//printf("Word: %8.8x\n", word);
for(j = 0, mask = 1; j < 16; j++, mask <<= 1) {
crc32.process_bit((word & mask) ? 1 : 0);
}
for(j = 0, mask = 1; j < addressLength; j++, mask <<= 1) {
crc32.process_bit((address & mask) ? 1 : 0);
}
}
// process the Auto CRC
if(autoCrc && address == fdriRegister) {
printf("Expected Auto CRC32: %8.8x\n",
(uint32_t((*p)[0]) << 16) | (*p)[1]);
printf("Calculated Auto CRC32: %8.8x\n", crc32.checksum());
*p = Spartan6Packet(crc32.checksum()); // current
packet is FDRI, next is Auto CRC
crc32.reset();
}
}
}
packet modifications. This is not a problem for Virtex/E/2/2P/4/5/6/7
or for Spartan3E, but Spartan6 is a different story altogether. I
posted this same question on Xilinx Forums, but there have been no
responses.
I know that Spartan6 packets consist of 16-bit words, unlike the 32-bit
words of the other architectures listed above. UG380 also states that
"The Cyclic Redundancy Check register utilizes a standard 32-bit CRC
checksum algorithm." My perhaps incorrect assumption is that the
polynomial is the same CRC-32C (Castagnoli) polynomial as for
Virtex4/5/6/7 families. I am also assuming that only "payload words"
(after the packet header) factor into the calculation, just as with the
other architectures, and UG380 explicitly shows the address length as 6
bits.
Does anybody know how to calculate this correctly for Spartan6? If
anyone cares to see the logic I'm trying to use, it's quite similar to
what works correctly for all the other Xilinx architectures:
// begin CRC calculation
uint32_t address = 0;
iterator p = begin();
iterator e = end();
// CRC-32C (Castagnoli) polynomial for Virtex4/5/6/7 families
boost::crc_basic<32> crc32(0x1edc6f41, 0, 0, false, true);
while(p < e) {
// look up the current packet
const Spartan6Packet& packet = *p++;
// only process write packets with non-zero payload length
if(!packet.isWrite()) continue;
address = packet.getAddress();
uint32_t wordCount = packet.getWordCount();
if(wordCount == 0) continue;
// CRC register write (this is what compares the expected and
supplied CRC values)
if(address == crcRegister) {
printf("Expected CRC32: %8.8x\n", (uint32_t(packet[1]) <<
16) | packet[2]);
printf("Calculated CRC32: %8.8x\n", crc32.checksum());
*(p-1) = Spartan6Packet::makeType1Write(crcRegister,
crc32.checksum());
crc32.reset();
// reset CRC command
} else if(address == cmdRegister && wordCount >= 1 && packet[1]
== rcrcCommand) {
crc32.reset();
// process packet contents
} else {
uint32_t j;
uint32_t mask;
for(uint32_t i = 1; i <= wordCount; i++) {
uint32_t word = packet;
//printf("Address: %4.4x\n", address);
//printf("Word: %8.8x\n", word);
for(j = 0, mask = 1; j < 16; j++, mask <<= 1) {
crc32.process_bit((word & mask) ? 1 : 0);
}
for(j = 0, mask = 1; j < addressLength; j++, mask <<= 1) {
crc32.process_bit((address & mask) ? 1 : 0);
}
}
// process the Auto CRC
if(autoCrc && address == fdriRegister) {
printf("Expected Auto CRC32: %8.8x\n",
(uint32_t((*p)[0]) << 16) | (*p)[1]);
printf("Calculated Auto CRC32: %8.8x\n", crc32.checksum());
*p = Spartan6Packet(crc32.checksum()); // current
packet is FDRI, next is Auto CRC
crc32.reset();
}
}
}