OpenCores
URL https://opencores.org/ocsvn/t65/t65/trunk

Subversion Repositories t65

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/trunk/rtl/vhdl/T16450.vhd
0,0 → 1,390
--
-- 16450 compatible UART with synchronous bus interface
-- RClk/BaudOut is XIn enable instead of actual clock
-- No break detection, no modem status change detection
-- Only one stop bit supported
--
-- Version : 0208
--
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity T16450 is
port(
MR_n : in std_logic;
XIn : in std_logic;
RClk : in std_logic;
CS_n : in std_logic;
Rd_n : in std_logic;
Wr_n : in std_logic;
A : in std_logic_vector(2 downto 0);
D_In : in std_logic_vector(7 downto 0);
D_Out : out std_logic_vector(7 downto 0);
SIn : in std_logic;
CTS_n : in std_logic;
DSR_n : in std_logic;
RI_n : in std_logic;
DCD_n : in std_logic;
SOut : out std_logic;
RTS_n : out std_logic;
DTR_n : out std_logic;
OUT1_n : out std_logic;
OUT2_n : out std_logic;
BaudOut : out std_logic;
Intr : out std_logic
);
end T16450;
 
architecture rtl of T16450 is
 
signal RBR : std_logic_vector(7 downto 0); -- Reciever Buffer Register
signal THR : std_logic_vector(7 downto 0); -- Transmitter Holding Register
signal IER : std_logic_vector(7 downto 0); -- Interrupt Enable Register
signal IIR : std_logic_vector(7 downto 0); -- Interrupt Ident. Register
signal LCR : std_logic_vector(7 downto 0); -- Line Control Register
signal MCR : std_logic_vector(7 downto 0); -- MODEM Control Register
signal LSR : std_logic_vector(7 downto 0); -- Line Status Register
signal MSR : std_logic_vector(7 downto 0); -- MODEM Status Register
signal SCR : std_logic_vector(7 downto 0); -- Scratch Register
signal DLL : std_logic_vector(7 downto 0); -- Divisor Latch (LS)
signal DLM : std_logic_vector(7 downto 0); -- Divisor Latch (MS)
 
signal DM0 : std_logic_vector(7 downto 0);
signal DM1 : std_logic_vector(7 downto 0);
 
signal Bit_Phase : unsigned(3 downto 0);
signal RX_Filtered : std_logic;
signal RX_ShiftReg : std_logic_vector(7 downto 0);
signal RX_Bit_Cnt : integer range 0 to 11;
signal RX_Parity : std_logic;
signal RXD : std_logic;
 
signal TX_Tick : std_logic;
signal TX_ShiftReg : std_logic_vector(7 downto 0);
signal TX_Bit_Cnt : integer range 0 to 11;
signal TX_Parity : std_logic;
signal TXD : std_logic;
 
begin
 
DTR_n <= MCR(4) or not MCR(0);
RTS_n <= MCR(4) or not MCR(1);
OUT1_n <= MCR(4) or not MCR(2);
OUT2_n <= MCR(4) or not MCR(3);
SOut <= (MCR(4) or TXD) and not LCR(6);
RXD <= SIn when MCR(4) = '0' else TXD;
 
Intr <= not IIR(0);
 
-- Registers
DM0 <= DLL when LCR(7) = '1' else RBR;
DM1 <= DLM when LCR(7) = '1' else IER;
with A select
D_Out <=
DM0 when "000",
DM1 when "001",
IIR when "010",
LCR when "011",
MCR when "100",
LSR when "101",
MSR when "110",
SCR when others;
process (MR_n, XIn)
begin
if MR_n = '0' then
THR <= "00000000";
IER <= "00000000";
LCR <= "00000000";
MCR <= "00000000";
MSR <= "00000000";
SCR <= "00000000"; -- ??
DLL <= "00000000"; -- ??
DLM <= "00000000"; -- ??
elsif XIn'event and XIn = '1' then
if Wr_n = '0' and CS_n = '0' then
case A is
when "000" =>
if LCR(7) = '1' then
DLL <= D_In;
else
THR <= D_In;
end if;
when "001" =>
if LCR(7) = '1' then
DLM <= D_In;
else
IER(3 downto 0) <= D_In(3 downto 0);
end if;
when "011" =>
LCR <= D_In;
when "100" =>
MCR <= D_In;
when "111" =>
SCR <= D_In;
when others =>
end case;
end if;
if MCR(4) = '0' then
MSR(4) <= CTS_n;
MSR(5) <= DSR_n;
MSR(6) <= RI_n;
MSR(7) <= DCD_n;
else
MSR(4) <= MCR(1);
MSR(5) <= MCR(0);
MSR(6) <= MCR(2);
MSR(7) <= MCR(3);
end if;
end if;
end process;
 
IIR(7 downto 3) <= "00000";
IIR(2 downto 0) <=
"110" when IER(2) = '1' and LSR(4 downto 1) /= "0000" else
"110" when (IER(0) and LSR(0)) = '1' else
"010" when (IER(1) and LSR(5)) = '1' else
"001" when IER(3) = '1' and ((MCR(4) = '0' and MSR(3 downto 0) /= "0000") or
(MCR(4) = '1' and MCR(3 downto 0) /= "0000")) else
"001";
 
-- Baud x 16 clock generator
process (MR_n, XIn)
variable Baud_Cnt : unsigned(15 downto 0);
begin
if MR_n = '0' then
Baud_Cnt := "0000000000000001";
BaudOut <= '0';
elsif XIn'event and XIn = '1' then
if Baud_Cnt = "0000000000000001" or (Wr_n = '0' and CS_n = '0' and A(2 downto 1) = "00" and LCR(7) = '1') then
Baud_Cnt(15 downto 8) := unsigned(DLM);
Baud_Cnt(7 downto 0) := unsigned(DLL);
BaudOut <= '1';
else
Baud_Cnt := Baud_Cnt - 1;
BaudOut <= '0';
end if;
end if;
end process;
 
-- Input filter
process (MR_n, XIn)
variable Samples : std_logic_vector(1 downto 0);
begin
if MR_n = '0' then
Samples := "11";
RX_Filtered <= '1';
elsif XIn'event and XIn = '1' then
if RClk = '1' then
Samples(1) := Samples(0);
Samples(0) := RXD;
end if;
if Samples = "00" then
RX_Filtered <= '0';
end if;
if Samples = "11" then
RX_Filtered <= '1';
end if;
end if;
end process;
 
-- Receive state machine
process (MR_n, XIn)
begin
if MR_n = '0' then
RBR <= "00000000";
LSR(4 downto 0) <= "00000";
Bit_Phase <= "0000";
RX_ShiftReg(7 downto 0) <= "00000000";
RX_Bit_Cnt <= 0;
RX_Parity <= '0';
elsif XIn'event and XIn = '1' then
if A = "000" and LCR(7) = '0' and Rd_n = '0' and CS_n = '0' then
LSR(0) <= '0'; -- DR
end if;
if A = "101" and Rd_n = '0' and CS_n = '0' then
LSR(3) <= '0'; -- FE
LSR(2) <= '0'; -- PE
LSR(1) <= '0'; -- OE
end if;
if RClk = '1' then
if RX_Bit_Cnt = 0 and (RX_Filtered = '1' or Bit_Phase = "0111") then
Bit_Phase <= "0000";
else
Bit_Phase <= Bit_Phase + 1;
end if;
if RX_Bit_Cnt = 0 then
if Bit_Phase = "0111" then
RX_Bit_Cnt <= RX_Bit_Cnt + 1;
RX_Parity <= not LCR(4); -- EPS
end if;
elsif Bit_Phase = "1111" then
RX_Bit_Cnt <= RX_Bit_Cnt + 1;
if RX_Bit_Cnt = 10 then -- Parity stop bit
RX_Bit_Cnt <= 0;
LSR(0) <= '1'; -- UART Receive complete
LSR(3) <= not RX_Filtered; -- Framing error
elsif (RX_Bit_Cnt = 9 and LCR(1 downto 0) = "11") or
(RX_Bit_Cnt = 8 and LCR(1 downto 0) = "10") or
(RX_Bit_Cnt = 7 and LCR(1 downto 0) = "01") or
(RX_Bit_Cnt = 6 and LCR(1 downto 0) = "00") then -- Stop bit/Parity
RX_Bit_Cnt <= 0;
if LCR(3) = '1' then -- PEN
RX_Bit_Cnt <= 10;
if LCR(5) = '1' then -- Stick parity
if RX_Filtered = LCR(4) then
LSR(2) <= '1';
end if;
else
if RX_Filtered /= RX_Parity then
LSR(2) <= '1';
end if;
end if;
else
LSR(0) <= '1'; -- UART Receive complete
LSR(3) <= not RX_Filtered; -- Framing error
end if;
RBR <= RX_ShiftReg(7 downto 0);
LSR(1) <= LSR(0);
if A = "101" and Rd_n = '0' and CS_n = '0' then
LSR(1) <= '0';
end if;
else
RX_ShiftReg(6 downto 0) <= RX_ShiftReg(7 downto 1);
RX_ShiftReg(7) <= RX_Filtered;
if LCR(1 downto 0) = "10" then
RX_ShiftReg(7) <= '0';
RX_ShiftReg(6) <= RX_Filtered;
end if;
if LCR(1 downto 0) = "01" then
RX_ShiftReg(7) <= '0';
RX_ShiftReg(6) <= '0';
RX_ShiftReg(5) <= RX_Filtered;
end if;
if LCR(1 downto 0) = "00" then
RX_ShiftReg(7) <= '0';
RX_ShiftReg(6) <= '0';
RX_ShiftReg(5) <= '0';
RX_ShiftReg(4) <= RX_Filtered;
end if;
RX_Parity <= RX_Filtered xor RX_Parity;
end if;
end if;
end if;
end if;
end process;
 
-- Transmit bit tick
process (MR_n, XIn)
variable TX_Cnt : unsigned(3 downto 0);
begin
if MR_n = '0' then
TX_Cnt := "0000";
TX_Tick <= '0';
elsif XIn'event and XIn = '1' then
TX_Tick <= '0';
if RClk = '1' then
if TX_Cnt = "1111" then
TX_Tick <= '1';
end if;
TX_Cnt := TX_Cnt + 1;
end if;
end if;
end process;
 
-- Transmit state machine
process (MR_n, XIn)
begin
if MR_n = '0' then
LSR(7 downto 5) <= "011";
TX_Bit_Cnt <= 0;
TX_ShiftReg <= (others => '0');
TXD <= '1';
TX_Parity <= '0';
elsif XIn'event and XIn = '1' then
if TX_Tick = '1' then
case TX_Bit_Cnt is
when 0 =>
if LSR(5) <= '0' then -- THRE
TX_Bit_Cnt <= 1;
end if;
TXD <= '1';
when 1 => -- Start bit
TX_ShiftReg(7 downto 0) <= THR;
LSR(5) <= '1'; -- THRE
TXD <= '0';
TX_Parity <= not LCR(4); -- EPS
TX_Bit_Cnt <= TX_Bit_Cnt + 1;
when 10 => -- Parity bit
TXD <= TX_Parity;
if LCR(5) = '1' then -- Stick parity
TXD <= not LCR(4);
end if;
TX_Bit_Cnt <= 0;
when others =>
TX_Bit_Cnt <= TX_Bit_Cnt + 1;
if (TX_Bit_Cnt = 9 and LCR(1 downto 0) = "11") or
(TX_Bit_Cnt = 8 and LCR(1 downto 0) = "10") or
(TX_Bit_Cnt = 7 and LCR(1 downto 0) = "01") or
(TX_Bit_Cnt = 6 and LCR(1 downto 0) = "00") then
TX_Bit_Cnt <= 0;
if LCR(3) = '1' then -- PEN
TX_Bit_Cnt <= 10;
end if;
LSR(6) <= '1'; -- TEMT
end if;
TXD <= TX_ShiftReg(0);
TX_ShiftReg(6 downto 0) <= TX_ShiftReg(7 downto 1);
TX_Parity <= TX_ShiftReg(0) xor TX_Parity;
end case;
end if;
if Wr_n = '0' and CS_n = '0' and A = "000" and LCR(7) = '0' then
LSR(5) <= '0'; -- THRE
LSR(6) <= '0'; -- TEMT
end if;
end if;
end process;
 
end;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.