update docs, bump required python to 3.8
This commit is contained in:
parent
4e44f7ac90
commit
2b95fea496
|
|
@ -0,0 +1,61 @@
|
|||
There's quite a few FPGA debugging tools out there, and it may happen that your needs are better met by another tool. This section aims to provide a list of alternatives, in hopes that you're able to be confident in your debugging flow.
|
||||
|
||||
## Open Source Tools
|
||||
|
||||
### LiteScope
|
||||
|
||||
An embedded logic analyzer written in Migen, primarily for use in LiteX SoC designs. Also includes IO peek and poke, as well as UART, Ethernet, and PCIe interfaces with a host machine. Includes VCD, Sigrok, CSV, and Python data export.
|
||||
|
||||
- [Source Code](https://github.com/enjoy-digital/litescope)
|
||||
- [Documentation](https://github.com/enjoy-digital/litex/wiki/Use-LiteScope-To-Debug-A-SoC)
|
||||
|
||||
### ZipCPU Debugger
|
||||
|
||||
A set of embedded debugging modules written by Dan Gisselquist of ZipCPU fame. Communication between the host and FPGA is accomplished with UART, and control of the debugger is performed with a C++ API on the host. A wishbone interface is provided on the FPGA side to connect to other Wishbone-based debugging tools that can provide control of user registers, block RAM, and an embedded logic analyzer. Supports dumping of signals to a VCD file.
|
||||
|
||||
- [Source Code](https://github.com/ZipCPU/dbgbus)
|
||||
- [Documentation](https://zipcpu.com/topics.html), under the _How to Debug an FPGA_ section.
|
||||
|
||||
## Commercial Tools
|
||||
|
||||
### Xilinx Integrated Logic Analzyer
|
||||
|
||||
An embedded logic analyzer for Xilinx FPGAs, provided as part of the Xilinx Vivado development suite. Communication between the host and FPGA is accomplished with JTAG, typically running over a USB cable to the device. Includes an integrated waveform viewer, and VCD and CSV export. Also supports a JTAG-to-AXI mode, which integrates well with Xilinx IP, which uses primarily AXI. Also integrates with the ChipScoPy API, which allows for Python control of the ILA on Versal devices. The ILA was previously known as ChipScope in earlier versions of Vivado.
|
||||
|
||||
- [ILA Documentation](https://docs.xilinx.com/v/u/en-US/pg172-ila)
|
||||
- [ILA User's Guide](https://docs.xilinx.com/r/en-US/ug936-vivado-tutorial-programming-debugging/Using-the-Vivado-Logic-Analyzer-to-Debug-Hardware)
|
||||
- [ChipScoPy API](https://github.com/Xilinx/chipscopy)
|
||||
|
||||
|
||||
### Xilinx Virtual IO
|
||||
|
||||
A tool for reading and writing to individual registers on the FPGA, provided as part of the Xilinx Vivado development suite. Just like the ILA, communication between the host and FPGA is done over JTAG. Control over the registers is done through the Vivado GUI or through the Tcl interpreter. In the case of Versal devices, the ChipScoPy API can also control the registers.
|
||||
|
||||
- [Virtual IO Documentation](https://docs.xilinx.com/v/u/en-US/pg159-vio)
|
||||
- [ChipScoPy API](https://github.com/Xilinx/chipscopy)
|
||||
|
||||
### Intel Signal Tap
|
||||
|
||||
An embedded logic analyzer for Intel/Altera FPGAs, provided as part of the Quartus development suite. Communication between the host and FPGA is accomplished with JTAG, and a programmable interface is provided via Tcl. Signal Tap is notable for providing a significant amount of configurability in the trigger conditions, and provides a small scripting language called _Trigger Flow_ that allows users to define triggers as state machines. Signal Tap also allows for _Simulation-Aware nodes_, which allows for running simulations with data captured from the real world. At the time of writing, this feature is only available in the most recent and full-featured version of the Quartus suite, Quartus Prime Pro Edition 22.4.
|
||||
|
||||
- [Documentation](https://www.intel.com/content/www/us/en/docs/programmable/683552/18-1/design-debugging-with-the-logic-analyzer-69524.html)
|
||||
|
||||
|
||||
### Intel In-System Sources and Probes
|
||||
|
||||
A tool for reading and writing to individual registers on the FPGA, provided for Intel/Altera FPGAs as part of the Quartus development suite. Just like Signal Tap, communication between the host and FPGA is accomplished with JTAG.
|
||||
|
||||
- [Documentation](https://www.intel.com/content/www/us/en/docs/programmable/683552/18-1/design-debugging-using-in-system-sources-45607.html)
|
||||
|
||||
### Lattice Reveal
|
||||
|
||||
An embedded logic analyzer for Lattice FPGAs, provided as part of the Diamond development suite. Communication between the host and FPGA is accomplished with JTAG. Reveal is notable for providing a significant amount of configurability in the trigger conditions, and supports trigger conditions formed with a mix of combinational and sequential logic. Reveal also provides special support for Wishbone buses, and for controlling SERDES modules on ECP5 devices.
|
||||
|
||||
- [Documentation](https://www.latticesemi.com/~/media/328D471BF2C74EB1907832FAA6FB344B.ashx)
|
||||
|
||||
### 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.
|
||||
|
||||
- [Documentation](https://docs.opalkelly.com/fpsdk/)
|
||||
- [User's Guide](https://assets00.opalkelly.com/library/FrontPanel-UM.pdf)
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
The whole system looks like the following:
|
||||
|
||||
{:style="width:80%"}
|
||||
{: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.
|
||||
|
||||
|
|
@ -56,4 +56,46 @@ An example of some bus traffic is provided below:
|
|||
| 5 | FPGA → Host: RBEEF(CR)(LF) | Read 0xBEEF from 0xF00D |
|
||||
| 6 | Host → FPGA: W12340000(CR)(LF) | Write 0x0000 to 0x1234 |
|
||||
|
||||
When UART is used, these bytes are transmitted directly across the wire, but when Ethernet is used, they're packed into the packet's payload field.
|
||||
When UART is used, these bytes are transmitted directly across the wire, but when Ethernet is used, they're packed into the packet's payload field.
|
||||
|
||||
# Cores
|
||||
|
||||
## IO Core
|
||||
|
||||
This is done with the architecture shown below:
|
||||
|
||||
{: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.
|
||||
|
||||
Whatever the number of registers required, these are read from and written to by the host machine - but the connection to the user's logic isn't direct. The value of each probe is buffered, and only once the `strobe` register has been set to one will the buffers update. When this happens, output probes provide new values to user logic, and new values for input probes are read from user logic. This provides a convenient place to perform clock domain crossing, and also mitigates the possibility of an inconsistent system state. This is explained in more detail in Chapter 3.6 of the [original thesis](thesis.pdf).
|
||||
|
||||
## Logic Analyzer
|
||||
The Logic Analyzer Core's implementation on the FPGA consists of three primary components:
|
||||
|
||||
{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.
|
||||
- The _Sample Memory_, which stores the states of the probes during a capture. This is implemented as a dual-port, dual-clock block memory, with the bus on one port and the probes on the other. The probe-connected port only writes to the memory, with the address and enable pins managed by the FSM. CDC is performed in the block RAM primitive itself.
|
||||
|
||||
|
||||
## Memory Core
|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
|
||||
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:
|
||||
|
||||
| Bus Address Space | BRAM Address Space |
|
||||
| ----------- | -------------------- |
|
||||
| BASE_ADDR + 0 | address 0, bits 0-15 |
|
||||
| BASE_ADDR + 1 | address 0, bits 16-31|
|
||||
| BASE_ADDR + 2 | address 0, bits 32-33|
|
||||
| BASE_ADDR + 3 | address 1, bits 0-15 |
|
||||
| BASE_ADDR + 4 | address 1, bits 16-31|
|
||||
| BASE_ADDR + 5 | address 1, bits 32-33|
|
||||
|
||||
...and so on.
|
||||
|
|
@ -11,6 +11,5 @@ Manta's bus clock must be equivalent to the PHY's reference clock if Ethernet is
|
|||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
## Overview
|
||||
|
||||
To use Manta, you'll need a host machine with a FPGA board connected over UART or Ethernet. You'll then:
|
||||
To use Manta, you'll need a host machine with a FPGA board connected over UART, or a FPGA board connected to the same network via Ethernet. You'll then:
|
||||
|
||||
- _Specify a set of debug cores you wish to include in your design._ This is done by writing a configuration file, typically called `manta.yaml`. Specifying files in JSON is also supported, as long as the hierarchy in the file is equivalent. Just make sure that your YAML files end in `.yaml` or `.yml`, and that JSON files end in `.json`.
|
||||
- _Invoke Manta to generate Verilog from the configuration provided._ This is done by running `manta gen [config_file] [verilog_file]` at the command line, which generates a Verilog file (typically named `manta.v`) from the provided configuration file. This Verilog file contains a definition for a Verilog module named `manta`, and all its constituent modules.
|
||||
|
|
|
|||
16
doc/index.md
16
doc/index.md
|
|
@ -2,7 +2,13 @@
|
|||
|
||||
## Manta: An In-Situ Debugging Tool for Programmable Hardware
|
||||
|
||||
Manta is a tool for getting information into and out of FPGAs over UART or Ethernet. It's primarily intended for debugging and experimentation, but it's robust enough to be a simple, reliable transport layer between a FPGA and a host machine. It works by letting you configure a series of cores, which live as digital logic on the FPGA and are represented with vendor-agnostic Verilog-2001. The information and behavior of these cores are accessible to the host machine, which presents a Python API to the user. Manta includes the following cores, any number and combination of which may be used at once:
|
||||
Manta is a tool for moving data between a host machine and a FPGA over UART or Ethernet. It's primarily intended for debugging and rapid prototyping of FPGA designs, but it's robust enough to be used as a simple, reliable transport layer.
|
||||
|
||||
Manta works by generating a number of cores that are instantiated in the FPGA design. These allow for a variety of functions, such as reading and writing to registers and memory, or capturing data with a logic analyzer. These cores are operated by the connected host machine through either the Manta CLI, or a simple Python API.
|
||||
|
||||
Manta is written in Amaranth HDL, and the generated designs may be used natively in other Amaranth designs, or exported to vendor-agnostic Verilog-2001. All dependencies are cross-platform, so Manta can be used on any machine that has at least Python 3.8 or newer installed.
|
||||
|
||||
Manta's capabilities are best reflected in its cores, for which a brief description of each is provided below:
|
||||
|
||||
### __Logic Analyzer Core__
|
||||
|
||||
|
|
@ -28,9 +34,9 @@ You may find this core useful for:
|
|||
|
||||
* _Making dashboards_ - you'd like to get some telemetry out of your existing FPGA design and display it nicely, but you don't want to implement an interface, design a packetization scheme, and write a library.
|
||||
|
||||
### __Block Memory Cores__
|
||||
### __Memory Cores__
|
||||
|
||||
_More details available on the [full documentation page](./block_memory_core.md)._
|
||||
_More details available on the [full documentation page](./memory_core.md)._
|
||||
|
||||
This core creates a two-port block memory on the FPGA, and gives one port to the host machine, and the other to your logic on the FPGA. The width and depth of this block memory is configurable, allowing large chunks of arbitrarily-sized data to be shuffled onto and off of the FPGA by the host machine, via the Python API. This lets you establish a transport layer between the host and FPGA, that treats the data as exactly how it exists on the FPGA.
|
||||
|
||||
|
|
@ -40,10 +46,6 @@ You may find this core useful for:
|
|||
|
||||
* _Hand-tuning ROMs_ - you're designing a digital filter for a DSP project and would like to tune it in real-time, or you're developing a soft processor and want to upload program code without rebuilding a bitstream.
|
||||
|
||||
|
||||
## Dependencies
|
||||
Manta is written in Python, and generates Verilog-2001 HDL. It's cross-platform, and its only strict dependency is pyYAML. However, [pySerial](https://github.com/pyserial/pyserial) is required for using UART, [scapy](https://github.com/secdev/scapy) is required for using Ethernet, and [pyvcd](https://github.com/westerndigitalcorporation/pyvcd) is required if you want to export a waveform from the Logic Analyzer core to a `.vcd` file.
|
||||
|
||||
## 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:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +1,42 @@
|
|||
## Dependencies
|
||||
Manta requires the following dependencies:
|
||||
Before installing, make sure to upgrade your `pip` to the latest version:
|
||||
|
||||
- pyYAML, which is used for parsing configuration files written in YAML.
|
||||
- pySerial, used for communicating with the FPGA over UART.
|
||||
- Scapy, used for communicating with FPGA over Ethernet.
|
||||
- pyVCD, used for writing waveforms captured by the Logic Analyzer Core to standard Value Change Dump (VCD) files.
|
||||
```
|
||||
pip install --upgrade pip
|
||||
```
|
||||
|
||||
All of these dependencies are technically optional. If you're comfortable writing configuration files in JSON, then you don't need pyYAML. If you're using UART exclusively in your project, then you won't need Scapy. That said, Manta will try to install (or use an existing copy of) pyYAML, pySerial, and pyVCD during its own installation to cover all use cases.
|
||||
|
||||
## Installation
|
||||
## Latest Version
|
||||
You can install the latest version of Manta directly from source with:
|
||||
|
||||
```
|
||||
pip install git+https://github.com/fischermoseley/manta.git
|
||||
pip install --upgrade git+https://github.com/fischermoseley/manta.git
|
||||
```
|
||||
|
||||
!!! warning "Note for Ubuntu users:"
|
||||
## Editable Development Install
|
||||
If you're working on the source, you might want an editable installation with some extra dependencies used for development:
|
||||
|
||||
If you're on Ubuntu, you'll probably need to run this first to dodge
|
||||
a bug in the current version of Python's `setuptools`:
|
||||
```
|
||||
export DEB_PYTHON_INSTALL_LAYOUT=deb_system
|
||||
```
|
||||
Do this before installing Manta. If you've already installed it, just
|
||||
uninstall, run the above command, and then reinstall.
|
||||
```
|
||||
git clone https://github.com/fischermoseley/manta.git
|
||||
cd manta
|
||||
pip install -e ".[dev]"
|
||||
```
|
||||
|
||||
## Adding Manta to Path (Recommended)
|
||||
|
||||
It's recommended to place Manta on your system path by adding `export PATH="~/.local/bin:$PATH"` to your `.bashrc` or `.zshrc`. This isn't strictly necessary, but it means that Manta (and any other executable Python modules) can be run as just `manta` on the command line, instead of `python3 -m manta`. If you're on Windows, this location will likely be different.
|
||||
|
||||
Feel free to install Manta within a virtual environment (venv, Conda, and so on) if you'd like!
|
||||
Later Manta will be availabe on the PyPI lists, and you'll be able to just `pip install mantaray`, but that's not configured quite yet.
|
||||
|
||||
Later Manta will be availabe on the PyPI lists, and you'll be able to just `pip install mantaray`, but that's not configured quite yet.
|
||||
## 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.
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -78,20 +78,10 @@ True
|
|||
5
|
||||
```
|
||||
|
||||
## Caveats
|
||||
## Limitations
|
||||
|
||||
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.md#playback) might be helpful.
|
||||
- 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.
|
||||
|
||||
## How It Works
|
||||
|
||||
This is done with the architecture shown below:
|
||||
|
||||
{: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.
|
||||
|
||||
Whatever the number of registers required, these are read from and written to by the host machine - but the connection to the user's logic isn't direct. The value of each probe is buffered, and only once the `strobe` register has been set to one will the buffers update. When this happens, output probes provide new values to user logic, and new values for input probes are read from user logic. This provides a convenient place to perform clock domain crossing, and also mitigates the possibility of an inconsistent system state. This is explained in more detail in Chapter 3.6 of the [original thesis](thesis.pdf).
|
||||
|
|
@ -101,50 +101,29 @@ manta capture [config file] [LA core] [path] [path]
|
|||
If the file `manta.yaml` contained the configuration above, and you wanted to export a .vcd and .mem of the captured data, you would execute:
|
||||
|
||||
```bash
|
||||
manta capture manta.yaml my_logic_analyzer capture.vcd capture.mem
|
||||
manta capture manta.yaml my_logic_analyzer capture.vcd capture.v
|
||||
```
|
||||
|
||||
This will reset your logic analyzer, configure it with the triggers specified in `manta.yaml`, and perform a capture. The resulting .vcd file can be opened in a waveform viewer like [GTKWave](https://gtkwave.sourceforge.net/), and the `.mem` file can be used for playback as described in the following section.
|
||||
|
||||
Manta will stuff the capture data into as many files as you provide it on the command line, so if you don't want the `.mem` or `.vcd` file, just omit their paths.
|
||||
This will reset your logic analyzer, configure it with the triggers specified in `manta.yaml`, and perform a capture. The resulting .vcd file can be opened in a waveform viewer like [GTKWave](https://gtkwave.sourceforge.net/). Manta will stuff the capture data into as many files as you provide it on the command line, so if you don't want the `.mem` or `.vcd` file, just omit their paths.
|
||||
|
||||
|
||||
### Playback
|
||||
|
||||
The Logic Analyzer Core has the ability to capture a recording of a set of signals on the FPGA, and then 'play them back' inside a Verilog simulation. This requires generating a small Verilog module that loads a capture from a `.mem` file, which can be done by:
|
||||
|
||||
```
|
||||
manta playback [config_file_path] [core_name] [verilog_file_path]
|
||||
```
|
||||
Manta has the ability to generate a module that _plays back_ a set of data captured from a Logic Analyzer core. This module has a set of outputs matching the inputs of the Logic Analyzer, which when enabled, will take the exact values captured by the logic analyzer. This module is synthesizable, and can either be used in simulation or included in the FPGA design. This is handy for
|
||||
|
||||
If the file `manta.yaml` contained the configuration above, then running:
|
||||
|
||||
```
|
||||
manta playback manta.yaml my_logic_analyzer sim/playback.v
|
||||
```bash
|
||||
manta capture manta.yaml my_logic_analyzer capture.v
|
||||
```
|
||||
|
||||
Generates a Verilog wrapper at `sim/playback.v`, which can then be instantiated in the testbench in which it is needed. An example instantiation is provided at the top of the output verilog, so a simple copy-paste into the testbench is all that's necessary to use the module. This module is also fully synthesizable, so you can use it in designs that live on the FPGA too, if so you so wish.
|
||||
Generates a Verilog module at `capture.v` which can then be instantiated in the testbench or FPGA design in which it is needed. An example instantiation is provided at the top of the output verilog, so a simple copy-paste into the testbench is all that's necessary to use the module.
|
||||
|
||||
This is useful for two situations in particular:
|
||||
|
||||
- _Input Verification._ Designs will often work in simulation, but fail in hardware. In the absence of any build errors, this usually means that the inputs being applied to the logic in simulation don't accurately represent those being applied to the logic in the real world. Playing signals back in simulation allows for easy comparison between simulated and measured input, and provides a nice way to check that the logic downstream is behaves properly.
|
||||
|
||||
- _Sparse Sampling_ Sometimes designs will have a small number of inputs, but a huge amount of internal state. In situations like these, it may be more effecient to sample the inputs and simulate the logic, instead of directly sampling the state. For instance, debugging a misbehaving branch predictor in a CPU can be done by recording activity on the address and data busses and playing them back in simulation - which would use less BRAM than sampling the entire pattern history table.
|
||||
- _Sparse Sampling_ Sometimes designs will have a small number of inputs, but a huge amount of internal state. In situations like these, it may be more efficient to sample the inputs and simulate the logic, instead of directly sampling the state. For instance, debugging a misbehaving branch predictor in a CPU can be done by recording activity on the address and data busses and playing them back in simulation - which would use less FPGA resources than sampling the entire pattern history table.
|
||||
|
||||
## Python API
|
||||
The Logic Analyzer core functionality is stored in the `Manta.LogicAnalyzerCore` class in [src/manta/la_core/\_\_init\_\_.py](https://github.com/fischermoseley/manta/blob/main/src/manta/la_core/__init__.py).
|
||||
|
||||
At present, this class contains methods used really only for capturing data, and exporting `.vcd` and `.mem` files. It'd be super handy to expose the data from the logic analyzer core in a Pythonic way - which is why the feature is on the [roadmap](https://github.com/fischermoseley/manta/milestones)!
|
||||
|
||||
## How It Works
|
||||
The Logic Analyzer Core's implementation on the FPGA consists of three primary components:
|
||||
|
||||
{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.
|
||||
- The _Sample Memory_, which stores the states of the probes during a capture. This is implemented as a dual-port, dual-clock block memory, with the bus on one port and the probes on the other. The probe-connected port only writes to the memory, with the address and enable pins managed by the FSM. CDC is performed in the block RAM primitive itself.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
The Logic Analyzer core functionality is stored in the `Manta.LogicAnalyzerCore` class in [src/manta/la_core/\_\_init\_\_.py](https://github.com/fischermoseley/manta/blob/main/src/manta/la_core/__init__.py). This class contains methods for capturing data, and exporting `.vcd` and `.v` files.
|
||||
|
||||
|
|
|
|||
|
|
@ -64,32 +64,9 @@ foo = m.my_block_memory.read(addrs)
|
|||
|
||||
A Block Memory core is used in the [video_sprite](https://github.com/fischermoseley/manta/blob/main/examples/nexys_a7/video_sprite) example. This uses the core to store a 128x128 image sprite in 12-bit color, and outputs it to a VGA display at 1024x768. The sprite contents can be filled with an arbitrary image using the [send_image.py](https://github.com/fischermoseley/manta/blob/main/examples/nexys_a7/video_sprite/send_image.py) python script.
|
||||
|
||||
## Under the Hood
|
||||
|
||||
Each Block 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:
|
||||
|
||||

|
||||
|
||||
This has one major consequence: if the core doesn't have a width that's an exact multiple of 16, synthesis engines (Vivado in particular) will throw some warnings as they optimize out the unused bits. This is expected behavior, and while the warnings are a little annoying, not having to manually deal with the unused bits simplifies the implementation immensely. No Python is needed to generate the core, and it'll configure itself just based on Verilog parameters. This turns the block memory core from a complicated conditionally-instantiated beast to a simple ~_100 line_ [Verilog file](https://github.com/fischermoseley/manta/blob/main/src/manta/block_memory.v).
|
||||
|
||||
### Address Assignment
|
||||
|
||||
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:
|
||||
|
||||
| Bus Address Space | BRAM Address Space |
|
||||
| ----------- | -------------------- |
|
||||
| BASE_ADDR + 0 | address 0, bits 0-15 |
|
||||
| BASE_ADDR + 1 | address 0, bits 16-31|
|
||||
| BASE_ADDR + 2 | address 0, bits 32-33|
|
||||
| BASE_ADDR + 3 | address 1, bits 0-15 |
|
||||
| BASE_ADDR + 4 | address 1, bits 16-31|
|
||||
| BASE_ADDR + 5 | address 1, bits 32-33|
|
||||
|
||||
...and so on.
|
||||
|
||||
### Synchronicity
|
||||
|
||||
Since Manta's [data bus](../system_architecture) 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.
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
- `.github/` also contains some GitHub Actions configuration for automatically running the SystemVerilog testbenches and building the examples, in addition to automatically rebuilding the site.
|
||||
|
||||
## Tools Used
|
||||
- [Icarus Verilog](https://github.com/steveicarus/iverilog) is used for functional simulation.
|
||||
- The [YosysHQ](https://github.com/YosysHQ) tools and [Vivado](https://www.xilinx.com/products/design-tools/vivado.html) are used for building bitstreams.
|
||||
- [Wavedrom](https://wavedrom.com/) is used for for waveform diagrams, and [draw.io](https://app.diagrams.net/) for block diagrams
|
||||
- [GitHub Pages](https://pages.github.com/) is used to serve the documentation site, which is built with [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/).
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
## Overview
|
||||
|
||||
Manta needs an interface to pass data between the host machine and FPGA, and UART is a convenient option. When configured to use UART, Manta will shuffle data back and forth using generic 8N1 serial with no flow control. This happens through a series of read and write transactions, which are specified using a messaging format described [here](../how_it_works/#message-format).
|
||||
Manta needs an interface to pass data between the host machine and FPGA, and UART is a convenient option. When configured to use UART, Manta will shuffle data back and forth using generic 8N1 serial with no flow control. This happens through a series of read and write transactions, which are specified using a messaging format described [here](architecture.md#message-format).
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
|
|||
|
|
@ -57,14 +57,15 @@ markdown_extensions:
|
|||
nav:
|
||||
- Home: index.md
|
||||
- Installation: installation.md
|
||||
- Reference:
|
||||
- Getting Started: getting_started.md
|
||||
- Getting Started: getting_started.md
|
||||
- Alternatives: alternatives.md
|
||||
- Architecture: architecture.md
|
||||
- Usage:
|
||||
- IO Core: io_core.md
|
||||
- Logic Analyzer Core: logic_analyzer_core.md
|
||||
- Memory Core: memory_core.md
|
||||
- UART Interace: uart_interface.md
|
||||
- UART Interface: uart_interface.md
|
||||
- Ethernet Interface: ethernet_interface.md
|
||||
- For Developers:
|
||||
- Repository Structure: repository_structure.md
|
||||
- How It Works: how_it_works.md
|
||||
- Roadmap: https://github.com/fischermoseley/manta/milestones
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ dependencies = [
|
|||
"pyvcd",
|
||||
]
|
||||
|
||||
requires-python = ">=3.7"
|
||||
requires-python = ">=3.8"
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
|
|
|
|||
Loading…
Reference in New Issue