mirror of
https://github.com/supleed2/ELEC50003-P1-CW.git
synced 2024-12-22 21:45:49 +00:00
Add UART interface IP
Tp be tested
This commit is contained in:
parent
6c31662970
commit
d178e7bee0
273
Vision/DE10_LITE_D8M_VIP_16/ip/de10lite-hdl/uart.v
Normal file
273
Vision/DE10_LITE_D8M_VIP_16/ip/de10lite-hdl/uart.v
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
Source: https://github.com/hildebrandmw/de10lite-hdl/blob/master/components/uart/hdl/uart.v
|
||||
Description: Very simple UART tx/rx module. Requires a streaming interface,
|
||||
provides no buffering for input or output data.
|
||||
*/
|
||||
|
||||
module uart
|
||||
#( parameter CLK_FREQ = 50_000_000,
|
||||
parameter BAUD = 115_200
|
||||
)
|
||||
( input clk,
|
||||
input reset,
|
||||
|
||||
// Receiving
|
||||
input rx, // Received serial stream
|
||||
output reg [7:0] rx_data, // Deserialized byte.
|
||||
output rx_valid, // Asserted when rx_data is valid
|
||||
|
||||
// Transmitting
|
||||
output reg tx, // Transmitted serial stream
|
||||
input [7:0] tx_data, // Deserialized byte to transmit.
|
||||
input tx_transmit, // Start Signal. No effect if tx_ready = 0
|
||||
output reg tx_ready // Asserted when ready to accept data
|
||||
);
|
||||
|
||||
///////////////////////////////
|
||||
// Functionality Description //
|
||||
///////////////////////////////
|
||||
|
||||
/*
|
||||
RECEIVING: Module receives a serial stream through the port rx.
|
||||
When a byte has been successfully received, the received data will be
|
||||
available on the output port rx_data and the output port rx_valid will be
|
||||
asserted for 1 clock cycle.
|
||||
|
||||
Validity of output data is not guaranteed if rx_valid is not 1. If this
|
||||
is important for you, you may modify this design to register the output.
|
||||
|
||||
TRANSMITTING: When input port tx_transmit is 1 (asserted), module will
|
||||
store the data on the input port tx_data and serialize through the output
|
||||
port tx.
|
||||
|
||||
Module will only save and transmit the data at tx_data if the signal
|
||||
tx_ready is asserted when tx_transmit is asserted. This module will not
|
||||
buffer input data. While transmitting, tx_ready is deasserted and the
|
||||
input port tx_transmit will have no effect.
|
||||
|
||||
Once tx_ready is deasserted, data at port tx_data is not used and need
|
||||
not be stable.
|
||||
*/
|
||||
|
||||
/////////////////////////
|
||||
// Signal Declarations //
|
||||
/////////////////////////
|
||||
|
||||
// ---------------------- //
|
||||
// -- Local Parameters -- //
|
||||
// ---------------------- //
|
||||
|
||||
// Number of synchronization stages to avoid metastability
|
||||
localparam SYNC_STAGES = 2;
|
||||
|
||||
// Over Sampling Factor
|
||||
localparam OSF = 16;
|
||||
|
||||
// Compute count to generate local clock enable
|
||||
localparam CLK_DIV_COUNT = CLK_FREQ / (OSF * BAUD);
|
||||
|
||||
// ---------------------------- //
|
||||
// -- Clock Dividing Counter -- //
|
||||
// ---------------------------- //
|
||||
|
||||
reg [15:0] count;
|
||||
reg enable; // Local Clock Enable
|
||||
|
||||
// -- RX Synchronizer --
|
||||
reg [SYNC_STAGES-1:0] rx_sync;
|
||||
reg rx_internal;
|
||||
|
||||
// ---------------- //
|
||||
// -- RX Signals -- //
|
||||
// ---------------- //
|
||||
|
||||
// State Machine Assignments
|
||||
localparam RX_WAIT = 0;
|
||||
localparam RX_CHECK_START = 1;
|
||||
localparam RX_RECEIVING = 2;
|
||||
localparam RX_WAIT_FOR_STOP = 3;
|
||||
|
||||
localparam RX_INITIAL_STATE = RX_WAIT;
|
||||
reg [1:0] rx_state = RX_INITIAL_STATE;
|
||||
|
||||
reg [4:0] rx_count; // Counts Over-sampling clock enables
|
||||
reg [2:0] rx_sampleCount; // Counts number of bits received
|
||||
|
||||
// These last two signals are used to make sure the "rx_valid" signal
|
||||
// is only asserted for one clock cycle.
|
||||
|
||||
reg rx_validInternal, rx_validLast;
|
||||
|
||||
// -----------------//
|
||||
// -- TX Signals -- //
|
||||
// -----------------//
|
||||
|
||||
// State Machine Assignments
|
||||
localparam TX_WAIT = 0;
|
||||
localparam TX_TRANSMITTING = 1;
|
||||
|
||||
localparam TX_INITIAL_STATE = TX_WAIT;
|
||||
reg tx_state = TX_INITIAL_STATE;
|
||||
|
||||
reg [9:0] tx_dataBuffer; // Capture Register for transmitted data
|
||||
reg [4:0] tx_count; // Counts over-sampling clock
|
||||
reg [3:0] tx_sampleCount; // Number of Bits Sent
|
||||
|
||||
/////////////////////
|
||||
// Implementations //
|
||||
/////////////////////
|
||||
|
||||
// ---------------------------- //
|
||||
// -- Misc Synchronous Logic -- //
|
||||
// ---------------------------- //
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
// Clock Divider
|
||||
if (reset) begin
|
||||
count <= 0;
|
||||
enable <= 0;
|
||||
end else if (count == CLK_DIV_COUNT - 1) begin
|
||||
count <= 0;
|
||||
enable <= 1;
|
||||
end else begin
|
||||
count <= count + 1;
|
||||
enable <= 0;
|
||||
end
|
||||
|
||||
// RX Synchronizer
|
||||
if (enable) begin
|
||||
{rx_sync,rx_internal} <= {rx, rx_sync};
|
||||
end
|
||||
|
||||
// Pulse Shortener for rx_valid signal
|
||||
rx_validLast <= rx_validInternal;
|
||||
end
|
||||
|
||||
// Pulse Shortner for rx_valid signal
|
||||
assign rx_valid = rx_validInternal & ~rx_validLast;
|
||||
|
||||
|
||||
// ---------------------- //
|
||||
// -- RX State Machine -- //
|
||||
// ---------------------- //
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
rx_state <= RX_INITIAL_STATE;
|
||||
rx_validInternal <= 0;
|
||||
end else if (enable) begin
|
||||
case (rx_state)
|
||||
|
||||
// Wait for the start bit. (RX = 0)
|
||||
|
||||
RX_WAIT: begin
|
||||
rx_validInternal <= 0;
|
||||
if (rx_internal == 0) begin
|
||||
rx_state <= RX_CHECK_START;
|
||||
rx_count <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Aligh with center of transmitted bit
|
||||
|
||||
RX_CHECK_START: begin
|
||||
|
||||
// Check if RX is still 0
|
||||
if (rx_count == (OSF >> 1) - 1 && rx_internal == 0) begin
|
||||
rx_state <= RX_RECEIVING;
|
||||
rx_count <= 0;
|
||||
rx_sampleCount <= 0;
|
||||
|
||||
// Faulty Start Bit
|
||||
end else if (rx_count == (OSF >> 1) - 1 && rx_internal == 1) begin
|
||||
rx_state <= RX_WAIT;
|
||||
|
||||
// Default Option: Count local clocks
|
||||
end else begin
|
||||
rx_count <= rx_count + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Sample in middle of received bit. Shift data into rx_data
|
||||
RX_RECEIVING: begin
|
||||
if (rx_count == OSF - 1) begin
|
||||
rx_count <= 0;
|
||||
rx_data <= {rx_internal, rx_data[7:1]};
|
||||
rx_sampleCount <= rx_sampleCount + 1;
|
||||
|
||||
// Check if this is the last bit of data
|
||||
if (rx_sampleCount == 7) begin
|
||||
rx_state <= RX_WAIT_FOR_STOP;
|
||||
end
|
||||
end else begin
|
||||
rx_count <= rx_count + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Wait until stop bit is received
|
||||
// Not the best logic in the world, but it works.
|
||||
RX_WAIT_FOR_STOP: begin
|
||||
if (rx_internal == 1'b1) begin
|
||||
rx_state <= RX_WAIT;
|
||||
rx_validInternal <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// In case something goes horribly wrong.
|
||||
default: begin
|
||||
rx_state <= RX_INITIAL_STATE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// ---------------------- //
|
||||
// -- TX State Machine -- //
|
||||
// ---------------------- //
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
tx_state <= TX_INITIAL_STATE;
|
||||
tx <= 1;
|
||||
end else begin
|
||||
case (tx_state)
|
||||
// Wait for start signal.
|
||||
// Register transmitted data and deassert ready.
|
||||
TX_WAIT: begin
|
||||
tx <= 1;
|
||||
if (tx_transmit) begin
|
||||
tx_dataBuffer <= {1'b1, tx_data, 1'b0};
|
||||
tx_count <= 0;
|
||||
tx_sampleCount <= 0;
|
||||
tx_ready <= 0;
|
||||
tx_state <= TX_TRANSMITTING;
|
||||
end else begin
|
||||
tx_ready <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Shift Out Data
|
||||
TX_TRANSMITTING: begin
|
||||
if (enable) begin
|
||||
if (tx_count == OSF - 1) begin
|
||||
tx_count <= 0;
|
||||
tx_sampleCount <= tx_sampleCount + 1;
|
||||
tx <= tx_dataBuffer[0];
|
||||
tx_dataBuffer <= {1'b1, tx_dataBuffer[9:1]};
|
||||
if (tx_sampleCount == 9) begin
|
||||
tx_state <= TX_WAIT;
|
||||
end
|
||||
end else begin
|
||||
tx_count <= tx_count + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
tx_state <= TX_WAIT;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
endmodule
|
Loading…
Reference in a new issue