Key Components Part 3: DMA and Peripherals.
Let’s wrap up the selection of key components for the BoxLambda computer.
DMA
I was on the fence for a while, deciding whether or not I should include a DMA engine in our machine. In a previous post, I said I would use DMA to move data between external and internal memory. However, a DMA Controller is by definition a bus master, and having multiple bus masters (DMAC and CPU) adds significant complexity to the architecture: access to shared buses and slaves, impact on timing, etc. In a system with only one bus master, the CPU, you don’t have to worry about any of that.
Then I snapped out of it and remembered that BoxLambda is intended to be a platform for RTL experimentation. It would be silly to restrict these RTL experiments to bus slave components only. In other words, the BoxLambda architecture is going to have to accommodate bus masters, so we might as well include a DMA Controller.
Some use cases for DMA in the scope of our computer include:
- Moving data between external (DDR) and internal (Block RAM) memory.
- Streaming from memory to the audio DAC.
- Blitting, i.e. copying data into video memory, taking into account the video memory’s organization. For instance, copying a rectangular block of data into a frame buffer requires striding between rows of pixel data. Another example: Bit planes with 1, 2, or 4 bits-per-pixel color depths require barrel shifting when copying data to a specific pixel offset.
I spent many hours online searching for DMA Controllers. I was a bit surprised that there were so few options, so I kept digging. I found ZipCPU’s, FreeCore’s, and Ant Micro’s DMA controllers. The Anti Micro DMAC seemed to be the most interesting option, with two Wishbone ports, pipelined mode, striding support, and support for any byte boundary alignment.
I had this post, with the Ant Micro selection, ready to go. But then I happened across an old post on Reddit where somebody proposed a ‘smart’ DMA concept: a DMAC with a tiny CPU embedded in it. That sounded like a great concept, so I pinged the author to check what became of his idea. In response, the author generously decided to release his code on GitHub! The core is called Praxos. Here is the repository:
https://github.com/esherriff/Praxos
Praxos has tiny CPU with a small amount of program and data memory embedded in the core, allowing you to write microcode specifying the DMA behavior you want: word/non-word alignment, incrementing/decrementing/non-incrementing source and/or destination address, strides between transfers, combining sources, barrel shifting… Maximum flexibility!
It’s not perfect though. Praxos only has one bus master port, an Avalon port at that. It should be doable to slap a standard Wishbone port onto it, but in its current form, I think it won’t be able to take advantage of Wishbone’s pipelined burst mode. That’s unfortunate for a DMAC.
Still, having the option to hack together my own application-specific DMA microcode sounds like a lot of fun. I just have to go with the Praxos option.
Many thanks to esherriff for making his code available!
Storage
I’m going to use ZipCPU’s SD Card Controller in combination with the FatFs software library to mount a FAT filesystem on the SD card:
- SD Card Controller: https://github.com/ZipCPU/sdspi
- FatFs library: http://elm-chan.org/fsw/ff/00index_e.html
The SD Card Controller has a Wishbone slave port.
Keyboard and Mouse
FreeCores has PS/2 keyboard and mouse modules: https://github.com/freecores/ps2
These cores don’t have a Wishbone slave port, so we’re going to have to add that ourselves.
Note that the Nexys A7 has a USB HID host interface for keyboard and mouse which, with the help of clever firmware on a PIC24 microcontroller, presents itself to the FPGA as a PS/2 interface. See the Nexys A7 Reference Manual for more details.
I2C
The I2C interface can be used to hook up a Real-Time Clock PMOD as well as a Wii Nunchuck Adapter.
ZipCPU has an I2C core with a Wishbone port: https://github.com/ZipCPU/wbi2c.
Serial Port
ZipCPU comes to the rescue once again with a UART implementation with a Wishbone interface: https://github.com/ZipCPU/wbuart32
I think that completes the list of Key Components for the time being. More components (e.g. IRQ controller, PIT timers, GPIO) may come into the picture as we get deeper into the architecture or design phase.
Interesting Links
- Amiga HRM, Blitter Section: An in-depth description of Amiga’s Blitter. A good example of how well-designed the Commodore Amiga was.
- www.zipcpu.com: The author of this website, Mr. Gisselquist, is a very experienced FPGA developer. He has contributed a lot of knowledge to the public domain, in the form of verilog code, Blog articles, and tutorials. The Verilog tutorial on this site also serves as a great introduction to formal verification, a frequently recurring topic in the ZipCPU Blog posts.