UART Communication in Verilog – "Hello World" to Arduino

This project demonstrates a simple UART (Universal Asynchronous Receiver/Transmitter) communication setup using Verilog. The design periodically sends the string "Hello World" from an FPGA to an Arduino over a serial UART interface.

 

 Project Overview

 

Platform: FPGA (tested with 27 MHz clock)

Target device: Any microcontroller with UART RX (e.g., Arduino)

Baud Rate: \~9600 bps

Message: "Hello World" (sent every 500 ms)




 

Top Module Highlights (`uart_top`)

 

 A simple counter generates a 500 ms delay using the 27 MHz clock.

 The message "Hello World" is stored in an internal ROM (array of ASCII characters).

 Each character is latched sequentially and sent one by one every 500 ms.

 The `UART` module handles bit-wise serial transmission of each character.

 

Code:

 

`timescale 1ns / 1ps

 

module uart_top (

    input clk,         // 27 MHz clock

    output uart_tx     // Connect to Arduino RX

);

 

// 500 ms delay = 13,500,000 cycles @ 27 MHz

reg [23:0] sendCounter = 0;

reg send_reg = 0;

wire send_pulse;

 

assign send_pulse = send_reg;

 

always @(posedge clk) begin

    if (sendCounter == 24'd13500000) begin

        sendCounter <= 0;

        send_reg <= 1;

    end else begin

        sendCounter <= sendCounter + 1;

        send_reg <= 0;

    end

end

 

// ROM to hold "Hello World"

reg [7:0] message [0:10];

initial begin

    message[0]   = "H";

    message[1]   = "e";

    message[2]   = "l";

    message[3]   = "l";

    message[4]   = "o";

    message[5]   = " ";

    message[6]   = "W";

    message[7]   = "o";

    message[8]   = "r";

    message[9]   = "l";

    message[10] = "d";

end

 

reg [3:0] char_index = 0;

reg [7:0] current_char = 8'h00;

 

// Latch the next character on send pulse

always @(posedge clk) begin

    if (send_pulse) begin

        current_char <= message[char_index];

        if (char_index == 4'd10)

            char_index <= 0;

        else

            char_index <= char_index + 1;

    end

end

 

// Instantiate UART with dynamic character input

UART uart_inst (

    .send(send_pulse),

    .clk(clk),

    .char_to_send(current_char),

    .uart_tx(uart_tx)

);

 

endmodule

 

 UART Module Highlights (`UART`)

 

 Implements a finite state machine with three states:

 

  • `rdy`: Wait for send pulse.
  • `load_bit`: Load the next bit to transmit.
  • `send_bit`: Send the current bit with precise timing.

 Adds start and stop bits to each character (8N1 format).

 Uses an internal baud rate timer (`bit_tmr_max = 2812`) to match \~9600 baud with a 27 MHz clock.

 

Code:

 

module UART (

    input send,

    input clk,

    input [7:0] char_to_send,  // <--- NEW INPUT

    output uart_tx

);

 

parameter [13:0] bit_tmr_max = 14'd2812;

parameter bit_index_max = 10;

 

parameter rdy = 0, load_bit = 1, send_bit = 2;

 

reg [13:0] bitTmr = 0;

reg bitDone;

reg [3:0] bitIndex;

reg txBit = 1'b1;

reg [9:0] txData;

reg [1:0] state = rdy;

 

reg send_prev = 0;

wire send_edge;

 

always @(posedge clk)

    send_prev <= send;

 

assign send_edge = send & ~send_prev;

 

always @(posedge clk) begin

    if (state == rdy) begin

        bitTmr <= 0;

        bitDone <= 0;

    end else begin

        if (bitTmr == bit_tmr_max - 1) begin

            bitDone <= 1'b1;

            bitTmr <= 0;

        end else begin

            bitTmr <= bitTmr + 1;

            bitDone <= 1'b0;

        end

    end

end

 

always @(posedge clk) begin

    case (state)

        rdy: begin

            txBit <= 1'b1;

            bitIndex <= 0;

            if (send_edge) begin

                txData <= {1'b1, char_to_send, 1'b0}; // stop, data, start

                state <= load_bit;

            end

        end

 

        load_bit: begin

            txBit <= txData[bitIndex];

            bitIndex <= bitIndex + 1;

            state <= send_bit;

        end

 

        send_bit: begin

            if (bitDone) begin

                if (bitIndex == bit_index_max)

                    state <= rdy;

                else

                    state <= load_bit;

            end

        end

 

        default: state <= rdy;

    endcase

end

 

assign uart_tx = txBit;

 

endmodule

 

 Wiring

 

  • Connect the `uart_tx` output to the RX pin of an Arduino or serial USB adapter.
  • Observe the "Hello World" message repeating every half second.




… ___Thank You___ …

Post a Comment (0)
Previous Post Next Post