Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Smallest GPL UART

277 views
Skip to first unread message

Giuseppe Marullo

unread,
Apr 29, 2012, 2:04:23 PM4/29/12
to
Hi all,
I am searching for the smallest/simpler UART in verilog. I need to
release the project under GPL and still confused about what are my options.

I would go with micro UART by Jeung Joon Lee but I am unable to
determine its license.

There are others, like osvudu by Timothy Goddard seems released under
(a) MIT license, thus compatible with GPL.

I need very simple stuff:

baud rate 9600-115200 with a clock of about 100MHz but should be able to
run with other clocks, like 12MHz. No buffers and other fancy stuff.

8N1, and possibility (I need some) to have rtx, tx and rx only
capability (I would like to instantiate just the parts I need).

Don't know if I need fullduplex, possibly yes.

What would you advice to use?

Thanks in advance.

Giuseppe Marullo

Andy Bartlett

unread,
Apr 29, 2012, 2:18:24 PM4/29/12
to

"Giuseppe Marullo" <giuseppe.ma...@iname.com> wrote in message
news:jnjvra$1fa$1...@speranza.aioe.org...
Why not roll your own? For the simple case you have specified it will take
less than half a day and the ip is all yours.

I'm am constantly amazed by people scratching around for cheap or free ip
when it would actually be quicker and more efficient to DIY!

Andy


Giuseppe Marullo

unread,
Apr 29, 2012, 5:00:45 PM4/29/12
to
> Why not roll your own? For the simple case you have specified it will take

Thank you Andy, but I need to concentrate on other things, I would pass
on serial stuff if I can this time.

Giuseppe Marullo



Tim Wescott

unread,
Apr 29, 2012, 6:37:50 PM4/29/12
to
I second that. I only an FPGA hacker, and yet an NSUART (not-so
universal asynchronous receiver transmitter) is a fairly easy proposition.

In fact: here: One serial interface. Easy, simple, and as an added
bonus, free of any confusing comments. I'm pretty sure this was for a
25MHz clock and a baud rate of 9600 -- but, since it lacks those comments
that might mislead, you'll have to figure that out yourself:

`define IDLE_BIT 0

`define START_BIT 1

`define DATA_BIT 2

`define STOP_BIT 3



module asyncTx(clock, reset, data, write, txd, rts, empty);

parameter baudDiv = 11'd1280;

input clock;

input reset;

input [7:0] data;

input write;

output reg txd;

output reg rts;

output reg empty;



reg [7:0] shift;

reg [2:0] count;

reg [1:0] state;

reg [10:0] baud;



always @ (state) empty = state == `IDLE_BIT;



always @ (posedge reset or posedge clock)

begin

if (reset)

begin

rts <= 0;

txd <= 1;

empty <= 1;

state <= `IDLE_BIT;

baud <= baudDiv - 1;

end

else

begin



if (state != `IDLE_BIT) baud <= baud ? baud - 1 : baudDiv - 1;

case (state)

`IDLE_BIT:

if (write)

begin

state <= `START_BIT;

shift <= data;

count <= 7;

end



`START_BIT:

if (!baud)

begin

txd <= 0;

state <= `DATA_BIT;

end



`DATA_BIT:

if (!baud)

begin

txd <= shift[0];

shift <= {1'bx, shift[7:1]};

count <= count - 1;

if (!count)

begin

state <= `STOP_BIT;

end

end



`STOP_BIT:

if (!baud)

begin

txd <= 1;

state <= `IDLE_BIT;

end

endcase

end

end

endmodule



module asyncRx(clock, reset, rxd, read, data, frameError, overflow,
ready);

parameter baudDiv = 7'd80;



input clock;

input reset;

input rxd;

input read;

output reg [7:0] data;

output reg frameError;

output reg overflow;

output wire ready;



reg intReady;

reg [2:0] rxdBuff; // shift register to prevent metastability

reg [2:0] count; // bit count (0-7)

reg [1:0] state; // receiver state

reg [6:0] baud; // baud rate * 16 register

reg [3:0] subBaud; // baud rate reg



wire rxdBit;



assign rxdBit = rxdBuff[2];

assign ready = intReady;



always @ (posedge reset or posedge clock)

if (reset)

begin

state <= `IDLE_BIT;

rxdBuff <= 0;

data <= 0;

count <= 7;

baud <= baudDiv - 1;

subBaud <= 15;

overflow <= 0;

intReady <= 0;

frameError <= 0;

end

else

begin

rxdBuff <= {rxdBuff[1:0], rxd}; // shift for metastability
prevention

if (baud) baud <= baud - 1;

else

begin

baud <= baudDiv - 1;

if (state != `IDLE_BIT) subBaud <= subBaud - 1;

end



if (read && intReady)

begin

intReady <= 0;

frameError <= 0;

overflow <= 0;

end



case (state)

`IDLE_BIT:

if (!rxdBit)

begin

state <= `START_BIT;

subBaud <= 15;

end



`START_BIT:

begin

if (!baud && subBaud == 8)

begin

if (rxdBit)

begin

overflow <= intReady;

if (!intReady) intReady <= 1;

frameError <= 1;

state <= `IDLE_BIT;

end

end



if (!baud && subBaud == 0)

begin

state <= `DATA_BIT;

count <= 7;

end

end



`DATA_BIT:

begin

if (!baud && subBaud == 8)

begin

data <= {!rxdBit, data[7:1]};

end



if (!baud && subBaud == 0)

begin

if (count == 0)

begin

state <= `STOP_BIT;

end

count <= count - 1;

end

end



`STOP_BIT:

begin

if (!baud && subBaud == 8)

begin

if (!rxdBit)

begin

frameError <= 1;

state <= `IDLE_BIT;

end

overflow <= intReady;

if (!intReady) intReady <= 1;

end



if (!baud && subBaud == 0)

begin

state <= `IDLE_BIT;

end

end

endcase

end



endmodule





--
My liberal friends think I'm a conservative kook.
My conservative friends think I'm a liberal kook.
Why am I not happy that they have found common ground?

Tim Wescott, Communications, Control, Circuits & Software
http://www.wescottdesign.com

Nico Coesel

unread,
Apr 29, 2012, 8:22:50 PM4/29/12
to
There is a very simple UART packed togethet with Xilinx's KCPSM. I
agree with the others. Open Source UARTs are not always the best
solution. I once used the 16550 UART from opencores but it is pretty
crappy. Very slow due to an overly complex design.

--
Failure does not prove something is impossible, failure simply
indicates you are not using the right tools...
nico@nctdevpuntnl (punt=.)
--------------------------------------------------------------

Frank Buss

unread,
Apr 30, 2012, 1:58:17 AM4/30/12
to
Giuseppe Marullo wrote:

> I am searching for the smallest/simpler UART in verilog. I need to
> release the project under GPL and still confused about what are my options.

This was one of my first projects for learning VHDL:

http://www.frank-buss.de/vhdl/spartan3e.html

Most programs can use VHDL and Verilog, so I guess you could integrate
it in your Verilog project. I released it under the BSD License, so do
whatever you want with it, but mention me as an author.

You should add a (clocked) input latch to the rx signal for the
receiver, to avoid metastability problems. Something I learned the hard
way years ago, by searching mysterious and rare occuring events, which
resulted in invalid state machine states.

--
Frank Buss, http://www.frank-buss.de
electronics and more: http://www.youtube.com/user/frankbuss

Tim Wescott

unread,
Apr 30, 2012, 1:17:28 PM4/30/12
to
On Mon, 30 Apr 2012 00:22:50 +0000, Nico Coesel wrote:

> Giuseppe Marullo <giuseppe.ma...@iname.com> wrote:
>
>>Hi all,
>>I am searching for the smallest/simpler UART in verilog. I need to
>>release the project under GPL and still confused about what are my
>>options.
>>
>>I would go with micro UART by Jeung Joon Lee but I am unable to
>>determine its license.
>>
>>There are others, like osvudu by Timothy Goddard seems released under
>>(a) MIT license, thus compatible with GPL.
>>
>>I need very simple stuff:
>>
>>baud rate 9600-115200 with a clock of about 100MHz but should be able to
>>run with other clocks, like 12MHz. No buffers and other fancy stuff.
>>
>>8N1, and possibility (I need some) to have rtx, tx and rx only
>>capability (I would like to instantiate just the parts I need).
>>
>>Don't know if I need fullduplex, possibly yes.
>>
>>What would you advice to use?
>
> There is a very simple UART packed togethet with Xilinx's KCPSM. I agree
> with the others. Open Source UARTs are not always the best solution. I
> once used the 16550 UART from opencores but it is pretty crappy. Very
> slow due to an overly complex design.

A design that did a good job of emulating the 16550 would have to be a
lot more complex than just a good asynchronous receiver-transmitter.
pair. Particularly if you can hard-code the division ratio, bit count,
etc., they are easy-peasy thing to write.

Certainly "overly complex" if you just need a serial interface -- but
maybe not so if you must have compatibility with existing software.

(Note: I don't know at what point in the process one loses the
"universal" moniker -- but hard-coding all the bits that are normally
software programmable would seem to be it).

Jan Coombs

unread,
Apr 30, 2012, 4:50:24 PM4/30/12
to
On 29/04/12 19:04, Giuseppe Marullo wrote:
> Hi all,
> I am searching for the smallest/simpler UART in verilog. I need to
> release the project under GPL and still confused about what are my
> options.

I have just completed a very simple UART model to communicate with
a FPGA dev board.

The package has been tested with an integrated test harness which
runs Tx & Rx back to back. Also tested in real hardware with a
CP2102 USB to serial adapter.

Requirements: Python with MyHDL package, see http://myhdl.org
Exports: VHDL or Verilog

Jan Coombs
--
(email valid at present)

Nico Coesel

unread,
Apr 30, 2012, 5:28:08 PM4/30/12
to
I designed a 16550 clone before and trust me: it was waaaaaaaaaay more
simple and faster than the one from Opencores. The one I designed is
running in over 10.000 products 24/7. The thing is that you can't take
designs from one employer to the other.

Where the Opencores design failes is using two clocks and asynchronous
FIFOs. Besides that the I/O for the registers is also asynchronous
while it doesn't need to be.

Giuseppe Marullo

unread,
Apr 30, 2012, 7:47:17 PM4/30/12
to
Jan, Frank, Tim, Nico and Andy,
many thanks for your answer. I would like to stick with Verilog, at the
moment I am trying with the following code:

// Documented Verilog UART
// Copyright (C) 2010 Timothy Goddard (t...@goddard.net.nz)
// Distributed under the MIT licence.
//
// Permission is hereby granted, free of charge, to any person obtaining
a copy
// of this software and associated documentation files (the "Software"),
to deal
// in the Software without restriction, including without limitation the
rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
module uart(
input clk, // The master clock for this module
input rst, // Synchronous reset.
input rx, // Incoming serial line
output tx, // Outgoing serial line
input transmit, // Signal to transmit
input [7:0] tx_byte, // Byte to transmit
output received, // Indicated that a byte has been received.
output [7:0] rx_byte, // Byte received
output is_receiving, // Low when receive line is idle.
output is_transmitting, // Low when transmit line is idle.
output recv_error // Indicates error in receiving packet.
);

//parameter CLOCK_DIVIDE = 1302; // clock rate (50Mhz) / (baud rate
(9600) * 4)
parameter CLOCK_DIVIDE = 2604; // clock rate (100Mhz) / (baud rate
(9600) * 4) by G. Marullo
// parameter CLOCK_DIVIDE = 217; // clock rate (100Mhz) / (baud rate
(115200) * 4) by G. Marullo

// States for the receiving state machine.
// These are just constants, not parameters to override.
parameter RX_IDLE = 0;
parameter RX_CHECK_START = 1;
parameter RX_READ_BITS = 2;
parameter RX_CHECK_STOP = 3;
parameter RX_DELAY_RESTART = 4;
parameter RX_ERROR = 5;
parameter RX_RECEIVED = 6;

// States for the transmitting state machine.
// Constants - do not override.
parameter TX_IDLE = 0;
parameter TX_SENDING = 1;
parameter TX_DELAY_RESTART = 2;

reg [11:0] rx_clk_divider = CLOCK_DIVIDE;
reg [11:0] tx_clk_divider = CLOCK_DIVIDE;

reg [2:0] recv_state = RX_IDLE;
reg [5:0] rx_countdown;
reg [3:0] rx_bits_remaining;
reg [7:0] rx_data;

reg tx_out = 1'b1;
reg [1:0] tx_state = TX_IDLE;
reg [5:0] tx_countdown;
reg [3:0] tx_bits_remaining;
reg [7:0] tx_data;

assign received = recv_state == RX_RECEIVED;
assign recv_error = recv_state == RX_ERROR;
assign is_receiving = recv_state != RX_IDLE;
assign rx_byte = rx_data;

assign tx = tx_out;
assign is_transmitting = tx_state != TX_IDLE;

always @(posedge clk) begin
if (rst) begin
recv_state = RX_IDLE;
tx_state = TX_IDLE;
end

// The clk_divider counter counts down from
// the CLOCK_DIVIDE constant. Whenever it
// reaches 0, 1/16 of the bit period has elapsed.
// Countdown timers for the receiving and transmitting
// state machines are decremented.
rx_clk_divider = rx_clk_divider - 1'b1;
if (!rx_clk_divider) begin
rx_clk_divider = CLOCK_DIVIDE;
rx_countdown = rx_countdown - 1'b1;
end
tx_clk_divider = tx_clk_divider - 1'b1;
if (!tx_clk_divider) begin
tx_clk_divider = CLOCK_DIVIDE;
tx_countdown = tx_countdown - 1'b1;
end

// Receive state machine
case (recv_state)
RX_IDLE: begin
// A low pulse on the receive line indicates the
// start of data.
if (!rx) begin
// Wait half the period - should resume in the
// middle of this first pulse.
rx_clk_divider = CLOCK_DIVIDE;
rx_countdown = 2;
recv_state = RX_CHECK_START;
end
end
RX_CHECK_START: begin
if (!rx_countdown) begin
// Check the pulse is still there
if (!rx) begin
// Pulse still there - good
// Wait the bit period to resume half-way
// through the first bit.
rx_countdown = 4;
rx_bits_remaining = 8;
recv_state = RX_READ_BITS;
end else begin
// Pulse lasted less than half the period -
// not a valid transmission.
recv_state = RX_ERROR;
end
end
end
RX_READ_BITS: begin
if (!rx_countdown) begin
// Should be half-way through a bit pulse here.
// Read this bit in, wait for the next if we
// have more to get.
rx_data = {rx, rx_data[7:1]};
rx_countdown = 4;
rx_bits_remaining = rx_bits_remaining - 1'b1;
recv_state = rx_bits_remaining ? RX_READ_BITS[2:0] : RX_CHECK_STOP[2:0];
end
end
RX_CHECK_STOP: begin
if (!rx_countdown) begin
// Should resume half-way through the stop bit
// This should be high - if not, reject the
// transmission and signal an error.
recv_state = rx ? RX_RECEIVED[2:0] : RX_ERROR[2:0];
end
end
RX_DELAY_RESTART: begin
// Waits a set number of cycles before accepting
// another transmission.
recv_state = rx_countdown ? RX_DELAY_RESTART[2:0] : RX_IDLE[2:0];
end
RX_ERROR: begin
// There was an error receiving.
// Raises the recv_error flag for one clock
// cycle while in this state and then waits
// 2 bit periods before accepting another
// transmission.
rx_countdown = 8;
recv_state = RX_DELAY_RESTART;
end
RX_RECEIVED: begin
// Successfully received a byte.
// Raises the received flag for one clock
// cycle while in this state.
recv_state = RX_IDLE;
end
endcase

// Transmit state machine
case (tx_state)
TX_IDLE: begin
if (transmit) begin
// If the transmit flag is raised in the idle
// state, start transmitting the current content
// of the tx_byte input.
tx_data = tx_byte;
// Send the initial, low pulse of 1 bit period
// to signal the start, followed by the data
tx_clk_divider = CLOCK_DIVIDE;
tx_countdown = 4;
tx_out = 0;
tx_bits_remaining = 8;
tx_state = TX_SENDING;
end
end
TX_SENDING: begin
if (!tx_countdown) begin
if (tx_bits_remaining) begin
tx_bits_remaining = tx_bits_remaining - 1'b1;
tx_out = tx_data[0];
tx_data = {1'b0, tx_data[7:1]};
tx_countdown = 4;
tx_state = TX_SENDING;
end else begin
// Set delay to send out 2 stop bits.
tx_out = 1;
tx_countdown = 8;
tx_state = TX_DELAY_RESTART;
end
end
end
TX_DELAY_RESTART: begin
// Wait until tx_countdown reaches the end before
// we send another transmission. This covers the
// "stop bit" delay.
tx_state = tx_countdown ? TX_DELAY_RESTART[1:0] : TX_IDLE[1:0];
end
endcase
end

endmodule

I had to massage it a bit (a counter was some bits shorter than I
expected, arrgh), and with some warnings but seems to fit my needs. I
need up to 4 uarts in a small design, they need to connect the FPGA with
the pc(diagnostic), USB Host (2) from HobbyTronics for a USB stick and a
USB keyboard and a serial LCD display (Nice Stuff!).

All can run either 9600 or 115200, and some needs just tx or rx, so I
could run rtx, rx-only or tx-only versions.

Proably it could be fun to compare the several suggestions you offered
to decide which is better, but sadly I need to code several other stuff,
so if this one will work I would not furhter investigate at the moment.

I am testing with the pc, sending simple chars and getting them back
from the fpga sligtly modified.

Many thanks for the help you give me while I explore this hobby, I would
be really lost without this group.

Giuseppe Marullo

Frank Buss

unread,
May 1, 2012, 4:14:44 PM5/1/12
to
Giuseppe Marullo wrote:
> Jan, Frank, Tim, Nico and Andy,
> many thanks for your answer. I would like to stick with Verilog, at the
> moment I am trying with the following code:

Looks good, it uses the same idea I've used, sampling in the middle of a
bit after the start bit detection. This is not perfect, better receivers
use e.g. 8 times oversampling and a majority algorithm, but should work,
if your signal is not too noisy.

But you should latch the rx input, to avoid metastability problems. I
don't know how to do this in Verilog, something like declare another reg
with the name "rx", rename the raw input signal and copy it on rising
clock edge to "rx".

glen herrmannsfeldt

unread,
May 1, 2012, 5:17:58 PM5/1/12
to
Frank Buss <f...@frank-buss.de> wrote:

(snip)
> But you should latch the rx input, to avoid metastability problems. I
> don't know how to do this in Verilog, something like declare another reg
> with the name "rx", rename the raw input signal and copy it on rising
> clock edge to "rx".

Can you explain the problem that you are considering?

Not that slow logic can't have metastability problems,
but in this case I wouldn't expect it.

-- glen

Frank Buss

unread,
May 1, 2012, 6:46:56 PM5/1/12
to
glen herrmannsfeldt wrote:
> Frank Buss <f...@frank-buss.de> wrote:
>
> (snip)
>> But you should latch the rx input, to avoid metastability problems. I
>> don't know how to do this in Verilog, something like declare another reg
>> with the name "rx", rename the raw input signal and copy it on rising
>> clock edge to "rx".
>
> Can you explain the problem that you are considering?

http://www.altera.com/literature/wp/wp-01082-quartus-ii-metastability.pdf

> Not that slow logic can't have metastability problems,
> but in this case I wouldn't expect it.

My experience differs: I've used my simple UART receiver in a design
with 115,200 baud, and without the buffer, the state machine halted
(going to an invalid state, as I debugged with an "other" case branch,
which was logically impossible) once every some hour. There was lots of
high-speed logic behind the receiver and I've used only the classic
timing analyzer of an old version of Quartus, so maybe in simpler
designs, and with proper timing constraints for the rx signal, there
would be no problem.

But it is good design practice to buffer just any signal, which is fed
asynchronously to the FPGA, then you don't have such problems, even if
you didn't calculate and define all timing constraints.

Tim Wescott

unread,
May 1, 2012, 7:22:18 PM5/1/12
to
It might be a good practice to have that "other" case statement feeding a
master reset or some other more sensible response to a bad state than
wedging the FPGA, too.

Just sayin'

Hal Murray

unread,
May 1, 2012, 8:09:18 PM5/1/12
to
In article <jnpp51$2vn$1...@newsreader4.netcologne.de>,
Frank Buss <f...@frank-buss.de> writes:

>My experience differs: I've used my simple UART receiver in a design
>with 115,200 baud, and without the buffer, the state machine halted
>(going to an invalid state, as I debugged with an "other" case branch,
>which was logically impossible) once every some hour. There was lots of
>high-speed logic behind the receiver and I've used only the classic
>timing analyzer of an old version of Quartus, so maybe in simpler
>designs, and with proper timing constraints for the rx signal, there
>would be no problem.

It doesn't take metastability to do that. You will miss setup/hold
if the signal has different timing paths to different FFs. One
FF will see the old version of the signal and another FF will see
the new version.

--
These are my opinions, not necessarily my employer's. I hate spam.

glen herrmannsfeldt

unread,
May 1, 2012, 9:11:04 PM5/1/12
to
Tim Wescott <t...@seemywebsite.com> wrote:
> On Wed, 02 May 2012 00:46:56 +0200, Frank Buss wrote:
>> glen herrmannsfeldt wrote:
>>> Frank Buss <f...@frank-buss.de> wrote:

>>> (snip)
>>>> But you should latch the rx input, to avoid metastability problems. I
>>>> don't know how to do this in Verilog, something like declare another
>>>> reg with the name "rx", rename the raw input signal and copy it on
>>>> rising clock edge to "rx".

>>> Can you explain the problem that you are considering?

(snip)
>>> Not that slow logic can't have metastability problems,
>>> but in this case I wouldn't expect it.

>> My experience differs: I've used my simple UART receiver in a design
>> with 115,200 baud, and without the buffer, the state machine halted
>> (going to an invalid state, as I debugged with an "other" case branch,
>> which was logically impossible) once every some hour.

OK, I suppose I could have looked at the actual logic before writing.

Yes, if one isn't careful with a state machine, it can have
metastability problems even with a slow clock.

There is also that Quartus likes to rearrange state machines logic,
such that it isn't like it is written. Some years ago, I found a
bug in Quartus where it converted to a one-hot state machine even
though I was using the state value in the design. (It had four
states, and as written two state bits. Quartus converted to one-hot
and gave two of the four as state bits.)

>> There was lots of
>> high-speed logic behind the receiver and I've used only the classic
>> timing analyzer of an old version of Quartus, so maybe in simpler
>> designs, and with proper timing constraints for the rx signal, there
>> would be no problem.

>> But it is good design practice to buffer just any signal, which is fed
>> asynchronously to the FPGA, then you don't have such problems, even if
>> you didn't calculate and define all timing constraints.

Yes, if the design is such that more than one FF latches the same
input, and can fail if different values are latched on the same
clock cycle.

> It might be a good practice to have that "other" case statement feeding
> a master reset or some other more sensible response to a bad state than
> wedging the FPGA, too.

That seems to be the easy way to fix it.

Now, it is likely that one additional clock cycle won't affect much,
but one does have to consider that in terms of the overall logic.

-- glen

Frank Buss

unread,
May 2, 2012, 1:43:02 AM5/2/12
to
Right, this is slightly different from metastability, and maybe was the
reason for the behaviour in my FPGA program, though the bugfix is the
same :-)

Is there a technical term for this special kind of problem?

Arlet Ottens

unread,
May 2, 2012, 2:59:03 AM5/2/12
to
On 05/02/2012 12:46 AM, Frank Buss wrote:

>>> But you should latch the rx input, to avoid metastability problems. I
>>> don't know how to do this in Verilog, something like declare another reg
>>> with the name "rx", rename the raw input signal and copy it on rising
>>> clock edge to "rx".
>>
>> Can you explain the problem that you are considering?
>
> http://www.altera.com/literature/wp/wp-01082-quartus-ii-metastability.pdf
>
>> Not that slow logic can't have metastability problems,
>> but in this case I wouldn't expect it.
>
> My experience differs: I've used my simple UART receiver in a design
> with 115,200 baud, and without the buffer, the state machine halted
> (going to an invalid state, as I debugged with an "other" case branch,
> which was logically impossible) once every some hour. There was lots of
> high-speed logic behind the receiver and I've used only the classic
> timing analyzer of an old version of Quartus, so maybe in simpler
> designs, and with proper timing constraints for the rx signal, there
> would be no problem.

Usually these problems are the result of an incoming asynchronous
signal, like a UART RxD, going to two different inputs in the FPGA at
the same time.

When the signal has an undefined voltage right at the clock edge, one
input could capture it as a '0', and the other input as a '1',
potentially resulting in inconsistent states.

Note that this has nothing to do with metastability.

Stef

unread,
May 2, 2012, 3:10:39 AM5/2/12
to
In comp.arch.fpga,
Frank Buss <f...@frank-buss.de> wrote:
> Hal Murray wrote:
>>
>> It doesn't take metastability to do that. You will miss setup/hold
>> if the signal has different timing paths to different FFs. One
>> FF will see the old version of the signal and another FF will see
>> the new version.
>
> Right, this is slightly different from metastability, and maybe was the
> reason for the behaviour in my FPGA program, though the bugfix is the
> same :-)
>
> Is there a technical term for this special kind of problem?

Race condition


--
Stef (remove caps, dashes and .invalid from e-mail address to reply by mail)

Experience varies directly with equipment ruined.

lang...@fonz.dk

unread,
May 2, 2012, 5:13:15 PM5/2/12
to
one "universal" thing I almost always use when I need a uart in an
FPGA
is to generate the baudrate with a DDS

very simple and able to hit almost any baud rate at any clock rate

-Lasse

Andy

unread,
May 3, 2012, 8:14:48 AM5/3/12
to
Including a "when others => state <= reset"; will not help unless you
turn off state machine optimization, or invoke other "safe" state
machine synthesis settings. One of the optimizations most any
synthesizer worth its salt will do is remove "unreachable" states
(those states that do not have a coded assignment or path to them.)
Thus since "others" is not directly reachable, it gets optimized out,
along with anything it was doing.

There are multiple ways of dealing with this, most depend either on
invoking synthesis tool settings or turning off state machine
optimizations and manually handling it yourself in the RTL (such as
with a "when others". Be careful though; some of the simplest to code
methods result in the worst utilization and performance.

However, it is best to handle the root of the problem, which is an
improperly synchronized asynchronous input.

The term for this problem is not "race condition" it is an "improper
parallel synchronizer", or a circuit that clocks the same
asynchronous input into more than one register in parallel.

A "race condition" is when proper operation requires that one
combinatorial path must be faster than another.

Andy

Martin Thompson

unread,
May 3, 2012, 12:45:57 PM5/3/12
to
Tim Wescott <t...@seemywebsite.com> writes:

>> But it is good design practice to buffer just any signal, which is fed
>> asynchronously to the FPGA, then you don't have such problems, even if
>> you didn't calculate and define all timing constraints.

Mandatory, I'd say, unless you can make a cast-iron argument as to why it
doesn't matter if it is sampled differently by two different flops.

>
> It might be a good practice to have that "other" case statement feeding a
> master reset or some other more sensible response to a bad state than
> wedging the FPGA, too.

You'd think, wouldn't you?

But ( at least in VHDL) you also have to be aware that synthesis tools
(unless you do some hoop-jumping) are "clever" enough to "know" that you
can't get to those invalid states (especially in VHDL when using an
enumerated type: in language terms, anything outside the enumeration
doesn't exist!).

So they optimise out your nice recovery logic :(

Quartus has an attribute to make the synth put its own reset logic in for
invalid states, to go back to the reset state.

XST has an attribute to specify the safe state it should go to when
state is invalid. And another to enable that behaviour.

Synplify has an option to generate logic to put things back to the reset
state if an illegal state is detected.

None of which makes the implementation match the code...

Synplify also has an option to create an "exact" state machine, which
does do precisely what your code says (or so it claims) at the expense
of disabling all its clever optimisations for that machine.

Take your pick :)

Cheers,
Martin





>
> Just sayin'

--
martin.j...@trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.co.uk/capabilities/39-electronic-hardware

Hal Murray

unread,
May 4, 2012, 6:15:11 PM5/4/12
to
In article <pv5y5p9...@trw.com>,
Martin Thompson <martin.j...@trw.com> writes:
>Tim Wescott <t...@seemywebsite.com> writes:
>
>>> But it is good design practice to buffer just any signal, which is fed
>>> asynchronously to the FPGA, then you don't have such problems, even if
>>> you didn't calculate and define all timing constraints.
>
>Mandatory, I'd say, unless you can make a cast-iron argument as to why it
>doesn't matter if it is sampled differently by two different flops.

Even if you are sure it doesn't matter, you aren't out of the water yet.

You still have to consider metastability.

You also have to consider the design lifetime. Will the guy who
changes something in this area several years from now be smart
enough to know that he needs check again? Will he get it right?

glen herrmannsfeldt

unread,
May 4, 2012, 6:33:51 PM5/4/12
to
Hal Murray <hal-u...@ip-64-139-1-69.sjc.megapath.net> wrote:

(snip)
>> Mandatory, I'd say, unless you can make a cast-iron argument as
>> to why it doesn't matter if it is sampled differently by
>> two different flops.

> Even if you are sure it doesn't matter, you aren't out of the water yet.

> You still have to consider metastability.

In most cases, for slow logic you don't.

Metastability becomes a problem if the logic after the FF is
long enough, and the FF is likely (ever) to be metastable long
enough to cause problems.

Note that you can never get rid of metastability, but only
make it unlikely enough to cause a problem. In high speed
designs, the logic delay is a significant part of a clock cycle,
and even a short metastability can be long enough.

> You also have to consider the design lifetime. Will the guy who
> changes something in this area several years from now be smart
> enough to know that he needs check again? Will he get it right?

As with metastability, there is no way to avoid that.

-- glen

Hal Murray

unread,
May 4, 2012, 11:37:55 PM5/4/12
to
In article <jo1lgf$e5r$1...@speranza.aioe.org>,
glen herrmannsfeldt <g...@ugcs.caltech.edu> writes:
>Hal Murray <hal-u...@ip-64-139-1-69.sjc.megapath.net> wrote:
...

>> Even if you are sure it doesn't matter, you aren't out of the water yet.
>> You still have to consider metastability.

>In most cases, for slow logic you don't.

Good point. Thanks.


The key idea being "slow logic" where the metastability settling time
is small relative to the cycle time.

j.m.gr...@gmail.com

unread,
May 5, 2012, 8:54:59 PM5/5/12
to
On Wednesday, May 2, 2012 5:43:02 PM UTC+12, Frank Buss wrote:
> Right, this is slightly different from metastability, and maybe was the
> reason for the behaviour in my FPGA program, though the bugfix is the
> same :-)
>
> Is there a technical term for this special kind of problem?

My preference is to call it an Aperture Effect, as it is actually a small, but finite time window, and you can even calculate the width (in ns/ps) of this Aperture, given a large enough data-set sample size.

Giuseppe Marullo

unread,
May 16, 2012, 7:00:53 PM5/16/12
to
>
> Note that this has nothing to do with metastability.
Houston we have a problem.

I am implementing this stuff on a LX9 board that has a direct USB serial
interface. I tried to run it at 9600 baud, and it seemed to work fine.

I Implemented a small FSM that would echo a char back, maybe with a
little modification, ie send 'a' get back a 'c' (+2).

It worked but not if I kept sending char (a key always pressed down),
after about 20 chars there was some strange char back.

Thinking about baud rate tolerance and/or problem sending back fast the
char it received, I fiddled with the stop bits, hoping that it would
allow more time to "process" the incoming char.

No dice.

I tried to slow down the pace at which I would send chars, like 1 every
second or so, but every 15-20 char max, there was a very different char
back.

I was unable to debug with a LA (there is not much where I could connect
between the pc and the fpga) I tried to simulate a workbench
to exercise the fsm. It was rather difficult for me (several tasks in
parallel and so on) but the simulation seemed to work.

I tried to send the char it received from my pc to a serial LCD, and
there was even more errors on the output of the LCD.


At the end, I added this to the rx pin:

reg [2:0] rx_buffer;
wire rx_clean = rx_buffer[2];
always @(posedge clk)
rx_buffer <= {rx_buffer[1:0], rx};

It is working perfectly so far. Metastability, noise or whatever there
is something I don't get here. I have a very fast clock (100MHz) so
maybe it would benefit from a oversampling approach but the difference
with this metastabilitywhatever dirty fix is very noticeable.


Giuseppe Marullo

glen herrmannsfeldt

unread,
May 16, 2012, 9:37:01 PM5/16/12
to
Giuseppe Marullo <giuseppe.ma...@iname.com> wrote:

>> Note that this has nothing to do with metastability.
> Houston we have a problem.

> I am implementing this stuff on a LX9 board that has a direct USB serial
> interface. I tried to run it at 9600 baud, and it seemed to work fine.

> I Implemented a small FSM that would echo a char back, maybe with a
> little modification, ie send 'a' get back a 'c' (+2).

> It worked but not if I kept sending char (a key always pressed down),
> after about 20 chars there was some strange char back.

> Thinking about baud rate tolerance and/or problem sending back fast the
> char it received, I fiddled with the stop bits, hoping that it would
> allow more time to "process" the incoming char.

Add one more stop bit to the device sending to your board.

Also, your board should start counting bits half way through the
start bit, such that it looks at the center of each bit.

You should be ready to start a new character after the middle of
the stop bit, though there really should be a whole stop bit.

As you note, because of clock tolerance, data might be coming in
faster than you can send it out. You could add a fifo, but eventually
you will fill it up unless you send data slower than it comes back.

-- glen

j.m.gr...@gmail.com

unread,
May 23, 2012, 8:44:57 PM5/23/12
to
On Thursday, May 17, 2012 11:00:53 AM UTC+12, Giuseppe Marullo wrote:
> I tried to run it at 9600 baud, and it seemed to work fine.
> I tried to slow down the pace at which I would send chars, like 1 every
> second or so, but every 15-20 char max, there was a very different char
> back.
>
> At the end, I added this to the rx pin:
>
> reg [2:0] rx_buffer;
> wire rx_clean = rx_buffer[2];
> always @(posedge clk)
> rx_buffer <= {rx_buffer[1:0], rx};
>
> It is working perfectly so far. Metastability, noise or whatever there
> is something I don't get here. I have a very fast clock (100MHz) so
> maybe it would benefit from a oversampling approach but the difference
> with this metastabilitywhatever dirty fix is very noticeable.

Did you also add a majority vote on those samples ?

it does seem strange from a random sampling angle - if you are running 9600 baud, and you get failures of 1 in 25, that suggests an error window equivalent of around 4us.

Things may not be random, I'd look around for something else wrong.
(ie you may not have fully fixed a problem, just moved it slightly)

Samples should be ~52us clear of any edges, and Stop bit should flip to start edge polling, at 50% stop time (this gives margin for baud rate skews)
( Shipping UARTS have made this mistake, you can also check by sending two stop bits )
You could output a pulse when you sample, and another when ready-for-Start, and scope that - at least a 1:25 failure is often enough, to be easy to catch.
0 new messages