diff --git a/CMakeLists.txt b/CMakeLists.txt index 8320494..9f1bf20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ set(OPENFPGALOADER_SOURCE src/dirtyJtag.cpp src/efinix.cpp src/efinixHexParser.cpp + src/ice40.cpp src/spiFlash.cpp src/rawParser.cpp src/usbBlaster.cpp @@ -81,6 +82,7 @@ set(OPENFPGALOADER_HEADERS src/dirtyJtag.hpp src/efinix.hpp src/efinixHexParser.hpp + src/ice40.cpp src/progressBar.hpp src/rawParser.hpp src/usbBlaster.hpp diff --git a/README.md b/README.md index 5719b36..b6529c3 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,15 @@ __Current support kits:__ * [Digilent Arty S7 xc7s50](https://reference.digilentinc.com/reference/programmable-logic/arty-s7/start) (memory and spi flash) * [Digilent Nexys Video xc7a200t](https://reference.digilentinc.com/reference/programmable-logic/nexys-video/start) (memory and spi flash) * [Fireant Trion T8](https://www.crowdsupply.com/jungle-elec/fireant) (spi flash active mode) +* [iCEBreaker](https://1bitsquared.com/collections/fpga/products/icebreaker) +* [icestick](https://www.latticesemi.com/icestick) +* [iCE40-HX8K](https://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx) * [Lattice MachXO2 Breakout Board Evaluation Kit (LCMXO2-7000HE)](https://www.latticesemi.com/products/developmentboardsandkits/machxo2breakoutboard) (memory and flash) * Lattice MachXO3LF Starter Kit LCMX03LF-6900C (memory and flash) * [Lattice MachXO3D Development Board (LCMXO3D-9400HC)](https://www.latticesemi.com/products/developmentboardsandkits/machxo3d_development_board) * [Lattice CrossLink-NX Evaluation Board (LIFCL-40-EVN)](https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/CrossLink-NXEvaluationBoard) (memory and spi flash) * [Lattice ECP5 5G Evaluation Board (LFE5UM5G-85F-EVN)](https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP5EvaluationBoard) (memory and spi flash) +* [Olimex iCE40HX1K-EVB](https://www.olimex.com/Products/FPGA/iCE40/iCE40HX1K-EVB/open-source-hardware) * [QMTech CycloneV Core Board](https://fr.aliexpress.com/i/1000006622149.html) (memory) * [Trenz Gowin LittleBee (TEC0117)](https://shop.trenz-electronic.de/en/TEC0117-01-FPGA-Module-with-GOWIN-LittleBee-and-8-MByte-internal-SDRAM) * [Saanlima Pipistrello LX45](http://pipistrello.saanlima.com/index.php?title=Welcome_to_Pipistrello) (memory) @@ -28,6 +32,7 @@ __Supported (tested) FPGA:__ * Anlogic [EG4S20](http://www.anlogic.com/prod_view.aspx?TypeId=10&Id=168&FId=t3:10:3) (SRAM and Flash) * Efinix [Trion T8](https://www.efinixinc.com/products-trion.html) (active mode) * Gowin [GW1N (GW1N-1, GW1N-4, GW1NR-9)](https://www.gowinsemi.com/en/product/detail/2/) (SRAM and Flash) +* Lattice [iCE40 (HX1K,HX8K, UP5K)](https://www.latticesemi.com/en/Products/FPGAandCPLD/iCE40) * Lattice [MachXO2](https://www.latticesemi.com/en/Products/FPGAandCPLD/MachXO2) (SRAM and Flash) * Lattice [MachXO3LF](http://www.latticesemi.com/en/Products/FPGAandCPLD/MachXO3.aspx) (SRAM and Flash) * Lattice [MachXO3D](http://www.latticesemi.com/en/Products/FPGAandCPLD/MachXO3D.aspx) (SRAM and Flash) @@ -442,4 +447,29 @@ __hex file load__ openFPGALoader -b fireant /somewhere/project/outflow/*.hex ``` -Since openFPGALoader access the flash directly in SPI mode the *-b fireant* is required (no autodetection possible) \ No newline at end of file +Since openFPGALoader access the flash directly in SPI mode the *-b fireant* is required (no autodetection possible) + +### ice40 boards (icestick, iCE40-HX8K, iCEBreaker, iCE40HX1K-EVB) + +*.bin* is the default format generated by *nextpnr*, so nothing special +must be done. + +Since most ice40 boards uses the same pinout between *FTDI* and *SPI flash* a generic *ice40_generic* board is provided. + +For the specific case of the *iCE40HX1K-EVB* where no onboard programmer is present, please use this: + +| FTDI | iCE40HX1K-EVB (PGM1) | +|--------------|----------------------| +| SCK (ADBUS0) | Pin 9 | +| SI (ADBUS1) | Pin 7 | +| SO (ADBUS2) | Pin 8 | +| CS (ABDUS4) | Pin 10 | +| RST (ADBUS6 | Pin 6 | +| DONE (ADBUS7)| Pin 5 | + +__bin file load__ +```bash +openFPGALoader -b ice40_generic /somewhere/*.bin +``` + +Since it's a direct access to the flash (SPI) the *-b* option is required. \ No newline at end of file diff --git a/src/board.hpp b/src/board.hpp index bcd9496..192230f 100644 --- a/src/board.hpp +++ b/src/board.hpp @@ -93,6 +93,11 @@ static std::map board_list = { JTAG_BOARD("ecp5_evn", "ft2232", 0, 0), SPI_BOARD("fireant", "efinix", "ft232", DBUS4, DBUS5, DBUS3, DBUS0, DBUS1, DBUS2, DBUS6, 0), + /* most ice40 boards uses the same pinout */ + SPI_BOARD("ice40_generic", "lattice", "ft2232", + DBUS7, DBUS6, + DBUS4, DBUS0, DBUS1, DBUS2, + 0, 0), JTAG_BOARD("machXO2EVN", "ft2232", 0, 0), JTAG_BOARD("machXO3SK", "ft2232", 0, 0), JTAG_BOARD("machXO3EVN", "ft2232", 0, 0), diff --git a/src/ice40.cpp b/src/ice40.cpp new file mode 100644 index 0000000..1a1b379 --- /dev/null +++ b/src/ice40.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 Gwenhael Goavec-Merou + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ice40.hpp" + +#include +#include + +#include +#include + +#include "display.hpp" +#include "ftdispi.hpp" +#include "device.hpp" +#include "rawParser.hpp" +#include "spiFlash.hpp" + +Ice40::Ice40(FtdiSpi* spi, const std::string &filename, + uint16_t rst_pin, uint16_t done_pin, + bool verbose): + Device(NULL, filename, verbose), _rst_pin(rst_pin), + _done_pin(done_pin) +{ + _spi = spi; + _spi->gpio_set_input(_done_pin); + _spi->gpio_set_output(_rst_pin); +} + +Ice40::~Ice40() +{} + +void Ice40::reset() +{ + uint32_t timeout = 1000; + _spi->gpio_clear(_rst_pin); + usleep(1000); + _spi->gpio_set(_rst_pin); + printInfo("Reset ", false); + do { + timeout--; + usleep(12000); + } while (((_spi->gpio_get(true) & _done_pin) == 0) || timeout > 0); + if (timeout == 0) + printError("FAIL"); + else + printSuccess("DONE"); +} + +void Ice40::program(unsigned int offset) +{ + uint32_t timeout = 1000; + + if (_filename == "") + return; + + RawParser bit(_filename, false); + + printInfo("Parse file ", false); + if (bit.parse() == EXIT_SUCCESS) { + printSuccess("DONE"); + } else { + printError("FAIL"); + return; + } + + _spi->gpio_clear(_rst_pin); + + SPIFlash flash(reinterpret_cast(_spi), _verbose); + flash.reset(); + flash.power_up(); + + printf("%02x\n", flash.read_status_reg()); + flash.read_id(); + flash.erase_and_prog(offset, bit.getData(), bit.getLength() / 8); + + _spi->gpio_set(_rst_pin); + usleep(12000); + + printInfo("Wait for CDONE ", false); + do { + timeout--; + usleep(12000); + } while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0); + if (timeout == 0) + printError("FAIL"); + else + printSuccess("DONE"); +} diff --git a/src/ice40.hpp b/src/ice40.hpp new file mode 100644 index 0000000..633369b --- /dev/null +++ b/src/ice40.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 Gwenhael Goavec-Merou + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SRC_ICE40_HPP_ +#define SRC_ICE40_HPP_ + +#include + +#include "device.hpp" +#include "ftdispi.hpp" + +class Ice40: public Device { + public: + Ice40(FtdiSpi *spi, const std::string &filename, + uint16_t rst_pin, uint16_t done_pin, + bool verbose); + ~Ice40(); + + void program(unsigned int offset = 0) override; + /* not supported in SPI Active mode */ + int idCode() override {return 0;} + void reset() override; + + private: + FtdiSpi *_spi; + uint16_t _rst_pin; + uint16_t _done_pin; +}; + +#endif // SRC_ICE40_HPP_ diff --git a/src/main.cpp b/src/main.cpp index 9bbee5d..56fb1b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,7 @@ #include "efinix.hpp" #include "ftdispi.hpp" #include "gowin.hpp" +#include "ice40.hpp" #include "lattice.hpp" #include "jtag.hpp" #include "part.hpp" @@ -163,6 +164,10 @@ int main(int argc, char **argv) Efinix target(spi, args.bit_file, board->reset_pin, board->done_pin, args.verbose); target.program(args.offset); + } else if (board->manufacturer == "lattice") { + Ice40 target(spi, args.bit_file, board->reset_pin, board->done_pin, + args.verbose); + target.program(args.offset); } else { RawParser *bit = NULL; if (board->reset_pin) {