-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- =============================================================================
-- Authors: Martin Zabel
-- Patrick Lehmann
--
-- Entity: UART Wrapper with Embedded FIFOs and Optional Flow Control
--
-- Description:
--
-- Small :abbr:`FIFO (first-in, first-out)` s are included in this module, if
-- larger or asynchronous transmit / receive FIFOs are required, then they must
-- be connected externally.
--
-- old comments:
-- :abbr:`UART (Universal Asynchronous Receiver Transmitter)` BAUD rate generator
-- bclk = bit clock is rising
-- bclk_x8 = bit clock times 8 is rising
--
--
-- License:
-- =============================================================================
-- Copyright 2008-2015 Technische Universitaet Dresden - Germany
-- Chair of VLSI-Design, Diagnostics and Architecture
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- =============================================================================
library IEEE;
use IEEE.std_logic_1164.all;
library PoC;
use PoC.vectors.all;
use PoC.physical.all;
use PoC.components.all;
use PoC.utils.all;
use PoC.uart.all;
entity [docs]uart_fifo is
generic (
-- Communication Parameters
CLOCK_FREQ : FREQ;
BAUDRATE : BAUD;
ADD_INPUT_SYNCHRONIZERS : boolean := TRUE;
-- Buffer Dimensioning
TX_MIN_DEPTH : positive := 16;
TX_ESTATE_BITS : natural := 0;
RX_MIN_DEPTH : positive := 16;
RX_FSTATE_BITS : natural := 0;
-- Flow Control
FLOWCONTROL : T_IO_UART_FLOWCONTROL_KIND := UART_FLOWCONTROL_NONE;
SWFC_XON_CHAR : std_logic_vector(7 downto 0) := x"11"; -- ^Q
SWFC_XON_TRIGGER : real := 0.0625;
SWFC_XOFF_CHAR : std_logic_vector(7 downto 0) := x"13"; -- ^S
SWFC_XOFF_TRIGGER : real := 0.75
);
port (
Clock : in std_logic;
Reset : in std_logic;
-- FIFO interface
TX_put : in std_logic;
TX_Data : in std_logic_vector(7 downto 0);
TX_Full : out std_logic;
TX_EmptyState : out std_logic_vector(imax(0, TX_ESTATE_BITS-1) downto 0);
RX_Valid : out std_logic;
RX_Data : out std_logic_vector(7 downto 0);
RX_got : in std_logic;
RX_FullState : out std_logic_vector(imax(0, RX_FSTATE_BITS-1) downto 0);
RX_Overflow : out std_logic;
-- External pins
UART_TX : out std_logic;
UART_RX : in std_logic;
UART_RTS : out std_logic;
UART_CTS : in std_logic
);
end entity;
architecture [docs]rtl of uart_fifo is
signal FC_TX_Strobe : std_logic;
signal FC_TX_Data : T_SLV_8;
signal FC_TX_got : std_logic;
signal FC_RX_put : std_logic;
signal FC_RX_Data : T_SLV_8;
signal TXFIFO_Valid : std_logic;
signal TXFIFO_Data : T_SLV_8;
signal RXFIFO_Full : std_logic;
signal TXUART_Full : std_logic;
signal RXUART_Strobe : std_logic;
signal RXUART_Data : T_SLV_8;
signal BitClock : std_logic;
signal BitClock_x8 : std_logic;
signal UART_RX_sync : std_logic;
begin
assert FALSE report "uart_fifo: BAUDRATE=: " & to_string(BAUDRATE, 3) severity NOTE;
-- ===========================================================================
-- Transmit and Receive FIFOs
-- ===========================================================================
TXFIFO : entity PoC.fifo_cc_got
generic map (
D_BITS => 8, -- Data Width
MIN_DEPTH => TX_MIN_DEPTH, -- Minimum FIFO Depth
DATA_REG => TRUE, -- Store Data Content in Registers
STATE_REG => FALSE, -- Registered Full/Empty Indicators
OUTPUT_REG => FALSE, -- Registered FIFO Output
ESTATE_WR_BITS => TX_ESTATE_BITS, -- Empty State Bits
FSTATE_RD_BITS => 0 -- Full State Bits
)
port map (
rst => Reset,
clk => Clock,
put => TX_put,
din => TX_Data,
full => TX_Full,
estate_wr => TX_EmptyState,
valid => TXFIFO_Valid,
dout => TXFIFO_Data,
got => FC_TX_got,
fstate_rd => open
);
RXFIFO : entity PoC.fifo_cc_got
generic map (
D_BITS => 8, -- Data Width
MIN_DEPTH => RX_MIN_DEPTH, -- Minimum FIFO Depth
DATA_REG => TRUE, -- Store Data Content in Registers
STATE_REG => FALSE, -- Registered Full/Empty Indicators
OUTPUT_REG => FALSE, -- Registered FIFO Output
ESTATE_WR_BITS => 0, -- Empty State Bits
FSTATE_RD_BITS => RX_FSTATE_BITS -- Full State Bits
)
port map (
rst => Reset,
clk => Clock,
put => FC_RX_put,
din => FC_RX_Data,
full => RXFIFO_Full,
estate_wr => open,
valid => RX_Valid,
dout => RX_Data,
got => RX_got,
fstate_rd => RX_FullState
);
genNOFC : if FLOWCONTROL = UART_FLOWCONTROL_NONE generate
signal Overflow_r : std_logic := '0';
begin
FC_TX_Strobe <= TXFIFO_Valid and not TXUART_Full;
FC_TX_Data <= TXFIFO_Data;
FC_TX_got <= FC_TX_Strobe;
FC_RX_put <= RXUART_Strobe;
FC_RX_Data <= RXUART_Data;
Overflow_r <= ffrs(q => Overflow_r, rst => Reset, set => (RXUART_Strobe and RXFIFO_Full)) when rising_edge(Clock);
RX_Overflow <= Overflow_r;
end generate;
-- ===========================================================================
-- Software Flow Control
-- ===========================================================================
genSWFC : if FLOWCONTROL = UART_FLOWCONTROL_XON_XOFF generate
constant XON : std_logic_vector(7 downto 0) := x"11"; -- ^Q
constant XOFF : std_logic_vector(7 downto 0) := x"13"; -- ^S
constant XON_TRIG : integer := integer(SWFC_XON_TRIGGER * real(2**RX_FSTATE_BITS));
constant XOFF_TRIG : integer := integer(SWFC_XOFF_TRIGGER * real(2**RX_FSTATE_BITS));
signal send_xoff : std_logic;
signal send_xon : std_logic;
signal set_xoff_transmitted : std_logic;
signal clr_xoff_transmitted : std_logic;
signal discard_user : std_logic;
signal set_overflow : std_logic;
-- registers
signal xoff_transmitted : std_logic;
begin
-- -- send XOFF only once when fill state goes above trigger level
-- send_xoff <= (not xoff_transmitted) when (rf_fs >= XOFF_TRIG) else '0';
-- set_xoff_transmitted <= tx_rdy when (rf_fs >= XOFF_TRIG) else '0';
--
-- -- send XON only once when receive FIFO is almost empty
-- send_xon <= xoff_transmitted when (rf_fs = XON_TRIG) else '0';
-- clr_xoff_transmitted <= tx_rdy when (rf_fs = XON_TRIG) else '0';
--
-- -- discard any user supplied XON/XOFF
-- discard_user <= '1' when (tf_dout = SWFC_XON_CHAR) or (tf_dout = SWFC_XOFF_CHAR) else '0';
--
-- -- tx / tf control
-- tx_din <= SWFC_XOFF_CHAR when (send_xoff = '1') else
-- SWFC_XON_CHAR when (send_xon = '1') else
-- tf_dout;
--
-- tx_stb <= send_xoff or send_xon or (tf_valid and (not discard_user));
-- tf_got <= (send_xoff nor send_xon) and
-- tf_valid and tx_rdy; -- always check tf_valid
--
-- -- rx / rf control
-- rf_put <= (not rf_full) and rx_dos; -- always check rf_full
-- rf_din <= rx_dout;
--
-- set_overflow <= rf_full and rx_dos;
--
-- -- registers
-- process (Clock)
-- begin -- process
-- if rising_edge(Clock) then
-- if (rst or set_xoff_transmitted) = '1' then
-- -- send a XON after reset
-- xoff_transmitted <= '1';
-- elsif clr_xoff_transmitted = '1' then
-- xoff_transmitted <= '0';
-- end if;
--
-- if rst = '1' then
-- overflow <= '0';
-- elsif set_overflow = '1' then
-- overflow <= '1';
-- end if;
-- end if;
-- end process;
end generate;
-- ===========================================================================
-- Hardware Flow Control
-- ===========================================================================
genHWFC1 : if FLOWCONTROL = UART_FLOWCONTROL_RTS_CTS generate
begin
end generate;
-- ===========================================================================
-- Hardware Flow Control
-- ===========================================================================
genHWFC2 : if FLOWCONTROL = UART_FLOWCONTROL_RTR_CTS generate
begin
end generate;
-- ===========================================================================
-- BitClock, Transmitter, Receiver
-- ===========================================================================
genNoSync : if not ADD_INPUT_SYNCHRONIZERS generate
UART_RX_sync <= UART_RX;
end generate;
genSync : if ADD_INPUT_SYNCHRONIZERS generate
sync_i : entity PoC.sync_Bits
port map (
Clock => Clock, -- Clock to be synchronized to
Input(0) => UART_RX, -- Data to be synchronized
Output(0) => UART_RX_sync -- synchronised data
);
end generate;
-- ===========================================================================
-- BitClock, Transmitter, Receiver
-- ===========================================================================
bclk : entity PoC.uart_bclk
generic map (
CLOCK_FREQ => CLOCK_FREQ,
BAUDRATE => BAUDRATE
)
port map (
clk => Clock,
rst => Reset,
bclk => BitClock,
bclk_x8 => BitClock_x8
);
TX : entity PoC.uart_tx
port map (
clk => Clock,
rst => Reset,
bclk => BitClock,
tx => UART_TX,
di => FC_TX_Data,
put => FC_TX_Strobe,
ful => TXUART_Full
);
RX : entity PoC.uart_rx
port map (
clk => Clock,
rst => Reset,
bclk_x8 => BitClock_x8,
rx => UART_RX_sync,
do => RXUART_Data,
stb => RXUART_Strobe
);
end architecture;