You dont have javascript enabled! Please enable it!

Practical case: passive UART monitor with ULX3S

Practical case: passive UART monitor with ULX3S — hero

Objective and use case

What you’ll build: A practical UART monitor on the Radiona ULX3S (Lattice ECP5-85F) that passively taps a real 3.3 V, 115200 baud, 8N1 TX line, decodes each byte in FPGA logic, and forwards readable lines such as RX 48 OK to a PC over a second UART. The design also flashes an on-board LED on traffic and is clean enough to lint with Verilator and synthesize with Yosys.

Why it matters / Use cases

  • Debug embedded devices without changing their firmware by watching a live 3.3 V UART stream non-invasively.
  • Turn raw serial traffic into human-readable monitor output for bring-up, factory test, and field diagnostics.
  • Practice reliable FPGA serial design with concrete timing: 115200 baud means about 86.8 µs per byte frame in 8N1, so the monitor must sample and format data correctly at line rate.
  • Useful when validating boot logs, sensor controllers, GPS modules, or MCU debug prints that already transmit over UART.

Expected outcome

  • The ULX3S receives bytes from an external 3.3 V UART source and decodes them correctly at 115200 baud, 8N1.
  • For every received byte, the FPGA emits a readable line like RX 48 OK to a USB-UART adapter connected to a PC terminal.
  • An on-board LED blinks briefly on each character, giving immediate visual confirmation of traffic.
  • The RTL passes Verilator lint and synthesizes with Yosys for the ECP5-85F, with very low FPGA load relative to available logic and no meaningful GPU usage (0% GPU).

Audience: FPGA learners, embedded engineers, and hardware debuggers working with UART-based systems; Level: beginner to intermediate

Architecture/flow: 3.3 V device TX -> ULX3S UART RX decoder -> formatter -> ULX3S UART TX -> USB-UART adapter -> PC terminal

Conceptual block diagram

High-level view: what enters the system, what each block processes, and what comes out.

Functional architecture

3.3 V device TX

ULX3S UART RX decoder

formatter

ULX3S UART TX

USB-UART adapter

PC terminal

Conceptual signal and responsibility flow between device blocks.

Validation path

Source code

Verilator

Yosys

Hardware implementation

Conceptual summary of the tools used to check the published material.

Prerequisites

Educational validation note

Before publication, this case passed the Prometeo automated validation gate with status PASS. For this FPGA/ULX3S profile, the synthesizable Verilog blocks were checked with Yosys (read_verilog) and the Verilog design/test set was linted with Verilator. The validator also checked code-block structure, copy/paste-safe ASCII command options, unsupported stacks, and availability of the ULX3S/ECP5 toolchain (yosys, nextpnr-ecp5, ecppack, openFPGALoader).

This validation confirms syntax and tool compatibility for the published code, but it does not replace physical testing on your exact ULX3S board revision, pin-constraint file and real wiring.

You need:

  • A ULX3S board from the Lattice ECP5-85F family
  • A 3.3 V UART source device
  • A USB-UART adapter
  • Jumper wires
  • A shell environment with these tools installed:
  • verilator
  • yosys
  • nextpnr-ecp5
  • ecppack
  • openFPGALoader
  • A serial terminal program such as picocom or screen

Quick tool check:

verilator --version
yosys -V
nextpnr-ecp5 --version
ecppack --help | head -n 1
openFPGALoader --version

Materials

ItemExact model/familyPurpose
FPGA boardRadiona ULX3S, Lattice ECP5-85FRuns the UART monitor
Serial source3.3 V UART deviceSignal being observed
USB-UART adapter3.3 V compatible adapterSends monitor output to the PC
USB cableFor ULX3SPower and programming
USB cableFor adapterPC serial connection
Jumper wiresAs neededTX and GND wiring

Educational safety note

Low-voltage digital electronics only.

  • Do not connect RS-232 voltage levels directly to FPGA pins.
  • Do not connect 5 V UART directly to ULX3S I/O.
  • Share GND between the external device, ULX3S, and USB-UART adapter.
  • This project assumes 3.3 V UART signaling only.

Wiring

Signals used by the FPGA design:

  • mon_rx: monitored UART input from the external device TX
  • host_tx: UART output from the FPGA to the USB-UART adapter RX
  • led0: activity LED

Connect:

  1. External device TX -> ULX3S pin assigned to mon_rx
  2. External device GND -> ULX3S GND
  3. ULX3S pin assigned to host_tx -> USB-UART adapter RX
  4. USB-UART adapter GND -> ULX3S GND
  5. ULX3S USB -> PC
  6. USB-UART adapter USB -> PC

Project files

Create these files:

  • uart_monitor_top.v
  • tb_uart_monitor_top.v
  • ulx3s_uart_monitor.lpf

Verilog: uart_monitor_top.v

Public preview of the validated file. The complete source is shown to members and in PDF/Print.

module uart_rx #(
    parameter integer CLK_HZ = 25000000,
    parameter integer BAUD   = 115200
)(
    input  wire clk,
    input  wire rst,
    input  wire rx,
    output reg  [7:0] data,
    output reg  valid,
    output reg  framing_error
);
    localparam integer CLKS_PER_BIT  = CLK_HZ / BAUD;
    localparam integer HALF_BIT_CLKS = CLKS_PER_BIT / 2;

    reg rx_sync_0;
    reg rx_sync_1;
    reg [15:0] clk_count;
    reg [3:0] bit_index;
    reg [7:0] rx_shift;
    reg [1:0] state;

    localparam [1:0] S_IDLE  = 2'd0;
    localparam [1:0] S_START = 2'd1;
    localparam [1:0] S_DATA  = 2'd2;
    localparam [1:0] S_STOP  = 2'd3;

    always @(posedge clk) begin
        if (rst) begin
            rx_sync_0 <= 1'b1;
            rx_sync_1 <= 1'b1;
        end else begin
            rx_sync_0 <= rx;
            rx_sync_1 <= rx_sync_0;
        end
    end

    always @(posedge clk) begin
        if (rst) begin
            data <= 8'h00;
            valid <= 1'b0;
            framing_error <= 1'b0;
            clk_count <= 16'd0;
            bit_index <= 4'd0;
            rx_shift <= 8'h00;
            state <= S_IDLE;
        end else begin
            valid <= 1'b0;

            case (state)
                S_IDLE: begin
                    framing_error <= 1'b0;
                    clk_count <= 16'd0;
                    bit_index <= 4'd0;
                    if (rx_sync_1 == 1'b0) begin
                        state <= S_START;
                    end
                end

                S_START: begin
                    if (clk_count == HALF_BIT_CLKS - 1) begin
                        clk_count <= 16'd0;
                        if (rx_sync_1 == 1'b0) begin
                            state <= S_DATA;
                        end else begin
                            state <= S_IDLE;
                        end
                    end else begin
                        clk_count <= clk_count + 16'd1;
                    end
                end

                S_DATA: begin
                    if (clk_count == CLKS_PER_BIT - 1) begin
                        clk_count <= 16'd0;
                        rx_shift[bit_index] <= rx_sync_1;
                        if (bit_index == 4'd7) begin
                            bit_index <= 4'd0;
                            state <= S_STOP;
                        end else begin
                            bit_index <= bit_index + 4'd1;
                        end
                    end else begin
                        clk_count <= clk_count + 16'd1;
                    end
                end

                S_STOP: begin
                    if (clk_count == CLKS_PER_BIT - 1) begin
                        clk_count <= 16'd0;
                        data <= rx_shift;
                        valid <= 1'b1;
                        framing_error <= (rx_sync_1 != 1'b1);
                        state <= S_IDLE;
                    end else begin
                        clk_count <= clk_count + 16'd1;
                    end
                end

                default: begin
                    state <= S_IDLE;
                end
            endcase
        end
    end
endmodule

module uart_tx #(
    parameter integer CLK_HZ = 25000000,
    parameter integer BAUD   = 115200
)(
    input  wire clk,
    input  wire rst,
    input  wire [7:0] data,
    input  wire start,
    output reg  tx,
    output reg  busy
);
    localparam integer CLKS_PER_BIT = CLK_HZ / BAUD;

    reg [15:0] clk_count;
    reg [3:0] bit_index;
    reg [9:0] shifter;

    always @(posedge clk) begin
        if (rst) begin
            tx <= 1'b1;
            busy <= 1'b0;
            clk_count <= 16'd0;
            bit_index <= 4'd0;
            shifter <= 10'b1111111111;
        end else begin
            if (!busy) begin
                tx <= 1'b1;
                clk_count <= 16'd0;
                bit_index <= 4'd0;
                if (start) begin
                    shifter <= {1'b1, data, 1'b0};
                    busy <= 1'b1;
                    tx <= 1'b0;
                end
            end else begin
                if (clk_count == CLKS_PER_BIT - 1) begin
                    clk_count <= 16'd0;
                    bit_index <= bit_index + 4'd1;
                    shifter <= {1'b1, shifter[9:1]};
                    tx <= shifter[1];
                    if (bit_index == 4'd9) begin
                        busy <= 1'b0;
                        tx <= 1'b1;
                    end
                end else begin
                    clk_count <= clk_count + 16'd1;
                end
            end
        end
    end
endmodule
// ... continues for members in the complete validated source ...

🔒 Part of the validated code is premium. With the 7-day pass or the monthly membership you can view the complete validated source.

module uart_rx #(
    parameter integer CLK_HZ = 25000000,
    parameter integer BAUD   = 115200
)(
    input  wire clk,
    input  wire rst,
    input  wire rx,
    output reg  [7:0] data,
    output reg  valid,
    output reg  framing_error
);
    localparam integer CLKS_PER_BIT  = CLK_HZ / BAUD;
    localparam integer HALF_BIT_CLKS = CLKS_PER_BIT / 2;

    reg rx_sync_0;
    reg rx_sync_1;
    reg [15:0] clk_count;
    reg [3:0] bit_index;
    reg [7:0] rx_shift;
    reg [1:0] state;

    localparam [1:0] S_IDLE  = 2'd0;
    localparam [1:0] S_START = 2'd1;
    localparam [1:0] S_DATA  = 2'd2;
    localparam [1:0] S_STOP  = 2'd3;

    always @(posedge clk) begin
        if (rst) begin
            rx_sync_0 <= 1'b1;
            rx_sync_1 <= 1'b1;
        end else begin
            rx_sync_0 <= rx;
            rx_sync_1 <= rx_sync_0;
        end
    end

    always @(posedge clk) begin
        if (rst) begin
            data <= 8'h00;
            valid <= 1'b0;
            framing_error <= 1'b0;
            clk_count <= 16'd0;
            bit_index <= 4'd0;
            rx_shift <= 8'h00;
            state <= S_IDLE;
        end else begin
            valid <= 1'b0;

            case (state)
                S_IDLE: begin
                    framing_error <= 1'b0;
                    clk_count <= 16'd0;
                    bit_index <= 4'd0;
                    if (rx_sync_1 == 1'b0) begin
                        state <= S_START;
                    end
                end

                S_START: begin
                    if (clk_count == HALF_BIT_CLKS - 1) begin
                        clk_count <= 16'd0;
                        if (rx_sync_1 == 1'b0) begin
                            state <= S_DATA;
                        end else begin
                            state <= S_IDLE;
                        end
                    end else begin
                        clk_count <= clk_count + 16'd1;
                    end
                end

                S_DATA: begin
                    if (clk_count == CLKS_PER_BIT - 1) begin
                        clk_count <= 16'd0;
                        rx_shift[bit_index] <= rx_sync_1;
                        if (bit_index == 4'd7) begin
                            bit_index <= 4'd0;
                            state <= S_STOP;
                        end else begin
                            bit_index <= bit_index + 4'd1;
                        end
                    end else begin
                        clk_count <= clk_count + 16'd1;
                    end
                end

                S_STOP: begin
                    if (clk_count == CLKS_PER_BIT - 1) begin
                        clk_count <= 16'd0;
                        data <= rx_shift;
                        valid <= 1'b1;
                        framing_error <= (rx_sync_1 != 1'b1);
                        state <= S_IDLE;
                    end else begin
                        clk_count <= clk_count + 16'd1;
                    end
                end

                default: begin
                    state <= S_IDLE;
                end
            endcase
        end
    end
endmodule

module uart_tx #(
    parameter integer CLK_HZ = 25000000,
    parameter integer BAUD   = 115200
)(
    input  wire clk,
    input  wire rst,
    input  wire [7:0] data,
    input  wire start,
    output reg  tx,
    output reg  busy
);
    localparam integer CLKS_PER_BIT = CLK_HZ / BAUD;

    reg [15:0] clk_count;
    reg [3:0] bit_index;
    reg [9:0] shifter;

    always @(posedge clk) begin
        if (rst) begin
            tx <= 1'b1;
            busy <= 1'b0;
            clk_count <= 16'd0;
            bit_index <= 4'd0;
            shifter <= 10'b1111111111;
        end else begin
            if (!busy) begin
                tx <= 1'b1;
                clk_count <= 16'd0;
                bit_index <= 4'd0;
                if (start) begin
                    shifter <= {1'b1, data, 1'b0};
                    busy <= 1'b1;
                    tx <= 1'b0;
                end
            end else begin
                if (clk_count == CLKS_PER_BIT - 1) begin
                    clk_count <= 16'd0;
                    bit_index <= bit_index + 4'd1;
                    shifter <= {1'b1, shifter[9:1]};
                    tx <= shifter[1];
                    if (bit_index == 4'd9) begin
                        busy <= 1'b0;
                        tx <= 1'b1;
                    end
                end else begin
                    clk_count <= clk_count + 16'd1;
                end
            end
        end
    end
endmodule

module uart_monitor_top(
    input  wire clk_25mhz,
    input  wire btn_rst,
    input  wire mon_rx,
    output wire host_tx,
    output reg  led0
);
    wire rst;
    wire [7:0] rx_data;
    wire rx_valid;
    wire rx_ferr;

    reg [7:0] tx_data;
    reg tx_start;
    wire tx_busy;

    reg [7:0] msg_mem [0:17];
    reg [4:0] msg_len;
    reg [4:0] msg_idx;
    reg sending;
    reg [23:0] led_count;
    integer i;

    assign rst = btn_rst;

    uart_rx #(
        .CLK_HZ(25000000),
        .BAUD(115200)
    ) u_rx (
        .clk(clk_25mhz),
        .rst(rst),
        .rx(mon_rx),
        .data(rx_data),
        .valid(rx_valid),
        .framing_error(rx_ferr)
    );

    uart_tx #(
        .CLK_HZ(25000000),
        .BAUD(115200)
    ) u_tx (
        .clk(clk_25mhz),
        .rst(rst),
        .data(tx_data),
        .start(tx_start),
        .tx(host_tx),
        .busy(tx_busy)
    );

    function [7:0] hexchar;
        input [3:0] nib;
        begin
            if (nib < 4'd10) begin
                hexchar = 8'h30 + {4'b0000, nib};
            end else begin
                hexchar = 8'h41 + ({4'b0000, nib} - 8'd10);
            end
        end
    endfunction

    always @(posedge clk_25mhz) begin
        if (rst) begin
            tx_data <= 8'h00;
            tx_start <= 1'b0;
            msg_len <= 5'd0;
            msg_idx <= 5'd0;
            sending <= 1'b0;
            led0 <= 1'b0;
            led_count <= 24'd0;
            for (i = 0; i < 18; i = i + 1) begin
                msg_mem[i] <= 8'h20;
            end
        end else begin
            tx_start <= 1'b0;

            if (led_count != 24'd0) begin
                led_count <= led_count - 24'd1;
                led0 <= 1'b1;
            end else begin
                led0 <= 1'b0;
            end

            if (rx_valid && !sending) begin
                led_count <= 24'd5000000;

                msg_mem[0] <= "R";
                msg_mem[1] <= "X";
                msg_mem[2] <= " ";
                msg_mem[3] <= hexchar(rx_data[7:4]);
                msg_mem[4] <= hexchar(rx_data[3:0]);
                msg_mem[5] <= " ";

                if (!rx_ferr) begin
                    msg_mem[6] <= "O";
                    msg_mem[7] <= "K";
                    msg_mem[8] <= 8'h0A;
                    msg_len <= 5'd9;
                end else begin
                    msg_mem[6]  <= "F";
                    msg_mem[7]  <= "R";
                    msg_mem[8]  <= "A";
                    msg_mem[9]  <= "M";
                    msg_mem[10] <= "I";
                    msg_mem[11] <= "N";
                    msg_mem[12] <= "G";
                    msg_mem[13] <= "_";
                    msg_mem[14] <= "E";
                    msg_mem[15] <= "R";
                    msg_mem[16] <= "R";
                    msg_mem[17] <= 8'h0A;
                    msg_len <= 5'd18;
                end

                msg_idx <= 5'd0;
                sending <= 1'b1;
            end

            if (sending && !tx_busy) begin
                if (msg_idx < msg_len) begin
                    tx_data <= msg_mem[msg_idx];
                    tx_start <= 1'b1;
                    msg_idx <= msg_idx + 5'd1;
                end else begin
                    sending <= 1'b0;
                end
            end
        end
    end
endmodule

Testbench: tb_uart_monitor_top.v

Public preview of the validated file. The complete source is shown to members and in PDF/Print.

`timescale 1ns/1ps

module tb_uart_monitor_top;
    reg clk;
    reg btn_rst;
    reg mon_rx;
    wire host_tx;
    wire led0;

    localparam integer CLK_HALF_NS = 20;
    localparam integer BIT_NS = 8680;

    integer fd;
    integer i;
    reg [9:0] frame;

    uart_monitor_top dut (
        .clk_25mhz(clk),
        .btn_rst(btn_rst),
        .mon_rx(mon_rx),
        .host_tx(host_tx),
        .led0(led0)
    );

    always #CLK_HALF_NS clk = ~clk;

    task uart_send_byte;
        input [7:0] b;
        integer j;
        begin
            mon_rx = 1'b0;
            #(BIT_NS);
            for (j = 0; j < 8; j = j + 1) begin
                mon_rx = b[j];
                #(BIT_NS);
            end
            mon_rx = 1'b1;
            #(BIT_NS);
// ... continues for members in the complete validated source ...

🔒 Part of the validated code is premium. With the 7-day pass or the monthly membership you can view the complete validated source.

`timescale 1ns/1ps

module tb_uart_monitor_top;
    reg clk;
    reg btn_rst;
    reg mon_rx;
    wire host_tx;
    wire led0;

    localparam integer CLK_HALF_NS = 20;
    localparam integer BIT_NS = 8680;

    integer fd;
    integer i;
    reg [9:0] frame;

    uart_monitor_top dut (
        .clk_25mhz(clk),
        .btn_rst(btn_rst),
        .mon_rx(mon_rx),
        .host_tx(host_tx),
        .led0(led0)
    );

    always #CLK_HALF_NS clk = ~clk;

    task uart_send_byte;
        input [7:0] b;
        integer j;
        begin
            mon_rx = 1'b0;
            #(BIT_NS);
            for (j = 0; j < 8; j = j + 1) begin
                mon_rx = b[j];
                #(BIT_NS);
            end
            mon_rx = 1'b1;
            #(BIT_NS);
        end
    endtask

    initial begin
        clk = 1'b0;
        btn_rst = 1'b1;
        mon_rx = 1'b1;
        fd = $fopen("sim_host_tx_bits.txt", "w");

        #500;
        btn_rst = 1'b0;

        #(BIT_NS * 3);
        uart_send_byte(8'h48);
        #(BIT_NS * 2);
        uart_send_byte(8'h45);
        #(BIT_NS * 2);
        uart_send_byte(8'h4C);

        #(BIT_NS * 250);
        $fclose(fd);
        $finish;
    end

    initial begin
        forever begin
            @(negedge host_tx);
            #(BIT_NS/2);
            frame[0] = host_tx;
            for (i = 1; i < 10; i = i + 1) begin
                #(BIT_NS);
                frame[i] = host_tx;
            end
            $fwrite(fd, "frame bits: %b\n", frame);
        end
    end
endmodule

Constraints: ulx3s_uart_monitor.lpf

Edit the SITE values to match your exact ULX3S pinout.

BLOCK RESETPATHS;
BLOCK ASYNCPATHS;

FREQUENCY PORT "clk_25mhz" 25 MHz;

LOCATE COMP "clk_25mhz" SITE "ULX3S_PIN_CLK25";
IOBUF PORT "clk_25mhz" IO_TYPE=LVCMOS33;

LOCATE COMP "btn_rst" SITE "ULX3S_PIN_BTN";
IOBUF PORT "btn_rst" IO_TYPE=LVCMOS33 PULLMODE=UP;

LOCATE COMP "mon_rx" SITE "ULX3S_PIN_MON_RX";
IOBUF PORT "mon_rx" IO_TYPE=LVCMOS33;

LOCATE COMP "host_tx" SITE "ULX3S_PIN_HOST_TX";
IOBUF PORT "host_tx" IO_TYPE=LVCMOS33;

LOCATE COMP "led0" SITE "ULX3S_PIN_LED0";
IOBUF PORT "led0" IO_TYPE=LVCMOS33;

Build and run

1) Verilator lint

verilator -Wall -Wno-DECLFILENAME --lint-only uart_monitor_top.v tb_uart_monitor_top.v

2) Run simulation

verilator -Wall -Wno-DECLFILENAME --binary uart_monitor_top.v tb_uart_monitor_top.v
./obj_dir/Vtb_uart_monitor_top

Expected evidence:

  • The simulation exits normally.
  • A file named sim_host_tx_bits.txt is created.
  • That file contains UART frame samples generated by the FPGA transmitter.

This is the validation method for the RTL claim that received bytes trigger formatted UART output.

3) Synthesize

yosys -p "read_verilog uart_monitor_top.v; synth_ecp5 -top uart_monitor_top -json uart_monitor_top.json"

4) Place and route

nextpnr-ecp5 --85k --json uart_monitor_top.json --lpf ulx3s_uart_monitor.lpf --textcfg uart_monitor_top.config

5) Pack bitstream

ecppack uart_monitor_top.config uart_monitor_top.bit

6) Program the board

openFPGALoader -b ulx3s uart_monitor_top.bit

7) Open a serial terminal on the USB-UART adapter

picocom example:

picocom -b 115200 /dev/ttyUSB0

screen example:

screen /dev/ttyUSB0 115200

Hardware validation

Validate idle behavior

With the external serial device disconnected:

  • The terminal should stay quiet.
  • The LED should stay off after reset.
  • mon_rx should not be driven by any out-of-range voltage.

Validate with a known UART source

Configure the external 3.3 V device to repeatedly send HELLO at 115200 8N1.

Expected evidence in the terminal:

RX 48 OK
RX 45 OK
RX 4C OK
RX 4C OK
RX 4F OK
RX 0D OK
RX 0A OK

This is the validation method for the accuracy claim that the monitor decodes bytes correctly: compare the transmitted known string with the hexadecimal byte values printed by the FPGA.

Validate framing error handling

Keep the FPGA monitor at 115200 8N1, but configure the source device to a different baud rate such as 9600.

Expected evidence:

  • Output becomes sparse, incorrect, or absent.
  • Some received lines may show FRAMING_ERR.

Troubleshooting

No terminal output

Check:

  1. host_tx goes to the adapter RX
  2. Grounds are shared
  3. The correct serial device is opened on the PC
  4. The source device is actually transmitting
  5. The LPF pin mapping matches the real board

LED flashes but no PC text

Likely causes:

  • Wrong host_tx pin assignment
  • Wrong USB-UART adapter wiring
  • Wrong terminal device on the PC

Lint or synthesis fails

Check that:

  • File names match the commands exactly
  • Only uart_monitor_top.v is passed to Yosys synthesis
  • The LPF uses the same top-level signal names as the Verilog

Framing errors on every byte

Usually caused by:

  • Baud mismatch
  • Wrong voltage level
  • Noisy wiring
  • Incorrect clock pin mapping

Capture terminal logs

To save a monitor session:

script -c "picocom -b 115200 /dev/ttyUSB0" uart_monitor_session.txt

Final checklist

  • [ ] I used a Radiona ULX3S (Lattice ECP5-85F).
  • [ ] My observed serial signal is 3.3 V UART, not RS-232 and not 5 V UART.
  • [ ] All grounds are connected together.
  • [ ] I updated ulx3s_uart_monitor.lpf with valid ULX3S pins.
  • [ ] Verilator lint passes.
  • [ ] Yosys synthesis completes.
  • [ ] nextpnr completes.
  • [ ] The bitstream programs successfully.
  • [ ] The PC terminal is set to 115200 baud.
  • [ ] The terminal shows expected monitor lines for a known byte stream.

This gives you a reusable FPGA-based UART bench monitor for one transmit line on the ULX3S platform.

        <div class="amazon-affiliate">
          <p><strong>Find this product and/or books on this topic on Amazon</strong></p>
          <p><a class="amazon-affiliate-btn" href="https://amzn.to/4mt8r4C" target="_blank" rel="nofollow sponsored noopener">Go to Amazon</a></p>
          <p class="amazon-affiliate-disclaimer">As an Amazon Associate, I earn from qualifying purchases. If you buy through this link, you help keep this project running.</p>
        </div>

Quick Quiz

Question 1: What FPGA board is used for the UART monitor project described in the text?




Question 2: What is the baud rate of the UART line being tapped in this project?




Question 3: What happens on the FPGA board when a character is received?




Question 4: Which tool is used to synthesize the RTL design for the ECP5-85F?




Question 5: What is the approximate time per byte frame in 8N1 at 115200 baud?




Question 6: What is the voltage of the UART line being tapped in this project?




Question 7: What kind of output does the FPGA send to the PC terminal for every received byte?




Question 8: How does the UART monitor interact with the embedded device's firmware?




Question 9: Which tool is mentioned for linting the RTL design?




Question 10: What is one of the use cases mentioned for this UART monitor?




Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Telecommunications Electronics Engineer and Computer Engineer (official degrees in Spain).

Follow me:
Scroll to Top