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
and:-- @daveshah1
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.
-- @emard
- 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:
-- @reostat
and:-- @emard
- ULX3S is unbrickable.
-- @daveshah1
- 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
--12
option, nextpnr-ecp5
failed: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
In fact, things were looking pretty bleak, as the nextpnr-ecp5 does not even list the 12F:
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)
@daveshah1 to the rescue once again!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
-- @daveshah1
I'm not sure I would have ever guessed the
25F
, and certainly not the --idcode 0x21111043
part. I pulled the latest SymbiFlow/prjtrellis and nextpnr now (git sha1 4c73061), cleaned and rebuilt everything with my new Makefile, and success to build!
[... 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
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.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:
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.
And I learned a few more things in the close comment: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:
-- gornjas
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.
-- @emard
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
then run yosys
, and from the yosys>
prompt:plugin -i vhdl
plugin -l
This will add a new read_vhdl
command to yosys
.
There is more documentation on yosys here.
If the plugin is listed and working, typing
read_vhdl
in yosys
will show help: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.
The yosys VHDL plugin reads a VDHL file like this: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 is probably a different message if it was successful.There's also the vhd2vl noted on the yosys README.
git clone https://github.com/ldoolitt/vhd2vl.git
cd vhd2vl/src
make
./vhd2vl ../../ulx3s-passthru/rtl/ulx3s_v20_passthru_wifi.vhd
With a bit of help info: ./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
That also had limited success:
// 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.