UART recommendation? Verilog/VHDL, supports 2 stop bits - Page 1
Forum section: electronics / general

author: ebastler
author_rank: Super Contributor
timestamp: September 17, 2024, 10:09:44 am
content: For a serial interface to legacy systems, I am looking for a UART softcore which can support 2 stop bits when transmitting. I have happily used Ken Chapman's UART for Xilinx FPGAs so far, which is amazingly compact, works well, but is fixed at 8 bits, 1 stop bit.(https://userpages.cs.umbc.edu/tinoosh/cmpe650/slides/UART_Manual.pdf)Any recommendations for a free UART core that works robustly (samples properly on the receiver side), is not totally over-engineered, but has the flexibility to support either 1 or 2 stop bits? I will use this on a Spartan-6, but any VHDL or Verilog core should be adaptable. Thanks!

author: woofy
author_rank: Frequent Contributor
timestamp: September 17, 2024, 10:21:30 am
content: This one looks as if it meets your spec'https://www.fpga4fun.com/SerialInterface.html

author: ebastler
author_rank: Super Contributor
timestamp: September 17, 2024, 10:49:15 am
content: That does look like a great fit indeed. Fixing the transmitter to 2 stop bits while the receiver is happy with just one gives me all the flexibility I need. Thank you very much!Why didn't I find that one? I have used stuff from fpga4fun before -- their TMDS decoder works nicely to generate HDMI output directly from the FPGA, in this very same project of mine...

author: BrianHG
author_rank: Super Contributor
timestamp: September 18, 2024, 12:24:02 pm
content: Quote from: ebastler on September 17, 2024, 10:09:44 amYou can modify my transmitter to 2 stop bits as well. The receiver doesn't care:Here:https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/and here:https://github.com/BrianHGinc/Verilog-RS232-Synch-UART-RS232-Debugger-and-PC-host-RS232-Hex-editor?tab=readme-ov-fileIt supports synchronous clock re-sync and generation.Every line of my source code is documented thoroughly for everyone.Just look for the tx_positionand rx_position, they just need to be increased by 1.

author: AussieBruce
author_rank: Regular Contributor
timestamp: September 23, 2024, 10:29:42 am
content: Agree, simple and transparent, except Jeans code for baud generation has me beat, have spent ages trying to figure out how it works. I tried to simply calculate a counter target value offline for my desired rate, and run the baud generator as a simple timer loop, but the result was garbage.

author: ebastler
author_rank: Super Contributor
timestamp: September 23, 2024, 10:37:08 am
content: Quote from: AussieBruce on September 23, 2024, 10:29:42 amHmm... I continued to use the baud rate generation and RX part with 16-byte buffer from Ken Chapman's UART, and just replaced the TX part with the 2-stop-bit transmitter from fpga4fun. The baud rate clock it expects is one logic-high tick (lasting for the duration of the main clock period) for every bit time. I.e. a bit-rate clock with a very low duty cycle. I just divided Ken's 16x baud rate, which is still needed for the receiver, down with another 4-bit counter to dorive the new transmitter.Edit: I had to modify the transmitter's state machine as well. As downloaded, it started sending the start bit as soon as I trigger a transmission -- which may be in the middle of a bit-clock period, resulting in a start bit that is too short. I had to add another "wait for next bit tick, then start" state which is active before the transmission actually starts.(It looks like this was originally planned already: There was an unused state 0001 readily available for that purpose. Not sure why it was removed in the published code; maybe Jean last used the TX in a context where the transmission trigger was always in sync with the bit clock?)Code:reg [7:0] TxD_shift = 0;always @(posedge clk)beginif (TxD_ready & TxD_start)TxD_shift <= TxD_data;else if (TxD_state & BitTick)TxD_shift <= (TxD_shift >> 1);case (TxD_state)4'b0000: if (TxD_start)TxD_state <= 4'b0001;4'b0001: if (BitTick)TxD_state <= 4'b0100; // wait for BitTick to get in sync4'b0100: if (BitTick)TxD_state <= 4'b1000; // start bit4'b1000: if (BitTick)TxD_state <= 4'b1001; // bit 04'b1001: if (BitTick)TxD_state <= 4'b1010; // bit 14'b1010: if (BitTick)TxD_state <= 4'b1011; // bit 24'b1011: if (BitTick)TxD_state <= 4'b1100; // bit 34'b1100: if (BitTick)TxD_state <= 4'b1101; // bit 44'b1101: if (BitTick)TxD_state <= 4'b1110; // bit 54'b1110: if (BitTick)TxD_state <= 4'b1111; // bit 64'b1111: if (BitTick)TxD_state <= 4'b0010; // bit 74'b0010: if (BitTick)TxD_state <= 4'b0011; // stop14'b0011: if (BitTick)TxD_state <= 4'b0000; // stop2default: if (BitTick)TxD_state <= 4'b0000;endcaseendassign TxD = (TxD_state<4) | (TxD_state & TxD_shift); // put together the start, data and stop bits

author: Nominal Animal
author_rank: Super Contributor
timestamp: September 23, 2024, 11:02:33 am
content: Quote from: AussieBruce on September 23, 2024, 10:29:42 amI can help you with that: it's the plain old accumulator-basedpulse density modulation.If you have clock source with \$F\$ pulses per second, and an \$n\$-bit accumulator with the most significant bit being the output clock, then accumulator value \$a\$ generates \$f\$ pulses per second at approximately 50% duty cycle:$$f = F \frac{a}{2^{n-1}} \quad \iff \quad a = \left\lceil \frac{f}{F} 2^{n-1} \right\rfloor$$To understand how it works, start by considering the purely mathematical model where \$a\$ is a real number, \$0 \lt a \le 1\$, and we have an infinite precision accumulator, so that \$f = F a\$ and \$a = f / F\$. Whenever the integer part of the accumulator is odd, the output state is high, and whenever the integer part is even (and zero is considered even), the output state is low.When \$a\$ is 1, the accumulator varies between odd and even every clock cycle, so \$f = F\$, right?When \$a\$ is say \$1/2 = 0.5\$, the accumulator varies between odd and even every second clock cycle, so \$f = F/2 = 0.5 F\$.When \$a\$ is say \$1/5 = 0.2\$, the accumulator varies between odd and even every fifth clock cycle, so \$f = F/5 = 0.2 F\$.Now, instead of a real \$a\$, consider \$a\$ a fixed point number with \$n-1\$ fractional bits –– because that's exactly what we have here. Instead of a real value, you have a fixed point value \$a / 2^{n-1}\$ approximating the desired real value. Overflow bits are discarded, and that corresponds to themodulooperation in Jean's math.The jitter in the generated pulse sequence is one clock cycle, in that high and low states may vary by one clock. With a constant \$a\$, it gives the optimal sequence –– smallest timing errors –– between the synthesized PDM output and the desired output, if you start with perfectly aligned pulse edge. All you need to do, is add \$a\$ to the \$n\$-bit accumulator once every clock cycle, and use the most significant bit of the result as the output.Edited to add after seeing ebastler's post:If you want just a one-clock cycle pulse whenever the PDM outputtransitions, use one bit less and the overflow bit as the output. That gives you two one-clock-cycle long pulse per period. For one clock cycle long pulse per period, use \$n\$ bits, \$2^n\$ divisor above, and the overflow bit as the output. This is equivalent to halving \$a\$ and clearing the output bit just before every addition (because it isn't stored!), and generates the desired one-clock-cycle-long pulse at \$1/f\$ intervals.