170 lines
3.1 KiB
Verilog
170 lines
3.1 KiB
Verilog
// Copyright (c) 2014 Sergiusz 'q3k' Bazański <sergiusz@bazanski.pl>
|
|
// Released under the 2-clause BSD license - see the COPYING file
|
|
|
|
`timescale 1ns / 1ps
|
|
|
|
/// This is not the prettiest UART you've seen...
|
|
|
|
module uart_controller(
|
|
// Data input
|
|
input [7:0] tx_data_in,
|
|
// Data input latch
|
|
input tx_data_latch,
|
|
|
|
// baud rate clock
|
|
input clock,
|
|
|
|
// reset line
|
|
input reset,
|
|
|
|
// goes 1 when the UART finished transmitting
|
|
output reg tx_transmitted,
|
|
// the actual UART transmitter output
|
|
output reg tx_signal,
|
|
|
|
output reg rx_present,
|
|
input rx_present_clear,
|
|
output reg [7:0] rx_data,
|
|
|
|
input rx_signal
|
|
);
|
|
|
|
// Internal TX data (latched from tx_data_in)
|
|
reg [7:0] tx_data;
|
|
|
|
reg [3:0] tx_state;
|
|
reg [3:0] rx_state;
|
|
`define IDLE 0
|
|
`define START 1
|
|
`define BIT0 2
|
|
`define BIT1 3
|
|
`define BIT2 4
|
|
`define BIT3 5
|
|
`define BIT4 6
|
|
`define BIT5 7
|
|
`define BIT6 8
|
|
`define BIT7 9
|
|
`define STOP 10
|
|
|
|
/// Receiver
|
|
always @(posedge clock)
|
|
begin
|
|
if (reset) begin
|
|
rx_state <= `IDLE;
|
|
rx_present <= 0;
|
|
rx_data <= 0;
|
|
end else begin
|
|
if (rx_present_clear)
|
|
rx_present <= 0;
|
|
case (rx_state)
|
|
`IDLE: begin
|
|
if (!rx_signal) begin
|
|
// We received a start bit
|
|
rx_state <= `BIT0;
|
|
rx_present <= 0;
|
|
end
|
|
end
|
|
`BIT0: begin
|
|
rx_data[0] <= rx_signal;
|
|
rx_state <= `BIT1;
|
|
end
|
|
`BIT1: begin
|
|
rx_data[1] <= rx_signal;
|
|
rx_state <= `BIT2;
|
|
end
|
|
`BIT2: begin
|
|
rx_data[2] <= rx_signal;
|
|
rx_state <= `BIT3;
|
|
end
|
|
`BIT3: begin
|
|
rx_data[3] <= rx_signal;
|
|
rx_state <= `BIT4;
|
|
end
|
|
`BIT4: begin
|
|
rx_data[4] <= rx_signal;
|
|
rx_state <= `BIT5;
|
|
end
|
|
`BIT5: begin
|
|
rx_data[5] <= rx_signal;
|
|
rx_state <= `BIT6;
|
|
end
|
|
`BIT6: begin
|
|
rx_data[6] <= rx_signal;
|
|
rx_state <= `BIT7;
|
|
end
|
|
`BIT7: begin
|
|
rx_data[7] <= rx_signal;
|
|
rx_state <= `STOP;
|
|
end
|
|
`STOP: begin
|
|
rx_present <= 1;
|
|
rx_state <= `IDLE;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
/// Transmitter
|
|
always @(posedge clock)
|
|
begin
|
|
if (reset) begin
|
|
tx_state <= `IDLE;
|
|
tx_signal <= 1;
|
|
tx_data <= 0;
|
|
tx_transmitted <= 1;
|
|
end else begin
|
|
case (tx_state)
|
|
`IDLE: begin
|
|
if (tx_data_latch)
|
|
begin
|
|
tx_data <= tx_data_in;
|
|
tx_state <= `START;
|
|
tx_transmitted <= 0;
|
|
end
|
|
end
|
|
`START: begin
|
|
tx_signal <= 0;
|
|
tx_state <= `BIT0;
|
|
end
|
|
`BIT0: begin
|
|
tx_signal <= tx_data[0];
|
|
tx_state <= `BIT1;
|
|
end
|
|
`BIT1: begin
|
|
tx_signal <= tx_data[1];
|
|
tx_state <= `BIT2;
|
|
end
|
|
`BIT2: begin
|
|
tx_signal <= tx_data[2];
|
|
tx_state <= `BIT3;
|
|
end
|
|
`BIT3: begin
|
|
tx_signal <= tx_data[3];
|
|
tx_state <= `BIT4;
|
|
end
|
|
`BIT4: begin
|
|
tx_signal <= tx_data[4];
|
|
tx_state <= `BIT5;
|
|
end
|
|
`BIT5: begin
|
|
tx_signal <= tx_data[5];
|
|
tx_state <= `BIT6;
|
|
end
|
|
`BIT6: begin
|
|
tx_signal <= tx_data[6];
|
|
tx_state <= `BIT7;
|
|
end
|
|
`BIT7: begin
|
|
tx_signal <= tx_data[7];
|
|
tx_state <= `STOP;
|
|
end
|
|
`STOP: begin
|
|
tx_signal <= 1;
|
|
tx_state <= `IDLE;
|
|
tx_transmitted <= 1;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
endmodule
|