URL
https://opencores.org/ocsvn/wb_uart/wb_uart/trunk
Subversion Repositories wb_uart
[/] [wb_uart/] [trunk/] [src/] [wb8_uart_16750.vhd] - Rev 8
Compare with Previous | Blame | View Log
-- -- 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;