6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 10, 2024 11:00 am

All times are UTC




Post new topic Reply to topic  [ 33 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: UART receiver
PostPosted: Sun Aug 04, 2024 5:26 pm 
Offline

Joined: Tue Jul 30, 2024 6:20 pm
Posts: 73
I just implemented a simple UART transmitter (10 flops + timing generator), and am looking at the receiver. As a compulsive minimalist, I am offended by the elaborate and enormous 'examples' I've seen. The receiver seems trickier than the transmitter register, but is it really?

I believe that modern devices are likely to have very stable timing, so things like 16x oversampling (or any oversampling) is an overkill. A straightforward shift register with a 1/2-bit start delay should stay in sync for the remaining 8 bits.

So the tricky parts:
* detect 1-0 start bit transition (and ignore other such transitions), which requires two states - idle and busy, and the associated counter for asserting the busy state while shifting;
* set the timing counter to 1/2 the total baud-rate count, to assure sampling mid-bit;
* enable the shift register and busy-state bit and bit counter;
* don't forget to shift out the start bit (count to 8 to 0?)
* upon transition to idle, stop shifting, buffer the data and signal 'data ready'
* if you want to be fancy, check for stop bit and signal 'framing error'

This seems pretty minimal.

Does anyone have experience implementing UARTs for FPGAs?

TLDR: got something working here:
https://tildegit.org/stack/Tangnano9K-UART


Last edited by enso1 on Mon Aug 05, 2024 7:49 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Sun Aug 04, 2024 6:11 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10976
Location: England
There's a simple UART (a page of verilog) in the OPC project (which is GPL-licensed although the file has no comment to that effect.) It's probably the work of hoglet, or possibly revaldinho.
https://github.com/revaldinho/opc/blob/ ... src/uart.v


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Sun Aug 04, 2024 6:21 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
Also, Bill Shen (Plasmo here and on RetroBrew) has implemented a UART in the Altera EPM7064S... he uses it on his CRC65. You can find his project here:

https://www.retrobrewcomputers.org/doku ... rc65r2home

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Sun Aug 04, 2024 6:40 pm 
Offline

Joined: Tue Jul 30, 2024 6:20 pm
Posts: 73
OPC's UART is pretty compact. My transmitter is a bit shorter and simpler, I think. I think I could live with OPC's receiver...

@floobydust, I think the link you sent me does not have a UART -- on the schematic, at least, it only shows an I2C port...

verilog can be misleading -- a page of verilog can potentially generate an enormous circuit! It's pretty easy to miss things like unhandled conditions which generate tons of latches, etc.


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Sun Aug 04, 2024 6:58 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
I built up one of Bill's original CRC65 boards... and it's running as a UART at 115,200 N-8-1 via a USB/UART adapter. Perhaps looks at the build files... which requires the older Quartus II tooling.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Sun Aug 04, 2024 7:38 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8538
Location: Southern California
enso1 wrote:
I believe that modern devices are likely to have very stable timing, so things like 16x oversampling (or any oversampling) is an overkill. A straightforward shift register with a 1/2-bit start delay should stay in sync for the remaining 8 bits.

I always understood that to be for "taking a vote" of samples in order to get over noise that could get into the line, rather than trying to correct timing instabilities.  I imagine it wouldn't really be a problem for the uses most of us put the UART to.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Sun Aug 04, 2024 8:10 pm 
Offline

Joined: Fri Dec 21, 2018 1:05 am
Posts: 1114
Location: Albuquerque NM USA
This is the UART receiver I used for several years. It is in Altera schematic, about 20 flip flops. It does have 16X clock and sample in mid-bit.
Bill
download/file.php?id=14303&mode=view

Schematic is from the CPLD trainer topic, viewtopic.php?f=10&t=6974&p=90671&hilit=74165#p90670


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 2:58 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
GARTHWILSON wrote:
I always understood that to be for "taking a vote" of samples in order to get over noise that could get into the line, rather than trying to correct timing instabilities.  I imagine it wouldn't really be a problem for the uses most of us put the UART to.

The sampling algorithm’s purpose is to attempt to mask differences in the transmit and receive timing, which may make spacing between consecutive bits in a frame look longer or shorter to the receiver than to the transmitter.  Compensating for such differences becomes quite important at high bit rates.

A TIA-232 link operating at nominal voltages (±12 volts) is actually quite immune to noise, assuming reasonable cable routing and in-spec line drivers.

Typically, 1× sampling would be used in synchronous serial, since both stations are being clocked from the same source.  1× sampling would not, as a fairly general rule, be used in async serial due to inevitable timing variations at each end.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 4:44 am 
Offline
User avatar

Joined: Sun Dec 29, 2002 8:56 pm
Posts: 460
Location: Canada
I have what is supposed to be a 6551 compatible uart. It is about as complex as need be. It does sampling and majority logic on the bit receive. It also has fifos. It is <400 LUTs. There are a couple of top level interfaces, one with component discovery.

An issue with the timing is that the hosts and device clocks may not be exactly the same rate. So for a long stream of bits I think the 16x(or 8x) clock with resyncing is needed.

https://github.com/robfinch/Cores/tree/master/uart6551/trunk

_________________
http://www.finitron.ca


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 6:45 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 954
Location: Potsdam, DE
I've implemented successful UART receivers using just a timer in software running at four times the baud rate. The clock testing the receive start bit has to happen multiple times during each bit to allow a close hit to the centre of the start bit; that's then doing the sampling in the middle of successive bits by using a single bit delay after the initial start.

Running the clock at 16x baud means the first bit will be within 1/16th of the centre, and successive bits can be 2.5% fast and still hit in the active part of the sample on the last bit. 4x baud has tighter timing requirements for the transmitter.

If you're detecting the falling edge of the start bit, then you can use a x2 clock (or a simple delay) to find the centre of the first bit. The x16 is used - as Garth indicates - to give best-of-three centre samples in hardware which does such things. I've never found it necessary; as also pointed out above, we tend to use short cable runs in generally noise free environments, and in most cases I suspect using serial-usb adaptors which are effectively tied to the 24MHz USB clock; drift is not an option. I don't usually bother with frame error detection; it just doesn't happen on such systems.

What you do need to remember is that the two clock rates have to be within +/- 2.5% for the sampling to work for the last bit and the stop bit. That is independent of the baud rate...

Neil


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 6:59 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10976
Location: England
Just a note on matching or mismatching clock rates at sender and receiver
- crystals are really very accurate
- but sometimes a pragmatic design takes a high frequency and divides it down to something rather near to the ideal value. This clock will be precisely inaccurate.
- sometimes we encounter bit-banged senders or receivers, which can only manage some approximation of ideal timing


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 8:21 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1485
Location: Scotland
Never having built an FPGA UART, I have had very good results implementing serial Rx/Tx in software - bit-banged in the output, timed sampling on the input. Results have been good to 19200 baud on a 2Mhz system. It does need good timing loops and cycle counting though.

I don't think my code has been anything special - no oversampling:

Wait for the next High to Low transition (Don't bother checking for line idle for any time, just the next High to Low to indicate a potential start bit)

Delay 1.5 bit times.

Repeat 8 times:
- Read input pin, shift into input register
- Delay one bit time

Do a final read of the input pin - if it's not High then we have a framing error

And that's basically it.

I know of one that will read data at 115200 baud on a 2Mhz 6502 but the code is quite special for that as timings are vanishingly small at that rate.

If I were doing it in hardware, then the hardware doesn't need to check parity or framing - just present the data to the program doing the reading. So a bit goes high in the status register after you clock in those 8 bits to indicate "ready" (bit is cleared on a data register read) Another bit is simply the 9th bit - the stop bit (so if software reads it high then it can simply ignore the data and read another byte) Parity can be calculated by feeding the input bits through an XOR stage and present the output as another bit in the status register - again hardware doesn't need to check as the software can check the polarity of that bit against what's expected.

Maybe this makes for a far-too-simple UART but for simple console/terminal IO do you need more?

I can download code into my 6507 SBC with a software UART without any real issues, although with no flow control I need to reduce the baud to 9600 and get the sending program to delay at each CR sent but that's all that's needed for me here.

So it'll be time vs effort at the end of the day, I suspect.

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 1:51 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
Rob Finch wrote:
An issue with the timing is that the hosts and device clocks may not be exactly the same rate. So for a long stream of bits I think the 16x(or 8x) clock with resyncing is needed.

That’s what I said.  :D

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 3:26 pm 
Offline

Joined: Tue Jul 30, 2024 6:20 pm
Posts: 73
Thank you for informative responses!

My own clock is actually 27MHz, with a count of 234 the baud rate comes out as 115384.6, close enough for rock and roll. At some point I'll get a PLL working, and if I had to I could jitter out the UART clock to correct, but whatever. I should probably do the math to figure out how much of an error I can take, but I really think starting midway I can get 8 bits in consistently (especially since I am talking to a very specific chip on-board.

I'm also not concerned with noise, as the RS-232 signal has to travel about 8mm to the USB chip. The USB chip, btw, is a blackboxed RISC-V SOC pretending to be one of those cheap USB-serial chips. I guess they can make those even cheaper!

I'll report when I get something working.


Last edited by enso1 on Mon Aug 05, 2024 3:45 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: UART receiver
PostPosted: Mon Aug 05, 2024 3:32 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
BigEd wrote:
Just a note on matching or mismatching clock rates at sender and receiver
- crystals are really very accurate...

They can be, assuming operating conditions (ambient, applied voltage, etc.) are reasonable.  Something to consider is as crystals age, they will permanently drift from nominal frequency.  High-quality crystals are artificially aged by storing them at elevated temperatures for some period of time prior to being encapsulated.

In my POC V1.3 unit, the system jiffy IRQ, which ultimately is responsible for maintaining the date and time-of-day (ZULU time), is generated by the counter/timer in one of the DUARTs, which, in turn, is clocked by a 3.6864 MHz oscillator whose output is divided down to generate a 100 Hz IRQ that maintains the system timers to a resolution of one centisecond.  Being curious about how stable my system is or isn’t, I’ve written a program that is able to copy UNIX time from my Linux file-and-print server to my POC V1.3 unit, convert UNIX time to the binary sequential time format used in V1.3, and then compare the two.  The Linux machine’s timekeeping is synced to several stratum-2 time servers to maintain stability.

Working with that, I’ve determined that V1.3’s time drift appears to average about 2.0 seconds per 30-day period when using a 100 PPM oscillator to clock the DUARTs.  I have also tested with a 50 PPM oscillator, which slightly improved drift to 1.8 seconds per 30-day period.¹  In both cases, these time drift values are better than what my Linux software development server can maintain with the ntpd time service daemon disabled and time accuracy solely dependent on the stability of the PIT that generates jiffy IRQs.

The relatively-small improvement seen with the 50 PPM oscillator implies that the 100 PPM part was running well below 100 PPM.  The accuracy of oscillators in our machines is obviously not critical.  However, it is interesting to observe the effects of their tolerances and drift.

Quote:
- sometimes we encounter bit-banged senders or receivers, which can only manage some approximation of ideal timing

As Neil noted, async serial transmission has an approximate ±2.5 percent tolerance.  I’d expect that a well-written bit-bang serial driver could do that, assuming the system on which it is running has a good time reference.  That said, a UART is a whole lot less trouble, and not the burden on the MPU that is a bit-bang serial driver.

————————————————————
¹By “drift,” I meant to say V1.3 loses time with either oscillator, which means they are running a tad below nominal frequency.  Someday I may be motivated to measure actual frequency to see how much it is off.  It’s not anything over which I am losing sleep.  :D

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Last edited by BigDumbDinosaur on Mon Aug 05, 2024 10:23 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 33 posts ]  Go to page 1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: