diff --git a/doc/alternatives.md b/doc/alternatives.md index 7758656..44f998d 100644 --- a/doc/alternatives.md +++ b/doc/alternatives.md @@ -55,7 +55,7 @@ An embedded logic analyzer for Lattice FPGAs, provided as part of the Diamond de ### Opal Kelly FrontPanel SDK -Unlike other entries in this list, Opal Kelly's FrontPanel SDK is not marketed as a debugger (although it can be used as such). Instead, it's designed to provide a host computer with a real time interface to FGPA signals, and present them on a graphical “front panel". These front panels exist as a GUI window on the host, and contain buttons, knobs, and indicators, much like a LabVIEW virtual instrument. Communication between the host and FPGA is accomplished with either USB or PCIe. Bindings for hosts running Windows, macOS, and Linux are provided, and target C, C++, C#, Python, Java, Ruby, and MATLAB. The FrontPanel SDK differs from other debuggers in that it provides a skeleton module into which the user logic is instantiated, instead of being instantiated inside the user's logic. +Unlike other entries in this list, Opal Kelly's FrontPanel SDK is not marketed as a debugger (although it can be used as such). Instead, it's designed to provide a host computer with a real time interface to FPGA signals, and present them on a graphical “front panel". These front panels exist as a GUI window on the host, and contain buttons, knobs, and indicators, much like a LabVIEW virtual instrument. Communication between the host and FPGA is accomplished with either USB or PCIe. Bindings for hosts running Windows, macOS, and Linux are provided, and target C, C++, C#, Python, Java, Ruby, and MATLAB. The FrontPanel SDK differs from other debuggers in that it provides a skeleton module into which the user logic is instantiated, instead of being instantiated inside the user's logic. - [Documentation](https://docs.opalkelly.com/fpsdk/) - [User's Guide](https://assets00.opalkelly.com/library/FrontPanel-UM.pdf) diff --git a/doc/architecture.md b/doc/architecture.md index be7f57b..588ab59 100644 --- a/doc/architecture.md +++ b/doc/architecture.md @@ -2,19 +2,19 @@ The whole system looks like the following: -![](assets/system_architecture.drawio.svg){:style="width:80%"} +
Manta is operated via its Python API, which communicates with the connected FPGA over an interface API like `pySerial` or `Scapy`. These abstract away the OS device drivers, which function differently depending on the host machine's platform. The OS device drivers ultimately send out bytes to the FPGA, across either a USB or Ethernet cable. -Once sent across the wire, bytes are picked up by an interface transciever on the FPGA development board. This is either a USB-UART converter or a RMII PHY depending on if you're using UART or Ethernet. This chip is connected to the FPGA's IO, which routes the signals to the Verilog module generated by Manta. This module parses incoming messages, passes them down a set of daisy-chained cores, and then packetizes it and sends it back to the host. +Once sent across the wire, bytes are picked up by an interface transceiver on the FPGA development board. This is either a USB-UART converter or a RMII PHY depending on if you're using UART or Ethernet. This chip is connected to the FPGA's IO, which routes the signals to the Verilog module generated by Manta. This module parses incoming messages, passes them down a set of daisy-chained cores, and then packetizes it and sends it back to the host. ## Manta Architecture The logic Manta places on the FPGA consists of a series of cores connected in a chain along a common bus. Each core provides a unique method for interacting with the user’s logic, which it connects to by routing signals (called _probes_) between the user’s logic and the cores that interface with it. -![](assets/bus_architecture.drawio.svg){:style="width:40%"} +
-These probes are presented as addressable memory, and are be controlled by reading and writing to their corresponing memory - not unlike registers on a microcontroller. Each core is allotted a section of address space at compile time, and operations addressed to a core’s address space control the behavior of the core. These cores are then daisy-chained along an internal bus, which permits a chain arbitrarily many cores to be placed on the bus. +These probes are presented as addressable memory, and are be controlled by reading and writing to their corresponding memory - not unlike registers on a microcontroller. Each core is allotted a section of address space at compile time, and operations addressed to a core’s address space control the behavior of the core. These cores are then daisy-chained along an internal bus, which permits a chain arbitrarily many cores to be placed on the bus. At the beginning of this chain is a module called a _receive bridge_, which converts incoming UART/Ethernet communication from the host into read and write requests, which are placed on the bus. These are called _bus transactions_, and once placed on the bus, they travel through each core before reaching the _transmit bridge_ at the end of the chain. This module places the result of the bus transaction back on the UART/Ethernet interface, and sends it back to the host. This produces a request-response style of communication between the host machine and the FPGA. @@ -37,7 +37,7 @@ Each core has a bus input and output port, so that cores can be daisy-chained to Ethernet and UART both allow a stream of bytes to be sent between the host and FPGA, but since they're just interfaces, they don't define how these bytes are structured. As a result, Manta implements its own messaging format, with the following structure: -![](assets/uart_packets.drawio.svg){:style="width:85%"} +
Each of these messages is a string of ASCII characters consisting of a preamble, optional address and data fields, and an End of Line (EOL). The preamble denotes the type of operation, _R_ for a read and _W_ for a write. The address and data fields are encoded as hexadecimal digits, represented with the characters 0-9 and A-F in ASCII. As a result, four characters are needed to encode a 16-bit address or 16-bits of data. If the message specifies a write request, then it will contain a data field after the address field. Both request types will conclude with an End of Line, which consists of the two ASCII characters indicating a Carriage Return (CR) and a Line Feed (LF). @@ -64,7 +64,7 @@ When UART is used, these bytes are transmitted directly across the wire, but whe This is done with the architecture shown below: -![](assets/io_core_architecture.drawio.svg){:style="width:49%"} +
Each of the probes is mapped to a register of Manta's internal memory. Since Manta's internal registers are 16 bits wide, probes less than 16 bits are mapped to a single register, but probes wider than 16 bits require multiple. @@ -73,7 +73,7 @@ Whatever the number of registers required, these are read from and written to by ## Logic Analyzer The Logic Analyzer Core's implementation on the FPGA consists of three primary components: -![](assets/logic_analyzer_architecture.drawio.svg){style="width:85%"} +
- The _Finite State Machine (FSM)_, which controls the operation of the core. The FSM's operation is driven by its associated registers, which are placed in a separate module. This permits simple CDC between the bus and user clock domains. - The _Trigger Block_, which generates the core's trigger condition. The trigger block contains a trigger for each input probe, and the registers necessary to configure them. It also contains the $N$-logic gate (either AND or OR) that generates the core's trigger from the individual probe triggers. CDC is performed in exactly the same manner as the FSM. If an external trigger is specified, the trigger block is omitted from the Logic Analyzer Core, and the external trigger is routed to the FSM's `trig` input. @@ -84,8 +84,7 @@ The Logic Analyzer Core's implementation on the FPGA consists of three primary c Each Memory core is actually a set of 16-bit wide BRAMs with their ports concatenated together, with any spare bits masked off. Here's a diagram: -![](assets/memory_architecture.drawio.svg) - +
Since each $n$-bit wide block memory is actually $ceil(n/16)$ BRAMs under the hood, addressing the BRAMs correctly from Manta's internal bus is important. BRAMs are organized such that each 16-bit slice of a $N$-bit word in the Block Memory core are placed next to each other in bus address space. For instance, a 34-bit wide block memory would exist on Manta's internal bus as: diff --git a/doc/assets/bus_architecture.drawio.svg b/doc/assets/bus_architecture.drawio.svg index e4858e0..a8b8077 100644 --- a/doc/assets/bus_architecture.drawio.svg +++ b/doc/assets/bus_architecture.drawio.svg @@ -1,8 +1,68 @@ - - + + + + + - + diff --git a/doc/assets/io_core_architecture.drawio.svg b/doc/assets/io_core_architecture.drawio.svg index d5b5064..65f936d 100644 --- a/doc/assets/io_core_architecture.drawio.svg +++ b/doc/assets/io_core_architecture.drawio.svg @@ -1,122 +1,182 @@ - - + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + -
+
-
+
output_0
- + output_0 - - - + + + -
+
-
+
output_n
- + output_n - - + + -
+
-
+
bus
- + bus - + -
+
-
+
input_n
- + input_n - - - + + + -
+
-
+
strobe
- + strobe - + -
+
-
+

IO Core

@@ -124,37 +184,37 @@
- + IO Core - - - + + + -
+
-
+
input_0
- + input_0 - + -
+
-
+
... @@ -162,165 +222,165 @@
- + ... - + -
+
-
+
input_0 buffer
- + input_0 buffer - + -
+
-
+
input_n buffer
- + input_n buffer - + -
+
-
+
output_n buffer
- + output_n buffer - - + + -
+
-
+
bus
- + bus - - + + -
-
-
+
+
+
output_0
- + output_0 - + -
+
-
+
output_0 buffer
- + output_0 buffer - - + + -
-
-
+
+
+
input_0
- + input_0 - - + + -
-
-
+
+
+
output_n
- + output_n - - + + -
-
-
+
+
+
input_n
- + input_n diff --git a/doc/assets/io_core_memory_map.drawio.svg b/doc/assets/io_core_memory_map.drawio.svg deleted file mode 100644 index 35576a4..0000000 --- a/doc/assets/io_core_memory_map.drawio.svg +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - - -
-
-
- foo[4:0] -
-
-
-
- - foo[4:0] - -
-
- - - - -
-
-
- bar[15:0] -
-
-
-
- - bar[15:0] - -
-
- - - - -
-
-
- baz[31:16] -
-
-
-
- - baz[31:16] - -
-
- - - - -
-
-
- baz[15:0] -
-
-
-
- - baz[15:0] - -
-
- - - - -
-
-
- zero pad -
-
-
-
- - zero pad - -
-
- - - - -
-
-
- baz[36:32] -
-
-
-
- - baz[36:32] - -
-
- - - - -
-
-
- zero pad -
-
-
-
- - zero pad - -
-
- - - - -
-
-
- 0x0000 -
-
-
-
- - 0x0000 - -
-
- - - - -
-
-
- 0x0001 -
-
-
-
- - 0x0001 - -
-
- - - - -
-
-
- 0x0002 -
-
-
-
- - 0x0002 - -
-
- - - - -
-
-
- 0x0003 -
-
-
-
- - 0x0003 - -
-
- - - - -
-
-
- 0x0004 -
-
-
-
- - 0x0004 - -
-
- - - - -
-
-
- 0 -
-
-
-
- - 0 - -
-
- - - - -
-
-
- 16 -
-
-
-
- - 16 - -
-
-
- - - - - Text is not SVG - cannot display - - - -
\ No newline at end of file diff --git a/doc/assets/logic_analyzer_architecture.drawio.svg b/doc/assets/logic_analyzer_architecture.drawio.svg index c2123ab..4f3dc26 100644 --- a/doc/assets/logic_analyzer_architecture.drawio.svg +++ b/doc/assets/logic_analyzer_architecture.drawio.svg @@ -1,14 +1,76 @@ - - + + + + - - + + + -
+
-
+
block
memory @@ -16,55 +78,55 @@
- + block... - - + + -
+
-
+
bus
- + bus - - - + + + -
+
-
+
bus
- + bus - + -
+
-
+
fsm
registers @@ -72,389 +134,389 @@
- + fsm... - + -
+
-
+
fsm
- + fsm - - + + -
+
-
+
bus
- + bus - + -
+
-
+
trigger registers
- + trigger re... - + -
+
-
+
trigger
- + trigger - - + + -
+
-
+
arg
- + arg - - + + -
+
-
+
op
- + op - + -
+
-
+
trigger
- + trigger - - + + -
+
-
+
arg
- + arg - - + + -
+
-
+
op
- + op - - + + -
+
-
+
trigger_mode
- + trigger_mode - - + + -
+
-
+
request_start
- + request_start - - + + -
+
-
+
request_stop
- + request_stop - - + + -
+
-
+
read_pointer
- + read_pointer - - + + -
+
-
+
write_pointer
- + write_pointer - - + + -
+
-
+
state
- + state - - + + -
+
-
+
trigger_location
- + trigger_location - + -
+
-
+
...
- + ... - - + + -
+
-
+
bus
- + bus - + -
+
-
+
port A
- + port A - - + + -
+
-
+
data
- + data - + -
+
-
+
port B
- + port B - + -
+
-
+

Trigger Block @@ -464,121 +526,121 @@

- + Trigger Block - - + + -
+
-
+
trig
- + trig - + -
+
-
+
OR
- + OR - - + + -
+
-
+
- + - - + + -
+
-
+
probe_2
- + probe_2 - + -
+
-
+
- + - - + + -
+
-
+
probe_1
- + probe_1 - - + + -
+
-
+

Logic Analyzer

@@ -586,96 +648,96 @@
- + Logic Analyzer - - + + -
+
-
+
probe_0
- + probe_0 - + -
+
-
+
trigger
- + trigger - - + + -
+
-
+
arg
- + arg - - + + -
+
-
+
op
- + op - - + + -
+
-
+
we
- + we @@ -683,33 +745,33 @@ -
+
-
+
we
- + we - - + + -
+
-
+
addr
- + addr @@ -717,25 +779,25 @@ -
+
-
+
addr
- + addr - - - - - - + + + + + + diff --git a/doc/assets/memory_architecture.drawio.svg b/doc/assets/memory_architecture.drawio.svg index ca3a1c9..ef58678 100644 --- a/doc/assets/memory_architecture.drawio.svg +++ b/doc/assets/memory_architecture.drawio.svg @@ -1,475 +1,537 @@ - - + + + + - - + + + -
+
-
+
block RAM
- + block RAM - + -
+
-
+
port A
- + port A - - + + -
+
-
+
addr
- + addr - - + + -
+
-
+
din
- + din - - + + -
+
-
+
dout
- + dout - - + + -
+
-
+
we
- + we - + -
+
-
+
port B
- + port B - + -
+
-
+
Bus Controller
- + Bus Controller - + -
+
-
+
block RAM
- + block RAM - + -
+
-
+
port A
- + port A - + -
+
-
+
port B
- + port B - - - - - + + + + + -
+
-
+
user_addr
- + user_addr - - + + -
+
-
+
user_din
- + user_din - - + + -
+
-
+
user_dout
- + user_dout - - + + -
+
-
+
user_we
- + user_we - - + + -
+
-
+
addr
- + addr - - + + -
+
-
+
din
- + din - - + + -
+
-
+
dout
- + dout - - + + -
+
-
+
we
- + we - + -
+
-
+
block RAM
- + block RAM - + -
+
-
+
port A
- + port A - + -
+
-
+
port B
- + port B - - + + -
+
-
+
addr
- + addr - - + + -
+
-
+
din
- + din - - + + -
+
-
+
dout
- + dout - - + + -
+
-
+
we
- + we - + -
+
-
+
... @@ -479,111 +541,111 @@
- + ... - - - + + + -
+
-
+
16 bits
- + 16 bits - - - + + + -
+
-
+
16 bits
- + 16 bits - - - + + + -
+
-
+
10 bits
- + 10 bits - - + + -
+
-
+
bus
- + bus - - + + -
+
-
+
bus
- + bus - + -
+
-
+

Memory Core

@@ -591,7 +653,7 @@
- + Memory Core diff --git a/doc/assets/system_architecture.drawio.svg b/doc/assets/system_architecture.drawio.svg index 930a0c7..6e01b9f 100644 --- a/doc/assets/system_architecture.drawio.svg +++ b/doc/assets/system_architecture.drawio.svg @@ -1,15 +1,133 @@ - - + + + + - - - + + + + + + + + -
+
+
+
+ Manta API +
+
+
+ + + Manta API + + + + + + + +
+
+
+ OS Device Driver +
+
+
+
+ + OS Device Driver + +
+
+ + + + + + + +
+
+
+ Your Code! +
+
+
+
+ + Your Code! + +
+
+ + + + +
-
+

Host Machine

@@ -17,305 +135,93 @@
- + Host Machine - - - + -
+
-
- User Application -
-
-
- - - User Application - - - - - - - - - -
-
-
- Manta API -
-
-
-
- - Manta API - -
-
- - - - - - -
-
-
- Interface API -
-
-
-
- - Interface API - -
-
- - - - - -
-
-
- USB/Ethernet Cable -
-
-
-
- - USB/Ethernet Cable - -
-
- - - - -
-
-
- OS Device Driver -
-
-
-
- - OS Device Driver - -
-
- - - - -
-
-
- Interface Transceiver -
-
- (USB UART -
- Converter / Ethernet PHY) -
-
-
-
- - Interface Trans... - -
-
- - - - - - -
-
-
- rxd -
-
-
-
- - rxd - -
-
- - - - -
-
-
- bridge_rx -
-
-
-
- - bridge_rx - -
-
- - - - -
-
-
+
logic_analyzer
- + logic_analyzer - + -
+
-
+
io_core
- + io_core - + -
+
-
+
block_memory
- + block_memory - + -
+
-
- bridge_tx +
+ Your RTL!
- - bridge_tx + + Your RTL! - - - - - - - - - + + + + + + + + -
-
-
- User Logic -
-
-
-
- - User Logic - -
-
- - - - - - - - - - - - -
-
-
- txd -
-
-
-
- - txd - -
-
- - - - -
-
-
-

- FPGA Development Board -

-
-
-
-
- - FPGA Development Board - -
-
- - - - -
-
-
+
+
+

Manta RTL @@ -325,11 +231,110 @@

- + Manta RTL + + + + +
+
+
+

+ FPGA Development Board +

+
+
+
+
+ + FPGA Development Board + +
+
+ + + + + + + + + +
+
+
+ Network +
+ Connection +
+
+
+
+ + Network... + +
+
+ + + + +
+
+
+ Ethernet PHY +
+
+
+
+ + Ethernet PHY + +
+
+ + + + + + + + + +
+
+
+ USB Cable +
+
+
+
+ + USB Cable + +
+
+ + + + +
+
+
+ USB-UART Converter +
+
+
+
+ + USB-UART Conver... + +
+
diff --git a/doc/assets/uart_packets.drawio.svg b/doc/assets/uart_packets.drawio.svg index b6c1fa6..e3cc3b0 100644 --- a/doc/assets/uart_packets.drawio.svg +++ b/doc/assets/uart_packets.drawio.svg @@ -1,758 +1,821 @@ - - + + + + - + + -
+
-
+
W
- + W - + -
+
-
+
8
- + 8 - + -
+
-
+
9
- + 9 - + -
+
-
+
A
- + A - + -
+
-
+
B
- + B - + -
+
-
+
CR
- + CR - + -
+
-
+
LF
- + LF - - - + + + -
+
-
+
Write Address
- + Write Address - - - + + + -
+
-
+
End Of Line
- + End Of Line - - - + + + -
+
-
+
Preamble
- + Preamble - + -
+
-
+
0
- + 0 - + -
+
-
+
8
- + 8 - + -
+
-
+
16
- + 16 - + -
+
-
+
24
- + 24 - + -
+
-
+
32
- + 32 - + -
+
-
+
48
- + 48 - + -
+
-
+
56
- + 56 - + -
+
-
+
C
- + C - + -
+
-
+
D
- + D - + -
+
-
+
E
- + E - + -
+
-
+
F
- + F - - - + + + -
+
-
+
Write Data
- + Write Data - + -
+
-
+
64
- + 64 - + -
+
-
+
72
- + 72 - + -
+
-
+
80
- + 80 - + -
+
-
+
88
- + 88 - + -
+
-
+
R
- + R - + -
+
-
+
0
- + 0 - + -
+
-
+
1
- + 1 - + -
+
-
+
2
- + 2 - + -
+
-
+
3
- + 3 - + -
+
-
+
CR
- + CR - + -
+
-
+
LF
- + LF - - - + + + -
+
-
+
Read Address
- + Read Address - - - + + + -
+
-
+
End Of Line
- + End Of Line - - - + + + -
+
-
+
Preamble
- + Preamble - + -
+
-
+
0
- + 0 - + -
+
-
+
8
- + 8 - + -
+
-
+
16
- + 16 - + -
+
-
+
24
- + 24 - + -
+
-
+
32
- + 32 - + -
+
-
+
48
- + 48 - + -
+
-
+
56
- + 56 - + -
+
-
+

Read Request

@@ -760,18 +823,18 @@
- + Read Request - + -
+
-
+

Read Response

@@ -779,18 +842,18 @@
- + Read Response - + -
+
-
+

Write Request

@@ -798,313 +861,313 @@
- + Write Request - + -
+
-
+
D
- + D - + -
+
-
+
4
- + 4 - + -
+
-
+
5
- + 5 - + -
+
-
+
6
- + 6 - + -
+
-
+
7
- + 7 - + -
+
-
+
CR
- + CR - + -
+
-
+
LF
- + LF - - - + + + -
+
-
+
Read Data
- + Read Data - - - + + + -
+
-
+
End Of Line
- + End Of Line - - - + + + -
+
-
+
Preamble
- + Preamble - + -
+
-
+
0
- + 0 - + -
+
-
+
8
- + 8 - + -
+
-
+
16
- + 16 - + -
+
-
+
24
- + 24 - + -
+
-
+
32
- + 32 - + -
+
-
+
48
- + 48 - + -
+
-
+
56
- + 56 - + -
+
-
+

Write Response

@@ -1112,18 +1175,18 @@
- + Write Response - + -
+
-
+
No Response @@ -1131,7 +1194,7 @@
- + No Response diff --git a/doc/ethernet_interface.md b/doc/ethernet_interface.md index 416c31b..e78ae9b 100644 --- a/doc/ethernet_interface.md +++ b/doc/ethernet_interface.md @@ -1,15 +1,39 @@ -!!! warning "This section is under construction!" - - The Ethernet interface is just about to get refactored to implement a few performance gains, so what's here represents the Ethernet interface circa April 2023. Hang tight for new stuff! - ## Overview -For situations where the onboard UART is not available, Manta provides a 100Mbps Ethernet link for communicating between the host machine and target FPGA. This link implements a L2 MAC on the FPGA, designed to be directly connected to a host machine on a dedicated network adapter. The MAC is controlled by a bridge interface, which performs the exact same function as it does on the UART interface. Incoming packets are parsed into bus transactions, placed on the bus, and any response data is encapsulated into another packet sent to the host. +For scenarios where UART is not available or higher bandwidth is desired, Manta provides an Ethernet interface for communicating between the host and FPGA. This interface uses UDP for communication, and leverages the builtin Python `sockets` module on the host side, and the open-source [LiteEth](https://github.com/enjoy-digital/liteeth) Ethernet core on the FPGA side. -This is done by interacting with an Ethernet PHY, an onboard transceiver IC that converts between the FPGA's logic-level signaling and the voltages on the cable's twisted pairs. The communication between the Ethernet PHY and the FPGA is done over an interface that's dependent on the speed of the PHY. The 10/100 Mbps interface used on the Nexys A7-100T uses the RMII as defined in IEEE 802.3u. RMII is the second-oldest member in the Media Independent Interface family, with newer revisions of 802.3 supporting faster interfaces. +!!! warning "Not every device is supported!" -Manta's bus clock must be equivalent to the PHY's reference clock if Ethernet is to be used - in the case of the 100Mbps RMII PHY on the Nexys A7 used in 6.205, this is 50MHz. This doesn't pose a problem for user logic, which is connected through Manta's cores that perform CDC internally. It does mean that a reference clock for the PHY has to be synthesized outside of Manta itself, and the means by which this is done varies by FPGA vendor and toolchain. + Although Manta aims to be as platform-agnostic as possible, Ethernet PHYs and FPGA clock primitives are very particular devices. As a result, the supported devices are loosely restricted to those on [this list](https://github.com/enjoy-digital/liteeth?tab=readme-ov-file#-features). If a device you'd like to use isn't on the list, the community would love your help! -This MAC allows for the usage of packets with the structure shown below. The bus transaction being communicated is placed at the beginning of the packet's payload field, which IEEE 802.3 allows to vary in length from 46 to 1500 bytes. The 46-byte lower limit requires 41 bytes of zero padding to be added to the five bytes used to specify a bus transaction, and only one bus transactions is specified in each Ethernet frame. This abundance of unused space results in all packets being the same length, whether the packet contains a read request, write request, or read response. Packets containing write requests elicit no response from the FPGA, just as write requests delivered over UART produce no response. +Although UDP does not guarantee reliable packet delivery, this usually doesn't pose an issue in practice. Manta will throw a runtime error if packets are dropped, and the UDP checksum and Ethernet FCS guarantee that any data delivered is not corrupted. Together, these two behaviors prevent corrupted data from being provided to the user, as Manta will error before returning invalid data. As long as your network is not terribly congested, Manta will operate without issue. +## Configuration -These packets are addressed directly to the host's MAC address, which is obtained during code autogeneration. These packets also use a fixed Ethertype of `0x88B5`, which is specially reserved for "public use and for prototype and vendor-specific protocol development" in IEEE 802.1. This was done to create an Ethernet II frame instead of a legacy 802.3 frame, without having to implement a higher level protocol like TCP or UDP to safely use a fixed Ethertype. This allows the MAC to use modern Ethernet II frames safely, but save FPGA resources. \ No newline at end of file +The configuration of the Ethernet core is best shown by example: +```yaml +ethernet: + phy: LiteEthPHYRMII + vendor: xilinx + toolchain: vivado + + clk_freq: 50e6 + refclk_freq: 50e6 + + fpga_ip_addr: "192.168.0.110" + host_ip_addr: "192.168.0.100" +``` +This snippet at the end of the configuration file defines the interface. The following parameters must be set: + +- `phy` _(required)_: The name of the LiteEth PHY class to use. Valid values consist of any of the names in [this list](https://github.com/enjoy-digital/liteeth/blob/b4e28506238c5340f2ade7899c2223424cabd410/liteeth/phy/__init__.py#L25-L45). Select the appropriate one for your FPGA vendor and family. + +- `vendor` _(required)_: The vendor of the FPGA being designed for. Currently only values of `xilinx` and `lattice` are supported. Used to generate timing constraints files, which are currently unused. + +- `toolchain` _(required)_: The toolchain being used. Currently only values of `vivado` and `diamond` are supported. + +- `clk_freq` _(required)_: The frequency of the clock provided to the Manta instance. Used to configure a PLL in the FPGA fabric for generating the PHY's `refclk`. + +- `refclk_freq` _(required)_: The frequency of the reference clock to be provided to the Ethernet PHY. This clock is generated from Manta's main clock using a PLL inside the FPGA. This frequency must match the MII variant supported by the PHY, as well as speed that the PHY is being operated at. For instance, a RGMII PHY may be operated at either 125MHz in Gigabit mode, or 25MHz in 100Mbps mode. + +- `fpga_ip_addr` _(required)_: The IP address the FPGA will attempt to claim. Upon power-on, the FPGA will issue a DHCP request for this IP address. The easiest way to check if this was successful is by pinging the FPGA's IP, but if you have access to your network's router it may report a list of connected devices. + +- `host_ip_addr` _(required)_: The IP address of the host machine, which the FPGA will send packets back to. diff --git a/doc/index.md b/doc/index.md index 41bae4d..3aada17 100644 --- a/doc/index.md +++ b/doc/index.md @@ -49,7 +49,7 @@ You may find this core useful for: ## About Manta and its source code are released under a [GPLv3 license](https://github.com/fischermoseley/manta/blob/main/LICENSE.txt), and it was originally developed as part of my [Master's Thesis at MIT](https://hdl.handle.net/1721.1/151223) in 2023, done under the supervision of [Dr. Joe Steinmeyer](https://www.jodalyst.com/). The thesis itself is copyrighted by Fischer Moseley (me!), but feel free to use the following Bibtex if you'd like to cite it: -``` +```bibtex @misc{manta2023, author={Fischer Moseley}, title={Manta: An In-Situ Debugging Tool for Programmable Hardware}, diff --git a/doc/installation.md b/doc/installation.md index 9141181..8fc2624 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -1,20 +1,20 @@ Before installing, make sure to upgrade your `pip` to the latest version: -``` +```bash pip install --upgrade pip ``` ## Latest Version You can install the latest version of Manta directly from source with: -``` +```bash pip install --upgrade git+https://github.com/fischermoseley/manta.git ``` ## Editable Development Install If you're working on the source, you might want an editable installation with some extra dependencies used for development: -``` +```bash git clone https://github.com/fischermoseley/manta.git cd manta pip install -e ".[dev]" @@ -29,14 +29,15 @@ Later Manta will be availabe on the PyPI lists, and you'll be able to just `pip ## Dependencies Manta requires the following dependencies: -- Amaranth HDL, which comes with it's own built-in copy of Yosys. -- pyYAML, which is used for parsing configuration files written in YAML. -- pySerial, used for communicating with the FPGA over UART. -- pyVCD, used for writing waveforms captured by the Logic Analyzer Core to standard Value Change Dump (VCD) files. +- [Amaranth HDL](https://amaranth-lang.org/docs/amaranth/latest/), which comes with it's own built-in copy of Yosys. +- [LiteEth](https://github.com/enjoy-digital/liteeth), for sending and receiving UDP packets on the FPGA. +- [pySerial](https://pyserial.readthedocs.io/en/latest/index.html), for communicating with the FPGA over UART. +- [pyYAML](https://pyyaml.org/), for parsing configuration files written in YAML. +- [pyVCD](https://github.com/westerndigitalcorporation/pyvcd), for writing waveforms captured by the Logic Analyzer Core to standard Value Change Dump (VCD) files. As well as these dependencies for development, which are installed with the `[dev]` argument: -- Pytest, for testing. -- Black, used for formatting the Python source. -- mkdocs-material, for generating the documentation site. -- amaranth_boards, for building designs for hardware-in-the-loop testing done by the CI. +- [Pytest](https://pytest.org/), for unit testing. +- [Black](https://black.readthedocs.io/en/stable/), for formatting the Python source. +- [mkdocs-material](https://squidfunk.github.io/mkdocs-material/), for generating the documentation site. +- [amaranth_boards](https://github.com/amaranth-lang/amaranth-boards), for building designs for hardware-in-the-loop testing done by the CI. diff --git a/doc/io_core.md b/doc/io_core.md index ba86a53..da61255 100644 --- a/doc/io_core.md +++ b/doc/io_core.md @@ -32,7 +32,7 @@ Inside this configuration, the following parameters may be configured: - `name` _(required)_: The name of the IO core. This name is used to reference the core when working with the API, and can be whatever you'd like. - `type` _(required)_: This denotes that this is an IO core. All cores contain a `type` field, which must be set to `io` to be recognized as an IO core. - `inputs` _(optional)_: This lists all inputs from from the FPGA fabric to the host machine. Signals in this list may be read by the host, but ___cannot___ be written to. Technically specifying input probes is totally optional - it's perfectly fine to have an IO core with only output probes. -- `outputs` _(optional)_: This lists all outputs from the host machine to the FPGA fabric. Signals in this list are usually written to by the host, but they can also be read from. Doing so returns the value last written to the register. Just like the `inputs` parameter, this list is techically optional, and it's perfectly valid to have an IO core with input probes only. +- `outputs` _(optional)_: This lists all outputs from the host machine to the FPGA fabric. Signals in this list are usually written to by the host, but they can also be read from. Doing so returns the value last written to the register. Just like the `inputs` parameter, this list is technically optional, and it's perfectly valid to have an IO core with input probes only. - `initial_value` _(optional)_: This sets an initial value for an output probe to take after the FPGA powers on. This is done with an `initial` statement in Manta's Verilog, and is independent of the input clock or resets elsewhere in the FPGA. This parameter is optional, and if it isn't provided the probe will initialize to zero. - `user_clock` _(optional)_: If set to True, an extra input port will be added to the `manta` module for an clock input to run the IO core on. This lets the IO Core handle clock domain crossing through its internal buffers. If set to False, Manta will run the IO core from its internal clock (the one provided through `manta`'s `clk` port). More information on this is available in the [diagram](#how-it-works) below. This parameter is optional, and defaults to False. @@ -50,7 +50,7 @@ The IO core functionality is stored in the `Manta.IOCore`, `Manta.InputProbe`, a - [`int`, `bool`] _data_: The value to write to an output probe. May be signed or unsigned, but will raise an exception if the value is too large for the width of the port. - _returns_: None -This method is blocking. When called it will dispatch a request to the FPGA, and wait until a response has been receieved. +This method is blocking. When called it will dispatch a request to the FPGA, and wait until a response has been received. --- @@ -58,7 +58,7 @@ This method is blocking. When called it will dispatch a request to the FPGA, and - _returns_: The value of an input or output probe. In the case of an output probe, the value returned will be the last value written to the probe. -This method is blocking. When called it will dispatch a request to the FPGA, and wait until a response has been receieved. +This method is blocking. When called it will dispatch a request to the FPGA, and wait until a response has been received. --- @@ -84,4 +84,4 @@ While the IO core performs a very, very simple task, it carries a few caveats. - First, __it's not instantaneous__. Manta has designed to be as fast as possible, but setting and querying registers relies on passing messages between the host and FPGA, which is slow relative to FPGA clock speeds! If you're trying to set values in your design with cycle-accurate timing, this will not do that for you. However, the [Logic Analyzer's playback feature](./logic_analyzer_core.md#playback) might be helpful. -- Second, __the API methods are blocking__, and will wait for a response from the FPGA before resuming program execution. Depending on your application, you might want to run your IO Core operations in a seperate thread, but you can also decrease the execution time by using a faster interface between the host and FPGA. This means using a higher UART baudrate, or using Ethernet. +- Second, __the API methods are blocking__, and will wait for a response from the FPGA before resuming program execution. Depending on your application, you might want to run your IO Core operations in a separate thread, but you can also decrease the execution time by using a faster interface between the host and FPGA. This means using a higher UART baudrate, or using Ethernet. diff --git a/doc/logic_analyzer_core.md b/doc/logic_analyzer_core.md index 50debe6..450f20d 100644 --- a/doc/logic_analyzer_core.md +++ b/doc/logic_analyzer_core.md @@ -60,14 +60,14 @@ Each individual trigger is specified with the following structure: - `EQ`, for equal to. - `NEQ`, for not equal to. - These operations require a constant to compare against, referred to as an _argument_, which is descirbed below: + These operations require a constant to compare against, referred to as an _argument_, which is described below: - __argument__: A constant to compare against, if the operation specified requires one. On the FPGA, the argument will have just as many bits as the probe width. -Lastly, if you're not able to express your desired trigger condition in terms of the operators above, fear not! You can also specifiy an `external_trigger: true` entry in the config file, which exposes an input on Manta's top level for your own trigger. +Lastly, if you're not able to express your desired trigger condition in terms of the operators above, fear not! You can also specify an `external_trigger: true` entry in the config file, which exposes an input on Manta's top level for your own trigger. ### Trigger Position (optional) -Sometimes, you care more about what happens before a trigger is met than afterwards, or vice versa. To accomodate this, the logic analyzer has an optional _Trigger Position_ parameter, which sets when probe data is captured relative to the trigger condition being met. This is specified with the `trigger_position` entry in the configuration file, which sets how many samples to save prior to the trigger condition occuring. This is best explained with a picture: +Sometimes, you care more about what happens before a trigger is met than afterwards, or vice versa. To accommodate this, the logic analyzer has an optional _Trigger Position_ parameter, which sets when probe data is captured relative to the trigger condition being met. This is specified with the `trigger_position` entry in the configuration file, which sets how many samples to save prior to the trigger condition occurring. This is best explained with a picture: ![](assets/trigger_positions.png){style="width:90%"} diff --git a/doc/memory_core.md b/doc/memory_core.md index 7189648..26109f8 100644 --- a/doc/memory_core.md +++ b/doc/memory_core.md @@ -68,6 +68,6 @@ A Block Memory core is used in the [video_sprite](https://github.com/fischermose Since Manta's [data bus](architecture.md#data-bus) is only 16-bits wide, it's only possible to manipulate the BRAM core in 16-bit increments. This means that if you have a BRAM that's ≤16 bits wide, you'll only need to issue a single bus transaction to read/write one entry in the BRAM. However, if you have a BRAM that's ≥16 bits wide, you'll need to issue a bus transaction to update each 16-bit slice of it. For instance, updating a single entry in a 33-bit wide BRAM would require sending 3 messages to the FPGA: one for bits 1-16, another for bits 17-32, and one for bit 33. If your application expects each BRAM entry to update instantaneously, this could be problematic. -There's a few different ways to solve this - you could use an IO core to signal when a BRAM's contents or valid - or you could ping-pong between two BRAMs while one is being modified. The choice is yours, and Manta makes no attempt to presribe any particular approach. +There's a few different ways to solve this - you could use an IO core to signal when a BRAM's contents or valid - or you could ping-pong between two BRAMs while one is being modified. The choice is yours, and Manta makes no attempt to prescribe any particular approach. Lastly, the interface you use (and to a lesser extent, your operating system) will determine the space between bus transactions. For instance, 100Mbit Ethernet is a thousand times faster than 115200bps UART, so the time where the BRAM is invalid is a thousand times smaller. diff --git a/doc/uart_interface.md b/doc/uart_interface.md index 847f52b..8813004 100644 --- a/doc/uart_interface.md +++ b/doc/uart_interface.md @@ -12,7 +12,7 @@ uart: baudrate: 3000000 clock_freq: 100000000 ``` -This snippet defines the interface, and lives at the bottom of a Manta configuration file. Three parameters must be set: +This snippet at the end of the configuration file defines the interface. The following parameters must be set: - `port` _(required)_: The name of the serial port on the host machine that's connected to the FPGA. Depending on your platform, this could be `/dev/ttyUSBXX`, `/dev/tty.usbserialXXX`, or `COMX`. If set to `auto`, then Manta will try to find the right serial port by looking for a USB device with the same VID and PID as a FT2232 - a USB/UART converter chip that's super popular on FPGA dev boards. This doesn't always work, but it's super convenient when it does. If your port isn't automatically detected, then just specify the port manually. diff --git a/mkdocs.yml b/mkdocs.yml index ca1d1d0..67f50e5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,18 +17,24 @@ theme: - navigation.expand palette: - - scheme: default - primary: custom - accent: light blue + - media: "(prefers-color-scheme)" toggle: - icon: material/brightness-7 - name: Switch to dark mode - - scheme: slate - primary: custom - accent: light blue - toggle: - icon: material/brightness-4 + icon: material/link name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: blue + accent: custom + toggle: + icon: material/toggle-switch + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: black + accent: custom + toggle: + icon: material/toggle-switch-off + name: Switch to system preference extra_css: - stylesheets/extra.css