diff --git a/doc/cores.md b/doc/cores.md index 55407f6..b86365d 100644 --- a/doc/cores.md +++ b/doc/cores.md @@ -1,8 +1,6 @@ # Cores -Manta has two types of debug cores: a logic analyzer core, and an IO core. - -## Logic Analyzer Core +## Logic Analyzer This emulates the look and feel of a logic analyzer, both benchtop and integrated. These work by continuously sampling a set of digital signals, and then when some condition (the _trigger_) is met, recording these signals to memory, which are then read out to the user. diff --git a/doc/getting_started.md b/doc/getting_started.md new file mode 100644 index 0000000..ff6922d --- /dev/null +++ b/doc/getting_started.md @@ -0,0 +1,5 @@ +## Getting Started +Manta is installed with `pip3 install mantaray`. Or at least it will be, once it's out of alpha. For now, it's installable with `pip install -i https://test.pypi.org/simple/ mantaray`, which just pulls from the PyPI testing registry. + +## Examples +Examples can be found under `examples/`. These target the Xilinx Series 7 FPGAs on the [Nexys A7](https://digilent.com/reference/programmable-logic/nexys-a7/start)/[Nexys4 DDR](https://digilent.com/reference/programmable-logic/nexys-4-ddr/start) and the Lattice iCE40 on the [Icestick](https://www.latticesemi.com/icestick). \ No newline at end of file diff --git a/doc/how_it_works.md b/doc/how_it_works.md new file mode 100644 index 0000000..a041f3e --- /dev/null +++ b/doc/how_it_works.md @@ -0,0 +1,41 @@ + +# How it Works +Manta works by having a set of configurable cores daisy-chained together across a simple bus that resembles AXI-lite. Each core exposes some region of addressible memory, which is accessed by the host machine over an interface of choice. Here's what this looks like as a block diagram, in this case UART is used as the interface: + +## Bus + +This daisy-chaining is done to make place-and-route as easy as possible - the critical timing path only exists between adjacent cores, instead of rouing back to some central core in a hub-and-spoke arrangement. This relaxed routing helps designs that span multiple clock domains and require BRAMs placed on the edges of clock domains for CDC. + +## Memory + +The memory is built of 16-bit registers living on a 16-bit address bus. Address space is assigned when the Verilog is generated, since each core can occupy a varying amount of address space depending on how it's configured. This space is assigned sequentially - the first core in the chain will occupy the first section of memory, and the last core will occupy the last section. Some registers are read-only to the host machine, and attempts to write to them will be ignored by the core. + +## Read/Write Transactions + +As you'd expect, reading from some address will elicit a response from the FGPA. However, writing to some address __will not__. If you want to verify that the data you wrote to some location is valid, read from it after the write. This is done to keep state machines simple and interfaces fast. + +Data moves between the host computer and the FPGA over UART. UART's just an interface though, so the choice of what data to send is arbitrary. Manta encodes data exchanged between devices as messages, which are ASCII text in the following format: + +```[preamble] [address] [data (optional)] [EOL]``` + +- The __preamble__ is just the character `M`, encoded as ASCII. + +- The __address__ is the memory location we wish to access. This must exist somewhere in the address space consumed by the cores. If it does not, then read/write operations addressed here will do nothing. The address itself is transmitted as hex values, encoded as ASCII using the characters `0-9` and `A-F`. + +- The __data__ gets stored in the memory location provided by __address__. The presence of any number of data bytes indicates a write operation, while no data bytes indicates a read operation. + +- An __EOL__ indicates the end of the message. CR, LF, or both are considered valid delimiters to for messages sent to the FPGA. For messages sent to the host machine, the FPGA will send CRLF. + +This message format can be either a sequence of bytes encoded over UART, or characters in a data field of an Ethernet packet. + +### Example Messages + +Some examples of valid messages to the FPGA are: +```MBEEF\r\n```, which writes `0xEF` to the memory at location `0xBE`. +```MBE\r\n```, which reads the value of the memory at location `0xBE`. + +Some examples of invalid messages to the FPGA are: +```MBEEEF\r\n```f, which contains 12 bits of data, which isn't a multiple of 8. +```NBEEF\r\n```, which contains the wrong preamble. + +For example, `M1234\r\n` specifies a read operation at address `0x1234` in the memory, and if that location contains the data `0x5678`, it will produce a response of `M5678\r\n`. diff --git a/doc/index.md b/doc/index.md index e69de29..d102233 100644 --- a/doc/index.md +++ b/doc/index.md @@ -0,0 +1,40 @@ +## Manta: An In-Situ Debugging Tool for Programmable Hardware +![functional_simulation](https://github.com/fischermoseley/manta/actions/workflows/functional_simulation.yml/badge.svg) +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) + +Manta is a tool for getting information into and out of FPGAs over an interface like UART or Ethernet. It's primarily intended for debugging, but it's robust enough to be a simple, reliable transport layer between a FPGA and a host machine. It lets you configure a series of cores on a shared bus via a YAML or JSON file, and then provides a Python API to each core, along with vendor-agnostic Verilog HDL to instantiate them on your FPGA. + + +You might find Manta useful for: + +* Verifying specification adherence for connected hardware - your I2S decoder works in simulation, but doesn't in hardware. Manta will help you figure out why. + +* Moving generic data between a host and connected FPGA - you're working on a cool new ML accerleator, but you don't want to think about how to get training data and weights out of TensorFlow, across some interface, and into your core. + +* Prototyping designs in Python, and incrementally migrating them to hardware. You're working on some real-time signal processing, but you want to prototype it with some sample data in numpy before meticulously implementing everything in Verilog. + +Manta is written in Python, and generates Verilog-2001 HDL. It's cross-platform, and its only strict dependencies are pySerial and pyYAML. However, pyvcd is required if you want to export a waveform from the Logic Analyzer core to a `.vcd` file. + +## Cores + +Manta includes a few cores, configurable to your liking: + +* __Logic Analyzer Core__: The host can arm the core, and then when a trigger condition is met, the debug output is wired back to the host, where it's saved as a waveform file. This can then be opened and inspected in a waveform viewer like GTKWave, or directly manipulated in Python using the generated API. This is similar to Xilinx's [Integrated Logic Analyzer (ILA)](https://docs.xilinx.com/r/en-US/ug908-vivado-programming-debugging/ILA) and accompanying [ChipScoPy API](https://xilinx.github.io/chipscopy/2022.2/overview.html) and Intel/Altera's [SignalTap](https://www.intel.com/content/www/us/en/docs/programmable/683819/21-3/logic-analyzer-introduction.html) utility. + +* __I/O Core__: This exposes a number of probes that can be read or set, allowing for signals inside the FPGA to be monitored and controlled by the host machine. This is similar to Xilinx's [Virtual IO](https://docs.xilinx.com/v/u/en-US/pg159-vio) core. + +* __LUT RAM__ and __BRAM Cores__: Under the hood, Manta is just a bunch of modules sharing a common address and data bus, so cores that add Block RAM and LUT RAM to said bus are also available. More information on this bus configuration is on the [How it Works](how_it_works) page. + +These are more explicity described on the [cores](cores) page. + +## Design Philosophy + +* _Things that are easy to misconfigure should be easy to reconfigure_. For instance, it's easy to accidentally put the wrong amount of holdoff in a logic analyzer core and shouldn't require regenerating a bitstream to fix. + +* _Don't use macros._ There's a possibility that they'll conflict with something in user code. + +* _Autogenerate Verilog 2001 for compatibility._ However, some SystemVerilog 2012 is used for simulation and test. + +## About +Manta was originally developed as part of my [Master's Thesis at MIT](dspace.mit.edu) in 2023, done under the supervision of Dr. Joe Steinmeyer. But I think it's a neat tool, so I'm still working on it :) \ No newline at end of file diff --git a/doc/roadmap.md b/doc/roadmap.md index cc69860..5ca8add 100644 --- a/doc/roadmap.md +++ b/doc/roadmap.md @@ -1,4 +1,4 @@ -# Planned Work: +## Planned Work: - _Verify Manta on non-Xilinx FPGAs_: This is in progress for the Lattice iCE40 on the Icestick, and the Altera Cyclone IV on the DE0 Nano. @@ -17,7 +17,7 @@ - _FuseSoC integration_: This will probably exist in some headless-ish mode that separates manta's core generation and operation, but it'd be kinda nice for folks who package their projects with FuseSoC. -# Potential Future Work: +## Potential Future Work: The guiding principle behind adding features here is to just do a bunch of projects, run into annoying bugs, and see what'd be useful to have as a tool, and then implement that. That said, there's a few ideas I've been kicking around at the moment: @@ -32,6 +32,6 @@ The guiding principle behind adding features here is to just do a bunch of proje * _Clock Domain Crossing:_ You should be able to put cores in different clock domains - although I'm struggling to figure out where exactly this would be useful. Xilinx's ILA will let you have multiple cores and it doesn't care much which clock domain those are under, so some more investigation will be needed there. -# Completed Features: +## Completed Features: * _Packaging_: Manta should fundamentally be out of the way of the hardware developer, so it needs to live on the system, not as source code in the project repo. We learned this with `lab-bc` last semester - we couldn't update it easily and it ended up living in people's git repos. Which shouldn't be necessary since they're not responsible for versioning it - we are. Same mentality here. \ No newline at end of file diff --git a/doc/theory_of_operation.md b/doc/theory_of_operation.md deleted file mode 100644 index 7702836..0000000 --- a/doc/theory_of_operation.md +++ /dev/null @@ -1,44 +0,0 @@ -# Theory of Operation - -- Manta works by having a set of configurable debug cores daisy-chained together across a simple bus. Each core exposes some region of addressible memory that can be controlled by sending read and write commands to the FPGA over UART. - -- These registers are 32-bits wide, and have a configurable address width. Manta will default to using the smallest possible address bus to minimize the burden on the place and route engine, but this can be overridden. This might be desirable if you wish to put other devices on the bus, such as a softcore. - -- The regions of memory assigned to each core are determined by Manta when it autogenerates the Verilog HDL. Address space is assigned sequentially. - -- Some registers, like captured sample data in a logic analyzer core, are not writeable by the host machine. - -- Reading from a register will return the contents of the register over serial. Writing to a register will return nothing over serial. If you want to verify that the data you wrote to some location is valid, read from it after the write. This lack of a return makes things simpler for the state machines and faster for the user, since the OS on the host machine doesn't have to empty it's UART RX buffer before moving on in the Python. - -These registers exist within whatever core you've asked manta to generate - be that an logic analyzer, or I/O. Each core is daisy-chained after the previous one in the arrangement shown below. This is done to provide maximum flexibility for place-and-route, as the critical timing path only exists between adjacent cores. If a hub-and-spoke arrangement were used, the critical timing path would exist between the hub and every spoke. For designs that span multiple clock domains and need to use BRAMs on the edges of clock domains for CDC, this makes designs that are very difficult to route. - -# Block Diagram - - - -# Message-Passing Format - -Data moves between the host computer and the FPGA over UART. UART's just an interface though, so the choice of what data to send is arbitrary. Manta encodes data exchanged between devices as messages, which are ASCII text in the following format: - -```[preamble] [address] [data (optional)] [EOL]``` - -- The __preamble__ is just the character `M`, encoded as ASCII. - -- The __address__ is the memory location we wish to access. This must exist somewhere in the address space consumed by the cores. If it does not, then a write operation addressed here will do nothing, and a read operation addressed here will return nothing. The address itself is transmitted as hex values, encoded as ASCII using the characters `0-9` and `A-F`. All addresses are a single byte, so ther can not be more than 256 register locations onboard. - -- The __data__ gets stored in the memory location provided by __address__. The presence of any number of data bytes indicates a write operation, while no data bytes indicates a read operation. - -- An __EOL__ indicates the end of the message. CR, LF, or both are considered valid delimiters to for messages sent to the FPGA. For messages sent to the host machine, the FPGA will send CRLF. - -## Example Messages - -Some examples of valid messages to the FPGA are: -```MBEEF\r\n```, which writes `0xEF` to the memory at location `0xBE`. -```MBE\r\n```, which reads the value of the memory at location `0xBE`. - -Some examples of invalid messages to the FPGA are: -```MBEEEF\r\n```f, which contains 12 bits of data, which isn't a multiple of 8. -```NBEEF\r\n```, which contains the wrong preamble. - - -# AXI-ish Interfaces \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index fb09e01..4801c3a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Manta +site_name: manta site_description: Manta Documentation site_author: Fischer Moseley @@ -8,6 +8,10 @@ docs_dir: 'doc' theme: name: material + features: + - content.code.copy + - content.code.annotate + palette: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" @@ -25,8 +29,18 @@ theme: icon: material/brightness-4 name: Switch to light mode +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + nav: - Home: index.md - - How it Works: theory_of_operation.md + - Getting Started: getting_started.md + - How it Works: how_it_works.md - Cores: cores.md - - Roadmap: roadmap.md \ No newline at end of file + - Roadmap: roadmap.md