Let's build (half a) UART
Aug 31, 2016

The problem with FPGAs is that they’re so low-level. It’s a bit like sitting on the floor with a huge pile of 7400 series chips, trying to make them do something … u s e f u l ?

When starting from scratch (just for my own education and entertainment), one of the first things I’ll want is to hook up the FPGA to some nearby computer or µC.

The one tool that comes to mind is a serial UART interface, so let’s try and build one. For now, I’ll aim for the absolute minimum: serial output, at a fixed 115200 baud rate, sending out a test byte once every second.

Let’s see… we’ll need:

  • a 115.2 KHz clock baudrate generator
  • a once-a-second tick, to trigger sends
  • logic to actually shift out the data

Or in schematic form (as generated by Quartus once this was all coded up):

There are more accurate ways to generate 115.2 KHz from our 50 MHz system clock, but for now we’ll use a divide-by-434:

module BaudGen (
    input clk,      // 50 MHz
    output baud     // 115.2 KHz (approx)
);

reg [8:0] tx_sample_cntr = 0;
always @(posedge clk)
    if (tx_sample_cntr == 0)
        tx_sample_cntr <= 50000000/115200-1;
    else
        tx_sample_cntr <= tx_sample_cntr - 1;
assign baud = tx_sample_cntr == 0;

endmodule

Similarly for the 1 Hz ticker:

module Tick1hz (
    input clk,      // 50 MHz
    output tick     // one short pulse every 1s
);

reg [31:0] counter = 0;
always @(posedge clk)
    if (counter == 50000000-1)
        counter <= 0;
    else
        counter <= counter + 1;
assign tick = counter == 0;

endmodule

The shifter is the most interesting part, but also the most complex. You can find it over here, it was copied and adapted from these very nice basic_verilog examples.

The core idea is to copy the start bit, the data bits, and the stop bit into an 10-bit shift register, and to then shift one bit out into the “txd” I/O pin on every baudrate clock tick. Since the stop bit is 1, we can simply keep on sending until the shift register is zero, which signals it is empty and can then be filled with a new byte.

Here is the generated circuit:

We then tie this together in a “top” module:

module top (
    input clk,      // 50 MHz
    output txd      // UART tx pin
);

wire tick, baud;
Tick1hz U1(.clk(clk), .tick(tick));
BaudGen U2(.clk(clk), .baud(baud));

UartTx U3(
    .clk(clk),
    .tx_clock(baud),
    .tx_data(8'h45), // "E"
    .tx_start(tick),
    .txd(txd)
);

endmodule

This entire setup uses 91 logic elements:

And sure enough, when hooking up a serial port (and setting up the proper I/O pins for clk and txd), I see the letter “E” coming out once a second. Magic!

The project files can be found on GitHub.

If any of this catches your interest, but you can’t make any heads or tails of this Verilog “language” - just as I’ve been scratching my head for days - then maybe this will help:

  1. Download this brilliant PDF (copy).
  2. Read the first 15 pages (out of 29).
  3. Then read these tips (also a PDF).
  4. Repeat until it makes a little sense.
  5. Continue reading that 1st PDF.

The trick is that if you’re used to writing software, then a “Hardware Description Language” such as Verilog requires you to re-wire your brain. I found the distinction between = and <= assignments particularly confusing until I realised that = is like C’s #define and <= is more like C’s variable assignments, but all happening in parallel!

For comments, visit the forum.

PMOD connectors
Aug 24, 2016

Last week’s post used the 12-pin “Pmod” connector on my FPGA board to generate the X, Y, and Z signals.

Pmod™ is a simple header pinout standard (PDF) defined by Digilent. There’s a (free) license for this, but only if we actually call it Pmod. So I won’t - I’ll simply refer to the two variants as 6-pin and 12-pin headers…

  • the 6-pin header is: IO1 IO2 IO3 IO4 GND +3.3V
  • the 12-pin header adds a 2nd row with: IO5..IO8 GND +3.3V

This scheme is extremely flexible, because FPGA’s can assign any function to any IO pin, and the 12-pin variant can also be used as two independent 6-pin connections.

A few more conventions are often used for the most common interfaces:

UART – IO1..4 = ¬CTS ¬TXD ¬RXD ¬RTS
SPI – IO1..4 = ¬SS MOSI MISO SCK
I2C – IO1..2 = SCL SDA

Another great convention, is that multiple headers are placed 0.3” apart, so that modules which need more than 8 I/O pins can simply have multiple headers placed next to each other for 16, 24, or even 32 bits of I/O goodness.

So here’s a custom module, with 3 D/A “converters” in the form of 1 kΩ + 0.1 µF RC filters, plus one digital I/O pass-through:

This in turn forms the input for an op-amp used as amplifier, level-shifter, and buffer:

The circuit on the above board is as follows:

There is room to include a dual-voltage DC-DC boost regulator, but for now I’m just feeding it ±10V from my lab power supply:

(PS. What a Kabelsalat / wire mess …)

Note that the third DAC output is used as a fixed reference for the two opamps, to allow shifting their output levels to a more or less symmetric swing around zero:

These connectors are really convenient!

There are commercial Pmod modules, but it’s just as easy to create custom ones using this same pinout. So much so in fact, that I’ve created a little 40-pin-to-quad-12-pin header breakout board for it:

From left to right:

  • the hand-wired breakout board
  • an EP4CE6 “Mini” from eBay
  • an EP4CE22 DE0-Nano from Terasic
  • an XC6SLX9 “Mini” from eBay

These all have 2 compatible 2x20 headers.

Here are some more ideas for plugs:

  • serial I/O using an FTDI adapter
  • very cheap µSD card “adapter”
  • I2C or SPI: flash/SRAM/FRAM
  • PS2 keyboard + VGA (8-colours)

The last two of these haven’t been wired up yet, but you get the idea…

For comments, visit the forum.

Sweep, staircase, and blanking
Aug 17, 2016

We’ve all seen images like this before:

Well, maybe not consciously, but this is the way images are “painted” across the screen of a CRT in old TVs. A sweep from left to right, combined with a step-wise change in the vertical direction. The dotted curves joining the straight lines are the “flyback” of the electron beam moving to the next step.

It’s also the basis of a Curve Tracer, used to plot the characteristics of semiconductors and other components: one variable is varied continuously, while another one changes in discrete steps. Do this fast enough and you get a constant “image” on an oscilloscope, when it’s set to X-Y mode.

Not to be confused with a Component Tester, which applies a sine wave and measures voltage + current patterns …

It’s very easy to generate these signals, you just need two digital output pins, each with an RC filter to smooth out some pulses.

The trick is to use a delta-sigma modulator to toggle an output pin such that the duty-cycle matches the desired analog output value. As this page shows, that can be done in an FPGA with a few lines of Verilog code:

module dac (input clk, output outx, outy, outz);

reg [31:0] count;
reg [15:0] accx;
reg [15:0] accy;

always @(posedge clk) begin
    count <= count + 1;
    accx <= accx[14:0] + count[17:3];
    accy <= accy[14:0] + { count[20:18], 12'b0 };
end

assign outx = accx[15];
assign outy = accy[15];
assign outz = count[17:3] >= 4096;

endmodule

As an extra feature, we’re also generating a “Z-blanking” signal which suppresses the beam display in the oscilloscope during the flyback periods, leading to a cleaner image:

Here are the same three generated signals, using the normal Y-T scope display mode:

You can see the sweeps (yellow), the steps (blue), and the flyback suppress (magenta) signals. The cycle time is about 24 Hz when driven from a 50 MHz input clock.

Here is my setup to generate these signals:

On the bottom left is a small custom board attached to the PMOD connector, with two 10 KHz low-pass RC filters (1 kΩ + 0.1 µF).

Only 3 I/O pins and 48 LEs (under 1% of the FPGA resources) are used in this setup.

I find these “crossovers” between analog vs. digital and FPGAs vs. µCs fascinating!

For comments, visit the forum.

Weblog © Jean-Claude Wippler. Generated by Hugo.