update 8c74c1794b
4
.buildinfo
Normal file
@ -0,0 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: ee76fe7757e9c92a05b8ad8b4d9d5bf7
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
BIN
_images/Zadig-Setup.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
_images/blinky.gif
Normal file
After Width: | Height: | Size: 7.3 MiB |
BIN
_images/blinky_board_options.gif
Normal file
After Width: | Height: | Size: 210 KiB |
BIN
_images/blinky_board_rules.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
_images/blinky_diagram.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
_images/blinky_module_rules.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
_images/blinky_steps.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
_images/blinky_video.gif
Normal file
After Width: | Height: | Size: 5.0 MiB |
BIN
_images/clk_buffering.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
_images/fomu-block-diagram.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
_images/hw-hacker-annotated.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
_images/hw-hacker-back-bare-small.jpg
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
_images/hw-hacker-back-case-small.jpg
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
_images/hw-hacker-front-bare-small.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
_images/hw-pvt-annotated.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
_images/hw-pvt-back-bare-small.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
_images/hw-pvt-front-bare-small.jpg
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
_images/ice40-arch.png
Normal file
After Width: | Height: | Size: 222 KiB |
BIN
_images/ice40-ledd.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
_images/ice40-lut.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
_images/ice40-plb.png
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
_images/ice40-rgb.png
Normal file
After Width: | Height: | Size: 268 KiB |
BIN
_images/litex-design.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
_images/logo.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
_images/pwm_generator.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
_images/sb_rgba_drv.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
_images/verilog-synthesis.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
_images/wishbone-usb-debug-bridge.png
Normal file
After Width: | Height: | Size: 84 KiB |
217
_sources/background.rst.txt
Normal file
@ -0,0 +1,217 @@
|
||||
.. _background:
|
||||
|
||||
Background
|
||||
----------
|
||||
|
||||
About FPGAs
|
||||
~~~~~~~~~~~
|
||||
|
||||
`Field Programmable Gate Arrays (FPGAs) <https://en.wikipedia.org/wiki/Field-programmable_gate_array>`_
|
||||
are integrated circuits containing arrays of gates which are programmable
|
||||
in the field. Most chips you will encounter, have transistor gates arranged
|
||||
in a fixed order, thus providing a fixed functionality. Conversely, FPGAs
|
||||
can change their internal connections by simply loading new configurations.
|
||||
Fundamentally, configurations program lookup tables (LUTs), which form the basic
|
||||
building blocks of logic. These lookup tables are so important to the design and usage of an
|
||||
FPGA that they usually form part of the name of the part. For example,
|
||||
Fomu uses a `UP5K <http://www.latticesemi.com/Products/FPGAandCPLD/iCE40UltraPlus>`_,
|
||||
which has about 5000 LUTs. NeTV used an `LX9 <https://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html>`_,
|
||||
which had about 9000 LUTs, and NeTV2 uses a `XC7A35T <https://www.xilinx.com/products/silicon-devices/fpga/artix-7.html>`_
|
||||
that has about 35000 LUTs.
|
||||
|
||||
FPGA LUTs are almost always *n*-inputs to 1-output. The ICE family of
|
||||
FPGAs from Lattice have 4-input LUTs. Xilinx parts tend to have 5-input or
|
||||
6-input LUTs which generally means they can do more logic in fewer LUTs.
|
||||
Comparing LUT count between FPGAs is a bit like comparing clock speed
|
||||
between different CPUs; not entirely accurate, but certainly a helpful
|
||||
rule of thumb.
|
||||
|
||||
.. figure:: _static/ice40-lut.png
|
||||
:width: 400px
|
||||
:align: center
|
||||
:alt: The ICE40 LUT4 is a basic 4-input 1-output LUT
|
||||
|
||||
The ICE40 LUT4 is a basic 4-input 1-output function table.
|
||||
|
||||
The basic building block of Fomu is the ``SB_LUT4``. It
|
||||
has four 1-bit inputs and one 1-bit output. To program Fomu, we must define what
|
||||
each possible input 4-bit pattern will create on the output. To do this, we turn to
|
||||
a `truth table <https://en.wikipedia.org/wiki/Truth_table>`_:
|
||||
|
||||
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|
||||
+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+
|
||||
| IO0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| IO1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
|
||||
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| IO2 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
|
||||
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| IO3 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
|
||||
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| O | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* | *?* |
|
||||
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
|
||||
For example, to create a LUT that acted as an AND gate, we would define
|
||||
``O`` to be 0 for everything except the last column. Conversely, to create
|
||||
a NAND gate, we would define ``O`` to be 1 for everything except the last column.
|
||||
It is from this simple primitive that we create the building logic blocks of
|
||||
FPGA design.
|
||||
|
||||
.. figure:: _static/ice40-plb.png
|
||||
:width: 400px
|
||||
:align: center
|
||||
:alt: PLB Block Diagram (from iCE40 UltraPlus Family Data Sheet)
|
||||
|
||||
Programmable Logic Block (PLB), Block Diagram.
|
||||
|
||||
Modern FPGA devices are no longer composed of arrays of gates (i.e. LUTs) only.
|
||||
Typically, LUTs are grouped with flip-flop registers (DFF) and some carry logic, in
|
||||
so-called Programmable Logic Blocks (PLBs) or Configurable Logic Blocks (CLBs);
|
||||
depending on the vendor. These resources allow combining multiple LUTs for
|
||||
describing larger logical functions and for providing sequential behaviour.
|
||||
|
||||
Furthermore, additional purpose-specific blocks are included in the devices:
|
||||
Block RAMs (BRAMs), Digital Signal Processing (DSP) blocks, high-performance serial
|
||||
transmitters/receivers, etc. Those so-called *hard* blocks allow better
|
||||
area and power usage than LUT-based components. Nevertheless, the behaviour
|
||||
of any of those *hard* blocks can be replicated using PLBs only. At the same time,
|
||||
custom behaviour can only be described through LUTs, because all *hard* blocks
|
||||
are programmable within the pre-fixed functionality only.
|
||||
|
||||
.. _background:code-into-gates:
|
||||
|
||||
Turning code into gates
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuring all the LUTs, carry logic and other *hard* blocks manually is
|
||||
hard and very challenging; so people have come up with abstract
|
||||
`Hardware Description Languages (HDLs) <https://en.wikipedia.org/wiki/Hardware_description_language>`_,
|
||||
that allow us to describe the expected behaviour and/or structure. The
|
||||
two most common languages are Verilog and VHDL. However, a modern trend
|
||||
is to achieve hardware description by embedding a Domain Specific Language (DSL)
|
||||
inside an existing programming language, such as how Migen is embedded in Python,
|
||||
Clash is embedded in Haskell, or Chisel and SpinalHDL are embedded in Scala.
|
||||
|
||||
Here is an example of a counter module with a registered output:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. group-tab:: Verilog
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
module example (
|
||||
input C,
|
||||
output reg [0:5] Q
|
||||
);
|
||||
reg [0:8] counter;
|
||||
|
||||
always @(posedge C)
|
||||
begin
|
||||
counter <= counter + 1'b1;
|
||||
end
|
||||
|
||||
always @(posedge C)
|
||||
begin
|
||||
Q <= counter[3] ^ counter[5] | counter<<2;
|
||||
end
|
||||
endmodule
|
||||
|
||||
We can run this HDL module through a synthesizer to turn it into
|
||||
LUT and DFF blocks, or we can turn it into a more familiar logic
|
||||
diagram:
|
||||
|
||||
.. figure:: _static/verilog-synthesis.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
:alt: A synthesis of the above logic into some gates
|
||||
|
||||
A synthesis of the above logic into basic blocks.
|
||||
|
||||
Turning gates into a bitstream
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If we do decide to synthesize to PLBs, we will end up with
|
||||
a pile of LUTs and DFFs that need to be strung together somehow. This is done by
|
||||
a Place-and-Route (PnR) tool. This performs the job of assigning physical PLBs
|
||||
to each LUT and DFF that gets defined by the synthesizer; and then figuring out
|
||||
how to wire it all up.
|
||||
|
||||
Once the PnR tool is done, it generates an abstract file that needs to be
|
||||
translated into a format that the hardware can recognize. This is done by a
|
||||
bitstream packing tool.
|
||||
|
||||
Loading a bitstream into a device
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Finally, the bitstream needs to be loaded onto the device somehow. It can be
|
||||
done manually by toggling wires of the FPGAs programming interface. However,
|
||||
most FPGAs are volatile, which means the configuration is lost when
|
||||
unplugged. Therefore, most FPGA boards include some flash memory, which is
|
||||
typically programmed through SPI. Then, when the FPGA is plugged again, it loads
|
||||
the configuration from a predefined location in the flash.
|
||||
|
||||
About the ICE40UP5K
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We will use an ICE40UP5K for this workshop. This chip has a number of
|
||||
very nice features:
|
||||
|
||||
1. 5280 4-input LUTs (LC)
|
||||
2. 16 kilobytes BRAM
|
||||
3. **128 kilobytes “SPRAM”**
|
||||
4. 1x Current-limited 3-channel LED driver
|
||||
5. 2x I2C and 2x SPI interfaces
|
||||
6. 8x 16-bit DSP units
|
||||
7. **Warmboot capability**
|
||||
8. **Open toolchain**
|
||||
|
||||
.. figure:: _static/ice40-arch.png
|
||||
:width: 400px
|
||||
:align: center
|
||||
:alt: iCE40UP5K Device, Top View (from iCE40 UltraPlus Family Data Sheet)
|
||||
|
||||
iCE40UP5K Device, Top View.
|
||||
|
||||
BRAM is frequently used to store data such as buffers, CPU register files,
|
||||
and large arrays of data. This type of memory is frequently reused as RAM on
|
||||
many FPGAs. The ICE40UP5K is unusual in that it also has 128 kilobytes of
|
||||
Single Ported RAM that can be used as memory for a softcore (a term used for
|
||||
a CPU core running inside an FPGA, to differentiate it from a ‘hard’ -
|
||||
i.e. fixed chip - implementation). That means that, unlike other FPGAs,
|
||||
valuable block RAM isn’t taken up by system memory.
|
||||
|
||||
Additionally, the ICE40 family of devices generally supports *warmboot*
|
||||
capability. This enables us to have multiple designs live on the same
|
||||
FPGA and tell the FPGA to swap between them.
|
||||
|
||||
As always, this workshop wouldn’t be nearly as easy without the open
|
||||
source tools that enable us to port it to a lot of different platforms.
|
||||
|
||||
.. _background:about-fomu:
|
||||
|
||||
About Fomu
|
||||
~~~~~~~~~~
|
||||
|
||||
Fomu is an ICE40UP5K that fits in your USB port. It contains two
|
||||
megabytes of SPI flash memory, four edge buttons, and a three-color LED.
|
||||
|
||||
Unlike most other ICE40 projects, Fomu implements its USB in a softcore.
|
||||
That means that the bitstream that runs on the FPGA must also provide
|
||||
the ability to communicate over USB. This uses up a lot of storage on
|
||||
this small FPGA, but it also enables us to have such a tiny form factor,
|
||||
and lets us do some really cool things with it.
|
||||
|
||||
.. figure:: _static/fomu-block-diagram.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
:alt: Block diagram of Fomu
|
||||
|
||||
Block diagram of Fomu.
|
||||
|
||||
The ICE40UP5K at the heart of Fomu really controls everything, and this
|
||||
workshop is all about trying to unlock the power of this chip.
|
||||
|
||||
.. NOTE::
|
||||
Some figures in this section were extracted from the `iCE40 UltraPlus Family Data Sheet <https://www.latticesemi.com/view_document?document_id=51968>`_.
|
93
_sources/bootloader.rst.txt
Normal file
@ -0,0 +1,93 @@
|
||||
.. _bootloader:
|
||||
|
||||
Bootloader
|
||||
==========
|
||||
|
||||
|
||||
.. _bootloader-update:
|
||||
|
||||
Updating the Fomu Bootloader
|
||||
----------------------------
|
||||
|
||||
|
||||
To update your Fomu, download the appropriate ``-updater`` dfu release from
|
||||
`foboot <https://github.com/im-tomu/foboot/releases/latest>`__.
|
||||
|
||||
#. Download the :file:`{board type}-updater-v2.0.3.dfu` file.
|
||||
|
||||
* If you have a ``PVT`` Fomu, download |pvt-updater|.
|
||||
* If you have a ``Hacker`` Fomu, download |hacker-updater|.
|
||||
|
||||
#. Run :file:`dfu-util -D pvt-updater-{version}.dfu`.
|
||||
#. Your Fomu will flash rainbow for about five seconds, then reboot and go back
|
||||
to blinking.
|
||||
#. To verify it has updated, ``dfu-util -l`` and check the version output.
|
||||
|
||||
.. |pvt-updater| replace:: `pvt-updater-v2.0.3.dfu <https://github.com/im-tomu/foboot/releases/download/v2.0.3/pvt-updater-v2.0.3.dfu>`__
|
||||
.. |hacker-updater| replace:: `hacker-updater-v2.0.3.dfu <https://github.com/im-tomu/foboot/releases/download/v2.0.3/hacker-updater-v2.0.3.dfu>`__
|
||||
|
||||
This is an example session for updating a production board:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ dfu-util -l
|
||||
dfu-util 0.9
|
||||
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Found DFU: [1209:5bf0] ver=0101, devnum=19, cfg=1, intf=0, path="1-2", alt=0, name="Fomu PVT running DFU Bootloader v1.9.1", serial="UNKNOWN"
|
||||
$ wget https://github.com/im-tomu/foboot/releases/download/v2.0.3/pvt-updater-v2.0.3.dfu -O ~/Downloads/pvt-updater-v2.0.3.dfu
|
||||
--2019-12-27 20:01:16-- https://github.com/im-tomu/foboot/releases/download/v2.0.3/pvt-updater-v2.0.3.dfu
|
||||
Resolving github.com (github.com)... 140.82.118.3
|
||||
Connecting to github.com (github.com)|140.82.118.3|:443... connected.
|
||||
HTTP request sent, awaiting response... 302 Found
|
||||
Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.138.107
|
||||
Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.138.107|:443... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 112844 (110K) [application/octet-stream]
|
||||
Saving to: ‘~/Downloads/pvt-updater-v2.0.3.dfu’
|
||||
|
||||
~/Downloads/pvt-updater-v2.0.3.dfu 100%[=====================================>] 110.20K 332KB/s in 0.3s
|
||||
|
||||
2019-12-27 20:01:17 (332 KB/s) - ‘~/Downloads/pvt-updater-v2.0.3.dfu’ saved [112844/112844]
|
||||
|
||||
$ dfu-util -D ~/Downloads/pvt-updater-v2.0.3.dfu
|
||||
dfu-util 0.9
|
||||
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Match vendor ID from file: 1209
|
||||
Match product ID from file: 70b1
|
||||
Opening DFU capable USB device...
|
||||
ID 1209:5bf0
|
||||
Run-time device DFU version 0101
|
||||
Claiming USB DFU Interface...
|
||||
Setting Alternate Setting #0 ...
|
||||
Determining device status: state = dfuIDLE, status = 0
|
||||
dfuIDLE, continuing
|
||||
DFU mode device DFU version 0101
|
||||
Device returned transfer size 1024
|
||||
Copying data from PC to DFU device
|
||||
Download [=========================] 100% 112828 bytes
|
||||
Download done.
|
||||
state(7) = dfuMANIFEST, status(0) = No error condition is present
|
||||
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
|
||||
Done!
|
||||
$ sleep 5
|
||||
$ dfu-util -l
|
||||
dfu-util 0.9
|
||||
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Found DFU: [1209:5bf0] ver=0101, devnum=20, cfg=1, intf=0, path="1-2", alt=0, name="Fomu PVT running DFU Bootloader v2.0.3", serial="UNKNOWN"
|
||||
$
|
||||
|
74
_sources/hdl.rst.txt
Normal file
@ -0,0 +1,74 @@
|
||||
.. _HDLs:
|
||||
|
||||
Hardware Description Languages
|
||||
------------------------------
|
||||
|
||||
The two most common **H**\ ardware **D**\ escription **L**\ anguages are Verilog and VHDL.
|
||||
As explained in :ref:`background:code-into-gates`, a *synthesis* tool is used for converting
|
||||
the human readable HDL into a netlist representation. The synthesis tool used in the Fomu
|
||||
toolchain is called ``yosys``. Once we have the netlist representation, a tool called
|
||||
``nextpnr`` performs an operation called *place and route* (PnR), which makes it something
|
||||
that will actually run on the FPGA. This is all done for you using the ``Makefiles`` in the
|
||||
subdirectories of any of the following examples: :repo:`verilog <hdl/verilog>`,
|
||||
:repo:`vhdl <hdl/vhdl>`, :repo:`mixed-hdl <hdl/mixed>`, or :repo:`migen <migen>`.
|
||||
|
||||
.. NOTE::
|
||||
``nextpnr`` is timing-driven. This means that a design will be generated with a given
|
||||
clock domain guaranteed to perform fast enough, but sometimes it won't optimise further.
|
||||
When the ``make`` command runs ``nextpnr-ice40`` you will see something similar to the
|
||||
following:
|
||||
|
||||
::
|
||||
|
||||
Info: Max frequency for clock 'clk': 73.26 MHz (PASS at 12.00 MHz)
|
||||
|
||||
This output example shows that we could run ``clk`` at up to 73.26
|
||||
MHz and it would still be stable (even though we only requested 12.00
|
||||
MHz). Note that there is some variation between designs depending on
|
||||
how the placer and router decided to lay things out, so your exact
|
||||
frequency numbers might be different from the ones shown in the code
|
||||
blocks of this documentation.
|
||||
|
||||
.. IMPORTANT::
|
||||
As explained in :ref:`background:about-fomu`, Fomu implements its USB in a softcore, and
|
||||
the bitstream that runs on the FPGA must provide the ability to communicate over USB.
|
||||
That is a tradeoff for achieving such a tiny board size, which unfortunately makes
|
||||
it not straightforward to use non-trivial HDL designs. This is because
|
||||
I/O is very limited, hence, it is challenging to actually *see* whether the designs are
|
||||
behaving as expected. Ideally, a USB-to-UART core would be provided for users to instantiate
|
||||
in their HDL designs. Should you be interested in helping achieve it, `let us know! <https://github.com/im-tomu/fomu-workshop/issues/new>`_
|
||||
Meanwhile, :ref:`HDLs:migen` examples provide a working SoC that allows interacting
|
||||
through USB using a Wishbone Bus.
|
||||
|
||||
.. figure:: _static/ice40-rgb.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
:alt: iCE40 UltraLite and iCE40 UltraPlus RGB Port Level Diagram
|
||||
|
||||
iCE40 UltraLite and iCE40 UltraPlus RGB Port Level Diagram.
|
||||
|
||||
Regardless of the HDL language or higher abstraction programming language used for
|
||||
describing the design, all the examples in this workshop do use the *hard* RGB block
|
||||
for driving the LED on the board. It is defined as a Verilog module or VHDL component
|
||||
named ``SB_RGBA_DRV``.
|
||||
As shown in the block diagram from the datasheet, the RGB driver has five inputs
|
||||
(``CURREN``, ``RGBLEDEN``, ``RGB0PWM``, ``RGB1PWM``, and ``RGB2PWM``),
|
||||
and three outputs (``RGB0``, ``RGB1``, and ``RGB2``). It also has four parameters:
|
||||
``CURRENT_MODE``, ``RGB0_CURRENT``, ``RGB1_CURRENT``, and ``RGB2_CURRENT``. As a result,
|
||||
it allows driving the LEDs safely, by specifying the current limit for each of them.
|
||||
More information on this driver can be found in the `ICE40 LED Driver Usage Guide <_static/reference/FPGA-TN-1288-ICE40LEDDriverUsageGuide.pdf>`_.
|
||||
|
||||
.. ATTENTION::
|
||||
Even though it is possible to drive the RGB outputs directly (i.e. without instantiating
|
||||
``SB_RGBA_DRV``), it is strongly discouraged, as it might damage the LEDs.
|
||||
|
||||
Languages and generators
|
||||
========================
|
||||
|
||||
.. toctree::
|
||||
|
||||
verilog
|
||||
vhdl
|
||||
mixed-hdl
|
||||
migen
|
||||
icestudio
|
23
_sources/help.rst.txt
Normal file
@ -0,0 +1,23 @@
|
||||
Getting Help
|
||||
============
|
||||
|
||||
If you get stuck anywhere in the workshop you can use the following channels to
|
||||
get help!
|
||||
|
||||
IRC Chat Channel
|
||||
----------------
|
||||
|
||||
IRC (`Internet Relay Chat <https://en.wikipedia.org/wiki/Internet_Relay_Chat>`__)
|
||||
is old school chat before Slack became popular. You can connect with a wide
|
||||
range of different clients including web based clients like
|
||||
`IRCCloud <https://irccloud.com>`__.
|
||||
|
||||
* `#tomu channel on irc.freenode.net <irc://irc.freenode.net/#tomu>`__
|
||||
* `Freenode WebChat <https://webchat.freenode.net/?channels=#tomu>`__
|
||||
* `Channel Logs <https://logs.timvideos.us/%23tomu/>`__ - `Latest <https://logs.timvideos.us/%23tomu/latest.log.html>`__
|
||||
|
||||
Mailing Lists
|
||||
-------------
|
||||
|
||||
* `Announcement mailing list <https://groups.google.com/forum/#!forum/tomu-announce/join>`__ - Low traffic list for announcements.
|
||||
* `Discussion mailing list <https://groups.google.com/forum/#!forum/tomu-discuss/join>`__ - List for discussing development / new features / etc.
|
115
_sources/icestudio.rst.txt
Normal file
@ -0,0 +1,115 @@
|
||||
Fomu on IceStudio *Nightly*
|
||||
---------------------------
|
||||
|
||||
.. IMPORTANT:: Fomu is currently not supported in the stable releases
|
||||
of IceStudio. Development or `nightly <https://github.com/juanmard/icestudio/releases/tag/nightly>`_
|
||||
releases need to be used.
|
||||
|
||||
“Hello world!” - Blink a LED
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The canonical “Hello, world!” of hardware is to blink a LED. The
|
||||
directory ``icestudio`` contains a Blinky example in ICE format.
|
||||
Moreover, ``Blinky_BoardTop.ice`` wraps Blinky, showcasing how
|
||||
to use the Design Under Test (DUT) as a black box.
|
||||
|
||||
Open ``Blinky_BoardTop.ice`` from `Icestudio <https://juanmard.github.io/icestudio/>`_
|
||||
and use the buttons at the botton:
|
||||
|
||||
.. image:: _static/icestudio/blinky_steps.png
|
||||
:width: 600 px
|
||||
:align: center
|
||||
:target: https://github.com/juanmard/icestudio
|
||||
|
||||
0. Check that the **selected board** is the Fomu.
|
||||
|
||||
- Click on the button with a 'microchip' icon, and a modal window will open.
|
||||
- There, select the device (UP5K) in the first dropdown list and the board (Fomu)
|
||||
in the second list.
|
||||
|
||||
1. Click on the **Verify** button for checking the design.
|
||||
2. Click on the **Build** button for having the design exported to Verilog, synthesised,
|
||||
placed, routed and, finally, the bitstream generated.
|
||||
3. Click on the **Upload** for sending the bitstream to the board.
|
||||
4. After each of the steps is executed, the corresponding log can be shown through button
|
||||
**View command output**.
|
||||
|
||||
You should see the rainbow pattern in the Fomu as soon as the *Upload*
|
||||
step is finished:
|
||||
|
||||
.. image:: _static/icestudio/blinky_video.gif
|
||||
:width: 600 px
|
||||
:align: center
|
||||
:target: https://github.com/juanmard/icestudio
|
||||
|
||||
However, that's just the beginning of the trip...
|
||||
|
||||
Navigation
|
||||
==========
|
||||
|
||||
You can navigate the hierarchy of the design by double-clicking on the main
|
||||
block. Go as deep as you want, until you find raw Verilog code. As you
|
||||
can observe, ICE modules are fancy wrappers around the Verilog code from
|
||||
``verilog/blink``.
|
||||
|
||||
.. image:: _static/icestudio/blinky.gif
|
||||
:width: 600 px
|
||||
:align: center
|
||||
|
||||
Editing submodules is blocked by default, but you can unlock the feature
|
||||
with the red button at the botton left. Do the modifications you wish,
|
||||
then save the changes and go back to the top. There is a 'Home' button
|
||||
at the bottom left for jumping to the root of the design straightaway.
|
||||
From the top, you can verify, build and upload the design again.
|
||||
|
||||
You can also open or save each of the blocks as an independent project.
|
||||
For instance, open ``Blinky.ice``, instead of ``Blinky_BoardTop.ice``:
|
||||
|
||||
.. image:: _static/icestudio/blinky_diagram.png
|
||||
:width: 600 px
|
||||
:align: center
|
||||
|
||||
Modules are browsable, as shown in the screencast above:
|
||||
|
||||
.. image:: _static/icestudio/clk_buffering.png
|
||||
:width: 33%
|
||||
.. image:: _static/icestudio/pwm_generator.png
|
||||
:width: 33%
|
||||
.. image:: _static/icestudio/sb_rgba_drv.png
|
||||
:width: 33%
|
||||
|
||||
Board rules
|
||||
===========
|
||||
|
||||
A feature in *IceStudio Nightly* named "*board rules*" allows predefining
|
||||
assignments for I/O pins. For instance, Fomu needs to disconnect its USB
|
||||
communication stack when writting raw HDL. Therefore, it is always necessary
|
||||
to define and set pins *usb_dn*, *usb_dp* and *usb_dp_pu*. Option
|
||||
*board rules* does so, allowing a cleaner graphical desing.
|
||||
|
||||
Open ``Blinky_BoardTop_rules.ice``, which is the result of using this feature
|
||||
in the Blinky example. As you see, USB pins need not to be defined explicitly:
|
||||
|
||||
.. image:: _static/icestudio/blinky_board_rules.png
|
||||
:width: 600 px
|
||||
:align: center
|
||||
|
||||
Instead, ensure that option *board rules* is activate in the board properties:
|
||||
|
||||
.. image:: _static/icestudio/blinky_board_options.gif
|
||||
:width: 600 px
|
||||
:align: center
|
||||
|
||||
As shown in the screencast, you can inpect the specific rules applied to each
|
||||
pin by using the "*View board rules*" button in the board properties window.
|
||||
|
||||
The same rules can be applied to modules lower in the hierarchy. For example, open
|
||||
``Blinky_rules.ice`` and compare with ``Blinky_rules.ice`` above:
|
||||
|
||||
.. image:: _static/icestudio/blinky_module_rules.png
|
||||
:width: 600 px
|
||||
:align: center
|
||||
|
||||
.. HINT:: Find more info about features of IceStudio (such as collections or
|
||||
plugins) in the `documentation <https://juanmard.github.io/icestudio/index.html>`_.
|
||||
|
32
_sources/index.rst.txt
Normal file
@ -0,0 +1,32 @@
|
||||
FPGA Tomu Workshop
|
||||
==================
|
||||
|
||||
.. image:: _static/logo.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
:alt: Fomu logo
|
||||
|
||||
Hi, I’m `Fomu <https://github.com/im-tomu/fomu-hardware>`_ (FPGA Tomu)!
|
||||
This workshop covers the basics of Fomu in a top-down approach. We’ll
|
||||
start out by learning **what Fomu is**, **how to load software** into Fomu,
|
||||
**how to write software** for Fomu, and finally **how to write hardware** for Fomu.
|
||||
|
||||
FPGAs are complex, weird things, so we’ll take a gentle approach and
|
||||
start out by treating it like a Python interpreter first, and gradually
|
||||
peel away layers until we’re writing our own hardware registers. You can
|
||||
take a break at any time and explore! Stop when you feel the concepts
|
||||
are too unfamiliar, or plough on and dig deep into the world of
|
||||
hardware.
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:maxdepth: 5
|
||||
|
||||
requirements/index
|
||||
background
|
||||
python
|
||||
riscv
|
||||
hdl
|
||||
renode
|
||||
bootloader
|
||||
help
|
200
_sources/migen.rst.txt
Normal file
@ -0,0 +1,200 @@
|
||||
.. _HDLs:migen:
|
||||
|
||||
Migen and LiteX
|
||||
---------------
|
||||
|
||||
.. _hello-world---blink-an-led-1:
|
||||
|
||||
“Hello world!” - Blink a LED
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Migen is an HDL embedded in Python. The verilog examples (in directory
|
||||
``verilog``) can also be written using Migen; an implementation is provided
|
||||
in directory ``migen``.
|
||||
|
||||
To try them out, go to the ``migen`` directory and execute ``blink.py`` or
|
||||
``blink-expanded.py`` respectively (before, ensure that you have set
|
||||
the ``FOMU_REV`` environment variable correctly). This will create a
|
||||
``build`` directory with a ``top.bin`` file.
|
||||
|
||||
Using ``dfu-util -D build/top.bin``, it can be loaded onto the Fomu and should
|
||||
work identically as the corresponding verilog example.
|
||||
|
||||
Wishbone Bus Basics
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
LiteX provides us with a Wishbone abstraction layer. There really is no
|
||||
reason we need to include a CPU with our design, but we can still reuse
|
||||
the USB Wishbone bridge in order to write HDL code.
|
||||
|
||||
We can use ``DummyUsb`` to respond to USB requests and bridge USB to
|
||||
Wishbone, and rely on LiteX to generate registers and wire them to
|
||||
hardware signals. We can still use ``wishbone-tool`` to read and write
|
||||
memory, and with a wishbone bridge we can actually have code running on
|
||||
our local system that can read and write memory on Fomu.
|
||||
|
||||
Go to the ``litex`` directory and build the design;
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ python3 workshop.py --board $FOMU_REV
|
||||
lxbuildenv: v2019.8.19.1 (run .\workshop.py --lx-help for help)
|
||||
lxbuildenv: Skipping git configuration because "skip-git" was found in LX_CONFIGURATION
|
||||
lxbuildenv: To fetch from git, run .\workshop.py --placer heap --lx-check-git
|
||||
Warning: Wire top.basesoc_adr has an unprocessed 'init' attribute.
|
||||
Warning: Wire top.basesoc_bus_wishbone_ack has an unprocessed 'init' attribute.
|
||||
Warning: Wire top.basesoc_bus_wishbone_dat_r has an unprocessed 'init' attribute.
|
||||
...
|
||||
Info: Device utilisation:
|
||||
Info: ICESTORM_LC: 1483/ 5280 28%
|
||||
Info: ICESTORM_RAM: 1/ 30 3%
|
||||
Info: SB_IO: 4/ 96 4%
|
||||
Info: SB_GB: 8/ 8 100%
|
||||
Info: ICESTORM_PLL: 1/ 1 100%
|
||||
Info: SB_WARMBOOT: 0/ 1 0%
|
||||
Info: ICESTORM_DSP: 0/ 8 0%
|
||||
Info: ICESTORM_HFOSC: 0/ 1 0%
|
||||
Info: ICESTORM_LFOSC: 0/ 1 0%
|
||||
Info: SB_I2C: 0/ 2 0%
|
||||
Info: SB_SPI: 0/ 2 0%
|
||||
Info: IO_I3C: 0/ 2 0%
|
||||
Info: SB_LEDDA_IP: 0/ 1 0%
|
||||
Info: SB_RGBA_DRV: 0/ 1 0%
|
||||
Info: ICESTORM_SPRAM: 4/ 4 100%
|
||||
...
|
||||
Info: [ 55530, 59533) |********+
|
||||
Info: [ 59533, 63536) |************************************************+
|
||||
Info: [ 63536, 67539) |******************************+
|
||||
Info: [ 67539, 71542) |*************+
|
||||
Info: [ 71542, 75545) |********************+
|
||||
Info: [ 75545, 79548) |************************************************************
|
||||
5 warnings, 0 errors
|
||||
$
|
||||
|
||||
Load it onto Fomu:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ dfu-util -D build/gateware/fomu_$FOMU_REV.bin
|
||||
dfu-util 0.8
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to dfu-util@lists.gnumonks.org
|
||||
|
||||
Opening DFU capable USB device...
|
||||
ID 1209:5bf0
|
||||
Run-time device DFU version 0101
|
||||
Claiming USB DFU Interface...
|
||||
Setting Alternate Setting #0 ...
|
||||
Determining device status: state = dfuIDLE, status = 0
|
||||
dfuIDLE, continuing
|
||||
DFU mode device DFU version 0101
|
||||
Device returned transfer size 1024
|
||||
Copying data from PC to DFU device
|
||||
Download [=========================] 100% 104090 bytes
|
||||
Download done.
|
||||
state(7) = dfuMANIFEST, status(0) = No error condition is present
|
||||
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
|
||||
Done!
|
||||
$
|
||||
|
||||
If you get an error message about missing modules, check you have all
|
||||
submodules cloned and setup with;
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ git submodule update --recursive --init
|
||||
$
|
||||
|
||||
Take a look at ``build/csr.csv``. This describes the various regions
|
||||
present in our design. You can see
|
||||
``memory_region,sram,0x10000000,131072``, which indicates the RAM is 128
|
||||
kilobytes long and is located at ``0x10000000``, just as when we had a
|
||||
CPU. You can also see the timer, which is a feature that comes as part
|
||||
of LiteX. Let’s try reading and writing RAM:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool 0x10000000
|
||||
Value at 10000000: 0baf801e
|
||||
$ wishbone-tool 0x10000000 0x98765432
|
||||
$ wishbone-tool 0x10000000
|
||||
Value at 10000000: 98765432
|
||||
$
|
||||
|
||||
Wishbone Bus Extension
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Aside from that, there’s not much we can *do* with this design. But
|
||||
there’s a lot of infrastructure there. So let’s add something we can see
|
||||
(``workshop_rgb.py`` contains the completed example).
|
||||
|
||||
As explained in :ref:`HDLs` the RGB LED driver is defined in Verilog/VHDL
|
||||
(as ``SB_RGBA_DRV``), but we can import it as a Module into Migen:
|
||||
|
||||
.. code:: python
|
||||
|
||||
class FomuRGB(Module, AutoCSR):
|
||||
def __init__(self, pads):
|
||||
self.output = CSRStorage(3)
|
||||
self.specials += Instance("SB_RGBA_DRV",
|
||||
i_CURREN = 0b1,
|
||||
i_RGBLEDEN = 0b1,
|
||||
i_RGB0PWM = self.output.storage[0],
|
||||
i_RGB1PWM = self.output.storage[1],
|
||||
i_RGB2PWM = self.output.storage[2],
|
||||
o_RGB0 = pads.r,
|
||||
o_RGB1 = pads.g,
|
||||
o_RGB2 = pads.b,
|
||||
p_CURRENT_MODE = "0b1",
|
||||
p_RGB0_CURRENT = "0b000011",
|
||||
p_RGB1_CURRENT = "0b000011",
|
||||
p_RGB2_CURRENT = "0b000011",
|
||||
)
|
||||
|
||||
This will instantiate this Verilog block and connect it up. It also
|
||||
creates a ``CSRStorage`` object that is three bits wide, and assigns it
|
||||
to ``output``. By having this derive from ``AutoCSR``, the CSRStorage
|
||||
will have CSR bus accessor methods added to it automatically. Finally,
|
||||
it wires the pads up to the outputs of the block.
|
||||
|
||||
We can instantiate this block by simply creating a new object and adding
|
||||
it to ``self.specials`` in our design:
|
||||
|
||||
.. code:: python
|
||||
|
||||
...
|
||||
# Add the LED driver block
|
||||
led_pads = soc.platform.request("rgb_led")
|
||||
soc.submodules.fomu_rgb = FomuRGB(led_pads)
|
||||
|
||||
Finally, we need to add it to the ``csr_map``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
...
|
||||
soc.add_csr("fomu_rgb")
|
||||
|
||||
Now, when we rebuild this design and check ``build/csr.csv`` we can see
|
||||
our new register:
|
||||
|
||||
.. code:: csv
|
||||
|
||||
csr_register,fomu_rgb_output,0x60003000,1,rw
|
||||
|
||||
We can use ``wishbone-tool`` to write values to ``0x60003000`` (or whatever
|
||||
your ``build/csr.csv`` says) and see them take effect immediately.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool 0x60003000 0x1 # make LED green
|
||||
$ wishbone-tool 0x60003000 0x2 # make LED red
|
||||
$ wishbone-tool 0x60003000 0x3 # make LED yellow
|
||||
$ wishbone-tool 0x60003000 0x4 # make LED blue
|
||||
$ wishbone-tool 0x60003000 0x5 # make LED teal
|
||||
$ wishbone-tool 0x60003000 0x6 # make LED pink
|
||||
$ wishbone-tool 0x60003000 0x7 # make LED white
|
||||
|
||||
You can see that it takes very little code to take a Signal from HDL and
|
||||
expose it on the Wishbone bus.
|
80
_sources/mixed-hdl.rst.txt
Normal file
@ -0,0 +1,80 @@
|
||||
.. _HDLs:mixed:
|
||||
|
||||
Mixed HDL on Fomu
|
||||
-----------------
|
||||
|
||||
.. HINT:: It is strongly suggested to get familiar with :ref:`HDLs:Verilog` and :ref:`HDLs:VHDL` examples before
|
||||
tinkering with these mixed language use cases.
|
||||
|
||||
|
||||
“Hello world!” - Blink a LED
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The canonical “Hello, world!” of hardware is to blink a LED.
|
||||
The directory :repo:`hdl/mixed/blink <hdl/mixed/blink>` contains a VHDL + Verilog example of a blink project.
|
||||
This takes the 48 MHz clock and divides it down by a large number so you get an on/off pattern.
|
||||
|
||||
Enter the :repo:`hdl/mixed/blink <hdl/mixed/blink>` directory and build the demo by using ``make``:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ make FOMU_REV=$FOMU_REV
|
||||
...
|
||||
Info: Max frequency for clock 'clk_generator.clko': 73.26 MHz (PASS at 12.00 MHz)
|
||||
|
||||
Info: Max delay posedge clk_generator.clko -> <async>: 3.15 ns
|
||||
|
||||
Info: Slack histogram:
|
||||
Info: legend: * represents 1 endpoint(s)
|
||||
Info: + represents [1,1) endpoint(s)
|
||||
Info: [ 69683, 70208) |**
|
||||
Info: [ 70208, 70733) |
|
||||
Info: [ 70733, 71258) |**
|
||||
Info: [ 71258, 71783) |**
|
||||
Info: [ 71783, 72308) |**
|
||||
Info: [ 72308, 72833) |**
|
||||
Info: [ 72833, 73358) |
|
||||
Info: [ 73358, 73883) |**
|
||||
Info: [ 73883, 74408) |*
|
||||
Info: [ 74408, 74933) |**
|
||||
Info: [ 74933, 75458) |**
|
||||
Info: [ 75458, 75983) |*
|
||||
Info: [ 75983, 76508) |*
|
||||
Info: [ 76508, 77033) |**
|
||||
Info: [ 77033, 77558) |**
|
||||
Info: [ 77558, 78083) |*
|
||||
Info: [ 78083, 78608) |
|
||||
Info: [ 78608, 79133) |*************************
|
||||
Info: [ 79133, 79658) |**
|
||||
Info: [ 79658, 80183) |***
|
||||
22 warnings, 0 errors
|
||||
icepack blink.asc blink.bit
|
||||
cp blink.bit blink.dfu
|
||||
dfu-suffix -v 1209 -p 70b1 -a blink.dfu
|
||||
dfu-suffix (dfu-util) 0.9
|
||||
|
||||
Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Suffix successfully added to file
|
||||
$
|
||||
|
||||
You can then load ``blink.dfu`` onto Fomu by using ``make load`` or the same ``dfu-util -D`` command we’ve been using so
|
||||
far.
|
||||
You should see a blinking pattern of varying color on your Fomu, indicating your bitstream was successfully loaded.
|
||||
|
||||
If you take a closer look at the sources in :repo:`hdl/mixed/blink <hdl/mixed/blink>`, you will find that
|
||||
modules/components ``blink`` and ``clkgen`` are written both in VHDL and Verilog.
|
||||
The :repo:`Makefile <hdl/mixed/blink/Makefile>` uses ``blink.vhd`` and ``clkgen.v`` by default.
|
||||
However, any of the following cases produce the same result:
|
||||
|
||||
- ``blink.vhd`` + ``clkgen.v``
|
||||
- ``blink.v`` + ``clkgen.vhdl``
|
||||
- ``blink.vhd`` + ``clkgen.vhdl``
|
||||
- ``blink.v`` + ``clkgen.v``
|
||||
|
||||
You can modify variables ``VHDL_SYN_FILES`` and ``VERILOG_SYN_FILES`` in the :repo:`Makefile <hdl/mixed/blink/Makefile>`
|
||||
for trying other combinations.
|
||||
For a better understanding, it is suggested to compare these modules with the single file solutions in
|
||||
:ref:`HDLs:Verilog` and :ref:`HDLs:VHDL`.
|
213
_sources/python.rst.txt
Normal file
@ -0,0 +1,213 @@
|
||||
Python on Fomu
|
||||
==============
|
||||
|
||||
You can load `MicroPython <https://micropython.org/>`__, a small Python
|
||||
implementation, onto Fomu as an ordinary RISC-V binary. A precompiled
|
||||
binary is located in the root of the Fomu workshop files.
|
||||
|
||||
Use ``dfu-util`` to load it:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ dfu-util -D micropython-fomu.dfu
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to dfu-util@lists.gnumonks.org
|
||||
|
||||
Opening DFU capable USB device...
|
||||
ID 1209:5bf0
|
||||
Run-time device DFU version 0101
|
||||
Claiming USB DFU Interface...
|
||||
Setting Alternate Setting #0 ...
|
||||
Determining device status: state = dfuIDLE, status = 0
|
||||
dfuIDLE, continuing
|
||||
DFU mode device DFU version 0101
|
||||
Device returned transfer size 1024
|
||||
$
|
||||
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. group-tab:: MacOS X
|
||||
|
||||
If you’re on a macOS machine, use the following command to connect to
|
||||
the device:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ screen /dev/cu.usb*
|
||||
|
||||
.. group-tab:: Linux
|
||||
|
||||
If you’re on Linux, use the following command to connect to the device,
|
||||
it will be called ``ttyACM?``:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ screen /dev/ttyACM*
|
||||
|
||||
If you are unable to connect you may need ``sudo`` access unless you
|
||||
grant permission for using the serial device from a non-privileged
|
||||
account by adding that account to the ``dialout`` group.
|
||||
|
||||
.. WARNING::
|
||||
Adding your user to the ``dialout`` group grants full and direct
|
||||
access to serial ports.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ ls -alh /dev/ttyACM*
|
||||
crw-rw---- 1 root dialout 166, 0 Nov 9 21:28 /dev/ttyACM0
|
||||
|
||||
$ sudo usermod -a -G dialout $USER
|
||||
|
||||
.. WARNING::
|
||||
You **must** log out and then log in again for the addition to group
|
||||
``dialout`` to take affect.
|
||||
|
||||
.. group-tab:: Windows
|
||||
|
||||
If you’re running a version of Windows earlier than Windows 10, you will
|
||||
need to install a driver for the serial port. Open Zadag again and
|
||||
select ``Fomu`` from the dropdown list. Install the driver for
|
||||
``USB Serial (CDC)``.
|
||||
|
||||
You can then use a program such as `Tera Term
|
||||
<https://tera-term.en.lo4d.com/download>`__.
|
||||
|
||||
.. session:: powershell
|
||||
|
||||
PS> ttermpro.exe
|
||||
|
||||
In Teraterm hit ``New Connection`` and select the ``Serial Port`` Radio
|
||||
Button. If it is greyed out you might have to change your USB Port
|
||||
driver for the Fomu.
|
||||
|
||||
See `Working with Fomu <#working-with-fomu>`__,
|
||||
above.
|
||||
|
||||
You should be greeted with a MicroPython banner and REPL:
|
||||
|
||||
.. session:: pycon
|
||||
|
||||
MicroPython v1.10-299-g8603316 on 2019-08-19; fomu with vexriscv
|
||||
>>>
|
||||
|
||||
This is a fully-functioning MicroPython shell. Try running some simple
|
||||
commands such as ``print()`` and ``hex(9876+1234)``.
|
||||
|
||||
Fomu Python Extensions
|
||||
----------------------
|
||||
|
||||
Fomu’s MicroPython binary contains a few extended Python modules that
|
||||
you can use to interact with some of the hardware. For example, the RGB
|
||||
LED has some predefined modes you can access. These are all located
|
||||
under the ``fomu`` module.
|
||||
|
||||
Import the ``fomu`` module and access the ``rgb`` block to change the
|
||||
mode to the predefined ``error`` mode:
|
||||
|
||||
.. session:: pycon
|
||||
|
||||
>>> import fomu
|
||||
>>> rgb = fomu.rgb()
|
||||
>>> rgb.mode("error")
|
||||
>>>
|
||||
|
||||
We can also look at some information from the SPI flash, such as the SPI
|
||||
ID. This ID varies between Fomu models, so it can be a good indication
|
||||
of what kind of Fomu your code is running on:
|
||||
|
||||
.. session:: pycon
|
||||
|
||||
>>> spi = fomu.spi()
|
||||
>>> hex(spi.id())
|
||||
'0xc2152815'
|
||||
>>>
|
||||
|
||||
Memory-mapped Registers
|
||||
-----------------------
|
||||
|
||||
If we look at the generated Fomu header files (to be found for instance in
|
||||
:repo:`riscv-blink <riscv-blink/include/generated/csr.h>`), we can see
|
||||
many, many memory-mapped registers. For example, the major, minor, and revision
|
||||
numbers all have registers:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#define CSR_VERSION_MAJOR_ADDR 0xe0007000
|
||||
#define CSR_VERSION_MINOR_ADDR 0xe0007004
|
||||
#define CSR_VERSION_REVISION_ADDR 0xe0007008
|
||||
#define CSR_VERSION_MODEL_ADDR 0xe0007028
|
||||
|
||||
These are special areas of memory that don’t really exist. Instead, they
|
||||
correspond to hardware. We can read these values using the ``machine``
|
||||
class. Read out the major, minor, and revision codes from your Fomu.
|
||||
They may be different from what you see here:
|
||||
|
||||
.. session:: pycon
|
||||
|
||||
>>> import machine
|
||||
>>> machine.mem32[0xe0007000]
|
||||
2
|
||||
>>> machine.mem32[0xe0007004]
|
||||
0
|
||||
>>> machine.mem32[0xe0007008]
|
||||
3
|
||||
>>>
|
||||
|
||||
The ``CSR_VERSION_MODEL_ADDR`` contains a single character that
|
||||
indicates what version of the hardware you have. We can convert this to
|
||||
a character and print it out.
|
||||
|
||||
If you have a production board you will get ``P`` as shown below;
|
||||
|
||||
.. session:: pycon
|
||||
|
||||
>>> chr(machine.mem32[0xe0007028])
|
||||
'P'
|
||||
>>>
|
||||
|
||||
If you have a hacker board you will get ``H`` as shown below;
|
||||
|
||||
.. session:: pycon
|
||||
|
||||
>>> chr(machine.mem32[0xe0007028])
|
||||
'H'
|
||||
>>>
|
||||
|
||||
Memory-mapped RGB driver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The blinking LED is actually a hardware block from Lattice. It has
|
||||
control registers, and we can modify these registers by writing to
|
||||
memory in Fomu. Some of these registers control things such as the
|
||||
timing of the fade in and fade out pulses, and some control the level of
|
||||
each of the three colors.
|
||||
|
||||
.. image:: _static/ice40-ledd.png
|
||||
:width: 100%
|
||||
:alt: Registers of the ICE40 RGB driver
|
||||
|
||||
There is a wrapper in Fomu’s MicroPython that simplifies the process of
|
||||
writing to these registers. The first argument is the register number,
|
||||
and the second argument is the value to write.
|
||||
|
||||
For the ``LEDDPWR`` registers, the second argument determines the
|
||||
brightness, value ranges from 0 to 255.
|
||||
|
||||
Try changing the color of the three LEDs:
|
||||
|
||||
.. session:: pycon
|
||||
|
||||
>>> ADDR_RED_LED_PULSE_WIDTH = 0b0001 # LEDDPWRR
|
||||
>>> ADDR_GREEN_LED_PULSE_WIDTH = 0b0010 # LEDDPWRG
|
||||
>>> ADDR_BLUE_LED_PULSE_WIDTH = 0b0011 # LEDDPWRB
|
||||
>>> rgb.write_raw(ADDR_RED_LED_PULSE_WIDTH, 255) # Red LED fully on
|
||||
>>> rgb.write_raw(ADDR_GREEN_LED_PULSE_WIDTH, 14) # Green LED mostly off
|
||||
>>> rgb.write_raw(ADDR_BLUE_LED_PULSE_WIDTH, 1) # Blue LED off
|
||||
>>>
|
||||
|
||||
The color should change immediately. More information on these registers
|
||||
can be found in the `ICE40 LED Driver Usage Guide <_static/reference/FPGA-TN-1288-ICE40LEDDriverUsageGuide.pdf>`__.
|
167
_sources/renode-bridge.rst.txt
Normal file
@ -0,0 +1,167 @@
|
||||
Wishbone bridge between Renode and Fomu
|
||||
=======================================
|
||||
|
||||
This part of the workshop is based on a `Renode, Fomu and Etherbone
|
||||
bridge
|
||||
example <https://renode.readthedocs.io/en/latest/tutorials/fomu-example.html>`__
|
||||
from the Renode documentation.
|
||||
|
||||
Just like we can access Fomu peripherals using ``wishbone-tool``, we can
|
||||
also connect to a physical board from Renode, mapping a part of the
|
||||
memory space to be accessible via the Etherbone protocol.
|
||||
|
||||
This is a very useful capability as it enables us to potentially
|
||||
simulate an advanced LiteX SoC system which would not normally fit in
|
||||
the FPGA (or e.g. take a long time to synthesize), and interface it with
|
||||
the remaining part of the physical system for I/O.
|
||||
|
||||
Setting up the server
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can use ``wishbone-tool`` to bridge protocols such as USB to Etherbone.
|
||||
To start the server, run the following command:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool -s wishbone
|
||||
INFO [wishbone_tool::bridge::usb] opened USB device device 006 on bus 001
|
||||
|
||||
This starts an Etherbone server on ``localhost:1234`` by default. See
|
||||
``wishbone-tool --help`` to change these settings.
|
||||
|
||||
Now you can start Renode and setup the platform.
|
||||
|
||||
Connecting from Renode
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Run ``renode`` and in the Monitor type:
|
||||
|
||||
::
|
||||
|
||||
(monitor) include @scripts/complex/fomu/renode_etherbone_fomu.resc
|
||||
(machine-0) start
|
||||
Starting emulation...
|
||||
(machine-0) sysbus LogPeripheralAccess sysbus.led
|
||||
|
||||
You see a new window with a `shell
|
||||
application <https://github.com/antmicro/zephyr/commit/29d8e51da15237f2a6bd2a3c8c97e004a66fc97a>`__,
|
||||
that provides additional commands allowing you to control LEDs on Fomu.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
uart:~$ led_toggle
|
||||
uart:~$ led_breathe
|
||||
|
||||
The ``led_toggle`` command controls the LED by turning it on and off.
|
||||
``led_breathe`` makes the LED fade slowly in and out, creating a
|
||||
“breathe” effect.
|
||||
|
||||
The script you loaded configures Renode to log all communication with
|
||||
Fomu. After issuing some commands in Zephyr’s shell you’ll see:
|
||||
|
||||
::
|
||||
|
||||
01:00:31.8276 [DEBUG] led: [cpu: 0x40000988] WriteUInt32 to 0x8 (unknown), value 0x7.
|
||||
01:00:31.8279 [DEBUG] led: [cpu: 0x40000990] WriteUInt32 to 0x4 (unknown), value 0x8.
|
||||
01:00:31.8290 [DEBUG] led: [cpu: 0x40000998] WriteUInt32 to 0x0 (unknown), value 0xC8.
|
||||
01:00:31.8298 [DEBUG] led: [cpu: 0x400009A0] WriteUInt32 to 0x4 (unknown), value 0x9.
|
||||
01:00:31.8301 [DEBUG] led: [cpu: 0x400009A8] WriteUInt32 to 0x0 (unknown), value 0xBA.
|
||||
01:00:31.8305 [DEBUG] led: [cpu: 0x400009B0] WriteUInt32 to 0x8 (unknown), value 0x6.
|
||||
01:00:31.8308 [DEBUG] led: [cpu: 0x400009B4] WriteUInt32 to 0x8 (unknown), value 0x7.
|
||||
01:00:31.8311 [DEBUG] led: [cpu: 0x400009BC] WriteUInt32 to 0x4 (unknown), value 0x5.
|
||||
01:00:31.8314 [DEBUG] led: [cpu: 0x400009C0] WriteUInt32 to 0x0 (unknown), value 0x0.
|
||||
01:00:31.8317 [DEBUG] led: [cpu: 0x400009C4] WriteUInt32 to 0x4 (unknown), value 0x6.
|
||||
01:00:31.8321 [DEBUG] led: [cpu: 0x400009C8] WriteUInt32 to 0x0 (unknown), value 0x0.
|
||||
01:00:31.8324 [DEBUG] led: [cpu: 0x400009D0] WriteUInt32 to 0x4 (unknown), value 0x2.
|
||||
01:00:31.8327 [DEBUG] led: [cpu: 0x400009D4] WriteUInt32 to 0x0 (unknown), value 0x0.
|
||||
01:00:31.8331 [DEBUG] led: [cpu: 0x400009DC] WriteUInt32 to 0x4 (unknown), value 0x3.
|
||||
01:00:31.8334 [DEBUG] led: [cpu: 0x400009E0] WriteUInt32 to 0x0 (unknown), value 0x0.
|
||||
01:00:31.8337 [DEBUG] led: [cpu: 0x400009E8] WriteUInt32 to 0x4 (unknown), value 0x1.
|
||||
01:00:31.8341 [DEBUG] led: [cpu: 0x400009F4] WriteUInt32 to 0x0 (unknown), value 0xFF.
|
||||
01:00:31.8344 [DEBUG] led: [cpu: 0x40000A08] WriteUInt32 to 0x4 (unknown), value 0xA.
|
||||
01:00:31.8347 [DEBUG] led: [cpu: 0x40000A0C] WriteUInt32 to 0x0 (unknown), value 0x0.
|
||||
01:00:31.8350 [DEBUG] led: [cpu: 0x40000A14] WriteUInt32 to 0x4 (unknown), value 0xB.
|
||||
01:00:31.8353 [DEBUG] led: [cpu: 0x40000A18] WriteUInt32 to 0x0 (unknown), value 0xFF.
|
||||
|
||||
You can interact with Fomu manually, via the Monitor. To do that, you
|
||||
first need to find the name of the peripheral that serves the connection
|
||||
to Fomu.
|
||||
|
||||
Type in ``peripherals`` to see a list of all the elements of the
|
||||
emulated SoC. Look for ``EtherBoneBridge`` entry:
|
||||
|
||||
::
|
||||
|
||||
(machine-0) peripherals
|
||||
Available peripherals:
|
||||
sysbus (SystemBus)
|
||||
│
|
||||
├── cpu (VexRiscv)
|
||||
│ Slot: 0
|
||||
│
|
||||
├── ddr (MappedMemory)
|
||||
│ <0x40000000, 0x4FFFFFFF>
|
||||
│ <0xC0000000, 0xCFFFFFFF>
|
||||
│
|
||||
├── eth (LiteX_Ethernet)
|
||||
│ │ <0x60007800, 0x600078FF>
|
||||
│ │ <0xE0007800, 0xE00078FF>
|
||||
│ │ <0x30000000, 0x30001FFF>
|
||||
│ │ <0xB0000000, 0xB0001FFF>
|
||||
│ │ <0x60007000, 0x600077FF>
|
||||
│ │ <0xE0007000, 0xE00077FF>
|
||||
│ │
|
||||
│ └── phy (EthernetPhysicalLayer)
|
||||
│ Address: 0
|
||||
│
|
||||
├── flash_mem (MappedMemory)
|
||||
│ <0x20000000, 0x21FFFFFF>
|
||||
│ <0xA0000000, 0xA1FFFFFF>
|
||||
│
|
||||
├── led (EtherBoneBridge)
|
||||
│ <0xE0006800, 0xE00068FF>
|
||||
│
|
||||
├── mem (MappedMemory)
|
||||
│ <0x00000000, 0x0003FFFF>
|
||||
│ <0x80000000, 0x8003FFFF>
|
||||
│
|
||||
├── spi (LiteX_SPI_Flash)
|
||||
│ │ <0x60005000, 0x6000500F>
|
||||
│ │ <0xE0005000, 0xE000500F>
|
||||
│ │
|
||||
│ └── flash (Micron_MT25Q)
|
||||
│
|
||||
├── sram (MappedMemory)
|
||||
│ <0x10000000, 0x1003FFFF>
|
||||
│ <0x90000000, 0x9003FFFF>
|
||||
│
|
||||
├── timer0 (LiteX_Timer)
|
||||
│ <0x60002800, 0x60002843>
|
||||
│ <0xE0002800, 0xE0002843>
|
||||
│
|
||||
└── uart (LiteX_UART)
|
||||
<0x60001800, 0x600018FF>
|
||||
<0xE0001800, 0xE00018FF>
|
||||
|
||||
The device that acts as a connector to Fomu is called ``led`` and is
|
||||
registered at ``0xE0006800``:
|
||||
|
||||
::
|
||||
|
||||
├── led (EtherBoneBridge)
|
||||
│ <0xE0006800, 0xE00068FF>
|
||||
|
||||
You can either use a full or relative address (via the ``sysbus`` or
|
||||
``led`` objects, respectively) to communicate with the physical LED
|
||||
controller:
|
||||
|
||||
::
|
||||
|
||||
(machine-0) sysbus WriteDoubleWord 0xE0006804 0x1234 # writes 0x1234 to the given address
|
||||
(machine-0) led WriteDoubleWord 0x4 0x4321 # writes 0x4321 to 0xE0006800 + 0x4
|
||||
|
||||
Note: the above values are just an example and won’t change the LED
|
||||
status in any visible way. If you want to enable “breathe” effect
|
||||
directly from the Monitor, see the necessary sequence in `the
|
||||
application source
|
||||
code <https://github.com/antmicro/zephyr/commit/29d8e51da15237f2a6bd2a3c8c97e004a66fc97a>`__.
|
49
_sources/renode-starting.rst.txt
Normal file
@ -0,0 +1,49 @@
|
||||
Getting Renode
|
||||
==============
|
||||
|
||||
Renode is available for Linux, macOS and Windows.
|
||||
|
||||
On Linux and macOS, you need to have
|
||||
`Mono <https://www.mono-project.com>`__ installed on your computer. You
|
||||
should follow the `Mono installation
|
||||
instructions <https://www.mono-project.com/download/stable/>`__ and
|
||||
install the ``mono-complete`` package.
|
||||
|
||||
On Windows it’s enough to have a fairly recent `.NET
|
||||
Framework <https://dotnet.microsoft.com/download/dotnet-framework>`__
|
||||
installed.
|
||||
|
||||
Then you can either install Renode from `prebuilt
|
||||
packages <https://github.com/renode/renode#installation>`__, or `compile
|
||||
it
|
||||
yourself <https://renode.readthedocs.io/en/latest/advanced/building_from_sources.html>`__.
|
||||
|
||||
Try out Renode quickly with precompiled LiteX demos
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Renode comes with several precompiled demos, which can be used to verify
|
||||
everything works for you before starting to compile and use your own
|
||||
software binaries.
|
||||
|
||||
There are three demo scripts available:
|
||||
|
||||
- ``litex_vexriscv_micropython.resc``
|
||||
- ``litex_vexriscv_zephyr.resc``
|
||||
- ``litex_vexriscv_linux.resc``
|
||||
|
||||
To run them, start Renode using the ``renode`` command (or ``./renode``
|
||||
if you built from sources).
|
||||
|
||||
You will see a terminal window pop up, which is the Renode CLI, called
|
||||
the Monitor.
|
||||
|
||||
In the Monitor type:
|
||||
|
||||
::
|
||||
|
||||
(monitor) start @scripts/single-node/<script_name>
|
||||
|
||||
(where is one of the above).
|
||||
|
||||
Voila! A UART analyzer window should appear and you should see LiteX
|
||||
booting the respective binary.
|
123
_sources/renode-verilator.rst.txt
Normal file
@ -0,0 +1,123 @@
|
||||
Renode Co-simulation using Verilator
|
||||
====================================
|
||||
|
||||
While connecting Renode to a real FPGA gives you some interesting
|
||||
possibilities in testing and debugging your gateware together with your
|
||||
software, there is another usage scenario which is completely hardware
|
||||
independent - connecting functional simulation of the base system in
|
||||
Renode with HDL simulation of a part of the system that is under
|
||||
development.
|
||||
|
||||
To this end, Renode provides an integration layer for Verilator. A
|
||||
typical setup with Renode + Verilator consists of several components:
|
||||
|
||||
- the ‘verilated’ HDL code itself (e.g. a UART peripheral),
|
||||
- Verilator integration library, `provided as a plugin to
|
||||
Renode <https://github.com/renode/renode/tree/master/src/Plugins/VerilatorPlugin/VerilatorIntegrationLibrary/src>`__,
|
||||
- shim layer in C++ connecting the above.
|
||||
|
||||
Currently Renode supports peripherals with the AXILite interface. Keep
|
||||
in mind that due to the abstract nature of bus operations in Renode, it
|
||||
doesn’t matter what kind of bus is used on the hardware you want to
|
||||
simulate.
|
||||
|
||||
In the Renode tree you will find an example with all the elements
|
||||
already prepared. To run it, start Renode and type:
|
||||
|
||||
::
|
||||
|
||||
(monitor) include @scripts/single-node/riscv_verilated_uartlite.resc
|
||||
(UARTLite) start
|
||||
|
||||
This script loads a RISC-V-based system with a verilated UARTLite. You
|
||||
can verify it by calling:
|
||||
|
||||
::
|
||||
|
||||
(UARTLite) sysbus WhatPeripheralIsAt 0x70000000
|
||||
Antmicro.Renode.Peripherals.Verilated.VerilatedUART
|
||||
|
||||
To inspect the communication with the UART, run:
|
||||
|
||||
::
|
||||
|
||||
(UARTLite) sysbus LogPeripheralAccess uart
|
||||
|
||||
You will see every read and write to the peripheral displayed in the
|
||||
Renode log.
|
||||
|
||||
Please note that, despite not being a Renode-native model, the UART is
|
||||
also capable of displaying an analyzer window. This is because Renode
|
||||
adds a special support for UART-type peripherals, allowing you not only
|
||||
to connect bus lines, but also the TX and RX UART lines, to the Renode
|
||||
infrastructure.
|
||||
|
||||
The HDL and integration layer for this UART peripheral is available on
|
||||
`Antmicro’s
|
||||
GitHub <https://github.com/antmicro/renode-verilator-integration/tree/master/samples/uartlite>`__.
|
||||
|
||||
To compile it manually, you need to have ``ZeroMQ`` (``libzmq3-dev`` on
|
||||
Debian-like systems) and ``Verilator`` installed in your system. You
|
||||
also need to provide a full path to the
|
||||
``src/Plugins/VerilatorPlugin/VerilatorIntegrationLibrary`` directory as
|
||||
the ``INTEGRATION_DIR`` environment variable. This means that you need
|
||||
to have a copy of Renode sources to build a verilated peripheral.
|
||||
|
||||
With this set up, simply run ``make``.
|
||||
|
||||
Integration with verilated code
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Renode supports integration with Verilator via AXILite bus, but can be
|
||||
easily expanded to support other standards as well.
|
||||
|
||||
We’ll briefly take a look on the integration layer implemented in
|
||||
`sim-main.cpp <https://github.com/antmicro/renode-verilator-integration/blob/master/samples/uartlite/sim_main.cpp>`__.
|
||||
|
||||
First, the user has to decide on the bus type and peripheral type. These
|
||||
are provided by the integration library:
|
||||
|
||||
.. code:: c
|
||||
|
||||
#include "src/peripherals/uart.h"
|
||||
#include "src/buses/axilite.h"
|
||||
|
||||
A bus is a type declaring all the signals and how should they be handled
|
||||
on each transaction. These signals have to be connected to the signals
|
||||
in the HDL design:
|
||||
|
||||
::
|
||||
|
||||
void Init() {
|
||||
AxiLite* bus = new AxiLite();
|
||||
|
||||
//=================================================
|
||||
// Init bus signals
|
||||
//=================================================
|
||||
bus->clk = &top->clk;
|
||||
bus->rst = &top->rst;
|
||||
bus->awaddr = (unsigned long *)&top->awaddr;
|
||||
bus->awvalid = &top->awvalid;
|
||||
bus->awready = &top->awready;
|
||||
bus->wdata = (unsigned long *)&top->wdata;
|
||||
bus->wstrb = &top->wstrb;
|
||||
bus->wvalid = &top->wvalid;
|
||||
bus->wready = &top->wready;
|
||||
bus->bresp = &top->bresp;
|
||||
bus->bvalid = &top->bvalid;
|
||||
bus->bready = &top->bready;
|
||||
[...]
|
||||
|
||||
To handle the “external” communication, the user can either use the base
|
||||
``RenodeAgent`` class of one of its derivatives: for example the
|
||||
``UART`` type allows you to connect RX and TX signals:
|
||||
|
||||
::
|
||||
|
||||
// Init peripheral
|
||||
//=================================================
|
||||
uart = new UART(bus, &top->txd, &top->rxd, prescaler);
|
||||
|
||||
For more details, see the `verilated uartlite
|
||||
repository <https://github.com/antmicro/renode-verilator-integration/tree/master/samples/uartlite>`__.
|
||||
|
83
_sources/renode-zephyr.rst.txt
Normal file
@ -0,0 +1,83 @@
|
||||
Running your own Zephyr binary on LiteX/VexRiscv in Renode
|
||||
==========================================================
|
||||
|
||||
Zephyr is a very capable RTOS governed by a Linux Foundation subproject.
|
||||
It is very well supported on the RISC-V architecture, as well as in
|
||||
LiteX.
|
||||
|
||||
Building a Zephyr application
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To install all the dependencies and prepare the environment for building
|
||||
the Zephyr application follow the official `Zephyr Getting Started
|
||||
Guide <https://docs.zephyrproject.org/latest/getting_started/index.html>`__
|
||||
up to point 4. On Linux you can follow the instructions from the point 5
|
||||
on installing the Software Development Toolchain. The python version
|
||||
in the FOMU toolchain may not work; remove it from your PATH before
|
||||
attempting to build zephyr.
|
||||
For other operating
|
||||
systems, if you followed the instructions from the ``Required Software``
|
||||
section of this tutorial, you should have a toolchain in ``PATH``.
|
||||
|
||||
On macOS and Windows you also need to set some additional variables.
|
||||
|
||||
For macOS:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ export ZEPHYR_TOOLCHAIN_VARIANT=cross-compile
|
||||
$ export CROSS_COMPILE=riscv64-unknown-elf-
|
||||
|
||||
For Windows:
|
||||
|
||||
::
|
||||
|
||||
set ZEPHYR_TOOLCHAIN_VARIANT=cross-compile
|
||||
set CROSS_COMPILE=riscv64-unknown-elf-
|
||||
|
||||
To build the ``shell`` demo application for the LiteX/VexRiscv board run
|
||||
the following commands on Linux and macOS:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ cd ~/zephyrproject/zephyr
|
||||
$ source zephyr-env.sh
|
||||
$ west build -p auto -b litex_vexriscv samples/subsys/shell/shell_module/
|
||||
|
||||
And on Windows:
|
||||
|
||||
::
|
||||
|
||||
cd %HOMEPATH%\zephyrproject\zephyr
|
||||
zephyr-env.cmd
|
||||
west build -p auto -b litex_vexriscv samples\subsys\shell\shell_module\
|
||||
|
||||
The resulting ELF file will be in ``build/zephyr/zephyr.elf``.
|
||||
|
||||
Run the app in Renode
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To run the app you just compiled, you basically need to replace the
|
||||
precomipled demo binary with the one you want, by setting the ``zephyr``
|
||||
variable - see below.
|
||||
|
||||
Just like before, start Renode using the ``renode`` command (or
|
||||
``./renode`` if you built from sources).
|
||||
|
||||
You will see the Monitor, where you should type:
|
||||
|
||||
::
|
||||
|
||||
(monitor) $zephyr=@/path/to/zephyrproject/zephyr/build/zephyr/zephyr.elf
|
||||
(monitor) start @scripts/single-node/litex_vexriscv_zephyr.resc
|
||||
|
||||
You should see a new window pop up for the serial port. In it, you
|
||||
should see the Zephyr interactive shell.
|
||||
|
||||
Debugging the app in Renode
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In general, debugging in Renode is done with GDB just like with a
|
||||
physical board - you connect to a debug port and execute GDB commands as
|
||||
usual. For details, see the `Renode debugging
|
||||
documentation <https://renode.readthedocs.io/en/latest/debugging/gdb.html>`__.
|
35
_sources/renode.rst.txt
Normal file
@ -0,0 +1,35 @@
|
||||
Working with LiteX and (co-)simulation with Renode
|
||||
==================================================
|
||||
|
||||
LiteX used as the soft SoC on Fomu is a very robust and scalable soft
|
||||
SoC platform, capable of running both bare metal binaries, Zephyr and
|
||||
even Linux.
|
||||
|
||||
It is also supported in `Renode <https://renode.io>`__, which is an open
|
||||
source simulation framework that lets you run unmodified software in a
|
||||
fully controlled and inspectable environment. Renode is a functional
|
||||
simulator, which means it aims to mimic the observable behavior of the
|
||||
hardware instead of trying to be cycle-accurate.
|
||||
|
||||
We will now see how a full-blown Zephyr RTOS can be run on LiteX in
|
||||
Renode, and then how this simulation can be interfaced with a Fomu for a
|
||||
useful HW/SW co-development workflow.
|
||||
|
||||
.. tip::
|
||||
Apart from RISC-V and LiteX platforms, Renode supports many
|
||||
other architectures and platforms, as described in the
|
||||
`documentation <https://renode.readthedocs.io/en/latest/introduction/supported-boards.html>`__,
|
||||
which also includes a user manual and a few tutorials. You can also
|
||||
take a look at a `Video Tutorials section on Renode’s
|
||||
website <https://renode.io/tutorials/>`__.
|
||||
|
||||
Keep in mind that all platforms and configurations in Renode used in
|
||||
this tutorial are contained in text/config files - you can also explore
|
||||
Renode’s usage patterns by just inspecting those files for details.
|
||||
|
||||
.. toctree::
|
||||
|
||||
renode-starting
|
||||
renode-zephyr
|
||||
renode-bridge
|
||||
renode-verilator
|
100
_sources/requirements/drivers.rst.txt
Normal file
@ -0,0 +1,100 @@
|
||||
.. _required-drivers:
|
||||
|
||||
Required Drivers
|
||||
================
|
||||
|
||||
On most systems (such as Windows 10 or newer, or MacOS X), the Fomu board does **not** need any special drivers.
|
||||
|
||||
* On GNU/Linux, you do not need to install any drivers, **however**, you may need
|
||||
``sudo`` access unless you :ref:`linux-udev` to grant permission for using the
|
||||
USB device from a non-privileged account.
|
||||
* Windows systems **earlier** than Windows 10: you will need to
|
||||
:ref:`install Zadig drivers <windows-zadig>`.
|
||||
|
||||
.. _linux-udev:
|
||||
|
||||
Setup udev rules
|
||||
----------------
|
||||
|
||||
.. WARNING::
|
||||
This set up is for GNU/Linux **only**. Setting up these udev rules grants
|
||||
permissions for using the USB device from a non-privileged account.
|
||||
|
||||
On GNU/Linux, try running ``dfu-util -l``. If you get an error message like the
|
||||
following, you should add a ``udev`` rule as to give your user permission to the
|
||||
USB device.
|
||||
|
||||
.. session:: shell-session
|
||||
:emphasize-lines: 9
|
||||
|
||||
$ dfu-util -l
|
||||
dfu-util 0.9
|
||||
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
dfu-util: Cannot open DFU device 1209:5bf0
|
||||
$
|
||||
|
||||
Steps to set up udev rule
|
||||
#########################
|
||||
|
||||
#. Add your user to group ``plugdev``:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ sudo groupadd plugdev
|
||||
$ sudo usermod -a -G plugdev $USER
|
||||
|
||||
.. WARNING::
|
||||
You **must** log out and then log in again for the addition to group ``plugdev`` to take affect.
|
||||
|
||||
#. Use ``id $USER`` and/or ``groups`` to check you are in group ``plugdev``:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ id $USER
|
||||
uid=1000(tim) gid=1000(tim) groups=500(plugdev),997(admin)
|
||||
|
||||
$ groups | grep plugdev
|
||||
tim plugdev admin
|
||||
|
||||
#. Create a file named ``/etc/udev/rules.d/99-fomu.rules`` and add the following.
|
||||
|
||||
.. code:: udev
|
||||
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="5bf0", MODE="0664", GROUP="plugdev"
|
||||
|
||||
.. NOTE::
|
||||
You need ``sudo`` privileges for creating this file.
|
||||
|
||||
#. Reload the udev-rules using the following:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ sudo udevadm control --reload-rules
|
||||
$ sudo udevadm trigger
|
||||
|
||||
|
||||
.. _windows-zadig:
|
||||
|
||||
Installing Zadig Drivers
|
||||
------------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This set up is only needed for Windows system **earlier** than Windows 10.
|
||||
|
||||
#. Download `Zadig <https://zadig.akeo.ie/>`__.
|
||||
#. Open Zadig.
|
||||
#. Under ``Options``, select ``List All Devices``.
|
||||
#. In the dropdown, select your Fomu; in the field right of the green arrow,
|
||||
choose the ``WinUSB`` driver; and hit ``Upgrade Driver``.
|
||||
|
||||
.. figure:: ../_static/Zadig-Setup.png
|
||||
:align: center
|
||||
:alt: Setup of Zadig for updating USB port driver on Windows earlier than 10
|
||||
|
||||
Setup of Zadig for updating USB port driver on Windows earlier than 10.
|
46
_sources/requirements/files.rst.txt
Normal file
@ -0,0 +1,46 @@
|
||||
.. _required-files:
|
||||
|
||||
Required Files
|
||||
--------------
|
||||
|
||||
.. NOTE::
|
||||
If you’re attending a workshop that provides USB drives, these files may be
|
||||
available on the USB drive under the ``Workshop`` directory.
|
||||
|
||||
You will need the Workshop files. They are located in the
|
||||
`fomu-workshop <https://github.com/im-tomu/fomu-workshop>`_ Github
|
||||
repository. You can clone it with git, or download
|
||||
`master.zip <https://codeload.github.com/im-tomu/fomu-workshop/zip/master>`_ |
|
||||
`master.tar.gz <https://codeload.github.com/im-tomu/fomu-workshop/tar.gz/master>`_.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ git clone --recurse-submodules https://github.com/im-tomu/fomu-workshop.git
|
||||
Cloning into 'fomu-workshop'...
|
||||
remote: Enumerating objects: 140, done.
|
||||
remote: Counting objects: 100% (140/140), done.
|
||||
remote: Compressing objects: 100% (93/93), done.
|
||||
remote: Total 871 (delta 87), reused 94 (delta 46), pack-reused 731
|
||||
Receiving objects: 100% (871/871), 6.22 MiB | 1.46 MiB/s, done.
|
||||
Resolving deltas: 100% (468/468), done.
|
||||
Submodule 'litex/deps/litedram' (https://github.com/enjoy-digital/litedram.git) registered for path 'litex/deps/litedram'
|
||||
Submodule 'litex/deps/litescope' (https://github.com/enjoy-digital/litescope.git) registered for path 'litex/deps/litescope'
|
||||
Submodule 'litex/deps/litex' (https://github.com/enjoy-digital/litex.git) registered for path 'litex/deps/litex'
|
||||
Submodule 'litex/deps/litex_boards' (https://github.com/litex-hub/litex-boards.git) registered for path 'litex/deps/litex_boards'
|
||||
Submodule 'litex/deps/migen' (https://github.com/m-labs/migen.git) registered for path 'litex/deps/migen'
|
||||
Submodule 'litex/deps/pyserial' (https://github.com/pyserial/pyserial.git) registered for path 'litex/deps/pyserial'
|
||||
Submodule 'litex/deps/valentyusb' (https://github.com/im-tomu/valentyusb.git) registered for path 'litex/deps/valentyusb'
|
||||
...
|
||||
remote: Enumerating objects: 78, done.
|
||||
remote: Counting objects: 100% (78/78), done.
|
||||
remote: Compressing objects: 100% (71/71), done.
|
||||
remote: Total 78 (delta 2), reused 78 (delta 2), pack-reused 0
|
||||
Receiving objects: 100% (78/78), 10.88 MiB | 3.86 MiB/s, done.
|
||||
Resolving deltas: 100% (2/2), done.
|
||||
Submodule path 'litex/deps/litex/litex/soc/cores/cpu/vexriscv/verilog/ext/VexRiscv/src/test/resources/VexRiscvRegressionData': checked out '539398c1481203a51115b5f1228ea961f0ac9bd3'
|
||||
Submodule path 'litex/deps/litex/litex/soc/software/compiler_rt': checked out '81fb4f00c2cfe13814765968e09931ffa93b5138'
|
||||
Submodule path 'litex/deps/litex_boards': checked out '91083f99a8551c3465aaf3d6130268c7f7f24a50'
|
||||
Submodule path 'litex/deps/migen': checked out '562c0466443f859d6cf0c87a0bb50db094d27cf4'
|
||||
Submodule path 'litex/deps/pyserial': checked out 'acab9d2c0efb63323faebfd5e3405d77cd4b5617'
|
||||
Submodule path 'litex/deps/valentyusb': checked out 'b34852eb2e77bd9d04ebc3e6e8454cf6d93a02fb'
|
||||
$
|
79
_sources/requirements/hardware.rst.txt
Normal file
@ -0,0 +1,79 @@
|
||||
.. _required-hardware:
|
||||
|
||||
Required Hardware
|
||||
#################
|
||||
|
||||
- For this workshop, you will need a `Fomu board <https://github.com/im-tomu/fomu-hardware>`_.
|
||||
- Aside from that, you need a computer with a USB port that can run the :ref:`required-software`.
|
||||
|
||||
.. NOTE::
|
||||
You should not need any special drivers, though on Linux you may need ``sudo``
|
||||
access, or special ``udev`` rules for granting permission to use the USB device from a
|
||||
non-privileged account.
|
||||
|
||||
.. ATTENTION::
|
||||
This workshop may be competed with any model of Fomu, though there are some
|
||||
parts that require you to identify which model you have. See the
|
||||
:ref:`which-fomu` below.
|
||||
|
||||
.. _which-fomu:
|
||||
|
||||
Which Fomu do I have?
|
||||
=====================
|
||||
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| | Hacker | Production |
|
||||
+==================+======================================================================+===================================================================+
|
||||
| **String** | hacker | pvt |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Bash Command** | ``export FOMU_REV=hacker`` | ``export FOMU_REV=pvt`` |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Front** | |Hacker Hardware Front without case| | |Production Hardware Front without case| |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Back** | |Hacker Hardware Back without case| | |Production Hardware Back without case| |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **In Case** | |Hacker Hardware Back with case| | |Production Hardware Back with case| |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Parts** | |Hacker Hardware Annotated Diagram| | |Production Hardware Annotated Diagram| |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Color** | |Dark Blue| | |Cyan Light Blue| |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Bootloader** | Fomu **Hacker** running DFU Bootloader vX.X.X | Fomu **PVT** running DFU Bootloader vX.X.X |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Description** | These are the original design and cut corners to make it easier to | If you ordered a Fomu from Crowd Supply, this is the model you'll |
|
||||
| | manufacture. If you received one directly from Tim before 36C3, you | receive. It is small, and fits in a USB port. There is no |
|
||||
| | probably have one of these. Hacker boards have white silkscreen on | silkscreen on it. This model of Fomu has a large silver crystal |
|
||||
| | the back. | oscillator that is the tallest component on the board. |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Schematic** | `schematic-hacker.pdf <../_static/reference/schematic-hacker.pdf>`__ | `schematic-pvt.pdf <../_static/reference/schematic-pvt.pdf>`__ |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Received at** | From Tim at 35C3, CCCamp19, HackADay Supercon 2019 | At RISC-V Summit 2019, 36C3, Crowdsupply, Mouser |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
| **Buy more** | End of Life | `CrowdSupply <https://j.mp/fomu-cs>`__, |
|
||||
+------------------+----------------------------------------------------------------------+-------------------------------------------------------------------+
|
||||
|
||||
.. |Dark Blue| raw:: html
|
||||
|
||||
<span style="background-color: #051b70; color: white;">dark blue</span>
|
||||
|
||||
.. |Cyan Light Blue| raw:: html
|
||||
|
||||
<span style="background-color: #03b1c4;">cyan / light blue</span>
|
||||
|
||||
.. |Hacker Hardware Front without case| image:: ../_static/hw-hacker-front-bare-small.jpg
|
||||
.. |Production Hardware Front without case| image:: ../_static/hw-pvt-front-bare-small.jpg
|
||||
.. |Hacker Hardware Back without case| image:: ../_static/hw-hacker-back-bare-small.jpg
|
||||
.. |Production Hardware Back without case| image:: ../_static/hw-pvt-back-bare-small.jpg
|
||||
.. |Hacker Hardware Back with case| image:: ../_static/hw-hacker-back-case-small.jpg
|
||||
.. |Production Hardware Back with case| image:: ../_static/hw-pvt-back-case-small.jpg
|
||||
.. |Hacker Hardware Annotated Diagram| image:: ../_static/hw-hacker-annotated.png
|
||||
.. |Production Hardware Annotated Diagram| image:: ../_static/hw-pvt-annotated.png
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
There are also Fomu EVT boards which were shipped to early backers of
|
||||
the Fomu crowd funding campaign. This model of Fomu is about the size
|
||||
of a credit card. It should have the text “Fomu EVT3” written across
|
||||
it in white silkscreen. If you have a different EVT board such as
|
||||
EVT2 or EVT1, they should also work.
|
45
_sources/requirements/index.rst.txt
Normal file
@ -0,0 +1,45 @@
|
||||
.. |Foboot Version| replace:: v2.0.3
|
||||
|
||||
Requirements
|
||||
############
|
||||
|
||||
.. NOTE::
|
||||
If you are at a workshop, please **install the tools first** and then get
|
||||
the hardware from your presenter.
|
||||
|
||||
For this workshop you will need:
|
||||
|
||||
- :ref:`The Fomu workshop files <required-files>`
|
||||
- :ref:`The Fomu toolchain <required-software>`
|
||||
- :ref:`A Fomu board <required-hardware>`
|
||||
- :ref:`Set up drivers <required-drivers>`
|
||||
|
||||
.. WARNING::
|
||||
Your Fomu should be running Foboot |Foboot Version| or newer.
|
||||
|
||||
You can see what version you are running by typing ``dfu-util -l`` like so;
|
||||
|
||||
.. session:: shell-session
|
||||
:emphasize-lines: 9
|
||||
|
||||
$ dfu-util -l
|
||||
dfu-util 0.9
|
||||
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Found DFU: [1209:5bf0] ver=0101, devnum=19, cfg=1, intf=0, path="1-2", alt=0, name="Fomu PVT running DFU Bootloader v2.0.3", serial="UNKNOWN"
|
||||
$
|
||||
|
||||
If your Fomu is running an version older than |Foboot Version|, follow the
|
||||
:ref:`bootloader-update` section.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 5
|
||||
|
||||
files
|
||||
software
|
||||
hardware
|
||||
drivers
|
146
_sources/requirements/software.rst.txt
Normal file
@ -0,0 +1,146 @@
|
||||
.. _required-software:
|
||||
|
||||
Required Software
|
||||
#################
|
||||
|
||||
Fomu requires specialized software.
|
||||
|
||||
.. NOTE::
|
||||
If you’re taking this workshop as a class, the toolchains are provided
|
||||
on the USB disk.
|
||||
|
||||
Static builds of this software are provided for GNU/Linux, macOS, and Windows via
|
||||
`Fomu Toolchain <https://github.com/im-tomu/fomu-toolchain/releases/latest>`__.
|
||||
|
||||
Debian packages are also `available for Raspberry Pi <https://github.com/im-tomu/fomu-raspbian-packages>`__.
|
||||
|
||||
Moreover, some examples can be executed using :ref:`required-software:containers`.
|
||||
|
||||
Fomu Toolchain
|
||||
--------------
|
||||
|
||||
To install the software, extract it somewhere on your computer, then
|
||||
open up a terminal window and add that directory to your ``PATH``:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. group-tab:: GNU/Linux or MacOS X
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ export PATH=[path-to-toolchain]/bin:$PATH
|
||||
|
||||
.. group-tab:: Windows
|
||||
|
||||
If you use PowerShell as your terminal;
|
||||
|
||||
.. session:: ps1con
|
||||
|
||||
PS> $ENV:PATH = "[path-to-toolchain]\bin;" + $ENV:PATH
|
||||
|
||||
If you use ``cmd.exe`` as your terminal;
|
||||
|
||||
.. session:: doscon
|
||||
|
||||
C:\> PATH=[path-to-toolchain]\bin;%PATH%
|
||||
|
||||
Examples in :ref:`HDLs:VHDL` and :ref:`HDLs:mixed` use `ghdl-yosys-plugin <https://github.com/ghdl/ghdl-yosys-plugin>`_,
|
||||
which looks for standard libraries in the path used when GHDL was configured/built.
|
||||
Therefore, when the toolchain is extracted to an arbitrary location, ``GHDL_PREFIX``
|
||||
needs to be set:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. group-tab:: GNU/Linux or MacOS X
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ export GHDL_PREFIX=[path-to-toolchain]/lib/ghdl
|
||||
|
||||
.. group-tab:: Windows
|
||||
|
||||
If you use PowerShell as your terminal;
|
||||
|
||||
.. session:: ps1con
|
||||
|
||||
PS> $ENV:GHDL_PREFIX = "[path-to-toolchain]\lib\ghdl"
|
||||
|
||||
If you use ``cmd.exe`` as your terminal;
|
||||
|
||||
.. session:: doscon
|
||||
|
||||
C:\> GHDL_PREFIX=[path-to-toolchain]\lib\ghdl
|
||||
|
||||
To confirm installation, run the ``yosys`` command and confirm you get
|
||||
the following output;
|
||||
|
||||
.. code-block:: shell-session
|
||||
:emphasize-lines: 23
|
||||
|
||||
$ yosys
|
||||
|
||||
/----------------------------------------------------------------------------\
|
||||
| |
|
||||
| yosys -- Yosys Open SYnthesis Suite |
|
||||
| |
|
||||
| Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at> |
|
||||
| |
|
||||
| Permission to use, copy, modify, and/or distribute this software for any |
|
||||
| purpose with or without fee is hereby granted, provided that the above |
|
||||
| copyright notice and this permission notice appear in all copies. |
|
||||
| |
|
||||
| THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
||||
| WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
||||
| MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
||||
| ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
||||
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
||||
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
||||
| OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
||||
| |
|
||||
\----------------------------------------------------------------------------/
|
||||
|
||||
Yosys 78b30bbb1102047585d1a2eac89b1c7f5ca7344e (git sha1 41d9173, gcc 5.5.0-12ubuntu1~14.04 -fPIC -Os)
|
||||
|
||||
yosys>
|
||||
|
||||
Type ``exit`` to quit ``yosys``.
|
||||
|
||||
.. NOTE::
|
||||
See the README of `Fomu Toolchain <https://github.com/im-tomu/fomu-toolchain/releases/latest>`_
|
||||
for a complete list of the tools included in the toolchain.
|
||||
|
||||
.. _required-software:containers:
|
||||
|
||||
Containers
|
||||
----------
|
||||
|
||||
There are several projects which provide ready to use container images including open source EDA tools.
|
||||
One of those is `hdl/containers <https://hdl.github.io/containers/>`__.
|
||||
As explained in `hdl.github.io/containers: Usage <https://hdl.github.io/containers/#_usage>`__, there are two main
|
||||
strategies for running EDA tools through containers:
|
||||
|
||||
* All-in-one: a single container is used, which includes all the required tools and dependencies.
|
||||
`make` and all the tools are executed inside that single container.
|
||||
* Fine-grained: `make` is executed on the host. For each tool/step, an specific container is used.
|
||||
|
||||
Both strategies are supported by the examples in subdir :repo:`hdl <hdl>` of this repository.
|
||||
Users willing to run those examples with containers need to take care about the following environment variables:
|
||||
|
||||
* `GHDL_PLUGIN_MODULE`: while ghdl-yosys-plugin is built into Yosys in the fomu-toolchain, it is provided as a module in
|
||||
most containers.
|
||||
Typically, `GHDL_PLUGIN_MODULE=ghdl` is required.
|
||||
Some specific containers might require `GHDL_PLUGIN_MODULE=path/to/ghdl-plugin-name.so`.
|
||||
* `CONTAINER_ENGINE`: in order to enable the fine-grained approach, `CONTAINER_ENGINE` needs to contain the CLI tool
|
||||
name of a container engine, such as `docker` or `podman`.
|
||||
This variable needs to be unset for the all-in-one approach.
|
||||
In that case, the build is agnostic to the fact that everything is being done inside a container.
|
||||
|
||||
.. NOTE::
|
||||
By default, container images defined in :repo:`hdl/container.mk <hdl/container.mk>` are used when
|
||||
`CONTAINER_ENGINE` is set.
|
||||
It's up to the users to customise that file in order to use different container images, or for executing some of the
|
||||
tools locally.
|
||||
|
||||
.. TIP::
|
||||
Find both approaches (and environment variables) used in the CI workflow
|
||||
(:repo:`.github/workflows/test.yml <.github/workflows/test.yml>`) of this repository.
|
351
_sources/riscv.rst.txt
Normal file
@ -0,0 +1,351 @@
|
||||
Fomu as a CPU
|
||||
-------------
|
||||
|
||||
The MicroPython interface is simply a RISC-V program. It interacts with
|
||||
the RISC-V softcore inside Fomu by reading and writing memory directly.
|
||||
|
||||
The CPU in Fomu is built on LiteX, which places every device on a
|
||||
Wishbone bus. This is a 32-bit internal bus that maps peripherals into
|
||||
memory.
|
||||
|
||||
.. image:: _static/litex-design.png
|
||||
:width: 100%
|
||||
:alt: Fomu peripherals on the Wishbone bus
|
||||
|
||||
If you look at the diagram above, you can see that everything in the
|
||||
system is on the Wishbone bus. The CPU is a bus master, and can initiate
|
||||
reads and writes. The system’s RAM is on the wishbone bus, and is
|
||||
currently located at address ``0x10000000``. The boot ROM is also on the
|
||||
bus, and is located at ``0x00000000``. There is also SPI flash which is
|
||||
memory-mapped, so when you load your program onto the SPI flash it shows
|
||||
up on the Wishbone bus at offset ``0x20040000``.
|
||||
|
||||
The Configuration and Status Registers (CSRs) all show up at offset
|
||||
``0xe0000000``. These are the registers we were accessing from Python.
|
||||
Just like before, these special memory addresses correspond to control
|
||||
values.
|
||||
|
||||
You’ll notice a “Bridge” in the diagram above. This is an optional
|
||||
feature that we ship by default on Fomu. It bridges the Wishbone bus to
|
||||
another device. In our case, it makes Wishbone available over USB.
|
||||
|
||||
.. image:: _static/wishbone-usb-debug-bridge.png
|
||||
:width: 100%
|
||||
:alt: Wishbone USB debug bridge interface
|
||||
|
||||
The above image shows the structure of a special USB packet we can
|
||||
generate to access the Wishbone bus from a host PC. It lets us do two
|
||||
things: Read a 32-bit value from Wishbone, or write a 32-bit value to
|
||||
Wishbone. These two primitives give us complete control over Fomu.
|
||||
|
||||
Recall these definitions from earlier:
|
||||
|
||||
.. literalinclude:: ../riscv-blink/include/generated/csr.h
|
||||
:language: cpp
|
||||
:lines: 668,674,680,712
|
||||
|
||||
We can use the ``wishbone-tool`` program to read these values directly
|
||||
out of Fomu:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool 0xe0007000
|
||||
Value at e0007000: 00000002
|
||||
$ wishbone-tool 0xe0007004
|
||||
Value at e0007004: 00000000
|
||||
$ wishbone-tool 0xe0007008
|
||||
Value at e0007008: 00000003
|
||||
$
|
||||
|
||||
The three values correspond to the version number of the board at time
|
||||
of writing: v2.0.3.
|
||||
|
||||
We can also read and write directly to memory. Recall that memory is
|
||||
mapped to address ``0x10000000``. Let’s write a test value there and try
|
||||
to read it back.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool 0x10000000
|
||||
Value at 10000000: 00000005
|
||||
$ wishbone-tool 0x10000000 0x12345678
|
||||
$ wishbone-tool 0x10000000
|
||||
Value at 10000000: 0x12345678
|
||||
|
||||
We can see that the value got stored in memory, just like we thought it
|
||||
would. The bridge is working, and we have access to Fomu over USB.
|
||||
|
||||
Interacting with the LED Directly
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Recall the LED block from Python. We used ``rgb.write_raw()`` to write
|
||||
values to the LED block. Because of how the LED block is implemented, we
|
||||
need to actually make two writes to the Wishbone bus in order to write
|
||||
one value to the LED block. The first write sets the address, and the
|
||||
second write sends the actual data.
|
||||
|
||||
The registers for the LED block are defined as:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#define CSR_RGB_DAT_ADDR 0xe0006800
|
||||
#define CSR_RGB_ADDR_ADDR 0xe0006804
|
||||
|
||||
Let’s change the red color to the maximum value. To do that, we’ll write
|
||||
a ``1`` to the address register, and ``0xff`` to the data register:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool 0xe0006804 1
|
||||
$ wishbone-tool 0xe0006800 0xff
|
||||
$
|
||||
|
||||
We can see that the LED immediately changed its behavior. Try playing
|
||||
around with various values to see what combinations you can come up
|
||||
with!
|
||||
|
||||
You can reset Fomu by writing a special value to the ``CSR_REBOOT_CTRL``
|
||||
register at ``0xe0006000L``. All writes to this register must start with
|
||||
``0xac``, to ensure random values aren’t written. We can reboot Fomu by
|
||||
simply writing this value:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool 0xe0006000 0xac
|
||||
INFO [wishbone_tool::usb_bridge] opened USB device device 007 on bus 001
|
||||
INFO [wishbone_tool::usb_bridge] waiting for target device
|
||||
ERROR [wishbone_tool] server error: BridgeError(USBError(Pipe))
|
||||
$
|
||||
|
||||
We can see that ``wishbone-tool`` has crashed with an error of
|
||||
``USBError(Pipe)``, because the USB device went away as we were talking
|
||||
to it. This is expected behavior. Fomu should be back to its normal
|
||||
color and blink rate now.
|
||||
|
||||
Compiling RISC-V Code
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Of course, Fomu’s softcore is a full CPU, so we can write C code for it.
|
||||
Go to the ``riscv-blink/`` directory and run ``make``. This will
|
||||
generate ``riscv-blink.dfu``, which we can load onto Fomu.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ make
|
||||
CC ./src/main.c main.o
|
||||
CC ./src/rgb.c rgb.o
|
||||
CC ./src/time.c time.o
|
||||
AS ./src/crt0-vexriscv.S crt0-vexriscv.o
|
||||
LD riscv-blink.elf
|
||||
OBJCOPY riscv-blink.bin
|
||||
IHEX riscv-blink.ihex
|
||||
DFU riscv-blink.dfu
|
||||
$ dfu-util -D riscv-blink.dfu
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to dfu-util@lists.gnumonks.org
|
||||
|
||||
Match vendor ID from file: 1209
|
||||
Match product ID from file: 5bf0
|
||||
Opening DFU capable USB device...
|
||||
ID 1209:5bf0
|
||||
Run-time device DFU version 0101
|
||||
Claiming USB DFU Interface...
|
||||
Setting Alternate Setting #0 ...
|
||||
Determining device status: state = dfuIDLE, status = 0
|
||||
dfuIDLE, continuing
|
||||
DFU mode device DFU version 0101
|
||||
Device returned transfer size 1024
|
||||
Copying data from PC to DFU device
|
||||
Download [====== ] 24% 804 bytes
|
||||
$
|
||||
|
||||
This will load the binary onto Fomu and start it immediately. The LED
|
||||
should be blinking quickly in a rainbow pattern. Congratulations! You’ve
|
||||
compiled and loaded a RISC-V program onto a softcore.
|
||||
|
||||
Let’s modify the program by increasing the fade rate so much that it
|
||||
appears solid. First, reboot Fomu by running
|
||||
``wishbone-tool 0xe0006000 0xac``. Next, apply the following patch to
|
||||
``src/main.c``:
|
||||
|
||||
.. code:: diff
|
||||
|
||||
--- a/riscv-blink/src/main.c
|
||||
+++ b/riscv-blink/src/main.c
|
||||
@@ -46,6 +46,7 @@ int main(void) {
|
||||
usb_init();
|
||||
rgb_init();
|
||||
usb_connect();
|
||||
+ rgb_write((100000/64000)-1, LEDDBR);
|
||||
int i = 0;
|
||||
while (1) {
|
||||
color_wheel(i++);
|
||||
|
||||
What this does is increase the LED blink rate from 250 Hz to a much
|
||||
higher value. Compile this and load it again with
|
||||
``dfu-util -D riscv-blink.bin``. The blink rate should appear solid,
|
||||
because it’s blinking too quickly to see.
|
||||
|
||||
Debugging RISC-V Code
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Because we have ``peek`` and ``poke``, and because the USB bridge is a
|
||||
bus master, we can actually halt (and reset!) the CPU over the USB
|
||||
bridge. We can go even further and attach a full debugger to it!
|
||||
|
||||
To start with, run ``wishbone-tool -s gdb``:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ wishbone-tool -s gdb
|
||||
INFO [wishbone_tool::usb_bridge] opened USB device device 008 on bus 001
|
||||
INFO [wishbone_tool::server] accepting connections on 127.0.0.1:3333
|
||||
$
|
||||
|
||||
In a second window, run gdb on ``riscv-blink.elf``:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ riscv64-unknown-elf-gdb riscv-blink.elf -ex 'target remote localhost:3333'
|
||||
GNU gdb (GDB) 8.2.90.20190228-git
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
Type "show copying" and "show warranty" for details.
|
||||
This GDB was configured as "--host=x86_64-w64-mingw32 --target=riscv64-unknown-elf".
|
||||
Type "show configuration" for configuration details.
|
||||
For bug reporting instructions, please see:
|
||||
<http://www.gnu.org/software/gdb/bugs/>.
|
||||
Find the GDB manual and other documentation resources online at:
|
||||
<http://www.gnu.org/software/gdb/documentation/>.
|
||||
|
||||
For help, type "help".
|
||||
Type "apropos word" to search for commands related to "word"...
|
||||
Reading symbols from .\riscv-blink.elf...
|
||||
Remote debugging using localhost:1234
|
||||
csr_writel (addr=3758106660, value=1) at ./include/hw/common.h:41
|
||||
41 *((volatile uint32_t *)addr) = value;
|
||||
(gdb)
|
||||
|
||||
If we run ``bt`` we can get a backtrace, and chances are that we landed
|
||||
in an ``msleep`` function:
|
||||
|
||||
.. code:: gdb
|
||||
|
||||
(gdb) bt
|
||||
#0 0x2004014c in csr_readl (addr=3758106664) at ./include/hw/common.h:46
|
||||
#1 timer0_value_read () at ./include/generated/csr.h:242
|
||||
#2 0x200401dc in msleep (ms=ms@entry=80) at ./include/hw/common.h:41
|
||||
#3 0x20040074 in main () at ./src/main.c:45
|
||||
(gdb)
|
||||
|
||||
We can insert breakpoints, step, continue execution, and generally debug
|
||||
the entire system. We can even reset the program by running
|
||||
``mon reset``.
|
||||
|
||||
|
||||
Using Rust
|
||||
~~~~~~~~~~
|
||||
|
||||
As an alternative to C, the `Rust Language <https://www.rust-lang.org/>`_ can be used to write software for the Fomu softcore.
|
||||
To install Rust, follow the instructions on https://rustup.rs/. After installing Rust, we can install support for RISCV
|
||||
targets using ``rustup``:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ rustup target add riscv32i-unknown-none-elf
|
||||
info: downloading component 'rust-std' for 'riscv32i-unknown-none-elf'
|
||||
4.5 MiB / 4.5 MiB (100 %) 2.1 MiB/s in 2s ETA: 0s
|
||||
info: installing component 'rust-std' for 'riscv32i-unknown-none-elf'
|
||||
|
||||
A Rust version of the C program used above is located in the ``riscv-rust-blink`` directory. Change into that directory,
|
||||
and build it using ``cargo``, the Rust package manager:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ cargo build --release
|
||||
Compiling semver-parser v0.7.0
|
||||
Compiling proc-macro2 v0.4.30
|
||||
Compiling unicode-xid v0.1.0
|
||||
Compiling rand_core v0.4.2
|
||||
Compiling vexriscv v0.0.1
|
||||
Compiling syn v0.15.44
|
||||
Compiling bit_field v0.9.0
|
||||
Compiling fomu-rt v0.0.3
|
||||
Compiling r0 v0.2.2
|
||||
Compiling vcell v0.1.2
|
||||
Compiling panic-halt v0.2.0
|
||||
Compiling rand_core v0.3.1
|
||||
Compiling semver v0.9.0
|
||||
Compiling rand v0.5.6
|
||||
Compiling rustc_version v0.2.3
|
||||
Compiling bare-metal v0.2.4
|
||||
Compiling quote v0.6.13
|
||||
Compiling fomu-pac v0.0.1
|
||||
Compiling riscv-rt-macros v0.1.6
|
||||
Compiling riscv-rust-blink v0.1.0 (/home/dominik/Coding/fomu-workshop/riscv-rust-blink)
|
||||
Finished release [optimized] target(s) in 29.39s
|
||||
|
||||
The resulting binary is located in the target subfolder: ``target/riscv32i-unknown-none-elf/release/riscv-rust-blink``. It can
|
||||
be flashed using the ``flash.sh`` script, also located in the ``riscv-rust-blink`` folder:
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ ./flash.sh
|
||||
dfu-suffix (dfu-util) 0.9
|
||||
|
||||
Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Suffix successfully added to file
|
||||
dfu-util 0.9
|
||||
|
||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
||||
Copyright 2010-2019 Tormod Volden and Stefan Schmidt
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Match vendor ID from file: 1209
|
||||
Match product ID from file: 70b1
|
||||
Opening DFU capable USB device...
|
||||
ID 1209:5bf0
|
||||
Run-time device DFU version 0101
|
||||
Claiming USB DFU Interface...
|
||||
Setting Alternate Setting #0 ...
|
||||
Determining device status: state = dfuIDLE, status = 0
|
||||
dfuIDLE, continuing
|
||||
DFU mode device DFU version 0101
|
||||
Device returned transfer size 1024
|
||||
Copying data from PC to DFU device
|
||||
Download [=========================] 100% 3012 bytes
|
||||
Download done.
|
||||
state(7) = dfuMANIFEST, status(0) = No error condition is present
|
||||
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
|
||||
Done!
|
||||
|
||||
|
||||
Now the Fomu should blink in the same rainbow pattern as before.
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
The Rust example currently does not support the USB functionality. After programming the example, we will not be able to
|
||||
acces the Fomu over USB anymore. To enable USB again, we have to reset the Fomu by removing it from the USB port and
|
||||
plugging it in again.
|
||||
|
||||
|
||||
Further RISC-V experiments
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The `TinyUSB <https://github.com/hathach/tinyusb>`__ USB stack supports Fomu. To get started with it, you might compile the mass storage example it provides. To do so, follow these steps:
|
||||
|
||||
* Clone the TinyUSB git repository: ``git clone https://github.com/hathach/tinyusb`` (you don't need to initialize the subrepositories)
|
||||
* Change to ``tinyusb/examples/device/cdc_msc``
|
||||
* Compile: ``make BOARD=fomu CROSS_COMPILE=riscv64-unknown-elf-``
|
||||
* Load it onto the Fomu: ``dfu-util -D _build/fomu/cdc_msc.bin``
|
||||
|
||||
Fomu should now appear as a USB storage device containing a README.
|
71
_sources/verilog.rst.txt
Normal file
@ -0,0 +1,71 @@
|
||||
.. _HDLs:Verilog:
|
||||
|
||||
Verilog on Fomu
|
||||
---------------
|
||||
|
||||
“Hello world!” - Blink a LED
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The canonical “Hello, world!” of hardware is to blink a LED.
|
||||
The directory :repo:`hdl/verilog/blink <hdl/verilog/blink>` contains a Verilog example of a blink project.
|
||||
This takes the 48 MHz clock and divides it down by a large number so you get an on/off pattern.
|
||||
|
||||
Enter the :repo:`hdl/verilog/blink <hdl/verilog/blink>` directory and build the demo by using ``make``:
|
||||
|
||||
**Make sure you set the** ``FOMU_REV`` **value to match your hardware!** See :ref:`required-hardware`.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ make FOMU_REV=$FOMU_REV
|
||||
...
|
||||
Info: Max frequency for clock 'clk': 73.26 MHz (PASS at 12.00 MHz)
|
||||
|
||||
Info: Max delay posedge clk -> <async>: 3.15 ns
|
||||
|
||||
Info: Slack histogram:
|
||||
Info: legend: * represents 1 endpoint(s)
|
||||
Info: + represents [1,1) endpoint(s)
|
||||
Info: [ 69683, 70208) |**
|
||||
Info: [ 70208, 70733) |
|
||||
Info: [ 70733, 71258) |**
|
||||
Info: [ 71258, 71783) |**
|
||||
Info: [ 71783, 72308) |**
|
||||
Info: [ 72308, 72833) |**
|
||||
Info: [ 72833, 73358) |
|
||||
Info: [ 73358, 73883) |**
|
||||
Info: [ 73883, 74408) |*
|
||||
Info: [ 74408, 74933) |**
|
||||
Info: [ 74933, 75458) |**
|
||||
Info: [ 75458, 75983) |*
|
||||
Info: [ 75983, 76508) |*
|
||||
Info: [ 76508, 77033) |**
|
||||
Info: [ 77033, 77558) |**
|
||||
Info: [ 77558, 78083) |*
|
||||
Info: [ 78083, 78608) |
|
||||
Info: [ 78608, 79133) |*************************
|
||||
Info: [ 79133, 79658) |**
|
||||
Info: [ 79658, 80183) |***
|
||||
22 warnings, 0 errors
|
||||
icepack blink.asc blink.bit
|
||||
cp blink.bit blink.dfu
|
||||
dfu-suffix -v 1209 -p 70b1 -a blink.dfu
|
||||
dfu-suffix (dfu-util) 0.9
|
||||
|
||||
Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Suffix successfully added to file
|
||||
$
|
||||
|
||||
You can then load ``blink.dfu`` onto Fomu by using the same ``dfu-util -D`` command we’ve been using so far.
|
||||
You should see a blinking pattern of varying color on your Fomu, indicating your bitstream was successfully loaded.
|
||||
|
||||
|
||||
Reading Input
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
There is another small example in :repo:`hdl/verilog/blink-expanded <hdl/verilog/blink-expanded>` which shows how to read
|
||||
out some given pins.
|
||||
Build and flash it like described above and see if you can enable the blue and red LED by shorting pins 1+2 or 3+4 on
|
||||
your Fomu (the pins are the exposed contacts sticking out of the USB port).
|
68
_sources/vhdl.rst.txt
Normal file
@ -0,0 +1,68 @@
|
||||
.. _HDLs:VHDL:
|
||||
|
||||
VHDL on Fomu
|
||||
------------
|
||||
|
||||
.. HINT:: Component declarations for instantiating hard cores (such as the ones in
|
||||
:repo:`hdl/sb_ice40_components.vhd <hdl/sb_ice40_components.vhd>`) are found in the installation of
|
||||
`iCEcube2 <http://www.latticesemi.com/iCEcube2>`_.
|
||||
|
||||
|
||||
“Hello world!” - Blink a LED
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The canonical “Hello, world!” of hardware is to blink a LED.
|
||||
The directory :repo:`hdl/vhdl/blink <hdl/vhdl/blink>` contains a VHDL example of a blink project.
|
||||
This takes the 48 MHz clock and divides it down by a large number so you get an on/off pattern.
|
||||
|
||||
Enter the :repo:`hdl/vhdl/blink <hdl/vhdl/blink>` directory and build the demo by using ``make``:
|
||||
|
||||
**Make sure you set the** ``FOMU_REV`` **value to match your hardware!** See :ref:`required-hardware`.
|
||||
|
||||
.. session:: shell-session
|
||||
|
||||
$ make FOMU_REV=$FOMU_REV
|
||||
...
|
||||
Info: Max frequency for clock 'clk': 70.39 MHz (PASS at 12.00 MHz)
|
||||
|
||||
Info: Max delay posedge clk -> <async>: 3.15 ns
|
||||
|
||||
Info: Slack histogram:
|
||||
Info: legend: * represents 1 endpoint(s)
|
||||
Info: + represents [1,1) endpoint(s)
|
||||
Info: [ 69127, 69680) |**
|
||||
Info: [ 69680, 70233) |**
|
||||
Info: [ 70233, 70786) |
|
||||
Info: [ 70786, 71339) |**
|
||||
Info: [ 71339, 71892) |**
|
||||
Info: [ 71892, 72445) |**
|
||||
Info: [ 72445, 72998) |**
|
||||
Info: [ 72998, 73551) |
|
||||
Info: [ 73551, 74104) |**
|
||||
Info: [ 74104, 74657) |**
|
||||
Info: [ 74657, 75210) |**
|
||||
Info: [ 75210, 75763) |**
|
||||
Info: [ 75763, 76316) |
|
||||
Info: [ 76316, 76869) |**
|
||||
Info: [ 76869, 77422) |**
|
||||
Info: [ 77422, 77975) |**
|
||||
Info: [ 77975, 78528) |
|
||||
Info: [ 78528, 79081) |***************************
|
||||
Info: [ 79081, 79634) |**
|
||||
Info: [ 79634, 80187) |***
|
||||
22 warnings, 0 errors
|
||||
docker run --rm -v //t/fomu/fomu-workshop/hdl/vhdl/blink/../..://src -w //src/hdl/vhdl/blink ghdl/synth:icestorm icepack blink.asc blink.bit
|
||||
cp blink.bit blink.dfu
|
||||
dfu-suffix -v 1209 -p 70b1 -a blink.dfu
|
||||
dfu-suffix (dfu-util) 0.9
|
||||
|
||||
Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden
|
||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
||||
|
||||
Suffix successfully added to file
|
||||
$
|
||||
|
||||
You can then load ``blink.dfu`` onto Fomu by using ``make load`` or the same ``dfu-util -D`` command we’ve been using so
|
||||
far.
|
||||
You should see a blinking pattern of varying color on your Fomu, indicating your bitstream was successfully loaded.
|
BIN
_static/Zadig-Setup.png
Normal file
After Width: | Height: | Size: 29 KiB |
134
_static/_sphinx_javascript_frameworks_compat.js
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* _sphinx_javascript_frameworks_compat.js
|
||||
* ~~~~~~~~~~
|
||||
*
|
||||
* Compatability shim for jQuery and underscores.js.
|
||||
*
|
||||
* WILL BE REMOVED IN Sphinx 6.0
|
||||
* xref RemovedInSphinx60Warning
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* select a different prefix for underscore
|
||||
*/
|
||||
$u = _.noConflict();
|
||||
|
||||
|
||||
/**
|
||||
* small helper function to urldecode strings
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
|
||||
*/
|
||||
jQuery.urldecode = function(x) {
|
||||
if (!x) {
|
||||
return x
|
||||
}
|
||||
return decodeURIComponent(x.replace(/\+/g, ' '));
|
||||
};
|
||||
|
||||
/**
|
||||
* small helper function to urlencode strings
|
||||
*/
|
||||
jQuery.urlencode = encodeURIComponent;
|
||||
|
||||
/**
|
||||
* This function returns the parsed url parameters of the
|
||||
* current request. Multiple values per key are supported,
|
||||
* it will always return arrays of strings for the value parts.
|
||||
*/
|
||||
jQuery.getQueryParameters = function(s) {
|
||||
if (typeof s === 'undefined')
|
||||
s = document.location.search;
|
||||
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||
var result = {};
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var tmp = parts[i].split('=', 2);
|
||||
var key = jQuery.urldecode(tmp[0]);
|
||||
var value = jQuery.urldecode(tmp[1]);
|
||||
if (key in result)
|
||||
result[key].push(value);
|
||||
else
|
||||
result[key] = [value];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* highlight a given string on a jquery object by wrapping it in
|
||||
* span elements with the given class name.
|
||||
*/
|
||||
jQuery.fn.highlightText = function(text, className) {
|
||||
function highlight(node, addItems) {
|
||||
if (node.nodeType === 3) {
|
||||
var val = node.nodeValue;
|
||||
var pos = val.toLowerCase().indexOf(text);
|
||||
if (pos >= 0 &&
|
||||
!jQuery(node.parentNode).hasClass(className) &&
|
||||
!jQuery(node.parentNode).hasClass("nohighlight")) {
|
||||
var span;
|
||||
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
|
||||
if (isInSVG) {
|
||||
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
||||
} else {
|
||||
span = document.createElement("span");
|
||||
span.className = className;
|
||||
}
|
||||
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||
document.createTextNode(val.substr(pos + text.length)),
|
||||
node.nextSibling));
|
||||
node.nodeValue = val.substr(0, pos);
|
||||
if (isInSVG) {
|
||||
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
var bbox = node.parentElement.getBBox();
|
||||
rect.x.baseVal.value = bbox.x;
|
||||
rect.y.baseVal.value = bbox.y;
|
||||
rect.width.baseVal.value = bbox.width;
|
||||
rect.height.baseVal.value = bbox.height;
|
||||
rect.setAttribute('class', className);
|
||||
addItems.push({
|
||||
"parent": node.parentNode,
|
||||
"target": rect});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!jQuery(node).is("button, select, textarea")) {
|
||||
jQuery.each(node.childNodes, function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
}
|
||||
}
|
||||
var addItems = [];
|
||||
var result = this.each(function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
for (var i = 0; i < addItems.length; ++i) {
|
||||
jQuery(addItems[i].parent).before(addItems[i].target);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
* backward compatibility for jQuery.browser
|
||||
* This will be supported until firefox bug is fixed.
|
||||
*/
|
||||
if (!jQuery.browser) {
|
||||
jQuery.uaMatch = function(ua) {
|
||||
ua = ua.toLowerCase();
|
||||
|
||||
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(msie) ([\w.]+)/.exec(ua) ||
|
||||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
|
||||
[];
|
||||
|
||||
return {
|
||||
browser: match[ 1 ] || "",
|
||||
version: match[ 2 ] || "0"
|
||||
};
|
||||
};
|
||||
jQuery.browser = {};
|
||||
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
|
||||
}
|
900
_static/basic.css
Normal file
@ -0,0 +1,900 @@
|
||||
/*
|
||||
* basic.css
|
||||
* ~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.section::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap : break-word;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox form.search {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="text"] {
|
||||
float: left;
|
||||
width: 80%;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||
float: left;
|
||||
width: 20%;
|
||||
border-left: none;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li p.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
table.indextable > tbody > tr > td > ul {
|
||||
padding-left: 0em;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.modindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
/* -- domain module index --------------------------------------------------- */
|
||||
|
||||
table.modindextable td {
|
||||
padding: 2px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
div.body {
|
||||
min-width: 360px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink,
|
||||
caption:hover > a.headerlink,
|
||||
p.caption:hover > a.headerlink,
|
||||
div.code-block-caption:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, figure.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, figure.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, figure.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
img.align-default, figure.align-default, .figure.align-default {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-default {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar,
|
||||
aside.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
clear: right;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
nav.contents,
|
||||
aside.topic,
|
||||
div.admonition, div.topic, blockquote {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
nav.contents,
|
||||
aside.topic,
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||
|
||||
div.sidebar > :last-child,
|
||||
aside.sidebar > :last-child,
|
||||
nav.contents > :last-child,
|
||||
aside.topic > :last-child,
|
||||
div.topic > :last-child,
|
||||
div.admonition > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sidebar::after,
|
||||
aside.sidebar::after,
|
||||
nav.contents::after,
|
||||
aside.topic::after,
|
||||
div.topic::after,
|
||||
div.admonition::after,
|
||||
blockquote::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-default {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table caption span.caption-text {
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 5px;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
table.citation td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
th > :first-child,
|
||||
td > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
th > :last-child,
|
||||
td > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* -- figures --------------------------------------------------------------- */
|
||||
|
||||
div.figure, figure {
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.figure p.caption, figcaption {
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-number,
|
||||
figcaption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-text,
|
||||
figcaption span.caption-text {
|
||||
}
|
||||
|
||||
/* -- field list styles ----------------------------------------------------- */
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.field-name {
|
||||
-moz-hyphens: manual;
|
||||
-ms-hyphens: manual;
|
||||
-webkit-hyphens: manual;
|
||||
hyphens: manual;
|
||||
}
|
||||
|
||||
/* -- hlist styles ---------------------------------------------------------- */
|
||||
|
||||
table.hlist {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
table.hlist td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -- object description styles --------------------------------------------- */
|
||||
|
||||
.sig {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
}
|
||||
|
||||
.sig-name, code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sig-name {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.sig-prename, code.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.sig-paren {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.sig-param.n {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* C++ specific styling */
|
||||
|
||||
.sig-inline.c-texpr,
|
||||
.sig-inline.cpp-texpr {
|
||||
font-family: unset;
|
||||
}
|
||||
|
||||
.sig.c .k, .sig.c .kt,
|
||||
.sig.cpp .k, .sig.cpp .kt {
|
||||
color: #0033B3;
|
||||
}
|
||||
|
||||
.sig.c .m,
|
||||
.sig.cpp .m {
|
||||
color: #1750EB;
|
||||
}
|
||||
|
||||
.sig.c .s, .sig.c .sc,
|
||||
.sig.cpp .s, .sig.cpp .sc {
|
||||
color: #067D17;
|
||||
}
|
||||
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:first-child > :first-child,
|
||||
:not(li) > ul > li:first-child > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:last-child > :last-child,
|
||||
:not(li) > ul > li:last-child > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
ol.simple ol p,
|
||||
ol.simple ul p,
|
||||
ul.simple ol p,
|
||||
ul.simple ul p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple > li:not(:first-child) > p,
|
||||
ul.simple > li:not(:first-child) > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple p,
|
||||
ul.simple p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
aside.footnote > span,
|
||||
div.citation > span {
|
||||
float: left;
|
||||
}
|
||||
aside.footnote > span:last-of-type,
|
||||
div.citation > span:last-of-type {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
aside.footnote > p {
|
||||
margin-left: 2em;
|
||||
}
|
||||
div.citation > p {
|
||||
margin-left: 4em;
|
||||
}
|
||||
aside.footnote > p:last-of-type,
|
||||
div.citation > p:last-of-type {
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
aside.footnote > p:last-of-type:after,
|
||||
div.citation > p:last-of-type:after {
|
||||
content: "";
|
||||
clear: both;
|
||||
}
|
||||
|
||||
dl.field-list {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(30%) auto;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
dl.field-list > dd {
|
||||
padding-left: 0.5em;
|
||||
margin-top: 0em;
|
||||
margin-left: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dl > dd:last-child,
|
||||
dl > dd:last-child > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt:target, span.highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
rect.highlighted {
|
||||
fill: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.guilabel, .menuselection {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.accelerator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.classifier {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
.classifier:before {
|
||||
font-style: normal;
|
||||
margin: 0 0.5em;
|
||||
content: ":";
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
pre, div[class*="highlight-"] {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
span.pre {
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div[class*="highlight-"] {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tbody {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tr {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td.code {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.highlight .hll {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.highlight pre,
|
||||
table.highlighttable pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption + div {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
margin-top: 1em;
|
||||
padding: 2px 5px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div.code-block-caption code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos,
|
||||
span.linenos,
|
||||
div.highlight span.gp { /* gp: Generic.Prompt */
|
||||
user-select: none;
|
||||
-webkit-user-select: text; /* Safari fallback only */
|
||||
-webkit-user-select: none; /* Chrome/Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE10+ */
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-number {
|
||||
padding: 0.1em 0.3em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-text {
|
||||
}
|
||||
|
||||
div.literal-block-wrapper {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
code.xref, a code {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
span.eqno a.headerlink {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.math:hover a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
156
_static/doctools.js
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* doctools.js
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* Base JavaScript utilities for all Sphinx HTML documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
|
||||
"TEXTAREA",
|
||||
"INPUT",
|
||||
"SELECT",
|
||||
"BUTTON",
|
||||
]);
|
||||
|
||||
const _ready = (callback) => {
|
||||
if (document.readyState !== "loading") {
|
||||
callback();
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", callback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Small JavaScript module for the documentation.
|
||||
*/
|
||||
const Documentation = {
|
||||
init: () => {
|
||||
Documentation.initDomainIndexTable();
|
||||
Documentation.initOnKeyListeners();
|
||||
},
|
||||
|
||||
/**
|
||||
* i18n support
|
||||
*/
|
||||
TRANSLATIONS: {},
|
||||
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
|
||||
LOCALE: "unknown",
|
||||
|
||||
// gettext and ngettext don't access this so that the functions
|
||||
// can safely bound to a different name (_ = Documentation.gettext)
|
||||
gettext: (string) => {
|
||||
const translated = Documentation.TRANSLATIONS[string];
|
||||
switch (typeof translated) {
|
||||
case "undefined":
|
||||
return string; // no translation
|
||||
case "string":
|
||||
return translated; // translation exists
|
||||
default:
|
||||
return translated[0]; // (singular, plural) translation tuple exists
|
||||
}
|
||||
},
|
||||
|
||||
ngettext: (singular, plural, n) => {
|
||||
const translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated !== "undefined")
|
||||
return translated[Documentation.PLURAL_EXPR(n)];
|
||||
return n === 1 ? singular : plural;
|
||||
},
|
||||
|
||||
addTranslations: (catalog) => {
|
||||
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
|
||||
Documentation.PLURAL_EXPR = new Function(
|
||||
"n",
|
||||
`return (${catalog.plural_expr})`
|
||||
);
|
||||
Documentation.LOCALE = catalog.locale;
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to focus on search bar
|
||||
*/
|
||||
focusSearchBar: () => {
|
||||
document.querySelectorAll("input[name=q]")[0]?.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialise the domain index toggle buttons
|
||||
*/
|
||||
initDomainIndexTable: () => {
|
||||
const toggler = (el) => {
|
||||
const idNumber = el.id.substr(7);
|
||||
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
|
||||
if (el.src.substr(-9) === "minus.png") {
|
||||
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
|
||||
toggledRows.forEach((el) => (el.style.display = "none"));
|
||||
} else {
|
||||
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
|
||||
toggledRows.forEach((el) => (el.style.display = ""));
|
||||
}
|
||||
};
|
||||
|
||||
const togglerElements = document.querySelectorAll("img.toggler");
|
||||
togglerElements.forEach((el) =>
|
||||
el.addEventListener("click", (event) => toggler(event.currentTarget))
|
||||
);
|
||||
togglerElements.forEach((el) => (el.style.display = ""));
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
|
||||
},
|
||||
|
||||
initOnKeyListeners: () => {
|
||||
// only install a listener if it is really needed
|
||||
if (
|
||||
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
|
||||
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
|
||||
)
|
||||
return;
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
// bail for input elements
|
||||
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
|
||||
// bail with special keys
|
||||
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
||||
|
||||
if (!event.shiftKey) {
|
||||
switch (event.key) {
|
||||
case "ArrowLeft":
|
||||
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||
|
||||
const prevLink = document.querySelector('link[rel="prev"]');
|
||||
if (prevLink && prevLink.href) {
|
||||
window.location.href = prevLink.href;
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
case "ArrowRight":
|
||||
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||
|
||||
const nextLink = document.querySelector('link[rel="next"]');
|
||||
if (nextLink && nextLink.href) {
|
||||
window.location.href = nextLink.href;
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// some keyboard layouts may need Shift to get /
|
||||
switch (event.key) {
|
||||
case "/":
|
||||
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
|
||||
Documentation.focusSearchBar();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// quick alias for translations
|
||||
const _ = Documentation.gettext;
|
||||
|
||||
_ready(Documentation.init);
|
14
_static/documentation_options.js
Normal file
@ -0,0 +1,14 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
FILE_SUFFIX: '.html',
|
||||
LINK_SUFFIX: '.html',
|
||||
HAS_SOURCE: true,
|
||||
SOURCELINK_SUFFIX: '.txt',
|
||||
NAVIGATION_WITH_KEYS: false,
|
||||
SHOW_SEARCH_SUMMARY: true,
|
||||
ENABLE_SEARCH_SHORTCUTS: true,
|
||||
};
|
BIN
_static/file.png
Normal file
After Width: | Height: | Size: 286 B |
BIN
_static/fomu-block-diagram.png
Normal file
After Width: | Height: | Size: 64 KiB |
1
_static/fomu.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2020-11-07T13:50:31.243Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.5.7 Chrome/83.0.4103.122 Electron/9.1.2 Safari/537.36" etag="VvqdxijonNfACcLSaJ12" version="13.5.7" type="device"><diagram id="yj2Z-7FWhddFFwL3RGEn" name="Page-1">5Vpbd6o4FP41PtrFLVweWy+nnalrnOOcmfYRISpLBCdiq/31k0CCIUGlFUU7dK2W7ISd5Mv3ZW9CW3pnsfmB3OVsEPswbGmKv2np3ZamAdXCv4lhmxl028gMUxT4mUndGUbBB6RGhVrXgQ9XhYZJHIdJsCwavTiKoJcUbC5C8Xux2SQOi70u3SmUDCPPDWXrP4GfzOgsdEXZVTzCYDqjXRumTR9ZuKw1bbqauX78zpn0XkvvoDhOsrvFpgNDAh4DJnuuv6c2HxmCUVLlgYX398h86T22+72n3+YDL5g/fLS1zMubG67pjFuaGWJ/D2N8MyU3T52eofwagt9ZDe4ir8xbI9HiB29k0smWQmn+uyYzfUjgJmm7YTCNWvo9bhHCSYL/pE/i9YmS9iplAakDy83uQbGD1dKNjg8DD7asITanA6x/zKpyaNCkcWkXlbyomo3r5qTX0fDn/YCbTeb4OiZZBviJEzfZvB8qTfualrx+NIBmY6krz53VbSFx2qwJ9VWzPQ6Ij+5o2Bj5D+5KVed40EnpNlZlklqhaw3F68iHZP8nM3mfBQkcLV2P1L7jcI1ts2QR4pJKBhiEYScOY5Q+q/sutCce4W+C4jnkakzPhuNJ3t8bRBi9vUFJzUMdzhFgvIAJ2uImG5YP0OhI8wOVld930VZlEXTGBVqVRWCXRvhp7nsXA/ENDYOfCIm6FBI7aLtK3FBeHYNwcvD4USvwk8lE80qB982xCcx6gNcqAG+X4G6cC3ZDgv3P0fAJW/qhu5rJ2JPGg5opD6DtG2XI29pYN8+EfA5pU8gDCXkD703KX/Hamy1df1UvuwH5Kd1W0ovulJw9u2rabgAoYJ/n8U1hb0rY//xBQs5zr1sr7FDF5LbKYHdMS3drorZhXBm8lgTvrxGBd7kOw/Wy5m0bmnu2bcsZK0o9CAPtyjYPuxzhOoG1PVgO7NgGBjgTsI3HQ3YCUng1F2BdzdwluZ2EcHNPTjswFjDy6W3Xw5FzFWTQuSiRzRzoGCa0faELlBZeSeEOsGJ3w1d2t3mJndporB+uDDdB8sJ6wPeZT1azc0kKW64whCjAMEJEbQIllPQiTKKLA1jf7JBGpWMrlDP8oC8d+QgkwRjHa+TBA6tD1wJ3OYXJMXnIpONIBUpIxWwIhm4SvBWHW8Y02sMwDtK3D8ZpReC0SNZsmvQp/uhIcKQ5RUeGKjjKcJAcpcTPp32CFtSTtRDFERSFMA5jb75HBuqdooCiFCzHqUUMSkEM4LAYiH9RDanjfkAwZN1ypX1aOa4PXk01asWqqBWtUa2oQmAVKV5VKwAccXRurZQd6Z5XK1yUeC3o4iSV5Mp45QJIuUq+JojGgoddURBWo4LQBR5bXxSE4eCldLir6NZ07hxldwnjPLdY5MOesweWOvOrSxB/J0iyOoU8TtE/nck1kIPpTcpIt4QcDHw1rgg5mCY6OrdU5AO6z0qFyeJ/oJWCTuxbUInRqEpEcn81+xLldvHsSz5MrUUlNMqUZ1+KrfNCUW9HJoUcTzksk7I3oao6aYrXhvAGrotfrSrz2sFpEtibRNkXZrl8bH3utOkWWX6TjLVrYqxhOXcWz1i9WcrKnwKGz88Saz93UB1HjFPppxXcMIimLfZOuu+zucCuTqePr9Z5Pqc7NB5x5Cn/mr6fJyedYrONgYP96Y/TUC/CLK7BNaCuARl19aKoy6+16QdFpYvwzoC+G+sNc89RBYe/cVH85Xelb8h6BxxF/bKsl3Pv74e6IR0DNL3XyLng90e9LK7WhDou7v4nPMt+dv9Zr/f+Aw==</diagram></mxfile>
|
92
_static/font/NotoSansCJKjp/LICENSE_OFL.txt
Normal file
@ -0,0 +1,92 @@
|
||||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font
|
||||
creation efforts of academic and linguistic communities, and to
|
||||
provide a free and open framework in which fonts may be shared and
|
||||
improved in partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply to
|
||||
any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software
|
||||
components as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to,
|
||||
deleting, or substituting -- in part or in whole -- any of the
|
||||
components of the Original Version, by changing formats or by porting
|
||||
the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed,
|
||||
modify, redistribute, and sell modified and unmodified copies of the
|
||||
Font Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components, in
|
||||
Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the
|
||||
corresponding Copyright Holder. This restriction only applies to the
|
||||
primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created using
|
||||
the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Black.ttf
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Black.woff
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Black.woff2
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Bold.ttf
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Bold.woff
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Bold.woff2
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-DemiLight.ttf
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-DemiLight.woff
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-DemiLight.woff2
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Light.ttf
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Light.woff
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Light.woff2
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Medium.ttf
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Medium.woff
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Medium.woff2
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Regular.ttf
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Regular.woff
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Regular.woff2
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Thin.ttf
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Thin.woff
Normal file
BIN
_static/font/NotoSansCJKjp/NotoSansCJKjp-Thin.woff2
Normal file
BIN
_static/font/Roboto/Roboto-Regular.eot
Normal file
BIN
_static/font/Roboto/Roboto-Regular.ttf
Normal file
BIN
_static/font/Roboto/Roboto-Regular.woff
Normal file
BIN
_static/font/Roboto/Roboto-Regular.woff2
Normal file
BIN
_static/hw-hacker-annotated.png
Normal file
After Width: | Height: | Size: 60 KiB |
346
_static/hw-hacker-annotated.svg
Normal file
@ -0,0 +1,346 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
width="300"
|
||||
height="300"
|
||||
viewBox="0 0 300 300"
|
||||
sodipodi:docname="hw-hacker-annotated.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
inkscape:export-filename="/home/tansell/github/im-tomu/fomu-workshop/img/hw-hacker-annotated.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4567"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#808000;stroke-width:1pt;stroke-opacity:1;fill:#808000;fill-opacity:1"
|
||||
transform="scale(0.8) rotate(180) translate(12.5,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4564"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.8) translate(12.5,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#00ffff;fill-opacity:1;fill-rule:evenodd;stroke:#00ffff;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:#800000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6-1"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6-1-0"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2-2-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6-1-0-6"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2-2-9-0"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1019"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.0412372"
|
||||
inkscape:cx="169.62194"
|
||||
inkscape:cy="105.4916"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<image
|
||||
sodipodi:absref="/home/tansell/github/im-tomu/fomu-workshop/img/hw-hacker-back-bare.jpg"
|
||||
xlink:href="hw-hacker-back-bare.jpg"
|
||||
width="113.28"
|
||||
height="155.2"
|
||||
preserveAspectRatio="none"
|
||||
id="image10"
|
||||
x="97.328812"
|
||||
y="62.59663" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff00ff;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4520"
|
||||
width="14.79661"
|
||||
height="16.769491"
|
||||
x="167.01016"
|
||||
y="148.74576" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4522"
|
||||
width="18.742382"
|
||||
height="33.538971"
|
||||
x="117.05762"
|
||||
y="158.61018" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ffff00;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4524"
|
||||
width="16.769487"
|
||||
height="23.34577"
|
||||
x="167.03729"
|
||||
y="175.70848" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#00ffff;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4526"
|
||||
width="26.962711"
|
||||
height="31.23728"
|
||||
x="138.43051"
|
||||
y="151.04745" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:26.08836365px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.6522091"
|
||||
x="81.924675"
|
||||
y="245.94275"
|
||||
id="text4530"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4528"
|
||||
x="81.924675"
|
||||
y="245.94275"
|
||||
style="fill:#00ffff;stroke:#000000;stroke-width:0.6522091">FPGA</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:24.85016441px;line-height:1.25;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#ff00ff;fill-opacity:1;stroke:#000000;stroke-width:0.62125415"
|
||||
x="288.30161"
|
||||
y="139.11916"
|
||||
id="text4534"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4532"
|
||||
x="288.30161"
|
||||
y="139.11916"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.62125415">RGB</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="288.30161"
|
||||
y="170.18185"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.62125415"
|
||||
id="tspan4560"> LED</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:23.88237572px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.59705943"
|
||||
x="80.206093"
|
||||
y="130.54811"
|
||||
id="text4538"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4536"
|
||||
x="80.206093"
|
||||
y="130.54811"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.59705943">SPI</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="80.206093"
|
||||
y="160.40108"
|
||||
id="tspan4540"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.59705943">Flash</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:16.27080154px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.40677005"
|
||||
x="178.89175"
|
||||
y="239.02901"
|
||||
id="text4544"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4542"
|
||||
x="178.89175"
|
||||
y="239.02901"
|
||||
style="fill:#ffff00;stroke:#000000;stroke-width:0.40677005">Oscillator</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff6600;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4548"
|
||||
width="17.755932"
|
||||
height="19.728813"
|
||||
x="122.31866"
|
||||
y="112.57628" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff6600;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4550"
|
||||
width="17.755932"
|
||||
height="18.742373"
|
||||
x="143.36272"
|
||||
y="113.2339" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff6600;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4552"
|
||||
width="18.08474"
|
||||
height="18.742374"
|
||||
x="164.4068"
|
||||
y="113.56271" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:20.54193497px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.51354837"
|
||||
x="109.64693"
|
||||
y="27.969992"
|
||||
id="text4556"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4554"
|
||||
x="109.64693"
|
||||
y="27.969992"
|
||||
style="fill:#ff6600;stroke:#000000;stroke-width:0.51354837">Voltage</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="109.64693"
|
||||
y="53.647408"
|
||||
id="tspan4558"
|
||||
style="fill:#ff6600;stroke:#000000;stroke-width:0.51354837">Regulators</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#808000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
|
||||
d="M 203.53558,225.35932 176.24406,190.83391"
|
||||
id="path4562"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#00ffff;stroke:#00ffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3)"
|
||||
d="m 150.08287,232.55486 2.63051,-56.55593"
|
||||
id="path4562-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#800080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5)"
|
||||
d="m 231.41378,150.60206 -54.25424,5.91864"
|
||||
id="path4562-7-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#800000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6)"
|
||||
d="m 79.19686,162.78321 41.7593,13.81017"
|
||||
id="path4562-7-5-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#aa4400;stroke:#aa4400;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6-1)"
|
||||
d="m 131.58505,56.134055 -0.98646,64.447455"
|
||||
id="path4562-7-5-9-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#aa4400;stroke:#aa4400;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6-1-0)"
|
||||
d="m 151.76828,56.818731 -0.98647,65.105089"
|
||||
id="path4562-7-5-9-7-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#aa4400;stroke:#aa4400;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6-1-0-6)"
|
||||
d="m 174.61911,56.22402 -1.97291,64.77627"
|
||||
id="path4562-7-5-9-7-3-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
BIN
_static/hw-hacker-back-bare-small.jpg
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
_static/hw-hacker-back-bare.jpg
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
_static/hw-hacker-back-case-small.jpg
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
_static/hw-hacker-back-case.jpg
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
_static/hw-hacker-front-bare-small.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
_static/hw-hacker-front-bare.jpg
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
_static/hw-hacker-front-case-small.jpg
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
_static/hw-hacker-front-case.jpg
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
_static/hw-pvt-annotated.png
Normal file
After Width: | Height: | Size: 58 KiB |
343
_static/hw-pvt-annotated.svg
Normal file
@ -0,0 +1,343 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
width="300"
|
||||
height="300"
|
||||
viewBox="0 0 300 300"
|
||||
sodipodi:docname="hw-pvt-annotated.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4567"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#808000;stroke-width:1pt;stroke-opacity:1;fill:#808000;fill-opacity:1"
|
||||
transform="scale(0.8) rotate(180) translate(12.5,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4564"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.8) translate(12.5,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:#800000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6-1"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6-1-0"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2-2-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-3-5-6-1-0-6"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567-6-3-2-2-9-0"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#aa4400;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1019"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.0412372"
|
||||
inkscape:cx="226.8355"
|
||||
inkscape:cy="189.94343"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<image
|
||||
sodipodi:absref="/home/tansell/github/im-tomu/fomu-workshop/img/hw-pvt-back-bare.jpg"
|
||||
xlink:href="hw-pvt-back-bare.jpg"
|
||||
y="62.59663"
|
||||
x="97.328812"
|
||||
id="image10"
|
||||
preserveAspectRatio="none"
|
||||
height="155.2"
|
||||
width="113.28" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff00ff;stroke-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-linejoin:round"
|
||||
id="rect4520"
|
||||
width="14.79661"
|
||||
height="16.769491"
|
||||
x="146.65085"
|
||||
y="99.423729" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4522"
|
||||
width="30.908474"
|
||||
height="40.444069"
|
||||
x="102.91864"
|
||||
y="128.03052" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ffff00;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4524"
|
||||
width="37.484745"
|
||||
height="32.881355"
|
||||
x="168.35254"
|
||||
y="141.84068" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#00ffff;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4526"
|
||||
width="34.196609"
|
||||
height="27.620335"
|
||||
x="135.8"
|
||||
y="118.49492" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:26.08836365px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.6522091"
|
||||
x="215.42297"
|
||||
y="118.03428"
|
||||
id="text4530"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4528"
|
||||
x="215.42297"
|
||||
y="118.03428"
|
||||
style="fill:#00ffff;stroke:#000000;stroke-width:0.6522091">FPGA</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:24.85016441px;line-height:1.25;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#ff00ff;fill-opacity:1;stroke:#000000;stroke-width:0.62125415"
|
||||
x="94.959236"
|
||||
y="85.522545"
|
||||
id="text4534"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4532"
|
||||
x="94.959236"
|
||||
y="85.522545"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.62125415">RGB</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="94.959236"
|
||||
y="116.58525"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.62125415"
|
||||
id="tspan4560"> LED</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:23.88237572px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.59705943"
|
||||
x="85.795921"
|
||||
y="188.74811"
|
||||
id="text4538"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4536"
|
||||
x="85.795921"
|
||||
y="188.74811"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.59705943">SPI</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="85.795921"
|
||||
y="218.60107"
|
||||
id="tspan4540"
|
||||
style="text-align:end;text-anchor:end;stroke-width:0.59705943">Flash</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:16.27080154px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.40677005"
|
||||
x="215.39006"
|
||||
y="196.61206"
|
||||
id="text4544"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4542"
|
||||
x="215.39006"
|
||||
y="196.61206"
|
||||
style="fill:#ffff00;stroke:#000000;stroke-width:0.40677005">Oscillator</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff6600;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4548"
|
||||
width="17.755932"
|
||||
height="19.728813"
|
||||
x="123.6339"
|
||||
y="183.92882" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff6600;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4550"
|
||||
width="17.755932"
|
||||
height="18.742373"
|
||||
x="168.02373"
|
||||
y="184.58644" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#ff6600;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4552"
|
||||
width="18.08474"
|
||||
height="18.742374"
|
||||
x="185.77966"
|
||||
y="184.58644" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:20.54193497px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.51354837"
|
||||
x="107.34523"
|
||||
y="245.64456"
|
||||
id="text4556"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4554"
|
||||
x="107.34523"
|
||||
y="245.64456"
|
||||
style="fill:#ff6600;stroke:#000000;stroke-width:0.51354837">Voltage</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="107.34523"
|
||||
y="271.32199"
|
||||
id="tspan4558"
|
||||
style="fill:#ff6600;stroke:#000000;stroke-width:0.51354837">Regulators</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#808000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
|
||||
d="m 218.98982,180.31187 -23.01695,-17.0983"
|
||||
id="path4562"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3)"
|
||||
d="m 213.54389,111.22266 -52.28136,18.41356"
|
||||
id="path4562-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#800080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5)"
|
||||
d="M 95.284973,92.730878 151.18327,106.21223"
|
||||
id="path4562-7-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#800000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6)"
|
||||
d="m 79.19686,162.78321 32.55252,-11.83729"
|
||||
id="path4562-7-5-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#aa4400;stroke:#aa4400;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6-1)"
|
||||
d="m 131.91387,225.14422 -0.65765,-28.93559"
|
||||
id="path4562-7-5-9-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#aa4400;stroke:#aa4400;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6-1-0)"
|
||||
d="m 157.68693,227.14415 18.08471,-31.89491"
|
||||
id="path4562-7-5-9-7-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#aa4400;stroke:#aa4400;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend-3-5-6-1-0-6)"
|
||||
d="M 179.88013,227.53588 194.67671,193.9969"
|
||||
id="path4562-7-5-9-7-3-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
BIN
_static/hw-pvt-back-bare-small.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
_static/hw-pvt-back-bare.jpg
Normal file
After Width: | Height: | Size: 52 KiB |