Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ttsiodras/uart_in_vhdl
My successful first experiment in VHDL - creating my own UART
https://github.com/ttsiodras/uart_in_vhdl
Last synced: 4 days ago
JSON representation
My successful first experiment in VHDL - creating my own UART
- Host: GitHub
- URL: https://github.com/ttsiodras/uart_in_vhdl
- Owner: ttsiodras
- License: gpl-3.0
- Created: 2016-10-21T20:26:55.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2016-11-12T15:07:37.000Z (about 8 years ago)
- Last Synced: 2023-03-10T22:53:03.431Z (almost 2 years ago)
- Language: VHDL
- Homepage:
- Size: 2.44 MB
- Stars: 7
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
![Data sent from minicom over the PL2303HX USB/TTL UART, read by the FPGA's GPIO pins, decoded and read back via a FIFO.](operational.jpg "Data sent from minicom over the PL2303HX USB/TTL UART, read by the FPGA's GPIO pins, decoded and read back via a FIFO.")
## My VHDL experiment - a UART of my own making
I started my career writing device drivers for 7 different FPGA designs.
I spent the next two decades writing software at all possible levels;
from device drivers, to GUIs, to real-time multithreaded processing
engines, to SSE, to CUDA, to parsers and code generators, to the web,
on both the backend and the frontend...I am a true "full-stacker", to use a modern term.
Or am I?
I haven't done VHDL now, have I? :-)
## Let's make a UART
I started by watching three magnificent introductory videos
by Nick Williams:- https://www.youtube.com/watch?v=pDE2qenDXKQ
- https://www.youtube.com/watch?v=uhxTgUSZvYE
- https://www.youtube.com/watch?v=yoytRxOjA-AI then spent the next 3 weekends, sitting down with a trusty XC3S1000 and
the free Xilinx ISE WebPACK. and moved from example to example, learning
about signals and processes and state machines.And at some point, I connected the TX and RX pins of my PL2303HX USB/TTL to
the GPIO pins of my FPGA board, and decided to write UART transmitting and
receiving of my own.---> .------> .------> ---> .----->
| | | | | | |Stop bit
| | | | | | |
| | | | | | |
| | | | | | |
| | Bit 0 | Bit 1 | Bit 2 | ... |Bit 7 |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
'------> '------> '--- '------>
Start bit ^
|
Samples must be taken in the middle of the pulses --'UARTs follow a very simple protocol; with one start bit pulling down the
line to the LOW voltage, then the N bits of the octet, then one or
two stop bits (8N1 or 8N2), pulling the line back UP.It turned out that transmitting serial data was child's play - I completed
it within a couple of hours, and it pretty much worked on the first try.
I simply had to count the appropriate number of cycles per baud,
so that I would transmit to my GPIO output pin at the appropriate
frequency: I chose 115200 baud as my target, so for my 48MHz FPGA,
I waited for...48000000/115200 =~ 416 cycles
...per baud.
Receiving however, and decoding properly, was another matter altogether,
The circuit had to synchronize to the droping of the start bit, so that
part of the circuit had to
[run at full speed (48MHz)](Example2.vhd#L643) -
whereas after the sync, it had to sample the 8 data bits
[at their middle](Example2.vhd#L660)
(so, running at the baud rate, with a phase shift).And the samples themselves have noise, which
[must be filtered](Example2.vhd#L521) out.All these seem simple, basic rules in hindsight - but it's a quite different
thing when you are discovering them on your own, as issues arise...
I started with a simple mirror of the TX circuit, which seemed to work...
until I started blasting data to it at full speed - and then it
emitted gibberish. Probing with my bitscope I saw that the sent values were
fine, so the bug was in my VHDL code - but how do you debug HW? So I learned
to do simulation in ISim, and saw my errors... I realized I had to sync to
the first drop (the start bit) at full speed, and then that I must save
the [decoded data in a FIFO](Example2.vhd#L686)
to decouple the C driver code that reads from the VHDL code that writes...And that that FIFO writing must be
[strobed at full speed](Example2.vhd#L583)...All in all, fascinating stuff.
## Conclusion
In the end, I made it work - you can have a look at my code and see how
I solved the various issues. I chose to use my board's register interface
in the end (even though I begun with the streaming one), since that gave
me more control over what happens and when. It's good to know both of
them, though.I have experienced mind-bending plenty of times...
- when I first learned LISP macros
- when I realized the power of compile-time checked discriminated unions
- when I wrote my first AST processor and code generator
- when I learned to think in functional style...
- etcWell... VHDL was yet another mind bend.
Totally worth it - nothing like it.