Merge pull request #69 from EnJens/spi-mode
libtrellis: Allow specifying spimode for ecppack
diff --git a/libtrellis/include/Bitstream.hpp b/libtrellis/include/Bitstream.hpp
index 7e00910..08b2d82 100644
--- a/libtrellis/include/Bitstream.hpp
+++ b/libtrellis/include/Bitstream.hpp
@@ -12,6 +12,7 @@
namespace Trellis {
enum class BitstreamCommand : uint8_t {
+ SPI_MODE = 0b01111001,
LSC_RESET_CRC = 0b00111011,
VERIFY_ID = 0b11100010,
LSC_WRITE_COMP_DIC = 0b00000010,
diff --git a/libtrellis/src/Bitstream.cpp b/libtrellis/src/Bitstream.cpp
index 16d6c8c..d87186a 100644
--- a/libtrellis/src/Bitstream.cpp
+++ b/libtrellis/src/Bitstream.cpp
@@ -23,6 +23,11 @@
{"38.8", 0x38},
{"62.0", 0x3b}};
+static const vector<pair<std::string, uint8_t>> spi_modes =
+ {{"fast-read", 0x49},
+ {"dual-spi", 0x51},
+ {"qspi", 0x59}};
+
// The BitstreamReadWriter class stores state (including CRC16) whilst reading
// the bitstream
class BitstreamReadWriter {
@@ -356,6 +361,20 @@
rd.check_crc16();
}
break;
+ case BitstreamCommand::SPI_MODE: {
+ uint8_t spi_mode;
+ rd.get_bytes(&spi_mode, 1);
+ rd.skip_bytes(2);
+
+ auto spimode = find_if(spi_modes.begin(), spi_modes.end(), [&](const pair<string, uint8_t> &fp){
+ return fp.second == spi_mode;
+ });
+ if (spimode == spi_modes.end())
+ throw runtime_error("bad SPI mode" + std::to_string(spi_mode));
+
+ BITSTREAM_NOTE("SPI Mode " << spimode->first);
+ }
+ break;
case BitstreamCommand::DUMMY:
break;
default: BITSTREAM_FATAL("unsupported command 0x" << hex << setw(2) << setfill('0') << int(cmd),
@@ -375,6 +394,19 @@
wr.write_bytes(preamble.begin(), preamble.size());
// Padding
wr.insert_dummy(4);
+
+ if (options.count("spimode")) {
+ auto spimode = find_if(spi_modes.begin(), spi_modes.end(), [&](const pair<string, uint8_t> &fp){
+ return fp.first == options.at("spimode");
+ });
+ if (spimode == spi_modes.end())
+ throw runtime_error("bad spimode option " + options.at("spimode"));
+
+ wr.write_byte(uint8_t(BitstreamCommand::SPI_MODE));
+ wr.write_byte(uint8_t(spimode->second));
+ wr.insert_zeros(2);
+ }
+
// Reset CRC
wr.write_byte(uint8_t(BitstreamCommand::LSC_RESET_CRC));
wr.insert_zeros(3);
diff --git a/libtrellis/tools/ecppack.cpp b/libtrellis/tools/ecppack.cpp
index 5ae362e..31a3f2b 100644
--- a/libtrellis/tools/ecppack.cpp
+++ b/libtrellis/tools/ecppack.cpp
@@ -35,6 +35,7 @@
options.add_options()("freq", po::value<std::string>(), "config frequency in MHz");
options.add_options()("svf", po::value<std::string>(), "output SVF file");
options.add_options()("svf-rowsize", po::value<int>(), "SVF row size in bits (default 8000)");
+ options.add_options()("spimode", po::value<std::string>(), "SPI Mode to use (fast-read, dual-spi, qspi)");
po::positional_options_description pos;
options.add_options()("input", po::value<std::string>()->required(), "input textual configuration");
@@ -110,6 +111,9 @@
if (vm.count("freq"))
bitopts["freq"] = vm["freq"].as<string>();
+ if (vm.count("spimode"))
+ bitopts["spimode"] = vm["spimode"].as<string>();
+
Bitstream b = Bitstream::serialise_chip(c, bitopts);
if (vm.count("bit")) {
ofstream bit_file(vm["bit"].as<string>(), ios::binary);