- Download Software from fomu.im/camp19
+ Software is available on the USB drive marked "Fomu Workshop"
+
+
+ Or, download software from fomu.im/camp19
@@ -95,7 +99,8 @@
Fomu: An FPGA in your USB Port
A whirlwind introduction to Fomu; a workshop in three levels
- Sean Cross - https://xobs.io/ - @xobs
+ Sean "xobs" Cross - https://xobs.io/ - @xobs
+ Tim "mithro" Ansell - https://github.com/timvideos/litex-buildenv/wiki/ - @mithro
@@ -109,6 +114,11 @@
FPGA / HDL
+
+ The overarching idea behind Fomu is to take a top-down approach to hardware design. Start at
+ something familiar, such as Python, and keep drilling down until you are no longer interested in
+ going further.
+
@@ -118,6 +128,10 @@
What is an FPGA, and what is Fomu?
Working with Fomu using Python, RISC-V, and HDL
+
+ Broadly, this workshop will cover three parts: What do you need to get started with Fomu, what is an
+ FPGA and why is Fomu special, and finally how to work with Fomu at three different levels.
+
@@ -130,6 +144,11 @@
FPGA Toolchain
Python 3
+
@@ -137,135 +156,143 @@
What is an FPGA?
-
-
-
-
- What is an FPGA?
-
-
-
- 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
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
-
-
-
+
+ An FPGA is an array of gates that's field-programmable. A more useful definition might be "a
+ chip you can reconfigure". Most chips are collections of transistors that take two inputs and
+ have one output. FPGAs have collections of transistors that look like this -- they take multiple
+ inputs and produce multiple outputs. On Fomu, the basic building block is a 4-input 1-output
+ lookup table called an "LC4". These are so important to FPGAs that the part number usually
+ contains how many LUTs there are. The Fomu has a UP5K, which has about 5000 LUTs. The NeTV had
+ an LX9, which had 9000 LUTs. The NeTV2 has an XC7A35T, which has 35000 LUTs.
+
+
+
+
+ What is an FPGA?
+
+
+
+ 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
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+ ?
+
+
+
+ A LUT is a lookup table. The value of the output depends on the value of all the inputs. You can
+ make arbitrary boolean logic here. For example, we could make a LUT that performs the logical
+ AND of all the inputs, and set it so that it only outputs a "1" if all of the inputs are 1. Or
+ we can make a NAND gate by taking the inverse. Each one of those 5000 LUTs in Fomu has a truth
+ table like this that it evaluates in real time.
+
+
What is an FPGA?
@@ -280,6 +307,11 @@
endmodule
+
+ It gets really tedious to be thinking about lookup tables all the time, so humans created programming languages to do it for them. This is an example of Verilog code. It makes a simple counter that outputs the xor of some values.
+
+ In order to turn this Verilog code into actual LUTs, we run it through a synthesizer. Much like how a compiler turns programming language into CPU opcodes, a synthesizer turns Verilog code into lookup tables
+
@@ -295,7 +327,7 @@
Open toolchain
-
+
- Fomu Block Design Diagram
-
-
-
-
+ Fomu Block Design Diagram
+
+
+
+
What is this PCB?
Fomu EVT1
@@ -344,12 +376,12 @@
-->
-
- Misleading Datasheets
-
-
+
+ Misleading Datasheets
+
+
-
+
What modifications does it have?
Shorting out two zero-ohm resistors (R7, PU)
@@ -370,25 +402,25 @@
Interpreters
Updates
-->
-
+
-
-
- FAT Bootloader
-
- Presents itself as a USB disk
- Drag and drop files to program
- Multiple interpreter support
-
-
-
-
-
+
+
+
+ FAT Bootloader
+
+ Presents itself as a USB disk
+ Drag and drop files to program
+ Multiple interpreter support
+
+
+
+
+
"fail safe" bootloader
@@ -448,28 +480,28 @@ $ dfu-util -D new-image.dfu # Load new program
>>> rgb.mode("error")
>>>
-
+
-
- Read SPI ID
-
+
+ Read SPI ID
+
>>> spi = fomu.spi()
>>> hex(spi.id())
'0xc2152815'
>>>
-
+
-
- Memory-Mapped Registers
- #define CSR_VERSION_MAJOR_ADDR 0xe0007000
+
+ Memory-Mapped Registers
+ #define CSR_VERSION_MAJOR_ADDR 0xe0007000
#define CSR_VERSION_MINOR_ADDR 0xe0007004
#define CSR_VERSION_REVISION_ADDR 0xe0007008
- >>> import machine
+ >>> import machine
>>> machine.mem32[0xe0007000]
1
>>>
-
+
RGB LED Driver reference
@@ -533,7 +565,7 @@ $ dfu-util -D new-image.dfu # Load new program
#define CSR_VERSION_GITEXTRA_ADDR 0xe000701c
#define CSR_VERSION_GITEXTRA_SIZE 2
-Excerpt from csr.h
+ Excerpt from csr.h
@@ -566,9 +598,9 @@ $ wishbone-tool --pid 0x5bf0 0xe0006800 0xff
OBJCOPY riscv-blink.bin
IHEX riscv-blink.ihex
$
-
- From riscv-blink
directory in teardown2019-workshop
-
+
+ From riscv-blink
directory in teardown2019-workshop
+
@@ -583,12 +615,12 @@ $
int i = 0;
while (1) {
i++;
-
-
-
- Other RISC-V Programs
- riscv-usb-cdcacm: echo characters back after adding 1
-
+
+
+
+ Other RISC-V Programs
+ riscv-usb-cdcacm: echo characters back after adding 1
+
- Yosys and NextPNR
-
- Max frequency for clock 'clk12': 24.63 MHz (PASS at 12.00 MHz)
+ Yosys and NextPNR
+
+ Max frequency for clock 'clk12': 24.63 MHz (PASS at 12.00 MHz)
Max frequency for clock 'clk48_1': 60.66 MHz (PASS at 48.00 MHz)
Max frequency for clock 'clkraw': 228.05 MHz (PASS at 48.00 MHz)
- Blinking an LED
- $ make FOMU_REV=evt
+ Blinking an LED
+ $ make FOMU_REV=evt
...
20 warnings, 0 errors
PACK blink.bin
@@ -617,72 +649,72 @@ $ dfu-util -D blink.bin
- LiteX and MiGen
-
- Define hardware in Python
- Evaluate Python to produce netlist
- Synthesize netlist to FPGA
-
+ LiteX and MiGen
+
+ Define hardware in Python
+ Evaluate Python to produce netlist
+ Synthesize netlist to FPGA
+
-
- lxbuildenv.py
-
- Python environment using native interpreter
- Very stable, good for hardware projects
- Should work with system Python
- Runs on Linux, Windows, Raspberry Pi
-
-
+
+ lxbuildenv.py
+
+ Python environment using native interpreter
+ Very stable, good for hardware projects
+ Should work with system Python
+ Runs on Linux, Windows, Raspberry Pi
+
+
-
- Why do we need a CPU?
+
+ Why do we need a CPU?
-
+
-
- What if we remove the CPU?
-
- Workshop project has no CPU
- DummyUsb module automatically enumerates
- Wishbone Debug Bridge still accessible
-
-
+
+ What if we remove the CPU?
+
+ Workshop project has no CPU
+ DummyUsb module automatically enumerates
+ Wishbone Debug Bridge still accessible
+
+
-
- Build Workshop Module
- $ python3 workshop.py --placer heap
+
+ Build Workshop Module
+ $ python3 workshop.py --placer heap
...
5 warnings, 0 errors
$
-
+
-
- Load onto Fomu
- $ dfu-util -D build/gateware/top.bin
+
+ Load onto Fomu
+ $ dfu-util -D build/gateware/top.bin
Download [=========================] 100% 104090 bytes
Download done.
$
-
+
-
- Write a value to RAM
- $ wishbone-tool --pid 0x5bf0 0x10000000
+
+ Write a value to RAM
+ $ wishbone-tool --pid 0x5bf0 0x10000000
Value at 10000000: 0baf801e
$ wishbone-tool --pid 0x5bf0 0x10000000 0x12345678
$ wishbone-tool --pid 0x5bf0 0x10000000
Value at 10000000: 12345678
$
-
+
-
- Adding Hardware
-
-
+
+ Adding Hardware
+
+
-
- Technology Library Reference
- // Verilog Instantiation
+
+ Technology Library Reference
+ // Verilog Instantiation
SB_RGBA_DRV RGBA_DRIVER (
.CURREN(ENABLE_CURR),
.RGBLEDEN(ENABLE_RGBDRV),
@@ -697,11 +729,11 @@ defparam RGBA_DRIVER.CURRENT_MODE = "0b0";
defparam RGBA_DRIVER.RGB0_CURRENT = "0b111111";
defparam RGBA_DRIVER.RGB1_CURRENT = "0b111111" ;
defparam RGBA_DRIVER.RGB2_CURRENT = "0b111111";
-SBTICETechnologyLibrary201504.pdf page 147
-
-
- RGB Block
- class FomuRGB(Module, AutoCSR):
+ SBTICETechnologyLibrary201504.pdf page 147
+
+
+ RGB Block
+ class FomuRGB(Module, AutoCSR):
def __init__(self, pads):
self.output = CSRStorage(3)
self.specials += Instance("SB_RGBA_DRV",
@@ -718,11 +750,11 @@ defparam RGBA_DRIVER.RGB2_CURRENT = "0b111111";
p_RGB1_CURRENT = "0b000011",
p_RGB2_CURRENT = "0b000011",
)
-
-
-
- Instantiating FomuRGB
- @@ -55,6 +75,10 @@ class BaseSoC(SoCCore):
+
+
+
+ Instantiating FomuRGB
+ @@ -55,6 +75,10 @@ class BaseSoC(SoCCore):
with_ctrl=False,
**kwargs)
@@ -733,23 +765,23 @@ defparam RGBA_DRIVER.RGB2_CURRENT = "0b111111";
# UP5K has single port RAM....
# Use this as CPU RAM.
spram_size = 128*1024
-
+
-
- Interacting with the CSR
- csr_register,rgb_output,0xe0006800,1,rw
- From test/csr.csv
-
+
+ Interacting with the CSR
+ csr_register,rgb_output,0xe0006800,1,rw
+ From test/csr.csv
+
-
-
-
- Thank you
- Lunch Time!
-
+
+
+
+ Thank you
+ Lunch Time!
+