A more simple UART tutorial


earlz

Recommended Posts

Hello, I saw the stickied (and locked) post at the top of this board about using the UART.

I'm not sure if I'm the only one interested or not, but I'd really like a bit of a walk through in developing a slow (9600bps or w/e) UART interface with the onboard FTDI. I saw the Xilinx "best" code, but honestly what person learning VHDL is going to be able to comprehend it. And I believe this way of teaching compromises the "open" nature of the papilio because of the crippled(with licenses) code used. So basically, people learning VHDL and wanting to create an open source core can't with the currently provided tutorial

Also, as a side note please more written tutorials and less screen casts. I like skimming, and skimming with video is impossible.

Link to comment
Share on other sites

Basically it goes like this (my preferred approach):

Oversampling

Choose a nice oversampling (like 16x or 32x). Use a majority voting filter on these values to output if you have a '0' or a '1' - meaning if in last 16 samples we saw more ones than zeros, output '1' else output '0'. The oversampling factor will influence the baud rate generator. I'll explain further on how this works.

Baud Rate Generator

The baud rate generator should output a '1' at each baud frequency, multiplied by the oversampling factor. This signal is used as an enable signal for the receiver unit.

In addition to this, a oversampling divider is connected to this enable signal, and outputs the baud rate to the transmitting unit. So, RX enable signal is 32x or 16x times faster than TX signal. The TX signal must match the correct baud rate. In order to implement these baud rates, use a counter you can preset and which counts down to 0, outputs the enable signal, then reloads.

Transmit

Have a transmit unit with a few bytes FIFO. One would do it, so you can queue another byte while one is still in the transmission line.

Receiver

Have a large RX fifo if you can afford it.

You can take a look at how ZPUino implements its UART:

https://github.com/alvieboy/ZPUino-HDL/tree/fb9841bb06cb337010e89c7708db12393fd6901a/zpu/hdl/zpuino

See tx_unit.vhd, uart_brgen.vhd, zpuino_uart.vhd, zpuino_uart_mv_filter.vhd and zpuino_uart_rx.vhd

Alvie

Link to comment
Share on other sites

if you just want a toy uart to learn, you can even make it more simple. Warning : not reliable enough for production !

Output is the same, but you can do without a FIFO, just showing a "ready" bit in your interface. You'll lose some time polling between bytes (the overall transmit rate will be lower), but that's not really a problem for simple debug/test output. I do it this way: when a byte is written, set a shift register to "1"&byte&"0". Output the low bit for the number right of clock cycles (same as oversampling) and shift right, repeat 10 times for the 10 bits.

Input is trickier. Alvieboy's way is the right way, but a more simple method gives decent results: supposing the signal has good quality, you just need look at the middle of each bit (where the signal is the most stable)

So, waiting for data, you keep an eye on the input bit bit and, when it goes low, you start a counter, which looping at (oversampling). Every time it reaches (oversampling/2), you pick a bit and put it at the bottom of a shift register. Repeat 9 times (start bit+8 data bits) and you're done. You can also check that the 10th bit (stop bit) is 1.

Again, you can drop the FIFO : set the output to the content of the shift register, and a "data ready" bit. If you poll it often enough, you will not lose data.

You can find an implementation of the output in the Sega Master System project, and an implementation of both (tx and rx) in my Forth project.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.