URL
https://opencores.org/ocsvn/wb_uart/wb_uart/trunk
Subversion Repositories wb_uart
Compare Revisions
- This comparison shows the changes necessary to convert path
/wb_uart
- from Rev 7 to Rev 8
- ↔ Reverse comparison
Rev 7 → Rev 8
/trunk/src/wb8_uart_16750.vhd
0,0 → 1,1056
-- |
-- UART 16750 |
-- |
-- Author: Federico Aglietti, www.ipdesign.eu |
-- Version: 2.0 |
-- Date: 30.08.2009 |
-- WishBone 8-bit bus compliant |
-- |
-- Author: Sebastian Witt |
-- Date: 29.01.2008 |
-- Version: 1.4 |
-- |
-- History: 1.0 - Initial version |
-- 1.1 - THR empty interrupt register connected to RST |
-- 1.2 - Registered outputs |
-- 1.3 - Automatic flow control |
-- 1.4 - De-assert IIR FIFO64 when FIFO is disabled |
-- |
-- |
-- This code is free software; you can redistribute it and/or |
-- modify it under the terms of the GNU Lesser General Public |
-- License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- |
-- This code is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
-- Lesser General Public License for more details. |
-- |
-- You should have received a copy of the GNU Lesser General Public |
-- License along with this library; if not, write to the |
-- Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
-- Boston, MA 02111-1307 USA |
-- |
|
LIBRARY IEEE; |
USE IEEE.std_logic_1164.all; |
USE IEEE.numeric_std.all; |
|
-- Serial UART |
entity uart_16750 is |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
BAUDCE : in std_logic; -- Baudrate generator clock enable |
WB_CYC : in std_logic; -- Chip select |
WB_STB : in std_logic; -- Chip select |
WB_WE : in std_logic; -- Write/NotRead to/from UART |
WB_ADR : in std_logic_vector(31 downto 0); -- Address input |
WB_DIN : in std_logic_vector(7 downto 0); -- Data bus input |
WB_DOUT : out std_logic_vector(7 downto 0); -- Data bus output |
WB_ACK : out std_logic; -- Transaction ACK |
INT : out std_logic; -- Interrupt output |
OUT1N : out std_logic; -- Output 1 |
OUT2N : out std_logic; -- Output 2 |
RCLK : in std_logic; -- Receiver clock (16x baudrate) |
BAUDOUTN : out std_logic; -- Baudrate generator output (16x baudrate) |
RTSN : out std_logic; -- RTS output |
DTRN : out std_logic; -- DTR output |
CTSN : in std_logic; -- CTS input |
DSRN : in std_logic; -- DSR input |
DCDN : in std_logic; -- DCD input |
RIN : in std_logic; -- RI input |
SIN : in std_logic; -- Receiver input |
SOUT : out std_logic -- Transmitter output |
); |
end uart_16750; |
|
architecture rtl of uart_16750 is |
-- UART transmitter |
component uart_transmitter is |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
TXCLK : in std_logic; -- Transmitter clock (2x baudrate) |
TXSTART : in std_logic; -- Start transmitter |
CLEAR : in std_logic; -- Clear transmitter state |
WLS : in std_logic_vector(1 downto 0); -- Word length select |
STB : in std_logic; -- Number of stop bits |
PEN : in std_logic; -- Parity enable |
EPS : in std_logic; -- Even parity select |
SP : in std_logic; -- Stick parity |
BC : in std_logic; -- Break control |
DIN : in std_logic_vector(7 downto 0); -- Input data |
TXFINISHED : out std_logic; -- Transmitter operation finished |
SOUT : out std_logic -- Transmitter output |
); |
end component; |
-- UART receiver |
component uart_receiver is |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
RXCLK : in std_logic; -- Receiver clock (16x baudrate) |
RXCLEAR : in std_logic; -- Reset receiver state |
WLS : in std_logic_vector(1 downto 0); -- Word length select |
STB : in std_logic; -- Number of stop bits |
PEN : in std_logic; -- Parity enable |
EPS : in std_logic; -- Even parity select |
SP : in std_logic; -- Stick parity |
SIN : in std_logic; -- Receiver input |
PE : out std_logic; -- Parity error |
FE : out std_logic; -- Framing error |
BI : out std_logic; -- Break interrupt |
DOUT : out std_logic_vector(7 downto 0); -- Output data |
RXFINISHED : out std_logic -- Receiver operation finished |
); |
end component; |
-- UART interrupt control |
component uart_interrupt is |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
IER : in std_logic_vector(3 downto 0); -- IER 3:0 |
LSR : in std_logic_vector(4 downto 0); -- LSR 4:0 |
THI : in std_logic; -- Transmitter holding register empty interrupt |
RDA : in std_logic; -- Receiver data available |
CTI : in std_logic; -- Character timeout indication |
AFE : in std_logic; -- Automatic flow control enable |
MSR : in std_logic_vector(3 downto 0); -- MSR 3:0 |
IIR : out std_logic_vector(3 downto 0); -- IIR 3:0 |
INT : out std_logic -- Interrupt |
); |
end component; |
-- UART baudrate generator |
component uart_baudgen is |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
CE : in std_logic; -- Clock enable |
CLEAR : in std_logic; -- Reset generator (synchronization) |
DIVIDER : in std_logic_vector(15 downto 0); -- Clock divider |
BAUDTICK : out std_logic -- 16xBaudrate tick |
); |
end component; |
-- UART FIFO |
component slib_fifo is |
generic ( |
WIDTH : integer := 8; -- FIFO width |
SIZE_E : integer := 6 -- FIFO size (2^SIZE_E) |
); |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
CLEAR : in std_logic; -- Clear FIFO |
WRITE : in std_logic; -- Write to FIFO |
READ : in std_logic; -- Read from FIFO |
D : in std_logic_vector(WIDTH-1 downto 0); -- FIFO input |
Q : out std_logic_vector(WIDTH-1 downto 0); -- FIFO output |
EMPTY : out std_logic; -- FIFO is empty |
FULL : out std_logic; -- FIFO is full |
USAGE : out std_logic_vector(SIZE_E-1 downto 0) -- FIFO usage |
); |
end component; |
-- Edge detect |
component slib_edge_detect is |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
D : in std_logic; -- Signal input |
RE : out std_logic; -- Rising edge detected |
FE : out std_logic -- Falling edge detected |
); |
end component; |
-- Input synchronization |
component slib_input_sync is |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
D : in std_logic; -- Signal input |
Q : out std_logic -- Signal output |
); |
end component; |
-- Input filter |
component slib_input_filter is |
generic ( |
SIZE : natural := 4 -- Filter width |
); |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
CE : in std_logic; -- Clock enable |
D : in std_logic; -- Signal input |
Q : out std_logic -- Signal output |
); |
end component; |
-- Clock enable generation |
component slib_clock_div is |
generic ( |
RATIO : integer := 8 -- Clock divider ratio |
); |
port ( |
CLK : in std_logic; -- Clock |
RST : in std_logic; -- Reset |
CE : in std_logic; -- Clock enable input |
Q : out std_logic -- New clock enable output |
); |
end component; |
|
-- Global device signals |
signal iWriteFE : std_logic; -- Write falling edge |
signal iReadFE : std_logic; -- Read falling edge |
signal iWrite : std_logic; -- Write to UART |
signal iRead : std_logic; -- Read from UART |
signal iA : std_logic_vector(2 downto 0); -- UART register address |
signal iDIN : std_logic_vector(7 downto 0); -- UART data input |
|
-- UART registers read/write signals |
signal iRBRRead : std_logic; -- Read from RBR |
signal iTHRWrite : std_logic; -- Write to THR |
signal iDLLWrite : std_logic; -- Write to DLL |
signal iDLMWrite : std_logic; -- Write to DLM |
signal iIERWrite : std_logic; -- Write to IER |
signal iIIRRead : std_logic; -- Read from IIR |
signal iFCRWrite : std_logic; -- Write to FCR |
signal iLCRWrite : std_logic; -- Write to LCR |
signal iMCRWrite : std_logic; -- Write to MCR |
signal iLSRRead : std_logic; -- Read from LSR |
signal iMSRRead : std_logic; -- Read from MSR |
signal iSCRWrite : std_logic; -- Write to SCR |
|
-- UART registers |
signal iTSR : std_logic_vector(7 downto 0); -- Transmitter holding register |
signal iRBR : std_logic_vector(7 downto 0); -- Receiver buffer register |
signal iDLL : std_logic_vector(7 downto 0); -- Divisor latch LSB |
signal iDLM : std_logic_vector(7 downto 0); -- Divisor latch MSB |
signal iIER : std_logic_vector(7 downto 0); -- Interrupt enable register |
signal iIIR : std_logic_vector(7 downto 0); -- Interrupt identification register |
signal iFCR : std_logic_vector(7 downto 0); -- FIFO control register |
signal iLCR : std_logic_vector(7 downto 0); -- Line control register |
signal iMCR : std_logic_vector(7 downto 0); -- Modem control register |
signal iLSR : std_logic_vector(7 downto 0); -- Line status register |
signal iMSR : std_logic_vector(7 downto 0); -- Modem status register |
signal iSCR : std_logic_vector(7 downto 0); -- Scratch register |
|
-- IER register signals |
signal iIER_ERBI : std_logic; -- IER: Enable received data available interrupt |
signal iIER_ETBEI : std_logic; -- IER: Enable transmitter holding register empty interrupt |
signal iIER_ELSI : std_logic; -- IER: Enable receiver line status interrupt |
signal iIER_EDSSI : std_logic; -- IER: Enable modem status interrupt |
|
-- IIR register signals |
signal iIIR_PI : std_logic; -- IIR: Pending interrupt |
signal iIIR_ID0 : std_logic; -- IIR: Interrupt ID0 |
signal iIIR_ID1 : std_logic; -- IIR: Interrupt ID1 |
signal iIIR_ID2 : std_logic; -- IIR: Interrupt ID2 |
signal iIIR_FIFO64 : std_logic; -- IIR: 64 byte FIFO enabled |
|
-- FCR register signals |
signal iFCR_FIFOEnable : std_logic; -- FCR: FIFO enable |
signal iFCR_RXFIFOReset : std_logic; -- FCR: Receiver FIFO reset |
signal iFCR_TXFIFOReset : std_logic; -- FCR: Transmitter FIFO reset |
signal iFCR_DMAMode : std_logic; -- FCR: DMA mode select |
signal iFCR_FIFO64E : std_logic; -- FCR: 64 byte FIFO enable |
signal iFCR_RXTrigger : std_logic_vector(1 downto 0); -- FCR: Receiver trigger |
|
-- LCR register signals |
signal iLCR_WLS : std_logic_vector(1 downto 0); -- LCR: Word length select |
signal iLCR_STB : std_logic; -- LCR: Number of stop bits |
signal iLCR_PEN : std_logic; -- LCR: Parity enable |
signal iLCR_EPS : std_logic; -- LCR: Even parity select |
signal iLCR_SP : std_logic; -- LCR: Sticky parity |
signal iLCR_BC : std_logic; -- LCR: Break control |
signal iLCR_DLAB : std_logic; -- LCR: Divisor latch access bit |
|
-- MCR register signals |
signal iMCR_DTR : std_logic; -- MCR: Data terminal ready |
signal iMCR_RTS : std_logic; -- MCR: Request to send |
signal iMCR_OUT1 : std_logic; -- MCR: OUT1 |
signal iMCR_OUT2 : std_logic; -- MCR: OUT2 |
signal iMCR_LOOP : std_logic; -- MCR: Loop |
signal iMCR_AFE : std_logic; -- MCR: Auto flow control enable |
|
-- LSR register signals |
signal iLSR_DR : std_logic; -- LSR: Data ready |
signal iLSR_OE : std_logic; -- LSR: Overrun error |
signal iLSR_PE : std_logic; -- LSR: Parity error |
signal iLSR_FE : std_logic; -- LSR: Framing error |
signal iLSR_BI : std_logic; -- LSR: Break Interrupt |
signal iLSR_THRE : std_logic; -- LSR: Transmitter holding register empty |
signal iLSR_TEMT : std_logic; -- LSR: Transmitter empty |
signal iLSR_FIFOERR : std_logic; -- LSR: Error in receiver FIFO |
|
-- MSR register signals |
signal iMSR_dCTS : std_logic; -- MSR: Delta CTS |
signal iMSR_dDSR : std_logic; -- MSR: Delta DSR |
signal iMSR_TERI : std_logic; -- MSR: Trailing edge ring indicator |
signal iMSR_dDCD : std_logic; -- MSR: Delta DCD |
signal iMSR_CTS : std_logic; -- MSR: CTS |
signal iMSR_DSR : std_logic; -- MSR: DSR |
signal iMSR_RI : std_logic; -- MSR: RI |
signal iMSR_DCD : std_logic; -- MSR: DCD |
|
-- UART MSR signals |
signal iCTSNs : std_logic; -- Synchronized CTSN input |
signal iDSRNs : std_logic; -- Synchronized DSRN input |
signal iDCDNs : std_logic; -- Synchronized DCDN input |
signal iRINs : std_logic; -- Synchronized RIN input |
signal iCTSn : std_logic; -- Filtered CTSN input |
signal iDSRn : std_logic; -- Filtered DSRN input |
signal iDCDn : std_logic; -- Filtered DCDN input |
signal iRIn : std_logic; -- Filtered RIN input |
signal iCTSnRE : std_logic; -- CTSn rising edge |
signal iCTSnFE : std_logic; -- CTSn falling edge |
signal iDSRnRE : std_logic; -- DSRn rising edge |
signal iDSRnFE : std_logic; -- DSRn falling edge |
signal iDCDnRE : std_logic; -- DCDn rising edge |
signal iDCDnFE : std_logic; -- DCDn falling edge |
signal iRInRE : std_logic; -- RIn rising edge |
signal iRInFE : std_logic; -- RIn falling edge |
|
-- UART baudrate generation signals |
signal iBaudgenDiv : std_logic_vector(15 downto 0); -- Baudrate divider |
signal iBaudtick16x : std_logic; -- 16x Baudrate output from baudrate generator |
signal iBaudtick2x : std_logic; -- 2x Baudrate for transmitter |
signal iRCLK : std_logic; -- 16x Baudrate for receiver |
|
-- UART FIFO signals |
signal iTXFIFOClear : std_logic; -- Clear TX FIFO |
signal iTXFIFOWrite : std_logic; -- Write to TX FIFO |
signal iTXFIFORead : std_logic; -- Read from TX FIFO |
signal iTXFIFOEmpty : std_logic; -- TX FIFO is empty |
signal iTXFIFOFull : std_logic; -- TX FIFO is full |
signal iTXFIFO16Full : std_logic; -- TX FIFO 16 byte mode is full |
signal iTXFIFO64Full : std_logic; -- TX FIFO 64 byte mode is full |
signal iTXFIFOUsage : std_logic_vector(5 downto 0); -- RX FIFO usage |
signal iTXFIFOQ : std_logic_vector(7 downto 0); -- TX FIFO output |
signal iRXFIFOClear : std_logic; -- Clear RX FIFO |
signal iRXFIFOWrite : std_logic; -- Write to RX FIFO |
signal iRXFIFORead : std_logic; -- Read from RX FIFO |
signal iRXFIFOEmpty : std_logic; -- RX FIFO is empty |
signal iRXFIFOFull : std_logic; -- RX FIFO is full |
signal iRXFIFO16Full : std_logic; -- RX FIFO 16 byte mode is full |
signal iRXFIFO64Full : std_logic; -- RX FIFO 64 byte mode is full |
signal iRXFIFOD : std_logic_vector(10 downto 0); -- RX FIFO input |
signal iRXFIFOQ : std_logic_vector(10 downto 0); -- RX FIFO output |
signal iRXFIFOUsage : std_logic_vector(5 downto 0); -- RX FIFO usage |
signal iRXFIFOTrigger : std_logic; -- FIFO trigger level reached |
signal iRXFIFO16Trigger : std_logic; -- FIFO 16 byte mode trigger level reached |
signal iRXFIFO64Trigger : std_logic; -- FIFO 64 byte mode trigger level reached |
signal iRXFIFOPE : std_logic; -- Parity error from FIFO |
signal iRXFIFOFE : std_logic; -- Frame error from FIFO |
signal iRXFIFOBI : std_logic; -- Break interrupt from FIFO |
|
-- UART transmitter signals |
signal iSOUT : std_logic; -- Transmitter output |
signal iTXStart : std_logic; -- Start transmitter |
signal iTXClear : std_logic; -- Clear transmitter status |
signal iTXFinished : std_logic; -- TX finished, character transmitted |
signal iTXRunning : std_logic; -- TX in progress |
|
-- UART receiver signals |
signal iSINr : std_logic; -- Synchronized SIN input |
signal iSIN : std_logic; -- Receiver input |
signal iRXFinished : std_logic; -- RX finished, character received |
signal iRXClear : std_logic; -- Clear receiver status |
signal iRXData : std_logic_vector(7 downto 0); -- RX data |
signal iRXPE : std_logic; -- RX parity error |
signal iRXFE : std_logic; -- RX frame error |
signal iRXBI : std_logic; -- RX break interrupt |
|
-- UART control signals |
signal iFERE : std_logic; -- Frame error detected |
signal iPERE : std_logic; -- Parity error detected |
signal iBIRE : std_logic; -- Break interrupt detected |
signal iFECounter : integer range 0 to 64; -- FIFO error counter |
signal iFEIncrement : std_logic; -- FIFO error counter increment |
signal iFEDecrement : std_logic; -- FIFO error counter decrement |
signal iRDAInterrupt : std_logic; -- Receiver data available interrupt (DA or FIFO trigger level) |
signal iTimeoutCount : unsigned(5 downto 0); -- Character timeout counter (FIFO mode) |
signal iCharTimeout : std_logic; -- Character timeout indication (FIFO mode) |
signal iLSR_THRERE : std_logic; -- LSR THRE rising edge for interrupt generation |
signal iTHRInterrupt : std_logic; -- Transmitter holding register empty interrupt |
signal iTXEnable : std_logic; -- Transmitter enable signal |
signal iRTS : std_logic; -- Internal RTS signal with/without automatic flow control |
|
signal WB_ACK_R : std_logic; |
|
|
begin |
|
|
iWrite <= '1' when WB_CYC = '1' and WB_STB = '1' and WB_WE = '1' and WB_ACK_r='1' else '0'; |
iRead <= '1' when WB_CYC = '1' and WB_STB = '1' and WB_WE = '0' and WB_ACK_r='1' else '0'; |
|
-- UART registers read/write signals |
iRBRRead <= '1' when iRead = '1' and iA = "000" and iLCR_DLAB = '0' else '0'; |
iTHRWrite <= '1' when iWrite = '1' and iA = "000" and iLCR_DLAB = '0' else '0'; |
iDLLWrite <= '1' when iWrite = '1' and iA = "000" and iLCR_DLAB = '1' else '0'; |
iDLMWrite <= '1' when iWrite = '1' and iA = "001" and iLCR_DLAB = '1' else '0'; |
iIERWrite <= '1' when iWrite = '1' and iA = "001" and iLCR_DLAB = '0' else '0'; |
iIIRRead <= '1' when iRead = '1' and iA = "010" else '0'; |
iFCRWrite <= '1' when iWrite = '1' and iA = "010" else '0'; |
iLCRWrite <= '1' when iWrite = '1' and iA = "011" else '0'; |
iMCRWrite <= '1' when iWrite = '1' and iA = "100" else '0'; |
iLSRRead <= '1' when iRead = '1' and iA = "101" else '0'; |
iMSRRead <= '1' when iRead = '1' and iA = "110" else '0'; |
iSCRWrite <= '1' when iWrite = '1' and iA = "111" else '0'; |
|
-- Async. input synchronization |
UART_IS_SIN: slib_input_sync port map (CLK, RST, SIN, iSINr); |
UART_IS_CTS: slib_input_sync port map (CLK, RST, CTSN, iCTSNs); |
UART_IS_DSR: slib_input_sync port map (CLK, RST, DSRN, iDSRNs); |
UART_IS_DCD: slib_input_sync port map (CLK, RST, DCDN, iDCDNs); |
UART_IS_RI: slib_input_sync port map (CLK, RST, RIN, iRINs); |
|
-- Input filter for UART control signals |
UART_IF_CTS: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iCTSNs, iCTSn); |
UART_IF_DSR: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iDSRNs, iDSRn); |
UART_IF_DCD: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iDCDNs, iDCDn); |
UART_IF_RI: slib_input_filter generic map (SIZE => 2) port map (CLK, RST, iBaudtick2x, iRINs, iRIn); |
|
|
-- Global device signals |
iA(2 downto 0) <= WB_ADR(2 downto 0); |
iDIN <= WB_DIN; |
|
-- WB_ACK <= WB_CYC and WB_STB after 1 ns; |
WB_ACK <= WB_ACK_r; |
|
WB_ACK_PR: process (CLK, RST) |
begin |
if (RST = '1') then |
WB_ACK_r <= '1'; |
elsif (CLK'event and CLK = '1') then |
if (WB_ACK_r = '1') then |
WB_ACK_r <= '0'; |
elsif (WB_CYC='1' and WB_STB='1') then |
WB_ACK_r <= '1'; |
end if; |
end if; |
end process; |
|
|
-- Divisor latch register |
UART_DLR: process (CLK, RST) |
begin |
if (RST = '1') then |
iDLL <= (others => '0'); |
iDLM <= (others => '0'); |
elsif (CLK'event and CLK = '1') then |
if (iDLLWrite = '1') then |
iDLL <= iDIN; |
end if; |
if (iDLMWrite = '1') then |
iDLM <= iDIN; |
end if; |
end if; |
end process; |
|
-- Interrupt enable register |
UART_IER: process (CLK, RST) |
begin |
if (RST = '1') then |
iIER(3 downto 0) <= (others => '0'); |
elsif (CLK'event and CLK = '1') then |
if (iIERWrite = '1') then |
iIER(3 downto 0) <= iDIN(3 downto 0); |
end if; |
end if; |
end process; |
|
iIER_ERBI <= iIER(0); |
iIER_ETBEI <= iIER(1); |
iIER_ELSI <= iIER(2); |
iIER_EDSSI <= iIER(3); |
iIER(7 downto 4) <= (others => '0'); |
|
-- Interrupt control and IIR |
UART_IIC: uart_interrupt port map (CLK => CLK, |
RST => RST, |
IER => iIER(3 downto 0), |
LSR => iLSR(4 downto 0), |
THI => iTHRInterrupt, |
RDA => iRDAInterrupt, |
CTI => iCharTimeout, |
AFE => iMCR_AFE, |
MSR => iMSR(3 downto 0), |
IIR => iIIR(3 downto 0), |
INT => INT |
); |
-- THR empty interrupt |
UART_IIC_THRE_ED: slib_edge_detect port map (CLK => CLK, RST => RST, D => iLSR_THRE, RE => iLSR_THRERE); |
UART_IIC_THREI: process (CLK, RST) |
begin |
if (RST = '1') then |
iTHRInterrupt <= '0'; |
elsif (CLK'event and CLK = '1') then |
if (iLSR_THRERE = '1' or iFCR_TXFIFOReset = '1' or (iIERWrite = '1' and iDIN(1) = '1' and iLSR_THRE = '1')) then |
iTHRInterrupt <= '1'; -- Set on THRE, TX FIFO reset (FIFO enable) or ETBEI enable |
elsif ((iIIRRead = '1' and iIIR(3 downto 1) = "001") or iTHRWrite = '1') then |
iTHRInterrupt <= '0'; -- Clear on IIR read (if source of interrupt) or THR write |
end if; |
end if; |
end process; |
|
iRDAInterrupt <= '1' when (iFCR_FIFOEnable = '0' and iLSR_DR = '1') or |
(iFCR_FIFOEnable = '1' and iRXFIFOTrigger = '1') else '0'; |
iIIR_PI <= iIIR(0); |
iIIR_ID0 <= iIIR(1); |
iIIR_ID1 <= iIIR(2); |
iIIR_ID2 <= iIIR(3); |
iIIR_FIFO64 <= iIIR(5); |
iIIR(4) <= '0'; |
iIIR(5) <= iFCR_FIFO64E when iFCR_FIFOEnable = '1' else '0'; |
iIIR(6) <= iFCR_FIFOEnable; |
iIIR(7) <= iFCR_FIFOEnable; |
|
-- Character timeout indication |
UART_CTI: process (CLK, RST) |
begin |
if (RST = '1') then |
iTimeoutCount <= (others => '0'); |
iCharTimeout <= '0'; |
elsif (CLK'event and CLK = '1') then |
if (iRXFIFOEmpty = '1' or iRBRRead = '1' or iRXFIFOWrite = '1') then |
iTimeoutCount <= (others => '0'); |
elsif (iRXFIFOEmpty = '0' and iBaudtick2x = '1' and iTimeoutCount(5) = '0') then |
iTimeoutCount <= iTimeoutCount + 1; |
end if; |
|
-- Timeout indication |
if (iFCR_FIFOEnable = '1') then |
if (iRBRRead = '1') then |
iCharTimeout <= '0'; |
elsif (iTimeoutCount(5) = '1') then |
iCharTimeout <= '1'; |
end if; |
else |
iCharTimeout <= '0'; |
end if; |
end if; |
end process; |
|
-- FIFO control register |
UART_FCR: process (CLK, RST) |
begin |
if (RST = '1') then |
iFCR_FIFOEnable <= '0'; |
iFCR_RXFIFOReset <= '0'; |
iFCR_TXFIFOReset <= '0'; |
iFCR_DMAMode <= '0'; |
iFCR_FIFO64E <= '0'; |
iFCR_RXTrigger <= (others => '0'); |
elsif (CLK'event and CLK = '1') then |
-- FIFO reset pulse only |
iFCR_RXFIFOReset <= '0'; |
iFCR_TXFIFOReset <= '0'; |
|
if (iFCRWrite = '1') then |
iFCR_FIFOEnable <= iDIN(0); |
iFCR_DMAMode <= iDIN(3); |
iFCR_RXTrigger <= iDIN(7 downto 6); |
|
if (iLCR_DLAB = '1') then |
iFCR_FIFO64E <= iDIN(5); |
end if; |
|
-- RX FIFO reset control, reset on FIFO enable/disable |
if (iDIN(1) = '1' or (iFCR_FIFOEnable = '0' and iDIN(0) = '1') or (iFCR_FIFOEnable = '1' and iDIN(0) = '0')) then |
iFCR_RXFIFOReset <= '1'; |
end if; |
-- TX FIFO reset control, reset on FIFO enable/disable |
if (iDIN(2) = '1' or (iFCR_FIFOEnable = '0' and iDIN(0) = '1') or (iFCR_FIFOEnable = '1' and iDIN(0) = '0')) then |
iFCR_TXFIFOReset <= '1'; |
end if; |
end if; |
end if; |
end process; |
|
iFCR(0) <= iFCR_FIFOEnable; |
iFCR(1) <= iFCR_RXFIFOReset; |
iFCR(2) <= iFCR_TXFIFOReset; |
iFCR(3) <= iFCR_DMAMode; |
iFCR(4) <= '0'; |
iFCR(5) <= iFCR_FIFO64E; |
iFCR(7 downto 6) <= iFCR_RXTrigger; |
|
-- Line control register |
UART_LCR: process (CLK, RST) |
begin |
if (RST = '1') then |
iLCR <= (others => '0'); |
elsif (CLK'event and CLK = '1') then |
if (iLCRWrite = '1') then |
iLCR <= iDIN; |
end if; |
end if; |
end process; |
|
iLCR_WLS <= iLCR(1 downto 0); |
iLCR_STB <= iLCR(2); |
iLCR_PEN <= iLCR(3); |
iLCR_EPS <= iLCR(4); |
iLCR_SP <= iLCR(5); |
iLCR_BC <= iLCR(6); |
iLCR_DLAB <= iLCR(7); |
|
-- Modem control register |
UART_MCR: process (CLK, RST) |
begin |
if (RST = '1') then |
iMCR(5 downto 0) <= (others => '0'); |
elsif (CLK'event and CLK = '1') then |
if (iMCRWrite = '1') then |
iMCR(5 downto 0) <= iDIN(5 downto 0); |
end if; |
end if; |
end process; |
|
iMCR_DTR <= iMCR(0); |
iMCR_RTS <= iMCR(1); |
iMCR_OUT1 <= iMCR(2); |
iMCR_OUT2 <= iMCR(3); |
iMCR_LOOP <= iMCR(4); |
iMCR_AFE <= iMCR(5); |
iMCR(6) <= '0'; |
iMCR(7) <= '0'; |
|
-- Line status register |
UART_LSR: process (CLK, RST) |
begin |
if (RST = '1') then |
iLSR_OE <= '0'; |
iLSR_PE <= '0'; |
iLSR_FE <= '0'; |
iLSR_BI <= '0'; |
iFECounter <= 0; |
elsif (CLK'event and CLK = '1') then |
-- Overrun error |
if ((iFCR_FIFOEnable = '0' and iLSR_DR = '1' and iRXFinished = '1') or |
(iFCR_FIFOEnable = '1' and iRXFIFOFull = '1' and iRXFinished = '1')) then |
iLSR_OE <= '1'; |
elsif (iLSRRead = '1') then |
iLSR_OE <= '0'; |
end if; |
-- Parity error |
if (iPERE = '1') then |
iLSR_PE <= '1'; |
elsif (iLSRRead = '1') then |
iLSR_PE <= '0'; |
end if; |
-- Frame error |
if (iFERE = '1') then |
iLSR_FE <= '1'; |
elsif (iLSRRead = '1') then |
iLSR_FE <= '0'; |
end if; |
-- Break interrupt |
if (iBIRE = '1') then |
iLSR_BI <= '1'; |
elsif (iLSRRead = '1') then |
iLSR_BI <= '0'; |
end if; |
|
-- FIFO error |
-- Datasheet: Cleared by LSR read when no subsequent errors in FIFO |
-- Observed: Cleared when no subsequent errors in FIFO |
if (iFECounter /= 0) then |
iLSR_FIFOERR <= '1'; |
--elsif (iLSRRead = '1' and iFECounter = 0 and not (iRXFIFOEmpty = '0' and iRXFIFOQ(10 downto 8) /= "000")) then |
elsif (iRXFIFOEmpty = '1' or iRXFIFOQ(10 downto 8) = "000") then |
iLSR_FIFOERR <= '0'; |
end if; |
|
-- FIFO error counter |
if (iRXFIFOClear = '1') then |
iFECounter <= 0; |
else |
if (iFEIncrement = '1' and iFEDecrement = '0') then |
iFECounter <= iFECounter + 1; |
elsif (iFEIncrement = '0' and iFEDecrement = '1') then |
iFECounter <= iFECounter - 1; |
end if; |
end if; |
end if; |
end process; |
|
iRXFIFOPE <= '1' when iRXFIFOEmpty = '0' and iRXFIFOQ(8) = '1' else '0'; |
iRXFIFOFE <= '1' when iRXFIFOEmpty = '0' and iRXFIFOQ(9) = '1' else '0'; |
iRXFIFOBI <= '1' when iRXFIFOEmpty = '0' and iRXFIFOQ(10) = '1' else '0'; |
UART_PEDET: slib_edge_detect port map (CLK, RST, iRXFIFOPE, iPERE); |
UART_FEDET: slib_edge_detect port map (CLK, RST, iRXFIFOFE, iFERE); |
UART_BIDET: slib_edge_detect port map (CLK, RST, iRXFIFOBI, iBIRE); |
iFEIncrement <= '1' when iRXFIFOWrite = '1' and iRXFIFOD(10 downto 8) /= "000" else '0'; |
iFEDecrement <= '1' when iFECounter /= 0 and iRXFIFOEmpty = '0' and (iPERE = '1' or iFERE = '1' or iBIRE = '1') else '0'; |
|
iLSR(0) <= iLSR_DR; |
iLSR(1) <= iLSR_OE; |
iLSR(2) <= iLSR_PE; |
iLSR(3) <= iLSR_FE; |
iLSR(4) <= iLSR_BI; |
iLSR(5) <= iLSR_THRE; |
iLSR(6) <= iLSR_TEMT; |
iLSR(7) <= '1' when iFCR_FIFOEnable = '1' and iLSR_FIFOERR = '1' else '0'; |
iLSR_DR <= '1' when iRXFIFOEmpty = '0' or iRXFIFOWrite = '1' else '0'; |
iLSR_THRE <= '1' when iTXFIFOEmpty = '1' else '0'; |
iLSR_TEMT <= '1' when iTXRunning = '0' and iLSR_THRE = '1' else '0'; |
|
-- Modem status register |
iMSR_CTS <= '1' when (iMCR_LOOP = '1' and iRTS = '1') or (iMCR_LOOP = '0' and iCTSn = '0') else '0'; |
iMSR_DSR <= '1' when (iMCR_LOOP = '1' and iMCR_DTR = '1') or (iMCR_LOOP = '0' and iDSRn = '0') else '0'; |
iMSR_RI <= '1' when (iMCR_LOOP = '1' and iMCR_OUT1 = '1') or (iMCR_LOOP = '0' and iRIn = '0') else '0'; |
iMSR_DCD <= '1' when (iMCR_LOOP = '1' and iMCR_OUT2 = '1') or (iMCR_LOOP = '0' and iDCDn = '0') else '0'; |
|
-- Edge detection for CTS, DSR, DCD and RI |
UART_ED_CTS: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_CTS, RE => iCTSnRE, FE => iCTSnFE); |
UART_ED_DSR: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_DSR, RE => iDSRnRE, FE => iDSRnFE); |
UART_ED_RI: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_RI, RE => iRInRE, FE => iRInFE); |
UART_ED_DCD: slib_edge_detect port map (CLK => CLK, RST => RST, D => iMSR_DCD, RE => iDCDnRE, FE => iDCDnFE); |
|
UART_MSR: process (CLK, RST) |
begin |
if (RST = '1') then |
iMSR_dCTS <= '0'; |
iMSR_dDSR <= '0'; |
iMSR_TERI <= '0'; |
iMSR_dDCD <= '0'; |
elsif (CLK'event and CLK = '1') then |
-- Delta CTS |
if (iCTSnRE = '1' or iCTSnFE = '1') then |
iMSR_dCTS <= '1'; |
elsif (iMSRRead = '1') then |
iMSR_dCTS <= '0'; |
end if; |
-- Delta DSR |
if (iDSRnRE = '1' or iDSRnFE = '1') then |
iMSR_dDSR <= '1'; |
elsif (iMSRRead = '1') then |
iMSR_dDSR <= '0'; |
end if; |
-- Trailing edge RI |
if (iRInFE = '1') then |
iMSR_TERI <= '1'; |
elsif (iMSRRead = '1') then |
iMSR_TERI <= '0'; |
end if; |
-- Delta DCD |
if (iDCDnRE = '1' or iDCDnFE = '1') then |
iMSR_dDCD <= '1'; |
elsif (iMSRRead = '1') then |
iMSR_dDCD <= '0'; |
end if; |
end if; |
end process; |
|
iMSR(0) <= iMSR_dCTS; |
iMSR(1) <= iMSR_dDSR; |
iMSR(2) <= iMSR_TERI; |
iMSR(3) <= iMSR_dDCD; |
iMSR(4) <= iMSR_CTS; |
iMSR(5) <= iMSR_DSR; |
iMSR(6) <= iMSR_RI; |
iMSR(7) <= iMSR_DCD; |
|
-- Scratch register |
UART_SCR: process (CLK, RST) |
begin |
if (RST = '1') then |
iSCR <= (others => '0'); |
elsif (CLK'event and CLK = '1') then |
if (iSCRWrite = '1') then |
iSCR <= iDIN; |
end if; |
end if; |
end process; |
|
|
-- Baudrate generator |
iBaudgenDiv <= iDLM & iDLL; |
UART_BG16: uart_baudgen port map (CLK => CLK, |
RST => RST, |
CE => BAUDCE, |
CLEAR => '0', |
DIVIDER => iBaudgenDiv, |
BAUDTICK => iBaudtick16x |
); |
UART_BG2: slib_clock_div generic map (RATIO => 8) |
port map (CLK => CLK, |
RST => RST, |
CE => iBaudtick16x, |
Q => iBaudtick2x |
); |
UART_RCLK: slib_edge_detect port map (CLK => CLK, |
RST => RST, |
D => RCLK, |
RE => iRCLK |
); |
|
-- Transmitter FIFO |
UART_TXFF: slib_fifo generic map (WIDTH => 8, SIZE_E => 6) |
port map (CLK => CLK, |
RST => RST, |
CLEAR => iTXFIFOClear, |
WRITE => iTXFIFOWrite, |
READ => iTXFIFORead, |
D => iDIN, |
Q => iTXFIFOQ, |
EMPTY => iTXFIFOEmpty, |
FULL => iTXFIFO64Full, |
USAGE => iTXFIFOUsage |
); |
-- Transmitter FIFO inputs |
iTXFIFO16Full <= iTXFIFOUsage(4); |
iTXFIFOFull <= iTXFIFO16Full when iFCR_FIFO64E = '0' else iTXFIFO64Full; |
iTXFIFOWrite <= '1' when ((iFCR_FIFOEnable = '0' and iTXFIFOEmpty = '1') or (iFCR_FIFOEnable = '1' and iTXFIFOFull = '0')) and iTHRWrite = '1' else '0'; |
iTXFIFOClear <= '1' when iFCR_TXFIFOReset = '1' else '0'; |
|
-- Receiver FIFO |
UART_RXFF: slib_fifo generic map (WIDTH => 11, SIZE_E => 6) |
port map (CLK => CLK, |
RST => RST, |
CLEAR => iRXFIFOClear, |
WRITE => iRXFIFOWrite, |
READ => iRXFIFORead, |
D => iRXFIFOD, |
Q => iRXFIFOQ, |
EMPTY => iRXFIFOEmpty, |
FULL => iRXFIFO64Full, |
USAGE => iRXFIFOUsage |
); |
-- Receiver FIFO inputs |
iRXFIFORead <= '1' when iRBRRead = '1' else '0'; |
iRXFIFO16Full <= iRXFIFOUsage(4); |
iRXFIFOFull <= iRXFIFO16Full when iFCR_FIFO64E = '0' else iRXFIFO64Full; |
|
|
-- Receiver FIFO outputs |
iRBR <= iRXFIFOQ(7 downto 0); |
|
-- FIFO trigger level: 1, 4, 8, 14 |
iRXFIFO16Trigger <= '1' when (iFCR_RXTrigger = "00" and iRXFIFOEmpty = '0') or |
(iFCR_RXTrigger = "01" and (iRXFIFOUsage(2) = '1' or iRXFIFOUsage(3) = '1')) or |
(iFCR_RXTrigger = "10" and iRXFIFOUsage(3) = '1') or |
(iFCR_RXTrigger = "11" and iRXFIFOUsage(3) = '1' and iRXFIFOUsage(2) = '1' and iRXFIFOUsage(1) = '1') or |
iRXFIFO16Full = '1' else '0'; |
-- FIFO 64 trigger level: 1, 16, 32, 56 |
iRXFIFO64Trigger <= '1' when (iFCR_RXTrigger = "00" and iRXFIFOEmpty = '0') or |
(iFCR_RXTrigger = "01" and (iRXFIFOUsage(4) = '1' or iRXFIFOUsage(5) = '1')) or |
(iFCR_RXTrigger = "10" and iRXFIFOUsage(5) = '1') or |
(iFCR_RXTrigger = "11" and iRXFIFOUsage(5) = '1' and iRXFIFOUsage(4) = '1' and iRXFIFOUsage(3) = '1') or |
iRXFIFO64Full = '1' else '0'; |
iRXFIFOTrigger <= iRXFIFO16Trigger when iFCR_FIFO64E = '0' else iRXFIFO64Trigger; |
|
-- Transmitter |
UART_TX: uart_transmitter port map (CLK => CLK, |
RST => RST, |
TXCLK => iBaudtick2x, |
TXSTART => iTXStart, |
CLEAR => iTXClear, |
WLS => iLCR_WLS, |
STB => iLCR_STB, |
PEN => iLCR_PEN, |
EPS => iLCR_EPS, |
SP => iLCR_SP, |
BC => iLCR_BC, |
DIN => iTSR, |
TXFINISHED => iTXFinished, |
SOUT => iSOUT |
); |
iTXClear <= '0'; |
|
-- Receiver |
UART_RX: uart_receiver port map (CLK => CLK, |
RST => RST, |
RXCLK => iRCLK, |
RXCLEAR => iRXClear, |
WLS => iLCR_WLS, |
STB => iLCR_STB, |
PEN => iLCR_PEN, |
EPS => iLCR_EPS, |
SP => iLCR_SP, |
SIN => iSIN, |
PE => iRXPE, |
FE => iRXFE, |
BI => iRXBI, |
DOUT => iRXData, |
RXFINISHED => iRXFinished |
); |
iRXClear <= '0'; |
iSIN <= iSINr when iMCR_LOOP = '0' else iSOUT; |
|
-- Transmitter enable signal |
-- TODO: Use iCTSNs instead of iMSR_CTS? Input filter increases delay for Auto-CTS recognition. |
iTXEnable <= '1' when iTXFIFOEmpty = '0' and (iMCR_AFE = '0' or (iMCR_AFE = '1' and iMSR_CTS = '1')) else '0'; |
|
-- Transmitter process |
UART_TXPROC: process (CLK, RST) |
type state_type is (IDLE, TXSTART, TXRUN, TXEND); |
variable State : state_type; |
begin |
if (RST = '1') then |
State := IDLE; |
iTSR <= (others => '0'); |
iTXStart <= '0'; |
iTXFIFORead <= '0'; |
iTXRunning <= '0'; |
elsif (CLK'event and CLK = '1') then |
-- Defaults |
iTXStart <= '0'; |
iTXFIFORead <= '0'; |
iTXRunning <= '0'; |
|
case State is |
when IDLE => if (iTXEnable = '1') then |
iTXStart <= '1'; -- Start transmitter |
State := TXSTART; |
else |
State := IDLE; |
end if; |
when TXSTART => iTSR <= iTXFIFOQ; |
iTXStart <= '1'; -- Start transmitter |
iTXFIFORead <= '1'; -- Increment TX FIFO read counter |
State := TXRUN; |
when TXRUN => if (iTXFinished = '1') then -- TX finished |
State := TXEND; |
else |
State := TXRUN; |
end if; |
iTXRunning <= '1'; |
iTXStart <= '1'; |
when TXEND => State := IDLE; |
when others => State := IDLE; |
end case; |
end if; |
end process; |
|
-- Receiver process |
UART_RXPROC: process (CLK, RST) |
type state_type is (IDLE, RXSAVE); |
variable State : state_type; |
begin |
if (RST = '1') then |
State := IDLE; |
iRXFIFOWrite <= '0'; |
iRXFIFOClear <= '0'; |
iRXFIFOD <= (others => '0'); |
elsif (CLK'event and CLK = '1') then |
-- Defaults |
iRXFIFOWrite <= '0'; |
iRXFIFOClear <= iFCR_RXFIFOReset; |
|
case State is |
when IDLE => if (iRXFinished = '1') then -- Receive finished |
iRXFIFOD <= iRXBI & iRXFE & iRXPE & iRXData; |
if (iFCR_FIFOEnable = '0') then |
iRXFIFOClear <= '1'; -- Non-FIFO mode |
end if; |
State := RXSAVE; |
else |
State := IDLE; |
end if; |
when RXSAVE => if (iFCR_FIFOEnable = '0') then |
iRXFIFOWrite <= '1'; -- Non-FIFO mode: Overwrite |
elsif (iRXFIFOFull = '0') then |
iRXFIFOWrite <= '1'; -- FIFO mode |
end if; |
State := IDLE; |
when others => State := IDLE; |
end case; |
end if; |
end process; |
|
-- Automatic flow control |
UART_AFC: process (CLK, RST) |
begin |
if (RST = '1') then |
iRTS <= '0'; |
elsif (CLK'event and CLK = '1') then |
if (iMCR_RTS = '0' or (iMCR_AFE = '1' and iRXFIFOTrigger = '1')) then |
-- Deassert when MCR_RTS is not set or AFC is enabled and the RX FIFO trigger level is reached |
iRTS <= '0'; |
elsif (iMCR_RTS = '1' and (iMCR_AFE = '0' or (iMCR_AFE = '1' and iRXFIFOEmpty = '1'))) then |
-- Assert when MCR_RTS is set and AFC is disabled or when AFC is enabled and the RX FIFO is empty |
iRTS <= '1'; |
end if; |
end if; |
end process; |
|
-- Output registers |
UART_OUTREGS: process (CLK, RST) |
begin |
if (RST = '1') then |
BAUDOUTN <= '0'; |
OUT1N <= '0'; |
OUT2N <= '0'; |
RTSN <= '0'; |
DTRN <= '0'; |
SOUT <= '0'; |
elsif (CLK'event and CLK = '1') then |
-- Default values |
BAUDOUTN <= '0'; |
OUT1N <= '0'; |
OUT2N <= '0'; |
RTSN <= '0'; |
DTRN <= '0'; |
SOUT <= '0'; |
|
-- BAUDOUTN |
if (iBaudtick16x = '0') then |
BAUDOUTN <= '1'; |
end if; |
-- OUT1N |
if (iMCR_LOOP = '1' or iMCR_OUT1 = '0') then |
OUT1N <= '1'; |
end if; |
-- OUT2N |
if (iMCR_LOOP = '1' or iMCR_OUT2 = '0') then |
OUT2N <= '1'; |
end if; |
-- RTS |
if (iMCR_LOOP = '1' or iRTS = '0') then |
RTSN <= '1'; |
end if; |
-- DTR |
if (iMCR_LOOP = '1' or iMCR_DTR = '0') then |
DTRN <= '1'; |
end if; |
-- SOUT |
if (iMCR_LOOP = '1' or iSOUT = '1') then |
SOUT <= '1'; |
end if; |
end if; |
end process; |
|
|
-- UART data output |
UART_DOUT: process (WB_ACK_r,iA, iLCR_DLAB, iRBR, iDLL, iDLM, iIER, iIIR, iLCR, iMCR, iLSR, iMSR, iSCR) |
begin |
WB_DOUT(7 downto 0) <= (others => '0'); |
if WB_ACK_r='1' then |
case iA is |
when "000" => if (iLCR_DLAB = '0') then |
WB_DOUT <= iRBR; |
else |
WB_DOUT <= iDLL; |
end if; |
when "001" => if (iLCR_DLAB = '0') then |
WB_DOUT <= iIER; |
else |
WB_DOUT <= iDLM; |
end if; |
when "010" => WB_DOUT <= iIIR; |
when "011" => WB_DOUT <= iLCR; |
when "100" => WB_DOUT <= iMCR; |
when "101" => WB_DOUT <= iLSR; |
when "110" => WB_DOUT <= iMSR; |
when "111" => WB_DOUT <= iSCR; |
when others => WB_DOUT <= iRBR; |
end case; |
end if; |
end process; |
|
end rtl; |
|
|