Merge pull request #71 from mcmasterg/demoscene
roi_harness Basys3 demo
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 4b751d6..bc53f61 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -45,12 +45,14 @@
xilinx/xc7series/bitstream_reader_test.cc
xilinx/xc7series/bitstream_writer_test.cc
xilinx/xc7series/block_type_test.cc
- xilinx/xc7series/frame_address_test.cc
xilinx/xc7series/configuration_bus_test.cc
xilinx/xc7series/configuration_column_test.cc
xilinx/xc7series/configuration_test.cc
xilinx/xc7series/configuration_packet_test.cc
xilinx/xc7series/configuration_packetizer_test.cc
+ xilinx/xc7series/crc_test.cc
+ xilinx/xc7series/ecc_test.cc
+ xilinx/xc7series/frame_address_test.cc
xilinx/xc7series/global_clock_region_test.cc
xilinx/xc7series/part_test.cc
xilinx/xc7series/row_test.cc)
diff --git a/lib/include/prjxray/xilinx/xc7series/crc.h b/lib/include/prjxray/xilinx/xc7series/crc.h
new file mode 100644
index 0000000..df6bcac
--- /dev/null
+++ b/lib/include/prjxray/xilinx/xc7series/crc.h
@@ -0,0 +1,40 @@
+#ifndef PRJXRAY_LIB_XILINX_XC7SERIES_CRC_H_
+#define PRJXRAY_LIB_XILINX_XC7SERIES_CRC_H_
+
+#include <cstdint>
+
+constexpr uint32_t kCrc32CastagnoliPolynomial = 0x82F63B78;
+
+namespace prjxray {
+namespace xilinx {
+namespace xc7series {
+
+// The CRC is calculated from each written data word and the current
+// register address the data is written to.
+
+// Extend the current CRC value with one register address (5bit) and
+// frame data (32bit) pair and return the newly computed CRC value.
+
+uint32_t icap_crc(uint32_t addr, uint32_t data, uint32_t prev) {
+ constexpr int kAddressBitWidth = 5;
+ constexpr int kDataBitWidth = 32;
+
+ uint64_t poly = static_cast<uint64_t>(kCrc32CastagnoliPolynomial) << 1;
+ uint64_t val = (static_cast<uint64_t>(addr) << 32) | data;
+ uint64_t crc = prev;
+
+ for (int i = 0; i < kAddressBitWidth + kDataBitWidth; i++) {
+ if ((val & 1) != (crc & 1))
+ crc ^= poly;
+
+ val >>= 1;
+ crc >>= 1;
+ }
+ return crc;
+}
+
+} // namespace xc7series
+} // namespace xilinx
+} // namespace prjxray
+
+#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CRC_H_
diff --git a/lib/include/prjxray/xilinx/xc7series/ecc.h b/lib/include/prjxray/xilinx/xc7series/ecc.h
new file mode 100644
index 0000000..6abab63
--- /dev/null
+++ b/lib/include/prjxray/xilinx/xc7series/ecc.h
@@ -0,0 +1,49 @@
+#ifndef PRJXRAY_LIB_XILINX_XC7SERIES_ECC_H_
+#define PRJXRAY_LIB_XILINX_XC7SERIES_ECC_H_
+
+#include <cstdint>
+
+namespace prjxray {
+namespace xilinx {
+namespace xc7series {
+
+// Extend the current ECC code with one data word (32 bit) at a given
+// word index in the configuration frame and return the new ECC code.
+
+uint32_t icap_ecc(uint32_t idx, uint32_t data, uint32_t ecc) {
+ uint32_t val = idx * 32; // bit offset
+
+ if (idx > 0x25) // avoid 0x800
+ val += 0x1360;
+ else if (idx > 0x6) // avoid 0x400
+ val += 0x1340;
+ else // avoid lower
+ val += 0x1320;
+
+ if (idx == 0x32) // mask ECC
+ data &= 0xFFFFE000;
+
+ for (int i = 0; i < 32; i++) {
+ if (data & 1)
+ ecc ^= val + i;
+
+ data >>= 1;
+ }
+
+ if (idx == 0x64) { // last index
+ uint32_t v = ecc & 0xFFF;
+ v ^= v >> 8;
+ v ^= v >> 4;
+ v ^= v >> 2;
+ v ^= v >> 1;
+ ecc ^= (v & 1) << 12; // parity
+ }
+
+ return ecc;
+}
+
+} // namespace xc7series
+} // namespace xilinx
+} // namespace prjxray
+
+#endif // PRJXRAY_LIB_XILINX_XC7SERIES_ECC_H_
diff --git a/lib/xilinx/xc7series/crc_test.cc b/lib/xilinx/xc7series/crc_test.cc
new file mode 100644
index 0000000..4e83367
--- /dev/null
+++ b/lib/xilinx/xc7series/crc_test.cc
@@ -0,0 +1,16 @@
+#include <prjxray/xilinx/xc7series/crc.h>
+
+#include <gtest/gtest.h>
+
+namespace xc7series = prjxray::xilinx::xc7series;
+
+TEST(IcapCrcTest, SimpleTests) {
+ // CRC for Zero Data
+ EXPECT_EQ(xc7series::icap_crc(0, 0, 0), 0x0L);
+ // Polynomial (single bit operation)
+ EXPECT_EQ(xc7series::icap_crc(1 << 4, 0, 0), 0x82F63B78);
+ // All Reg/Data bits
+ EXPECT_EQ(xc7series::icap_crc(~0, ~0, 0), 0xBF86D4DF);
+ // All CRC bits
+ EXPECT_EQ(xc7series::icap_crc(0, 0, ~0), 0xC631E365);
+}
diff --git a/lib/xilinx/xc7series/ecc_test.cc b/lib/xilinx/xc7series/ecc_test.cc
new file mode 100644
index 0000000..ae08cc8
--- /dev/null
+++ b/lib/xilinx/xc7series/ecc_test.cc
@@ -0,0 +1,20 @@
+#include <prjxray/xilinx/xc7series/ecc.h>
+
+#include <gtest/gtest.h>
+
+namespace xc7series = prjxray::xilinx::xc7series;
+
+TEST(IcapEccTest, SimpleTests) {
+ // ECC for Zero Data
+ EXPECT_EQ(xc7series::icap_ecc(0, 0, 0), (uint32_t)0x0);
+ // 0x1320 - 0x13FF (avoid lower)
+ EXPECT_EQ(xc7series::icap_ecc(0, 1, 0), (uint32_t)0x1320);
+ // 0x1420 - 0x17FF (avoid 0x400)
+ EXPECT_EQ(xc7series::icap_ecc(0x7, 1, 0), (uint32_t)0x1420);
+ // 0x1820 - 0x1FFF (avoid 0x800)
+ EXPECT_EQ(xc7series::icap_ecc(0x26, 1, 0), (uint32_t)0x1820);
+ // Masked ECC Value
+ EXPECT_EQ(xc7series::icap_ecc(0x32, ~0, 0), (uint32_t)0x000019AC);
+ // Final ECC Parity
+ EXPECT_EQ(xc7series::icap_ecc(0x64, 0, 1), (uint32_t)0x00001001);
+}