diff options
Diffstat (limited to 'testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl')
-rw-r--r-- | testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl new file mode 100644 index 0000000..e1c1c9e --- /dev/null +++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl @@ -0,0 +1,320 @@ +-- 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 +-- +-- Module: UART Wrapper with Embedded FIFOs and Optional Flow Control +-- +-- Description: +-- ------------------------------------ +-- Small FIFOs are included in this module, if larger or asynchronous +-- transmit / receive FIFOs are required, then they must be connected +-- externally. +-- +-- old comments: +-- UART 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 for 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.uart.all; + + +entity uart_fifo is + generic ( + CLOCK_FREQ : FREQ := 100 MHz; + BAUDRATE : BAUD := 115200 Bd; + FLOWCONTROL : T_IO_UART_FLOWCONTROL_KIND := UART_FLOWCONTROL_NONE; + TX_MIN_DEPTH : POSITIVE := 16; + TX_ESTATE_BITS : NATURAL := 1; + RX_MIN_DEPTH : POSITIVE := 16; + RX_FSTATE_BITS : NATURAL := 1; + RX_OUT_REGS : BOOLEAN := FALSE; + ADD_INPUT_SYNCHRONIZERS : BOOLEAN := TRUE; + + 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(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(RX_FSTATE_BITS - 1 downto 0); + RX_Overflow : out std_logic; + + -- External pins + UART_TX : out std_logic; + UART_RX : in std_logic + ); +end entity; + + +architecture 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_Ready : 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 TXUART_Ready; + FC_TX_Data <= TXFIFO_Data; + FC_TX_got <= TXFIFO_Valid and TXUART_Ready; + + 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 (ADD_INPUT_SYNCHRONIZERS = FALSE) generate + UART_RX_sync <= UART_RX; + end generate; + genSync: if (ADD_INPUT_SYNCHRONIZERS = TRUE) 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, + stb => FC_TX_Strobe, + din => FC_TX_Data, + rdy => TXUART_Ready, + txd => UART_TX + ); + + RX : entity PoC.uart_rx + generic map ( + OUT_REGS => RX_OUT_REGS + ) + port map ( + clk => Clock, + rst => Reset, + bclk_x8 => BitClock_x8, + dos => RXUART_Strobe, + dout => RXUART_Data, + rxd => UART_RX_sync + ); +end; |