//======================================================================
//
// uart.v
// ------
// Top level wrapper for the uart core.
//
// A simple universal asynchronous receiver/transmitter (UART)
// interface. The interface contains 16 byte wide transmit and
// receivea buffers and can handle start and stop bits. But in
// general is rather simple. The primary purpose is as host
// interface for the coretest design. The core also has a
// loopback mode to allow testing of a serial link.
//
// Note that the UART has a separate API interface to allow
// a control core to change settings such as speed. But the core
// has default values to allow it to start operating directly
// after reset. No config should be needed.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2014, SUNET
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module uart(
input wire clk,
input wire reset_n,
// External interface.
input wire rxd,
output wire txd,
// Internal receive interface.
output wire rxd_syn,
output [7 : 0] rxd_data,
input wire rxd_ack,
// Internal transmit interface.
input wire txd_syn,
input wire [7 : 0] txd_data,
output wire txd_ack,
// API interface.
input wire cs,
input wire we,
input wire [7 : 0] address,
input wire [31 : 0] write_data,
output wire [31 : 0] read_data,
output wire error,
// Debug output.
output wire [7 : 0] debug
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
// API addresses.
parameter ADDR_CORE_NAME0 = 8'h00;
parameter ADDR_CORE_NAME1 = 8'h01;
parameter ADDR_CORE_TYPE = 8'h02;
parameter ADDR_CORE_VERSION = 8'h03;
parameter ADDR_BIT_RATE = 8'h10;
parameter ADDR_DATA_BITS = 8'h11;
parameter ADDR_STOP_BITS = 8'h12;
// Core ID constants.
parameter CORE_NAME0 = 32'h75617274; // "uart"
parameter CORE_NAME1 = 32'h20202020; // " "
parameter CORE_TYPE = 32'h20202031; // " 1"
parameter CORE_VERSION = 32'h302e3031; // "0.01"
// The default bit rate is based on target clock frequency
// divided by the bit rate times in order to hit the
// center of the bits. I.e.
// Clock: 50 MHz, 9600 bps
// Divisor = 50*10E6 / 9600 = 5208
parameter DEFAULT_BIT_RATE = 16'd5208;
parameter DEFAULT_DATA_BITS = 4'h8;
parameter DEFAULT_STOP_BITS = 2'h1;
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [15 : 0] bit_rate_reg;
reg [15 : 0] bit_rate_new;
reg bit_rate_we;
reg [3 : 0] data_bits_reg;
reg [3 : 0] data_bits_new;
reg data_bits_we;
reg [1 : 0] stop_bits_reg;
reg [1 : 0] stop_bits_new;
reg stop_bits_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
wire [15 : 0] bit_rate;
wire [1 : 0] stop_bits;
wire core_rxd;
wire core_txd;
wire core_rxd_syn;
wire [7 : 0] core_rxd_data;
wire core_rxd_ack;
wire core_txd_syn;
wire [7 : 0] core_txd_data;
wire core_txd_ack;
reg [31 : 0] tmp_read_data;
reg tmp_error;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign txd = core_txd;
assign core_rxd = rxd;
assign rxd_syn = core_rxd_syn;
assign rxd_data = core_rxd_data;
assign core_rxd_ack = rxd_ack;
assign core_txd_syn = txd_syn;
assign core_txd_data = txd_data;
assign txd_ack = core_txd_ack;
assign read_data = tmp_read_data;
assign error = tmp_error;
assign debug = core_rxd_data;
//----------------------------------------------------------------
// core
//
// Instantiation of the uart core.
//----------------------------------------------------------------
uart_core core(
.clk(clk),
.reset_n(reset_n),
// Configuration parameters
.bit_rate(bit_rate_reg),
.data_bits(data_bits_reg),
.stop_bits(stop_bits_reg),
// External data interface
.rxd(core_rxd),
.txd(core_txd),
// Internal receive interface.
.rxd_syn(core_rxd_syn),
.rxd_data(core_rxd_data),
.rxd_ack(core_rxd_ack),
// Internal transmit interface.
.txd_syn(core_txd_syn),
.txd_data(core_txd_data),
.txd_ack(core_txd_ack)
);
//----------------------------------------------------------------
// reg_update
//
// Update functionality for all registers in the core.
// All registers are positive edge triggered with synchronous
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk)
begin: reg_update
if (!reset_n)
begin
bit_rate_reg <= DEFAULT_BIT_RATE;
data_bits_reg <= DEFAULT_DATA_BITS;
stop_bits_reg <= DEFAULT_STOP_BITS;
end
else
begin
if (bit_rate_we)
begin
bit_rate_reg <= bit_rate_new;
end
if (data_bits_we)
begin
data_bits_reg <= data_bits_new;
end
if (stop_bits_we)
begin
stop_bits_reg <= stop_bits_new;
end
end
end // reg_update
//----------------------------------------------------------------
// api
//
// The core API that allows an internal host to control the
// core functionality.
//----------------------------------------------------------------
always @*
begin: api
// Default assignments.
bit_rate_new = 16'h0000;
bit_rate_we = 0;
data_bits_new = 4'h0;
data_bits_we = 0;
stop_bits_new = 2'b00;
stop_bits_we = 0;
tmp_read_data = 32'h00000000;
tmp_error = 0;
if (cs)
begin
if (we)
begin
// Write operations.
case (address)
ADDR_BIT_RATE:
begin
bit_rate_new = write_data[15 : 0];
bit_rate_we = 1;
end
ADDR_DATA_BITS:
begin
data_bits_new = write_data[3 : 0];
data_bits_we = 1;
end
ADDR_STOP_BITS:
begin
stop_bits_new = write_data[1 : 0];
stop_bits_we = 1;
end
default:
begin
tmp_error = 1;
end
endcase // case (address)
end
else
begin
// Read operations.
case (address)
ADDR_CORE_NAME0:
begin
tmp_read_data = CORE_NAME0;
end
ADDR_CORE_NAME1:
begin
tmp_read_data = CORE_NAME1;
end
ADDR_CORE_TYPE:
begin
tmp_read_data = CORE_TYPE;
end
ADDR_CORE_VERSION:
begin
tmp_read_data = CORE_VERSION;
end
ADDR_BIT_RATE:
begin
tmp_read_data = {16'h0000, bit_rate_reg};
end
ADDR_DATA_BITS:
begin
tmp_read_data = {28'h0000000, data_bits_reg};
end
ADDR_STOP_BITS:
begin
tmp_read_data = {30'h0000000, stop_bits_reg};
end
default:
begin
tmp_error = 1;
end
endcase // case (address)
end
end
end
endmodule // uart
//======================================================================
// EOF uart.v
//======================================================================