Some key points (from https://gitter.im/ulx3s/Lobby/ ):
- the standard JTAG programming stuff only programs FPGA SRAM; So rebooting the board will "recover" it
In general you have to go through a fairly tedious process involving Diamond Deployment Tool to create a SVF file to program flash, and this will be very slow Otherwise, you are just programming SRAM(update: this is no longer the case; see ujprog -j flash file.bit
I case you are wondering about that second USB port (the left one, when facing them):
- I guess the ulx3s-passthru bitstream is by default shipped to you, when you have OLED and ESP32 in box then it makes sense to load the board with passthru.
- Other boards without OLED and/or ESP32 are probably shipped with f32c with FAT filesystem on config flash to run self-test application at power up.
- You can erase config flash and ESP32 with whatever you want and flash back to "factory default" from my ulx3s-bin repository.
- passthru is old source and it needs updated makefile like in prjtrellis-dvi. Yes it tries to find diamond.
- Passthru is very simple and it could be ported done using opensource tools only. I'm using vhd2vl. For most simple vhdl examples it works great.
- It can't convert if VHDL source is complex/advanced and has functions and packages.
don't touch the second USB port - it's wired directly into FPGA and thus won't even enumerate on the PC as a serial port unless you do some serious coding at FPGA side (see TinyFPGA Bootloader project - it's pretty much all about it) ... instead, use USB1 which is wired through FT231 chip (see info here)My favorite claims / features:
- ULX3S is unbrickable.
- There is no realistic chance of irreparable damage to the ULX3S in any case
The term "iCEStorm Toolchain" does not mean Yosys, arache-pnr, nextpnr, Trellis; just iCEStorm.
Yosys, arache-pnr, nextpnr, Trellis supports only Verilog, not VHDL
I have a ULX3S 12K. The Blinky from DoctorWkt expects a 45F chip. Even when editing the original Makefile to instead use the
In fact, things were looking pretty bleak, as the nextpnr-ecp5 does not even list the 12F:
Yosys 0.8+148 (git sha1 e112d2fb, clang 6.0.0-1ubuntu2 -fPIC -Os) Time spent: 54% 11x read_verilog (0 sec), 9% 6x techmap (0 sec), ... nextpnr-ecp5 --12k --json blinky.json --basecfg ulx3s_empty.config \ --lpf ulx3s_v20.lpf \ --textcfg ulx3s_out.config unrecognised option '--12k' Makefile:74: recipe for target 'ulx3s_out.config' failed make: * [ulx3s_out.config] Error 255
@daveshah1 to the rescue once again!
nextpnr-ecp5 -- Next Generation Place and Route (git sha1 4c73061) General options: -h [ --help ] show help -v [ --verbose ] verbose output -q [ --quiet ] quiet mode, only errors and warnings displayed -l [ --log ] arg log file, all log messages are written to this file regardless of -q --debug debug output -f [ --force ] keep running after errors --gui start gui --run arg python file to execute instead of default flow --pre-pack arg python file to run before packing --pre-place arg python file to run before placement --pre-route arg python file to run before routing --post-route arg python file to run after routing --json arg JSON design file to ingest --seed arg seed value for random number generator -r [ --randomize-seed ] randomize seed value for random number generator --slack_redist_iter arg number of iterations between slack redistribution --cstrweight arg placer weighting for relative constraint satisfaction --pack-only pack design only without placement or routing --ignore-loops ignore combinational loops in timing analysis -V [ --version ] show version --test check architecture database integrity --freq arg set target frequency for design in MHz --no-tmdriv disable timing-driven placement --save arg project file to write --load arg project file to read Architecture specific options: --25k set device type to LFE5U-25F --45k set device type to LFE5U-45F --85k set device type to LFE5U-85F --um-25k set device type to LFE5UM-25F --um-45k set device type to LFE5UM-45F --um-85k set device type to LFE5UM-85F --um5g-25k set device type to LFE5UM5G-25F --um5g-45k set device type to LFE5UM5G-45F --um5g-85k set device type to LFE5UM5G-85F --package arg select device package (defaults to CABGA381) --speed arg select device speedgrade (6, 7 or 8) --basecfg arg base chip configuration in Trellis text format (deprecated) --override-basecfg arg base chip configuration in Trellis text format --textcfg arg textual configuration in Trellis format to write --lpf arg LPF pin constraint file(s)
pass --25k to nextpnr, remove the basecfg if your nextpnr is yesterday or today's build otherwise point it to a 25k basecfg, and then pass --idcode 0x21111043 to ecppack
I'm not sure I would have ever guessed the
25F, and certainly not the
--idcode 0x21111043part. I pulled the latest SymbiFlow/prjtrellis and nextpnr now (git sha1 4c73061), cleaned and rebuilt everything with my new Makefile, and success to build!
Now recall I am doing this all in WSL Ubuntu, so there are no native USB devices - thus I am forced to use the Windows version of ujprog to actually upload the code to the ULX3S board.
[... snip ..] Info: [ 79471, 79958) | Info: [ 79958, 80445) |*** Info: [ 80445, 80932) |* Info: [ 80932, 81419) |*** Info: [ 81419, 81906) |******** 337 warnings, 0 errors ecppack ulx3s_out.config ulx3s.bit --idcode 0x21111043
The amazing thing here - is that Windows applications can be run from within WSL!
This seems to completely circumvent the "No Native USB Devices" in WSL. For example, here's the same app compiled for linux, not finding the JTAG device:
I'm using the very latest FTDI code in my fork of the f32c tools (I created this PR #9). I still encountered some problems with the syntax of the ujprog. I opened issue #10, which was promptly closed - regarding the expected operation. Bottom line is this is the syntax that works:
And I learned a few more things in the close comment:
C:\workspace-git\f32c_tools\ujprog>ujprog ulx3s.bit ULX2S / ULX3S JTAG programmer v 3.0.92 (built Feb 13 2019 12:27:20) Using USB cable: ULX3S FPGA 12K v3.0.3 Programming: 100% Completed in 18.66 seconds.
JTAG doesn't work in COM mode, so no wonder that uploading a bitstream can't work that way, especially not when using the -a modifier, which tells the ujprog to send the file as a stream of bytes.From gitter:
ujprog note: supported targets are either -j sram or -j flashSo, ya - I get that all this stuff is obvious to the developers & subject matter experts; However, I struggled to learn each of these things when seeing it all for the first time and relatively little documentation. Although there's no README in the f32c/tools/ujprog, I created one in my fork that hopefully will help others.
As mentioned above: in order to program the ESP32, the FPGA needs to be configured in "Pass-Through" mode. @emard's ulx3s-passthru is written in VHDL.
There's a tool called vhdl2vl that can convert some VHDL to Verilog. Yosys has a VDHL reader plugin based on vhdl2vl.
git clone https://github.com/YosysHQ/yosys-plugins.git cd yosys-plugins/vhdl make # mkdir -p /usr/local/share/yosys/plugins # cp vhdl.so /usr/local/share/yosys/plugins/vhdl.so sudo make install
yosys, and from the
This will add a new
plugin -i vhdl plugin -l
There is more documentation on yosys here.
If the plugin is listed and working, typing
yosyswill show help:
The yosys VHDL plugin reads a VDHL file like this:
1. Executing VHDL frontend. Syntax error in command `read_vhdl': read_vhdl [options] [filename] Load modules from a VHDL file to the current design. -dump_ast1 dump abstract syntax tree (before simplification) -dump_ast2 dump abstract syntax tree (after simplification) -no_dump_ptr do not include hex memory addresses in dump (easier to diff dumps) -dump_vhdl dump ast as VHDL code (after simplification) -yydebug enable parser debug output -nolatches usually latches are synthesized into logic loops this option prohibits this and sets the output to 'x' in what would be the latches hold condition this behavior can also be achieved by setting the 'nolatches' attribute on the respective module or always block. -nomem2reg under certain conditions memories are converted to registers early during simplification to ensure correct handling of complex corner cases. this option disables this behavior. this can also be achieved by setting the 'nomem2reg' attribute on the respective module or register. This is potentially dangerous. Usually the front-end has good reasons for converting an array to a list of registers. Prohibiting this step will likely result in incorrect synthesis results. -mem2reg always convert memories to registers. this can also be achieved by setting the 'mem2reg' attribute on the respective module or register. -nomeminit do not infer $meminit cells and instead convert initialized memories to registers directly in the front-end. -ppdump dump VHDL code after pre-processor -nopp do not run the pre-processor -nodpi disable DPI-C support -lib only create empty blackbox modules. This implies -DBLACKBOX. -noopt don't perform basic optimizations (such as const folding) in the high-level front-end. -icells interpret cell types starting with '$' as internal cell types -nooverwrite ignore re-definitions of modules. (the default behavior is to create an error message if the existing module is not a black box module, and overwrite the existing module otherwise.) -overwrite overwrite existing modules with the same name -defer only read the abstract syntax tree and defer actual compilation to a later 'hierarchy' command. Useful in cases where the default parameters of modules yield invalid or not synthesizable code. -noautowire make the default of `default_nettype be "none" instead of "wire". -setattr <attribute_name> set the specified attribute (to the value 1) on all loaded modules -Dname[=definition] define the preprocessor symbol 'name' and set its optional value 'definition' -Idir add 'dir' to the directories which are used when searching include files The command 'vhdl_defaults' can be used to register default options for subsequent calls to 'read_vhdl'. Note that the VHDL frontend does a pretty good job of processing valid VHDL input, but has not very good error reporting. It generally is recommended to use a simulator for checking the syntax of the code, rather than to rely on read_vhdl for that.
There is probably a different message if it was successful.
yosys> read_vhdl ulx3s_v20_passthru_wifi.vhd 3. Executing VHDL frontend. Parsing VHDL input from `ulx3s_v20_passthru_wifi.vhd' to AST representation. ERROR: NOT IMPLEMENTED: ulx3s_v20_passthru_wifi.vhd:16 (vhdl_parser.y:1583)
There's also the vhd2vl noted on the yosys README.
With a bit of help info:
git clone https://github.com/ldoolitt/vhd2vl.git cd vhd2vl/src make ./vhd2vl ../../ulx3s-passthru/rtl/ulx3s_v20_passthru_wifi.vhd
That also had limited success:
./vhd2vl --help Usage: vhd2vl [--debug] [--quiet] [--std 1995|2001] source_file.vhd > target_file.v or vhd2vl [--debug] [--quiet] [--std 1995|2001] source_file.vhd target_file.v
// File ../../ulx3s-passthru/rtl/ulx3s_v20_passthru_wifi.vhd translated with vhd2vl v3.0 VHDL to Verilog RTL translator // vhd2vl settings: // * Verilog Module Declaration Style: 2001 // vhd2vl is Free (libre) Software: // Copyright (C) 2001 Vincenzo Liguori - Ocean Logic Pty Ltd // http://www.ocean-logic.com // Modifications Copyright (C) 2006 Mark Gonzales - PMC Sierra Inc // Modifications (C) 2010 Shankar Giri // Modifications Copyright (C) 2002-2017 Larry Doolittle // http://doolittle.icarus.com/~larry/vhd2vl/ // Modifications (C) 2017 Rodrigo A. Melo // // vhd2vl comes with ABSOLUTELY NO WARRANTY. Always check the resulting // Verilog for correctness, ideally with a formal verification tool. // // You are welcome to redistribute vhd2vl under certain conditions. // See the license (GPLv2) file included with the source for details. // The result of translation follows. Its copyright status should be // considered unchanged from the original VHDL. WARNING (line 70): port default initialization ignored. WARNING (line 70): port default initialization ignored. WARNING (line 70): port default initialization ignored. WARNING (line 70): port default initialization ignored. WARNING (line 70): port default initialization ignored. syntax error, unexpected GENERATE at "generate" in line 145.
So the reality is that I probably won't be converting VHDL to Verilog anytime soon. However, writing my own Verilog passthrough app should be an excellent beginner FPGA to write.