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___ …