update tutorial_1

This commit is contained in:
Fischer Moseley 2023-04-18 13:55:40 -04:00
parent af5d3a9b4b
commit 0268572779
3 changed files with 99 additions and 13 deletions

BIN
doc/assets/ps2.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,7 +1,24 @@
## Getting Started
Manta is installed with `pip3 install mantaray`.
## Installation
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.
You can install the latest version of Manta directly from source with:
```
pip install git+https://github.com/fischermoseley/manta.git
```
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
```
And go ahead and throw Manta on your system path by adding the following to your `.bashrc` or `.zshrc`.
```
export PATH="~/.local/bin:$PATH"
```
This makes it so that you can run `manta` as it's own command on the command line, instead of having to do `python3 -m manta`.
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.
## 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).

View File

@ -1,7 +1,7 @@
## Welcome back!
Howdy and welcome back to the party! Today's format is going to be a little different - we'll be splitting ya'll up into two groups and having one set test Manta, and one set test lab-bc 2.0 - in _parallel_. This will hopefully take less time, give us some more meaningful tests, and just be better on the whole. Hopefully this works, parallelization is kind of our _whole thing_.
Howdy and welcome back to the party! Today's format is going to be a little different - we'll be splitting ya'll up into two groups and having one set test Manta, and one set test lab-bc 2.0 - in _parallel_. This will hopefully take less time, give us some more meaningful tests, and just be better on the whole. It'd be kinda embarassing if this doesn't work, parallelization is kind of our _whole thing_.
## Update Manta:
## Update Manta
There's been a fair bit of work since this time last week! Actually I'm curious how many commits there've been...
```
@ -16,14 +16,35 @@ Oh god - we should definitely update Manta. And I should definitely, like, go ou
While you've got a terminal open, go ahead and grab the starter code from fischer's [super exclusive, boutique, and bouguie code hosting site](https://github.com/fischermoseley/tutorial_2_template)
## The fun part!
Today we'll be experimenting with the most Manta feature - the Logic Analyzer core. If we ever connected an ILA to your code last semester (or used a proper, benchtop logic analyzer like the ones on top the tables), then this will feel pretty familiar. But if not, perfect :)
Today we'll be experimenting with the most powerful Manta feature - the Logic Analyzer core. If we ever connected an ILA to your code last semester (or used a proper, benchtop logic analyzer like the ones on top the tables), then this will feel pretty familiar. But if not, perfect :)
The logic analyzer core connects to a set of singals that you want to investigate, which you do by _capturing_ them. When a _trigger condition_ is met, the logic analyzer core will record the value of each signal to internal memory, until that memory is full. That memory is then read back by the host machine, and exported to a `.vcd` file, which we can open in GTKWave and poke around with. And later, we'll "play back" that capture data in our own simulation, where we'll prototype a PS2 decoder. And if it works there on data captured from the real world, it should work just dandy in hardware.
The logic analyzer core connects to a set of singals that you want to investigate, which you do by _capturing_ them. When a _trigger condition_ is met, the logic analyzer core will record the value of each signal to internal memory, until that memory is full. That memory is then read back by the host machine, and exported to a `.vcd` file which we can open in GTKWave and poke around with.
And later, we'll "play back" that capture data in our own simulation, where we'll prototype a PS2 decoder. And if it works there on data captured from the real world, it should work just dandy when we go to implement it in hardware.
We'll be kicking the tires on the Logic Analyzer core in the context of the PS/2 keyboards we used in [lab02](https://fpga.mit.edu/6205/F22/labs/lab02). If you remember, we had a catsoop checker on the page that ran a testbench on your code, but it was a little unreliable and would often fail code that would actually work perfectly fine in hardware. This was our fault - our testbench didn't model how the keyboard worked completely corectly - but in this exercise we'll work around that by just yoinking data from the real world.
## Quick Blast to the Past
Here's a quick refresher on PS/2, lifted straight from the [lab02](https://fpga.mit.edu/6205/F22/labs/lab02#section_8) text:
PS/2 works by representing each character on the keyboard as a one-byte value from a predefined table, and sending that across the interface when a key is pressed.
Whoa whoa whoa, what does "sent" mean?
Basically, the PS/2 protocol runs over two connections / 'lines' between the device (i.e. your keyboard) and the PS/2 controller. The first of these connections is a clock, driven at a few kilohertz2 by the keyboard. The second of these connections is where the actual data flows. When the clock line drops from high to low, we can grab the value of the data line and store it for later use - eventually stacking up a full eight bits of information. This byte of information corresponds to a "scancode" in the above table, which maps to the character that you just pushed on your keyboard. However, as is often the case in communication of data, more than just the message must be sent in order to avoid ambiguity.
The transmission of an entire byte, therefore looks like the following: When you press down a key (or release a key...see below), you're gonna see the following happen:
- The clock line, which is high at idle time, is going to start ticking at its frequency of a few kilohertz. Meanwhile, a start bit, which signals the beginning of the transmission (and is always zero), is asserted on the data line. So at the first falling edge of the clock in a given sequence, you're going to see a 'zero' value asserted on the data line.
- The next eight falling clock edges will bring along 8 data bits, which contain the byte that represents the key you pressed.
- Next you'll see a parity bit, which is used for error checking. This uses the same method as you saw in pset 03. PS/2 uses odd parity which means if there are an even number of 1's in the 8 bits of the actual message a 1 is in the parity bit slot. If not, then a 0 is in the parity bit slot.
- Finally, you'll see a stop bit which is always a one. This signals the end of the transmission, and its receipt corresponds with the last falling clock edge you'll see until the next key is pressed.
For you visual folks, here's a quick diagram summarizing the above.
![](assets/ps2.jpeg)
## Adding a logic analyzer
Just like last time, we'll be configuring out `manta` instance with a configuration file called `manta.yaml`. There's a template in the starter code, go ahead and tweak it to add in a logic analyzer core according to the [documentatation](../logic_analyzer_core). There's a few parameters we'll want to pay close attention to:
@ -54,11 +75,59 @@ Go ahead and open the `caputure.vcd` file with `gtkwave capture.vcd`. This shoul
## Onto something useful...
This is great! We can see our data and clock line, and it looks like what we expect. If we were working with something less standard than a PS2 keyboard, we could use Manta to double check that the signals received by the FPGA are the signals it expects.
Let's go one step farther - we're going to write a PS/2 decoder in Verilog (I know it's been a while, I tried to pick something easy), but we're going to bypass the annoyness of setting up a testbench. Instead, we're just going to use the capture data we got from before, chunk that into our decoder, and see if we can get it to work in simulation. And once we do, we'll chunk it on the FPGA, and see how we did.
Let's go one step farther - we're going to write a PS/2 decoder in Verilog (I know, I know it's been a while - I tried to pick something easy), but we're going to bypass the annoyness of setting up a testbench. Instead, we're just going to use the capture data we got from before, chunk that into our decoder, and see if we can get it to work in simulation. And once we do, we'll put our module on the FPGA, and see how we did.
# Debrief
- We made something that worked right the first time, without making a simulation beforehand. That's pretty cool. But it's got some caveats:
- Helps catch only one quadrant of the should(n't) work/does work
- Doesn't catch things that a normal simulation might. It only tests the nominal case. But it's an EXACT representation of the nominal case.
- This required us to have our FPGA next to us, and to test things in hardware. I could sit down, write a simulation in iverilog form scratch, and that'd be quicker than grabbing things from the real world. It's a tradeoff, and the purpose of Manta isn't to be a magic bullet - it's to give you more options.
## Playing Back Capture Data
There's a little bit of Verilog required to load our capture data from `capture.mem` into the simulation, but conveniently Manta will auto-generate this wrapper for you. If you run
```
manta playback manta.yaml my_logic_analyzer sim/playback.v
```
It'll create a module that outputs `ps2_clk` and `ps2_data`, and place it in `sim/playback.v`. There's an empty testbench in `sim/ps2_decoder_tb.sv`, go ahead and instantiate a copy of the playback module in the testbench. If you have a look at top of `sim/playback.v`, there's a little instantiation template you can copy-paste. Easy peasy.
While you're there, go ahead and instantiate a copy of ps2_decoder too, and wire it up to the output of the playback module.
## Writing ps2_decoder
Once you've got the plumbing all sorted, go ahead and type up the `ps2_decoder` module itself. VS Code should be installed on all the machines, and if you'd like to simulate with your captured data, just run:
```
iverilog -g2012 -o sim.out sim/ps2_decoder_tb.sv sim/playback.v src/ps2_decoder.sv
vvp sim.out
```
!!! tip
Feel free to ignore the parity bit - just making sure that there's a start and stop bit is suffecient for the time being.
Make sure that the output of your `ps2_decoder` matches the key you pressed when you made the capture. Once you think you've got it working, feel free to throw it on the FPGA and build. The decoder is already instantiated in `top_level.sv`, so you shouldn't have to change anything outside of `ps2_decoder.v`.
Once you've got it working on hardware, congratulations!
## Debrief
We made something that worked right the first time, without spending a ton of time making a testbench beforehand. That's pretty cool. But it's got some big caveats:
- __It only tests the nominal case__: What if we received data whose parity bit didn't match? What if we only received 10 data bits intead of 11? We won't know how our ps2_decoder behaves in this case - we'd have to code those cases in manually, and Manta can't help us with that.
- __It requires hardware__: This is somewhat obvious, but we needed to have our FPGA and a PS/2 keyboard next to us before we ever started writing Verillog. That's not the most convenient thing - especially when PS/2 is simple enough to the point where I could probably write a PS/2 testbench in about the same amount of time it'd take to get the capture data into a simulation.
However, there were a few things that were pretty cool:
- __We had an exact representation of the nominal case__: If all data looks like our capture data did, we _know_ our design will work. That's powerful.
- __We didn't need to know what PS/2 looks like to start writing the simulation__: If this was your first time working with PS/2, this changes the development process from:
- Understand PS/2.
- Write PS/2 signal generator in testbench.
- Write PS/2 decoder in testbench.
- and changes it to:
- Import PS/2 signal generator to testbench.
- Understand PS/2.
- Write PS/2 decoder in testbench.
And that might be useful, especially if you've got a device that you think is misbehaving. Being able to check it while you're writing your decoder is powerful.
Anyway, neither approach is perfect, and Manta's not meant to deliver something that is. It's meant to give you more options, all of which have tradeoffs.
That's about all I've got for now. Thanks for coming, and grab some pizza and stickers if you don't have some already :) Catch ya next week!