This commit is contained in:
GHA 2023-04-21 01:14:28 +00:00
commit a0e03bb9a4
480 changed files with 60964 additions and 0 deletions

4
.buildinfo Normal file
View 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

0
.nojekyll Normal file
View File

BIN
_images/Zadig-Setup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
_images/blinky.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
_images/blinky_diagram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
_images/blinky_steps.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
_images/blinky_video.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

BIN
_images/clk_buffering.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
_images/ice40-arch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

BIN
_images/ice40-ledd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
_images/ice40-lut.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
_images/ice40-plb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

BIN
_images/ice40-rgb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

BIN
_images/litex-design.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
_images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
_images/pwm_generator.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
_images/sb_rgba_drv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

217
_sources/background.rst.txt Normal file
View 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 isnt 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 wouldnt 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>`_.

View 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
View 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
View 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
View 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
View File

@ -0,0 +1,32 @@
FPGA Tomu Workshop
==================
.. image:: _static/logo.png
:align: center
:width: 600px
:alt: Fomu logo
Hi, Im `Fomu <https://github.com/im-tomu/fomu-hardware>`_ (FPGA Tomu)!
This workshop covers the basics of Fomu in a top-down approach. Well
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 well take a gentle approach and
start out by treating it like a Python interpreter first, and gradually
peel away layers until were 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
View 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. Lets 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, theres not much we can *do* with this design. But
theres a lot of infrastructure there. So lets 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.

View 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 weve 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
View 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 youre on a macOS machine, use the following command to connect to
the device:
.. session:: shell-session
$ screen /dev/cu.usb*
.. group-tab:: Linux
If youre 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 youre 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
----------------------
Fomus 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 dont 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 Fomus 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>`__.

View 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 Zephyrs shell youll 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 wont 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>`__.

View 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 its 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.

View 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
doesnt 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
`Antmicros
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.
Well 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>`__.

View 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
View 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 Renodes
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
Renodes usage patterns by just inspecting those files for details.
.. toctree::
renode-starting
renode-zephyr
renode-bridge
renode-verilator

View 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.

View File

@ -0,0 +1,46 @@
.. _required-files:
Required Files
--------------
.. NOTE::
If youre 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'
$

View 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.

View 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

View File

@ -0,0 +1,146 @@
.. _required-software:
Required Software
#################
Fomu requires specialized software.
.. NOTE::
If youre 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
View 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 systems 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.
Youll 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``. Lets 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
Lets change the red color to the maximum value. To do that, well 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 arent 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, Fomus 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! Youve
compiled and loaded a RISC-V program onto a softcore.
Lets 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 its 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
View 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 weve 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
View 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 weve 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View 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
View 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
View 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);

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

1
_static/fomu.drawio Normal file
View 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>

View 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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Some files were not shown because too many files have changed in this diff Show More