URL
https://opencores.org/ocsvn/System09/System09/trunk
Subversion Repositories System09
Compare Revisions
- This comparison shows the changes necessary to convert path
/System09/trunk/rtl/VHDL
- from Rev 99 to Rev 100
- ↔ Reverse comparison
Rev 99 → Rev 100
/peripheral_bus.vhd
0,0 → 1,304
--===========================================================================-- |
-- -- |
-- Peripheral Bus Interface -- |
-- -- |
--===========================================================================-- |
-- |
-- File name : peripheral_bus.vhd |
-- |
-- Entity name : peripheral_bus |
-- |
-- Purpose : Implements a 16 bit peripheral bus interface |
-- On the XESS XST-3.0 carrier board it is shared |
-- by an IDE interface, and Ethernet MAC |
-- and two 16 bit expansion slots. |
-- The same bus structure is used on the |
-- BurchED B3 and B5-X300 Spartan 2 boards |
-- to implement an IDE Compact Flash interface. |
-- |
-- The 16 bit data bus is accessed by two |
-- consecutive byte wide read or write cycles. |
-- |
-- On an even byte read a read strobe is generated |
-- on the peripheral bus and the high bits of the |
-- peripheral data bus are output to the CPU |
-- data bus and the lower 8 bits latched. |
-- A bus hold cycle is generated to allow time |
-- for the peripheral data bus to settle. |
-- On the odd byte read, the latched lower data |
-- bits of the peripheral bus are output on the |
-- CPU data bus. |
-- |
-- Conversely, on an even byte write the CPU data |
-- bus value is latched. On the odd byte write, the |
-- latched value is output to the high 8 bits of |
-- the peripheral bus, and the CPU data is output |
-- to the lower 8 bits of the peripheral bus and |
-- a peripheral write strobe is generated. |
-- A hold signal is geneated back to the CPU to |
-- allow the peripheral bus to settle. |
-- |
-- Dependencies : ieee.std_logic_1164 |
-- ieee.numeric_std |
-- unisim.vcomponents |
-- |
-- Author : John E. Kent |
-- |
-- Email : dilbert57@opencores.org |
-- |
-- Web : http://opencores.org/project,system09 |
-- |
-- Memory Map : |
-- |
-- IO address + $00 IDE Compact Flash interface |
-- IO address + $40 Ethernet MAC interface (XESS XST-3.0) |
-- IO address + $80 Expansion Slot 0 (XESS XST-3.0) |
-- IO address + $C0 Expansion Slot 1 (XESS XST-3.0) |
-- |
-- |
-- Copyright (C) 2010 John Kent |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program 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 General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
--===========================================================================-- |
-- -- |
-- Revision History -- |
-- -- |
--===========================================================================-- |
-- |
-- Version Author Date Changes |
-- |
-- 0.1 John Kent 2010-08-28 New model |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use ieee.std_logic_unsigned.all; |
library unisim; |
use unisim.vcomponents.all; |
|
----------------------------------------------------------------------- |
-- Entity for peripheral bus -- |
----------------------------------------------------------------------- |
|
entity peripheral_bus is |
port ( |
-- |
-- CPU Interface signals |
-- |
clk : in std_logic; -- System Clock |
rst : in std_logic; -- Reset input (active high) |
cs : in std_logic; -- Peripheral Bus Chip Select |
addr : in std_logic_vector(7 downto 0); -- Register Select |
rw : in std_logic; -- Read / Not Write |
data_in : in std_logic_vector(7 downto 0); -- Data Bus In |
data_out : out std_logic_vector(7 downto 0); -- Data Bus Out |
hold : out std_logic; -- Hold bus cycle output |
-- |
-- Peripheral Bus Interface Signals |
-- IO + ($00 - $FF) |
-- (for compatibility with XSA-3S1000 / XST 3.0) |
-- |
pb_rd_n : out std_logic; -- ide pin 25 |
pb_wr_n : out std_logic; -- ide pin 23 |
pb_addr : out std_logic_vector( 4 downto 0); |
pb_data : inout std_logic_vector(15 downto 0); |
|
-- Peripheral chip selects on Peripheral Bus |
ide_cs : out std_logic; -- IDE / CF interface ($00 - $3F) |
eth_cs : out std_logic; -- Ethernet interface ($40 - $7F) |
sl1_cs : out std_logic; -- Expansion slot 1 ($80 - $BF) |
sl2_cs : out std_logic -- Expansion slot 2 ($C0 - $FF) |
); |
end peripheral_bus; |
--================== End of entity ==============================-- |
|
------------------------------------------------------------------------------- |
-- Architecture for peripheral bus interface |
------------------------------------------------------------------------------- |
|
architecture rtl of peripheral_bus is |
|
|
type hold_state_type is ( hold_release_state, hold_request_state ); |
signal pb_hold_state : hold_state_type := hold_release_state; |
signal pb_wru : std_logic; -- upper byte write strobe |
signal pb_wrl : std_logic; -- lower byte write strobe |
signal pb_rdu : std_logic; -- upper byte read strobe |
signal pb_rdl : std_logic; -- lower byte read strobe |
signal pb_hold : std_logic := '0'; -- hold peripheral bus access |
signal pb_count : std_logic_vector(3 downto 0) := (others=>'0'); -- hold counter |
signal pb_wreg : std_logic_vector(7 downto 0) := (others=>'0'); -- lower byte write register |
signal pb_rreg : std_logic_vector(7 downto 0) := (others=>'0'); -- lower byte read register |
|
begin |
|
peripheral_bus_decode : process( addr, cs ) |
begin |
|
ide_cs <= '0'; |
eth_cs <= '0'; |
sl1_cs <= '0'; |
sl2_cs <= '0'; |
|
case addr(7 downto 6) is |
-- |
-- IDE Interface $E100 to $E13F |
-- |
when "00" => |
ide_cs <= cs; |
-- |
-- Ethernet Interface $E140 to $E17F |
-- |
when "01" => |
eth_cs <= cs; |
-- |
-- Slot 1 Interface $E180 to $E1BF |
-- |
when "10" => |
sl1_cs <= cs; |
-- |
-- Slot 2 Interface $E1C0 to $E1FF |
-- |
when "11" => |
sl2_cs <= cs; |
-- |
-- Nothing else |
-- |
when others => |
null; |
end case; |
|
end process; |
|
-- |
-- 16-bit Peripheral Bus |
-- 6809 Big endian |
-- ISA bus little endian |
-- Not sure about IDE interface |
-- |
peripheral_bus_control: process( clk, rst, cs, addr, rw, data_in, |
pb_hold, pb_wreg, pb_rreg, |
pb_wru, pb_wrl, pb_rdu, pb_rdl, pb_data ) |
begin |
pb_addr <= addr(5 downto 1); |
-- |
-- internal read/write strobes |
-- |
pb_wru <= cs and (not rw) and (not addr(0)); |
pb_wrl <= cs and (not rw) and addr(0) ; |
pb_rdu <= cs and rw and (not addr(0)); |
pb_rdl <= cs and rw and addr(0) ; |
|
pb_wr_n <= not pb_wrl; |
pb_rd_n <= not pb_rdu; |
|
-- |
-- The peripheral bus will be an output |
-- the registered even byte on data(15 downto 8) |
-- and the CPU odd bytes on data(7 downto 0) |
-- on odd byte writes |
-- |
if pb_wrl = '1' then |
pb_data <= pb_wreg & data_in; |
else |
pb_data <= (others => 'Z'); |
end if; |
|
-- |
-- On even byte reads, |
-- the CPU reads the low (even) byte of the peripheral bus |
-- On odd byte reads, |
-- the CPU reads the registered (odd byte) input from the peripheral bus |
-- |
if pb_rdu = '1' then |
data_out <= pb_data(15 downto 8); |
elsif pb_rdl = '1' then |
data_out <= pb_rreg; |
else |
data_out <= (others => '0'); |
end if; |
|
-- |
-- Register upper byte from CPU on first CPU write |
-- and lower byte from the peripheral bus on first CPU read |
-- |
if falling_edge(clk) then |
if rst = '1' then |
pb_wreg <= (others => '0'); |
pb_rreg <= (others => '0'); |
else |
|
if pb_wru = '1' then |
pb_wreg <= data_in; |
end if; |
|
if pb_rdu = '1' then |
pb_rreg <= pb_data(7 downto 0); |
end if; |
|
end if; |
end if; |
|
end process; |
|
-- |
-- Hold Peripheral bus accesses for a few cycles |
-- |
peripheral_bus_hold: process( clk, rst, cs, |
pb_hold_state, pb_hold, |
pb_rdu, pb_wrl ) |
begin |
if rising_edge( clk ) then |
if rst = '1' then |
pb_hold <= '0'; |
pb_count <= "0000"; |
pb_hold_state <= hold_release_state; |
else |
-- |
-- The perpheral bus hold signal should be generated on |
-- 16 bit bus even upper byte read or |
-- 16 bit bus odd lower byte write. |
-- |
case pb_hold_state is |
|
when hold_release_state => |
if (pb_rdu = '1') or (pb_wrl = '1') then |
pb_count <= "0011"; |
pb_hold <= '1'; |
pb_hold_state <= hold_request_state; |
else |
pb_hold <= '0'; |
pb_hold_state <= hold_release_state; |
end if; |
|
when hold_request_state => |
if pb_count = "0000" then |
pb_hold <= '0'; |
pb_hold_state <= hold_release_state; |
else |
pb_count <= pb_count - "0001"; |
end if; |
|
when others => |
null; |
|
end case; |
end if; |
end if; |
hold <= cs and pb_hold; |
end process; |
|
end rtl; |
/priority_rot.vhd
0,0 → 1,82
--===========================================================================-- |
-- -- |
-- priority_rot.vhd - Synthesizable Rotating Priority Encoder -- |
-- -- |
--===========================================================================-- |
-- |
-- File name : priority_rot.vhd |
-- |
-- Purpose : Implements a rotating priority encoder |
-- |
-- Dependencies : ieee.std_logic_1164 |
-- ieee.std_logic_unsigned |
-- ieee.std_logic_arith |
-- unisim.vcomponents |
-- |
-- Author : John E. Kent |
-- |
-- Email : dilbert57@opencores.org |
-- |
-- Web : http://opencores.org/project,system09 |
-- |
-- Priority_rot.vhd is a rotating priority encoder written in VHDL. |
-- |
-- Copyright (C) 2010 John Kent |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program 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 General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
--===========================================================================-- |
-- -- |
-- Revision History -- |
-- -- |
--===========================================================================-- |
-- |
-- Version Author Date Description |
-- 0.1 John Kent 30th May 2010 Initial version |
-- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
use ieee.std_logic_arith.all; |
|
library unisim; |
use unisim.vcomponents.all; |
|
entity priority_rot is |
generic ( |
WIDTH = 8 |
) |
port ( |
clk : in std_logic; |
rst : in std_logic; |
input : in std_logic_vector(WIDTH-1 downto 0); |
output : out std_logic_vector(log2(WIDTH)-1 downto 0); |
valid : out std_logic |
) |
); |
end priority_rot; |
|
architecture rtl of priority_rot is |
|
constant OUT_WIDTH : integer := log2(WIDTH); |
|
begin |
|
for i in 1 to WIDTH loop |
j := log2( i ); |
if( input(i-1) = '1' ) then |
|
end loop; |
end architecture; |
|
/GNU_GENERAL_PUBLIC_LICENSE.doc
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
GNU_GENERAL_PUBLIC_LICENSE.doc
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: dma6844.vhd
===================================================================
--- dma6844.vhd (nonexistent)
+++ dma6844.vhd (revision 100)
@@ -0,0 +1,243 @@
+--===========================================================================--
+-- --
+-- Synthesizable 6844 Compatible DMA Controller --
+-- --
+--===========================================================================--
+--
+-- File name : dma6844.vhd
+--
+-- Entity name : dma6844
+--
+-- Purpose : Implements a 6844 compatible Direct Memory Access Controller
+-- It is intended for use with 68xx compatible FPGA SoCs.
+--
+-- Dependencies : ieee.std_logic_1164
+-- ieee.std_logic_unsigned
+-- ieee.std_logic_arith
+-- unisim.vcomponents
+--
+-- Author : John E. Kent
+--
+-- Email : dilbert57@opencores.org
+--
+-- Web : http://opencores.org/project,system09
+--
+-- Registers :
+--
+-- 4 Channel version
+--
+-- IO + 0 = DMA_AH0 = Address Register 0 High
+-- IO + 1 = DMA_AL0 = Address Register 0 Low
+-- IO + 2 = DMA_CH0 = Count Register 0 High
+-- IO + 3 = DMA_CL0 = Count Register 0 Low
+--
+-- IO + 4 = DMA_AH1 = Address Register 1 High
+-- IO + 5 = DMA_AL1 = Address Register 1 Low
+-- IO + 6 = DMA_CH1 = Count Register 1 High
+-- IO + 7 = DMA_CL1 = Count Register 1 Low
+--
+-- IO + 8 = DMA_AH2 = Address Register 2 High
+-- IO + 9 = DMA_AL2 = Address Register 2 Low
+-- IO + 10 = DMA_CH2 = Count Register 2 High
+-- IO + 11 = DMA_CL2 = Count Register 2 Low
+--
+-- IO + 12 = DMA_AH3 = Address Register 3 High
+-- IO + 13 = DMA_AL3 = Address Register 3 Low
+-- IO + 14 = DMA_CH3 = Count Register 3 High
+-- IO + 15 = DMA_CL3 = Count Register 3 Low
+--
+-- IO + 16 = DMA_CC0 = Channel Control Register 0
+-- IO + 17 = DMA_CC1 = Channel Control Register 1
+-- IO + 18 = DMA_CC2 = Channel Control Register 2
+-- IO + 19 = DMA_CC3 = Channel Control Register 3
+-- Bit[7] = DMA_DEF = DMA END FLAG (DEND)
+-- Bit[6] = DMA_BSY = DMA BUSY FLAG (READ ONLY)
+-- Bit[3] = DMA_AUD = DMA ADDRESS NOT UP/DOWN
+-- Bit[2] = DMA_MCA = DMA MODE CONTROL 0=>DRQ2 1=>DRQ1
+-- Bit[1] = DMA_MCB = DMA MODE CONTROL 0=>SINGLE 1=>BLOCK
+-- 0 0 = DMA_MD2 = DMA MODE 2 - SINGLE TRANSFER - DRQ2
+-- 0 1 = DMA_MD3 = DMA MODE 3 - BLOCK TRANSFER - DRQ2
+-- 1 0 = DMA_MD1 = DMA MODE 1 - SINGLE TRANSFER - DRQ1
+-- 1 1 = DMA_MDU = DMA MODE 4 - BLOCK TRANSFER - DRQ1 - ACTUALLY UDEFINED
+-- Bit[0] = DMA_RW = DMA READ/NOT WRITE
+--
+-- IO + 20 = DMA_PRI = DMA Priority Control Register
+-- Bit[7] = DMA_ROT = DMA Rotate Control 0=>FIXED 1=>ROTATE
+-- Bit[3] = DMA_RE3 = DMA REQUEST ENABLE #3
+-- Bit[2] = DMA_RE2 = DMA REQUEST ENABLE #2
+-- Bit[1] = DMA_RE1 = DMA REQUEST ENABLE #1
+-- Bit[0] = DMA_RE0 = DMA REQUEST ENABLE #0
+--
+-- IO + 21 = DMA_INT = DMA Interrupt Control Register
+-- Bit[7] = DMA_IEF = DMA END IRQ FLAG
+-- Bit[3] = DMA_IE3 = DMA END IRQ ENABLE #3
+-- Bit[2] = DMA_IE2 = DMA END IRQ ENABLE #2
+-- Bit[1] = DMA_IE1 = DMA END IRQ ENABLE #1
+-- Bit[0] = DMA_IE0 = DMA END IRQ ENABLE #0
+--
+-- IO + 22 = DMA_CHN = DMA Data Chain register
+-- Bit[3] = DMA_C24 = TWO/FOUR CHANNEL SELECT
+-- Bit[2] = DMA_DCB = DATA CHAIN CHANNEL SELECT B
+-- Bit[1] = DMA_DCA = DATA CHAIN CHANNEL SELECT A
+-- Bit[0] = DMA_DCE = DATA CHAIN ENABLE
+--
+-- Copyright (C) 2010 John Kent
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program 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 General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see .
+--
+--===========================================================================--
+-- --
+-- Revision History --
+-- --
+--===========================================================================--
+--
+-- Revision Author Date Description
+-- 0.1 John E. Kent 18th April 2010 Initial release
+--
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.std_logic_unsigned.all;
+ use ieee.std_logic_arith.all;
+
+library unisim;
+ use unisim.vcomponents.all;
+
+entity dma6844 is
+ generic (
+ ADDR_WIDTH = 16;
+ DATA_WIDTH = 8;
+ CHAN_COUNT = 4
+ )
+ port (
+ --
+ -- CPU Slave Interface
+ --
+ clk : in std_logic;
+ rst : in std_logic;
+ rw : out std_logic;
+ cs : out std_logic;
+ addr : in std_logic_vector(LOG2(CHAN_COUNT*4*ADDR_WIDTH/DATA_WIDTH)-1 downto 0);
+ data_in : in std_logic_vector(DATA_WIDTH-1 downto 0);
+ data_out : out std_logic_vector(DATA_WIDTH-1 downto 0);
+ irq : out std_logic;
+ --
+ -- Bus Master Interface
+ --
+ breq : out std_logic;
+ bgnt : in std_logic;
+ brw : out std_logic;
+ bvma : out std_logic;
+ baddr : out std_logic_vector(ADDR_WIDTH-1 downto 0);
+ --
+ -- Device Interface
+ --
+ txreq : in std_logic_vector(CHAN_COUNT-1 downto 0);
+ txstb : out std_logic_vector(CHAN_COUNT-1 downto 0);
+ txack : out std_logic_vector(CHAN_COUNT-1 downto 0);
+ txend : out std_logic_vector(CHAN_COUNT-1 downto 0)
+ );
+end dma6844;
+
+architecture rtl of dma6844 is
+
+constant REG_COUNT : integer = (CHAN_COUNT * 2 * ADDR_WIDTH / DATA_WIDTH) + DMA_CHAN + 3;
+
+subtype addr_subtype is std_logic_vector(ADDR_WIDTH-1 downto 0);
+subtype data_subtype is std_logic_vector(DATA_WIDTH-1 downto 0);
+
+type addr_type is array(0 to CHAN_COUNT-1) of addr_subtype;
+type data_type is array(0 to CHAN_COUNT-1) of data_subtype;
+type reg_type is array(0 to REG_COUNT-1) of data_subtype;
+
+signal dma_addr : addr_type;
+signal dma_count : addr_type;
+signal dma_in_reg : reg_type;
+signal dma_out_reg : reg_type;
+
+signal dma_reg_wr : std_logic := '0';
+signal dma_reg_rd : std_logic := '0';
+
+--
+-- Registers
+--
+signal dma_adh_reg : data_type;
+signal dma_adl_reg : data_type;
+signal dma_cth_reg : data_type;
+signal dma_ctl_reg : data_type;
+signal dma_chc_reg : data_type;
+signal dma_pri_reg : std_logic_vector(DATA_WIDTH-1 downto 0);
+signal dma_irq_reg : std_logic_vector(DATA_WIDTH-1 downto 0);
+signal dma_chn_reg : std_logic_vector(DATA_WIDTH-1 downto 0);
+
+begin
+--
+-- Write to DMA input register
+--
+dma_reg_write : process( clk, rst )
+variable reg_addr : integer := 0;
+begin
+ if( falling_edge(clk) )
+ if( rst = '1' ) then
+ for i in 0 to CHAN_COUNT-1 loop
+ dma_addr(i) <= (others=>'0');
+ dma_count(i) <= (others=>'0');
+ end loop;
+ for i in 0 to REG_COUNT-1 loop
+ dma_in_reg(i) <= (others=>'0');
+ end loop;
+ else
+ if( cs='1' and rw='0' ) then
+ reg_addr := conv_integer(addr(ADDR_WIDTH-1 downto 0));
+ if( reg_addr < REG_COUNT ) then
+ dma_in_reg(reg_addr) <= data_in;
+ end if;
+ end if;
+ end if;
+ end if;
+end process;
+
+--
+-- Assign input register to specific register names
+--
+dma_reg_assign : process( dma_in_reg )
+begin
+ for i in 0 to CHAN_COUNT-1 loop
+ dma_adh_reg(i) <= dma_in_reg((i*4)+0);
+ dma_adl_reg(i) <= dma_in_reg((i*4)+1);
+ dma_cth_reg(i) <= dma_in_reg((i*4)+2);
+ dma_ctl_reg(i) <= dma_in_reg((i*4)+3);
+ dma_chc_reg(i) <= dma_in_reg((CHAN_COUNT*4)+i);
+ end loop;
+ dma_pri_reg <= dma_in_reg((CHAN_COUNT*5)+0);
+ dma_irq_reg <= dma_in_reg((CHAN_COUNT*5)+1);
+ dma_chn_reg <= dma_in_reg((CHAN_COUNT*5)+2);
+end process;
+
+--
+-- Process Transfer Request Inputs
+--
+dma_tx_req : process( clk, rst, txreq )
+begin
+ if( rising_edge( clk ) ) then
+ if( rst='1' ) then
+ else
+ for i in 0 to CHAN_COUNT-1 loop
+ end loop;
+ end if;
+ end if;
+end process;
+
+end architecture rtl;
+
Index: GNU_GENERAL_PUBLIC_LICENSE.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: GNU_GENERAL_PUBLIC_LICENSE.pdf
===================================================================
--- GNU_GENERAL_PUBLIC_LICENSE.pdf (nonexistent)
+++ GNU_GENERAL_PUBLIC_LICENSE.pdf (revision 100)
GNU_GENERAL_PUBLIC_LICENSE.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: acia6850.vhd
===================================================================
--- acia6850.vhd (nonexistent)
+++ acia6850.vhd (revision 100)
@@ -0,0 +1,897 @@
+--===========================================================================--
+-- --
+-- Synthesizable 6850 compatible ACIA --
+-- --
+--===========================================================================--
+--
+-- File name : acia6850.vhd
+--
+-- Entity name : acia6850
+--
+-- Purpose : Implements a RS232 6850 compatible
+-- Asynchronous Communications Interface Adapter (ACIA)
+--
+-- Dependencies : ieee.std_logic_1164
+-- ieee.numeric_std
+-- unisim.vcomponents
+--
+-- Author : John E. Kent
+--
+-- Email : dilbert57@opencores.org
+--
+-- Web : http://opencores.org/project,system09
+--
+-- Origins : miniUART written by Ovidiu Lupas olupas@opencores.org
+--
+-- Registers :
+--
+-- IO address + 0 Read - Status Register
+--
+-- Bit[7] - Interrupt Request Flag
+-- Bit[6] - Receive Parity Error (parity bit does not match)
+-- Bit[5] - Receive Overrun Error (new character received before last read)
+-- Bit[4] - Receive Framing Error (bad stop bit)
+-- Bit[3] - Clear To Send level
+-- Bit[2] - Data Carrier Detect (lost modem carrier)
+-- Bit[1] - Transmit Buffer Empty (ready to accept next transmit character)
+-- Bit[0] - Receive Data Ready (character received)
+--
+-- IO address + 0 Write - Control Register
+--
+-- Bit[7] - Rx Interupt Enable
+-- 0 - disabled
+-- 1 - enabled
+-- Bits[6..5] - Transmit Control
+-- 0 0 - TX interrupt disabled, RTS asserted
+-- 0 1 - TX interrupt enabled, RTS asserted
+-- 1 0 - TX interrupt disabled, RTS cleared
+-- 1 1 - TX interrupt disabled, RTS asserted, Send Break
+-- Bits[4..2] - Word Control
+-- 0 0 0 - 7 data, even parity, 2 stop
+-- 0 0 1 - 7 data, odd parity, 2 stop
+-- 0 1 0 - 7 data, even parity, 1 stop
+-- 0 1 1 - 7 data, odd parity, 1 stop
+-- 1 0 0 - 8 data, no parity, 2 stop
+-- 1 0 1 - 8 data, no parity, 1 stop
+-- 1 1 0 - 8 data, even parity, 1 stop
+-- 1 1 1 - 8 data, odd parity, 1 stop
+-- Bits[1..0] - Baud Control
+-- 0 0 - Baud Clk divide by 1
+-- 0 1 - Baud Clk divide by 16
+-- 1 0 - Baud Clk divide by 64
+-- 1 1 - Reset
+--
+-- IO address + 1 Read - Receive Data Register
+--
+-- Read when Receive Data Ready bit set
+-- Read resets Receive Data Ready bit
+--
+-- IO address + 1 Write - Transmit Data Register
+--
+-- Write when Transmit Buffer Empty bit set
+-- Write resets Transmit Buffer Empty Bit
+--
+--
+-- Copyright (C) 2002 - 2010 John Kent
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program 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 General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see .
+--
+--===========================================================================--
+-- --
+-- Revision History --
+-- --
+--===========================================================================--
+--
+-- Version Author Date Changes
+--
+-- 0.1 Ovidiu Lupas 2000-01-15 New model
+-- 1.0 Ovidiu Lupas 2000-01 Synthesis optimizations
+-- 2.0 Ovidiu Lupas 2000-04 Bugs removed - the RSBusCtrl did not
+-- process all possible situations
+--
+-- 3.0 John Kent 2002-10 Changed Status bits to match MC6805
+-- Added CTS, RTS, Baud rate control & Software Reset
+-- 3.1 John Kent 2003-01-05 Added Word Format control a'la mc6850
+-- 3.2 John Kent 2003-07-19 Latched Data input to UART
+-- 3.3 John Kent 2004-01-16 Integrated clkunit in rxunit & txunit
+-- TX / RX Baud Clock now external
+-- also supports x1 clock and DCD.
+-- 3.4 John Kent 2005-09-13 Removed LoadCS signal.
+-- Fixed ReadCS and Read
+-- in miniuart_DCD_Init process
+-- 3.5 John Kent 2006-11-28 Cleaned up code.
+--
+-- 4.0 John Kent 2007-02-03 Renamed ACIA6850
+-- 4.1 John Kent 2007-02-06 Made software reset synchronous
+-- 4.2 John Kent 2007-02-25 Changed sensitivity lists
+-- Rearranged Reset process.
+-- 4.3 John Kent 2010-06-17 Updated header
+-- 4.4 John Kent 2010-08-27 Combined with ACIA_RX & ACIA_TX
+-- Renamed to acia6850
+--
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+ use ieee.std_logic_unsigned.all;
+library unisim;
+ use unisim.vcomponents.all;
+
+-----------------------------------------------------------------------
+-- Entity for ACIA_6850 --
+-----------------------------------------------------------------------
+
+entity acia6850 is
+ port (
+ --
+ -- CPU Interface signals
+ --
+ clk : in std_logic; -- System Clock
+ rst : in std_logic; -- Reset input (active high)
+ cs : in std_logic; -- miniUART Chip Select
+ addr : in std_logic; -- Register Select
+ rw : in std_logic; -- Read / Not Write
+ data_in : in std_logic_vector(7 downto 0); -- Data Bus In
+ data_out : out std_logic_vector(7 downto 0); -- Data Bus Out
+ irq : out std_logic; -- Interrupt Request out
+ --
+ -- RS232 Interface Signals
+ --
+ RxC : in std_logic; -- Receive Baud Clock
+ TxC : in std_logic; -- Transmit Baud Clock
+ RxD : in std_logic; -- Receive Data
+ TxD : out std_logic; -- Transmit Data
+ DCD_n : in std_logic; -- Data Carrier Detect
+ CTS_n : in std_logic; -- Clear To Send
+ RTS_n : out std_logic -- Request To send
+ );
+end acia6850; --================== End of entity ==============================--
+
+-------------------------------------------------------------------------------
+-- Architecture for ACIA_6850 Interface registees
+-------------------------------------------------------------------------------
+
+architecture rtl of acia6850 is
+
+ type DCD_State_Type is (DCD_State_Idle, DCD_State_Int, DCD_State_Reset);
+
+ -----------------------------------------------------------------------------
+ -- Signals
+ -----------------------------------------------------------------------------
+ --
+ -- Reset signals
+ --
+ signal ac_rst : std_logic; -- Reset (Software & Hardware)
+ signal rx_rst : std_logic; -- Receive Reset (Software & Hardware)
+ signal tx_rst : std_logic; -- Transmit Reset (Software & Hardware)
+
+ --------------------------------------------------------------------
+ -- Status Register: StatReg
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 0 Read
+ --
+ -----------+--------+-------+--------+--------+--------+--------+--------+
+ -- Irq | PErr | OErr | FErr | CTS | DCD | TxRdy | RxRdy |
+ -----------+--------+-------+--------+--------+--------+--------+--------+
+ --
+ -- Irq - Bit[7] - Interrupt request
+ -- PErr - Bit[6] - Receive Parity error (parity bit does not match)
+ -- OErr - Bit[5] - Receive Overrun error (new character received before last read)
+ -- FErr - Bit[4] - Receive Framing Error (bad stop bit)
+ -- CTS - Bit[3] - Clear To Send level
+ -- DCD - Bit[2] - Data Carrier Detect (lost modem carrier)
+ -- TxRdy - Bit[1] - Transmit Buffer Empty (ready to accept next transmit character)
+ -- RxRdy - Bit[0] - Receive Data Ready (character received)
+ --
+
+ signal StatReg : std_logic_vector(7 downto 0) := (others => '0'); -- status register
+
+ ----------------------------------------------------------------------
+ -- Control Register: CtrlReg
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 0 Write
+ --
+ -----------+--------+--------+--------+--------+--------+--------+--------+
+ -- RxIE |TxCtl(1)|TxCtl(0)|WdFmt(2)|WdFmt(1)|WdFmt(0)|BdCtl(1)|BdCtl(0)|
+ -----------+--------+--------+--------+--------+--------+--------+--------+
+ -- RxIEnb - Bit[7]
+ -- 0 - Rx Interrupt disabled
+ -- 1 - Rx Interrupt enabled
+ -- TxCtl - Bits[6..5]
+ -- 0 1 - Tx Interrupt Enable
+ -- 1 0 - RTS high
+ -- WdFmt - Bits[4..2]
+ -- 0 0 0 - 7 data, even parity, 2 stop
+ -- 0 0 1 - 7 data, odd parity, 2 stop
+ -- 0 1 0 - 7 data, even parity, 1 stop
+ -- 0 1 1 - 7 data, odd parity, 1 stop
+ -- 1 0 0 - 8 data, no parity, 2 stop
+ -- 1 0 1 - 8 data, no parity, 1 stop
+ -- 1 1 0 - 8 data, even parity, 1 stop
+ -- 1 1 1 - 8 data, odd parity, 1 stop
+ -- BdCtl - Bits[1..0]
+ -- 0 0 - Baud Clk divide by 1
+ -- 0 1 - Baud Clk divide by 16
+ -- 1 0 - Baud Clk divide by 64
+ -- 1 1 - reset
+ signal CtrlReg : std_logic_vector(7 downto 0) := (others => '0'); -- control register
+
+ ----------------------------------------------------------------------
+ -- Receive Register
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 1 Read
+ --
+ signal RxReg : std_logic_vector(7 downto 0) := (others => '0');
+
+ ----------------------------------------------------------------------
+ -- Transmit Register
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 1 Write
+ --
+ signal TxReg : std_logic_vector(7 downto 0) := (others => '0');
+
+ signal TxDat : std_logic := '1'; -- Transmit data bit
+ signal TxRdy : std_logic := '0'; -- Transmit buffer empty
+ signal RxRdy : std_logic := '0'; -- Receive Data ready
+ --
+ signal FErr : std_logic := '0'; -- Frame error
+ signal OErr : std_logic := '0'; -- Output error
+ signal PErr : std_logic := '0'; -- Parity Error
+ --
+ signal TxIE : std_logic := '0'; -- Transmit interrupt enable
+ signal RxIE : std_logic := '0'; -- Receive interrupt enable
+ --
+ signal RxRd : std_logic := '0'; -- Read receive buffer
+ signal TxWr : std_logic := '0'; -- Write Transmit buffer
+ signal StRd : std_logic := '0'; -- Read status register
+ --
+ signal DCDState : DCD_State_Type; -- DCD Reset state sequencer
+ signal DCDDel : std_logic := '0'; -- Delayed DCD_n
+ signal DCDEdge : std_logic := '0'; -- Rising DCD_N Edge Pulse
+ signal DCDInt : std_logic := '0'; -- DCD Interrupt
+
+ signal BdFmt : std_logic_vector(1 downto 0) := "00"; -- Baud Clock Format
+ signal WdFmt : std_logic_vector(2 downto 0) := "000"; -- Data Word Format
+
+ -----------------------------------------------------------------------------
+ -- RX Signals
+ -----------------------------------------------------------------------------
+
+ type RxStateType is ( RxState_Wait, RxState_Data, RxState_Parity, RxState_Stop );
+
+ signal RxState : RxStateType; -- receive bit state
+
+ signal RxDatDel0 : Std_Logic := '0'; -- Delayed Rx Data
+ signal RxDatDel1 : Std_Logic := '0'; -- Delayed Rx Data
+ signal RxDatDel2 : Std_Logic := '0'; -- Delayed Rx Data
+ signal RxDatEdge : Std_Logic := '0'; -- Rx Data Edge pulse
+
+ signal RxClkDel : Std_Logic := '0'; -- Delayed Rx Input Clock
+ signal RxClkEdge : Std_Logic := '0'; -- Rx Input Clock Edge pulse
+ signal RxStart : Std_Logic := '0'; -- Rx Start request
+ signal RxEnable : Std_Logic := '0'; -- Rx Enabled
+ signal RxClkCnt : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Rx Baud Clock Counter
+ signal RxBdClk : Std_Logic := '0'; -- Rx Baud Clock
+ signal RxBdDel : Std_Logic := '0'; -- Delayed Rx Baud Clock
+
+ signal RxReq : Std_Logic := '0'; -- Rx Data Valid
+ signal RxAck : Std_Logic := '0'; -- Rx Data Valid
+ signal RxParity : Std_Logic := '0'; -- Calculated RX parity bit
+ signal RxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0'); -- Rx Bit counter
+ signal RxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0'); -- Shift Register
+
+ -----------------------------------------------------------------------------
+ -- TX Signals
+ -----------------------------------------------------------------------------
+ type TxStateType is ( TxState_Idle, TxState_Start, TxState_Data, TxState_Parity, TxState_Stop );
+
+ signal TxState : TxStateType; -- Transmitter state
+
+ signal TxClkDel : Std_Logic := '0'; -- Delayed Tx Input Clock
+ signal TxClkEdge : Std_Logic := '0'; -- Tx Input Clock Edge pulse
+ signal TxClkCnt : Std_Logic_Vector(5 downto 0) := (others => '0'); -- Tx Baud Clock Counter
+ signal TxBdClk : Std_Logic := '0'; -- Tx Baud Clock
+ signal TxBdDel : Std_Logic := '0'; -- Delayed Tx Baud Clock
+
+ signal TxReq : std_logic := '0'; -- Request transmit start
+ signal TxAck : std_logic := '0'; -- Acknowledge transmit start
+ signal TxParity : Std_logic := '0'; -- Parity Bit
+ signal TxBitCount : Std_Logic_Vector(2 downto 0) := (others => '0'); -- Data Bit Counter
+ signal TxShiftReg : Std_Logic_Vector(7 downto 0) := (others => '0'); -- Transmit shift register
+
+begin
+
+---------------------------------------------------------------
+-- ACIA Reset may be hardware or software
+---------------------------------------------------------------
+ acia_reset : process( clk, rst, ac_rst, dcd_n )
+ begin
+ --
+ -- ACIA reset Synchronous
+ -- Includes software reset
+ --
+ if falling_edge(clk) then
+ ac_rst <= (CtrlReg(1) and CtrlReg(0)) or rst;
+ end if;
+ -- Receiver reset
+ rx_rst <= ac_rst or DCD_n;
+ -- Transmitter reset
+ tx_rst <= ac_rst;
+
+ end process;
+
+
+-----------------------------------------------------------------------------
+-- Generate Read / Write strobes.
+-----------------------------------------------------------------------------
+
+ ACIA_Read_Write : process(clk, ac_rst)
+ begin
+ if falling_edge(clk) then
+ if ac_rst = '1' then
+ CtrlReg <= (others => '0');
+ TxReg <= (others => '0');
+ RxRd <= '0';
+ TxWr <= '0';
+ StRd <= '0';
+ else
+ RxRd <= '0';
+ TxWr <= '0';
+ StRd <= '0';
+ if cs = '1' then
+ if Addr = '0' then -- Control / Status register
+ if rw = '0' then -- write control register
+ CtrlReg <= data_in;
+ else -- read status register
+ StRd <= '1';
+ end if;
+ else -- Data Register
+ if rw = '0' then -- write transmiter register
+ TxReg <= data_in;
+ TxWr <= '1';
+ else -- read receiver register
+ RxRd <= '1';
+ end if;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -----------------------------------------------------------------------------
+ -- ACIA Status Register
+ -----------------------------------------------------------------------------
+
+ acia_status : process( clk )
+ begin
+ if falling_edge( clk ) then
+ StatReg(0) <= RxRdy; -- Receive Data Ready
+ StatReg(1) <= TxRdy and (not CTS_n); -- Transmit Buffer Empty
+ StatReg(2) <= DCDInt; -- Data Carrier Detect
+ StatReg(3) <= CTS_n; -- Clear To Send
+ StatReg(4) <= FErr; -- Framing error
+ StatReg(5) <= OErr; -- Overrun error
+ StatReg(6) <= PErr; -- Parity error
+ StatReg(7) <= (RxIE and RxRdy) or
+ (RxIE and DCDInt) or
+ (TxIE and TxRdy);
+ end if;
+ end process;
+
+
+-----------------------------------------------------------------------------
+-- ACIA Transmit Control
+-----------------------------------------------------------------------------
+
+ acia_control : process(CtrlReg, TxDat)
+ begin
+ case CtrlReg(6 downto 5) is
+ when "00" => -- Disable TX Interrupts, Assert RTS
+ TxD <= TxDat;
+ TxIE <= '0';
+ RTS_n <= '0';
+ when "01" => -- Enable TX interrupts, Assert RTS
+ TxD <= TxDat;
+ TxIE <= '1';
+ RTS_n <= '0';
+ when "10" => -- Disable Tx Interrupts, Clear RTS
+ TxD <= TxDat;
+ TxIE <= '0';
+ RTS_n <= '1';
+ when "11" => -- Disable Tx interrupts, Assert RTS, send break
+ TxD <= '0';
+ TxIE <= '0';
+ RTS_n <= '0';
+ when others =>
+ null;
+ end case;
+
+ RxIE <= CtrlReg(7);
+ WdFmt <= CtrlReg(4 downto 2);
+ BdFmt <= CtrlReg(1 downto 0);
+ end process;
+
+---------------------------------------------------------------
+-- Set Data Output Multiplexer
+--------------------------------------------------------------
+
+ acia_data_mux : process(Addr, RxReg, StatReg)
+ begin
+ if Addr = '1' then
+ data_out <= RxReg; -- read receiver register
+ else
+ data_out <= StatReg; -- read status register
+ end if;
+ end process;
+
+ irq <= StatReg(7);
+
+---------------------------------------------------------------
+-- Data Carrier Detect Edge rising edge detect
+---------------------------------------------------------------
+ acia_dcd_edge : process( clk, ac_rst )
+ begin
+ if falling_edge(clk) then
+ if ac_rst = '1' then
+ DCDDel <= '0';
+ DCDEdge <= '0';
+ else
+ DCDDel <= DCD_n;
+ DCDEdge <= DCD_n and (not DCDDel);
+ end if;
+ end if;
+ end process;
+
+
+---------------------------------------------------------------
+-- Data Carrier Detect Interrupt
+---------------------------------------------------------------
+-- If Data Carrier is lost, an interrupt is generated
+-- To clear the interrupt, first read the status register
+-- then read the data receive register
+
+ acia_dcd_int : process( clk, ac_rst )
+ begin
+ if falling_edge(clk) then
+ if ac_rst = '1' then
+ DCDInt <= '0';
+ DCDState <= DCD_State_Idle;
+ else
+ case DCDState is
+ when DCD_State_Idle =>
+ -- DCD Edge activates interrupt
+ if DCDEdge = '1' then
+ DCDInt <= '1';
+ DCDState <= DCD_State_Int;
+ end if;
+ when DCD_State_Int =>
+ -- To reset DCD interrupt,
+ -- First read status
+ if StRd = '1' then
+ DCDState <= DCD_State_Reset;
+ end if;
+ when DCD_State_Reset =>
+ -- Then read receive register
+ if RxRd = '1' then
+ DCDInt <= '0';
+ DCDState <= DCD_State_Idle;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+
+ ---------------------------------------------------------------------
+ -- Receiver Clock Edge Detection
+ ---------------------------------------------------------------------
+ -- A rising edge will produce a one clock cycle pulse
+ --
+ acia_rx_clock_edge : process( clk, rx_rst )
+ begin
+ if falling_edge(clk) then
+ if rx_rst = '1' then
+ RxClkDel <= '0';
+ RxClkEdge <= '0';
+ else
+ RxClkDel <= RxC;
+ RxClkEdge <= (not RxClkDel) and RxC;
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Receiver Data Edge Detection
+ ---------------------------------------------------------------------
+ -- A falling edge will produce a pulse on RxClk wide
+ --
+ acia_rx_data_edge : process( clk, rx_rst )
+ begin
+ if falling_edge(clk) then
+ if rx_rst = '1' then
+ RxDatDel0 <= '0';
+ RxDatDel1 <= '0';
+ RxDatDel2 <= '0';
+ RxDatEdge <= '0';
+ else
+ RxDatDel0 <= RxD;
+ RxDatDel1 <= RxDatDel0;
+ RxDatDel2 <= RxDatDel1;
+ RxDatEdge <= RxDatDel0 and (not RxD);
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Receiver Start / Stop
+ ---------------------------------------------------------------------
+ -- Enable the receive clock on detection of a start bit
+ -- Disable the receive clock after a byte is received.
+ --
+ acia_rx_start_stop : process( clk, rx_rst )
+ begin
+ if falling_edge(clk) then
+ if rx_rst = '1' then
+ RxEnable <= '0';
+ RxStart <= '0';
+ elsif (RxEnable = '0') and (RxDatEdge = '1') then
+ -- Data Edge detected
+ RxStart <= '1'; -- Request Start and
+ RxEnable <= '1'; -- Enable Receive Clock
+ elsif (RxStart = '1') and (RxAck = '1') then
+ -- Data is being received
+ RxStart <= '0'; -- Reset Start Request
+ elsif (RxStart = '0') and (RxAck = '0') then
+ -- Data has now been received
+ RxEnable <= '0'; -- Disable Receiver until next Start Bit
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Receiver Clock Divider
+ ---------------------------------------------------------------------
+ -- Hold the Rx Clock divider in reset when the receiver is disabled
+ -- Advance the count only on a rising Rx clock edge
+ --
+ acia_rx_clock_divide : process( clk, rx_rst )
+ begin
+ if falling_edge(clk) then
+ if rx_rst = '1' then
+ RxClkCnt <= (others => '0');
+ elsif RxDatEdge = '1' then
+ -- reset on falling data edge
+ RxClkCnt <= (others => '0');
+ elsif RxClkEdge = '1' then
+ -- increment count on Clock edge
+ RxClkCnt <= RxClkCnt + "000001";
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Receiver Baud Clock Selector
+ ---------------------------------------------------------------------
+ -- BdFmt
+ -- 0 0 - Baud Clk divide by 1
+ -- 0 1 - Baud Clk divide by 16
+ -- 1 0 - Baud Clk divide by 64
+ -- 1 1 - Reset
+ --
+ acia_rx_baud_clock_select : process( BdFmt, RxC, RxClkCnt )
+ begin
+ case BdFmt is
+ when "00" => -- Div by 1
+ RxBdClk <= RxC;
+ when "01" => -- Div by 16
+ RxBdClk <= RxClkCnt(3);
+ when "10" => -- Div by 64
+ RxBdClk <= RxClkCnt(5);
+ when others => -- Software Reset
+ RxBdClk <= '0';
+ end case;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Receiver process
+ ---------------------------------------------------------------------
+ -- WdFmt - Bits[4..2]
+ -- 0 0 0 - 7 data, even parity, 2 stop
+ -- 0 0 1 - 7 data, odd parity, 2 stop
+ -- 0 1 0 - 7 data, even parity, 1 stop
+ -- 0 1 1 - 7 data, odd parity, 1 stop
+ -- 1 0 0 - 8 data, no parity, 2 stop
+ -- 1 0 1 - 8 data, no parity, 1 stop
+ -- 1 1 0 - 8 data, even parity, 1 stop
+ -- 1 1 1 - 8 data, odd parity, 1 stop
+ acia_rx_receive : process( clk, rst )
+ begin
+ if falling_edge( clk ) then
+ if rx_rst = '1' then
+ FErr <= '0';
+ OErr <= '0';
+ PErr <= '0';
+ RxShiftReg <= (others => '0'); -- Reset Shift register
+ RxReg <= (others => '0');
+ RxParity <= '0'; -- reset Parity bit
+ RxAck <= '0'; -- Receiving data
+ RxBitCount <= (others => '0');
+ RxState <= RxState_Wait;
+ else
+ RxBdDel <= RxBdClk;
+ if RxBdDel = '0' and RxBdClk = '1' then
+ case RxState is
+ when RxState_Wait =>
+ RxShiftReg <= (others => '0'); -- Reset Shift register
+ RxParity <= '0'; -- Reset Parity bit
+ if WdFmt(2) = '0' then -- WdFmt(2) = '0' => 7 data bits
+ RxBitCount <= "110";
+ else -- WdFmt(2) = '1' => 8 data bits
+ RxBitCount <= "111";
+ end if;
+ if RxDatDel2 = '0' then -- look for start bit
+ RxState <= RxState_Data; -- if low, start reading data
+ end if;
+
+ when RxState_Data => -- Receiving data bits
+ RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1);
+ RxParity <= RxParity xor RxDatDel2;
+ RxAck <= '1'; -- Flag receive in progress
+ RxBitCount <= RxBitCount - "001";
+ if RxBitCount = "000" then
+ if WdFmt(2) = '0' then -- WdFmt(2) = '0' => 7 data
+ RxState <= RxState_Parity; -- 7 bits always has parity
+ elsif WdFmt(1) = '0' then -- WdFmt(2) = '1' => 8 data
+ RxState <= RxState_Stop; -- WdFmt(1) = '0' => no parity
+ PErr <= '0'; -- Reset Parity Error
+ else
+ RxState <= RxState_Parity; -- WdFmt(1) = '1' => 8 data + parity
+ end if;
+ end if;
+
+ when RxState_Parity => -- Receive Parity bit
+ if WdFmt(2) = '0' then -- if 7 data bits, shift parity into MSB
+ RxShiftReg <= RxDatDel2 & RxShiftReg(7 downto 1); -- 7 data + parity
+ end if;
+ if RxParity = (RxDatDel2 xor WdFmt(0)) then
+ PErr <= '1'; -- If parity not the same flag error
+ else
+ PErr <= '0';
+ end if;
+ RxState <= RxState_Stop;
+
+ when RxState_Stop => -- stop bit (Only one required for RX)
+ RxAck <= '0'; -- Flag Receive Complete
+ RxReg <= RxShiftReg;
+ if RxDatDel2 = '1' then -- stop bit expected
+ FErr <= '0'; -- yes, no framing error
+ else
+ FErr <= '1'; -- no, framing error
+ end if;
+ if RxRdy = '1' then -- Has previous data been read ?
+ OErr <= '1'; -- no, overrun error
+ else
+ OErr <= '0'; -- yes, no over run error
+ end if;
+ RxState <= RxState_Wait;
+
+ when others =>
+ RxAck <= '0'; -- Flag Receive Complete
+ RxState <= RxState_Wait;
+ end case;
+ end if;
+ end if;
+ end if;
+
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Receiver Read process
+ ---------------------------------------------------------------------
+ acia_rx_read : process( clk, rst, RxRdy )
+ begin
+ if falling_edge(clk) then
+ if rx_rst = '1' then
+ RxRdy <= '0';
+ RxReq <= '0';
+ elsif RxRd = '1' then
+ -- Data was read,
+ RxRdy <= '0'; -- Reset receive full
+ RxReq <= '1'; -- Request more data
+ elsif RxReq = '1' and RxAck = '1' then
+ -- Data is being received
+ RxReq <= '0'; -- reset receive request
+ elsif RxReq = '0' and RxAck = '0' then
+ -- Data now received
+ RxRdy <= '1'; -- Flag RxRdy and read Shift Register
+ end if;
+ end if;
+ end process;
+
+
+ ---------------------------------------------------------------------
+ -- Transmit Clock Edge Detection
+ -- A falling edge will produce a one clock cycle pulse
+ ---------------------------------------------------------------------
+
+ acia_tx_clock_edge : process( Clk, tx_rst )
+ begin
+ if falling_edge(clk) then
+ if tx_rst = '1' then
+ TxClkDel <= '0';
+ TxClkEdge <= '0';
+ else
+ TxClkDel <= TxC;
+ TxClkEdge <= TxClkDel and (not TxC);
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Transmit Clock Divider
+ -- Advance the count only on an input clock pulse
+ ---------------------------------------------------------------------
+
+ acia_tx_clock_divide : process( clk, tx_rst )
+ begin
+ if falling_edge(clk) then
+ if tx_rst = '1' then
+ TxClkCnt <= (others=>'0');
+ elsif TxClkEdge = '1' then
+ TxClkCnt <= TxClkCnt + "000001";
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Transmit Baud Clock Selector
+ ---------------------------------------------------------------------
+ acia_tx_baud_clock_select : process( BdFmt, TxClkCnt, TxC )
+ begin
+ -- BdFmt
+ -- 0 0 - Baud Clk divide by 1
+ -- 0 1 - Baud Clk divide by 16
+ -- 1 0 - Baud Clk divide by 64
+ -- 1 1 - reset
+ case BdFmt is
+ when "00" => -- Div by 1
+ TxBdClk <= TxC;
+ when "01" => -- Div by 16
+ TxBdClk <= TxClkCnt(3);
+ when "10" => -- Div by 64
+ TxBdClk <= TxClkCnt(5);
+ when others => -- Software reset
+ TxBdClk <= '0';
+ end case;
+ end process;
+
+ -----------------------------------------------------------------------------
+ -- Implements the Tx unit
+ -----------------------------------------------------------------------------
+ -- WdFmt - Bits[4..2]
+ -- 0 0 0 - 7 data, even parity, 2 stop
+ -- 0 0 1 - 7 data, odd parity, 2 stop
+ -- 0 1 0 - 7 data, even parity, 1 stop
+ -- 0 1 1 - 7 data, odd parity, 1 stop
+ -- 1 0 0 - 8 data, no parity, 2 stop
+ -- 1 0 1 - 8 data, no parity, 1 stop
+ -- 1 1 0 - 8 data, even parity, 1 stop
+ -- 1 1 1 - 8 data, odd parity, 1 stop
+ acia_tx_transmit : process( clk, tx_rst)
+ begin
+ if falling_edge(clk) then
+ if tx_rst = '1' then
+ TxDat <= '1';
+ TxShiftReg <= (others=>'0');
+ TxParity <= '0';
+ TxBitCount <= (others=>'0');
+ TxAck <= '0';
+ TxState <= TxState_Idle;
+ else
+
+ TxBdDel <= TxBdClk;
+ -- On rising edge of baud clock, run the state machine
+ if TxBdDel = '0' and TxBdClk = '1' then
+
+ case TxState is
+ when TxState_Idle =>
+ TxDat <= '1';
+ if TxReq = '1' then
+ TxShiftReg <= TxReg; -- Load Shift reg with Tx Data
+ TxAck <= '1';
+ TxState <= TxState_Start;
+ end if;
+
+ when TxState_Start =>
+ TxDat <= '0'; -- Start bit
+ TxParity <= '0';
+ if WdFmt(2) = '0' then
+ TxBitCount <= "110"; -- 7 data + parity
+ else
+ TxBitCount <= "111"; -- 8 data
+ end if;
+ TxState <= TxState_Data;
+
+ when TxState_Data =>
+ TxDat <= TxShiftReg(0);
+ TxShiftReg <= '1' & TxShiftReg(7 downto 1);
+ TxParity <= TxParity xor TxShiftReg(0);
+ TxBitCount <= TxBitCount - "001";
+ if TxBitCount = "000" then
+ if (WdFmt(2) = '1') and (WdFmt(1) = '0') then
+ if WdFmt(0) = '0' then -- 8 data bits
+ TxState <= TxState_Stop; -- 2 stops
+ else
+ TxAck <= '0';
+ TxState <= TxState_Idle; -- 1 stop
+ end if;
+ else
+ TxState <= TxState_Parity; -- parity
+ end if;
+ end if;
+
+ when TxState_Parity => -- 7/8 data + parity bit
+ if WdFmt(0) = '0' then
+ TxDat <= not(TxParity); -- even parity
+ else
+ TxDat <= TxParity; -- odd parity
+ end if;
+ if WdFmt(1) = '0' then
+ TxState <= TxState_Stop; -- 2 stops
+ else
+ TxAck <= '0';
+ TxState <= TxState_Idle; -- 1 stop
+ end if;
+
+ when TxState_Stop => -- first of two stop bits
+ TxDat <= '1';
+ TxAck <= '0';
+ TxState <= TxState_Idle;
+
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------
+ -- Transmitter Write process
+ ---------------------------------------------------------------------
+
+ acia_tx_write : process( clk, tx_rst, TxWr, TxReq, TxAck )
+ begin
+ if falling_edge(clk) then
+ if tx_rst = '1' then
+ TxRdy <= '0';
+ TxReq <= '0';
+ elsif TxWr = '1' then
+ -- Data was read,
+ TxRdy <= '0'; -- Reset transmit empty
+ TxReq <= '1'; -- Request data transmit
+ elsif TxReq = '1' and TxAck = '1' then -- Data is being transmitted
+ TxReq <= '0'; -- reset transmit request
+ elsif TxReq = '0' and TxAck = '0' then -- Data transmitted
+ TxRdy <= '1'; -- Flag TxRdy
+ end if;
+ end if;
+ end process;
+
+end rtl;
+
Index: Flasher.vhd
===================================================================
--- Flasher.vhd (nonexistent)
+++ Flasher.vhd (revision 100)
@@ -0,0 +1,99 @@
+--===========================================================================--
+-- --
+-- LED Flasher --
+-- --
+--===========================================================================--
+--
+-- File name : flasher.vhd
+--
+-- Entity name : flasher
+--
+-- Purpose : Implements a long counter used to flash a LED
+-- to indicate code has loaded correctly
+--
+-- Dependencies : ieee.std_logic_1164
+-- ieee.numeric_std
+-- ieee.std_logic_unsigned
+-- unisim.vcomponents
+--
+-- Author : John E. Kent
+--
+-- Email : dilbert57@opencores.org
+--
+-- Web : http://opencores.org/project,system09
+--
+--
+-- Copyright (C) 2010 John Kent
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program 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 General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see .
+--
+--===========================================================================--
+-- --
+-- Revision History --
+-- --
+--===========================================================================--
+--
+-- Version Author Date Changes
+--
+-- 0.1 John Kent 2010-08-28 Made separate module
+--
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+ use ieee.std_logic_unsigned.all;
+library unisim;
+ use unisim.vcomponents.all;
+
+-----------------------------------------------------------------------
+-- Entity for B3_SRAM --
+-----------------------------------------------------------------------
+
+entity flasher is
+ port (
+ clk : in std_logic; -- Clock input
+ rst : in std_logic; -- Reset input (active high)
+ LED : out Std_Logic -- LED output
+ );
+end flasher;
+
+--================== End of entity ==============================--
+
+-------------------------------------------------------------------------------
+-- Architecture for Flasher
+-------------------------------------------------------------------------------
+
+architecture rtl of flasher is
+
+-- Flashing LED test signals
+signal countL : std_logic_vector(23 downto 0);
+
+begin
+
+--
+-- LED Flasher to indicate code has loaded
+--
+my_LED_Flasher : process (clk, rst, CountL )
+begin
+ if falling_edge(clk) then
+ if rst = '1' then
+ countL <= (others=>'0');
+ else
+ countL <= countL + 1;
+ end if;
+ end if;
+ LED <= countL(23);
+end process;
+
+end rtl;
\ No newline at end of file
Index: twi-master.vhd
===================================================================
--- twi-master.vhd (nonexistent)
+++ twi-master.vhd (revision 100)
@@ -0,0 +1,399 @@
+--===========================================================================--
+--
+-- SYNTHEZIABLE VHDL TWO WIRE INTERFACE
+--
+--===========================================================================
+--
+-- This core adheres to the GNU public license
+--
+-- Design units : TWI Master core
+--
+-- File name : twi.vhd
+--
+-- Purpose : Implements an I2C master Interface
+--
+-- Dependencies : ieee.std_logic_1164
+-- ieee.numeric_std
+-- unisim.vcomponents
+--
+-- Revision list :
+--
+-- Version Author Date Changes
+--
+-- 0.1 John Kent 2010-05-04 New model
+--
+-- dilbert57@opencores.org
+--
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+library unisim;
+ use unisim.vcomponents.all;
+
+-----------------------------------------------------------------------
+-- Entity for TWI --
+-----------------------------------------------------------------------
+
+entity twi is
+ generic (
+ CLK_FREQ : integer := 25_000_000;
+ );
+
+ port (
+ --
+ -- CPU signals
+ --
+ clk : in std_logic; -- System Clock
+ rst : in std_logic; -- Reset input (active high)
+ cs : in std_logic; -- Chip Select
+ rw : in std_logic; -- Read / Not Write
+ irq : out std_logic; -- Interrupt
+ addr : in std_logic; -- Register Select
+ data_in : in std_logic_vector(7 downto 0); -- Data Bus In
+ data_out : out std_logic_vector(7 downto 0); -- Data Bus Out
+
+ -- I2C Signals
+ --
+ scl : inout std_logic; -- serial clock
+ sda : inout std_logic -- serial data
+ );
+end twi;
+
+-------------------------------------------------------------------------------
+-- Architecture for Two Wire Interface registers
+-------------------------------------------------------------------------------
+
+architecture rtl of twi is
+
+ -----------------------------------------------------------------------------
+ -- Signals
+ -----------------------------------------------------------------------------
+
+ ----------------------------------------------------------------------
+ -- Status Register: twi_status_reg
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 0 Read
+ --
+ --+-------+-------+-------+-------+-------+-------+-------+-------+
+ --| RXIRQ | TXIRQ | ACKE | | | | TXRDY | RXRDY |
+ --+-------+-------+-------+-------+-------+-------+-------+-------+
+ -- RXIRQ - Bit[7] - Receive Interrupt Request
+ -- TXIRQ - Bit[6] - Transmit Interrupt Request
+ -- ACKE - Bit[5] - Acknowledge Error
+ -- TXRDY - Bit[1] - Transmit Ready (byte transmitted)
+ -- RXRDY - Bit[0] - Receive Ready (byte received)
+ --
+ signal twi_status_reg : std_logic_vector(7 downto 0) := (others => '0');
+
+ ----------------------------------------------------------------------
+ -- Control Register: twi_control_reg
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 0 Write
+ --
+ --+--------+-------+--------+--------+--------+--------+--------+--------+
+ --| RXIE | TXIE | TWPS(1)| TWPS(0)| TWBR(3)| TWBR(2)| TWBR(1)| TWBR(0)|
+ --+--------+-------+--------+--------+--------+--------+--------+--------+
+ -- RXIE - Bit[7]
+ -- 0 - Rx Interrupt disabled
+ -- 1 - Rx Interrupt enabled
+ -- TXIE - Bit[6]
+ -- 0 - Tx Interrupt disabled
+ -- 1 - Tx Interrupt enabled
+ --
+ -- SCL frequency = CPU Clock Frequency / ( 16 + 2(TWBR) . 4^TWPS)
+ --
+ -- TWPS - Bits[5..4]
+ -- 0 0 - Prescale by 1
+ -- 0 1 - Prescale by 4
+ -- 1 0 - Prescale by 16
+ -- 1 1 - Prescale by 64
+ --
+ -- TWBR - Bits[3..0]
+ -- 0 0 0 0 - Baud Clk divide by 1
+ -- 0 0 0 1 - Baud Clk divide by 2
+ -- 0 0 1 0 - Baud Clk divide by 3
+ -- 0 0 1 1 - Baud Clk divide by 4
+ -- 0 1 0 0 - Baud Clk divide by 5
+ -- 0 1 0 1 - Baud Clk divide by 6
+ -- 0 1 1 0 - Baud Clk divide by 7
+ -- 0 1 1 1 - Baud Clk divide by 8
+ -- 1 0 0 0 - Baud Clk divide by 9
+ -- 1 0 0 1 - Baud Clk divide by 10
+ -- 1 0 1 0 - Baud Clk divide by 11
+ -- 1 0 1 1 - Baud Clk divide by 12
+ -- 1 1 0 0 - Baud Clk divide by 13
+ -- 1 1 0 1 - Baud Clk divide by 14
+ -- 1 1 1 0 - Baud Clk divide by 15
+ -- 1 1 1 1 - Baud Clk divide by 16
+
+
+ signal twi_control_reg : std_logic_vector(7 downto 0) := (others => '0'); -- control register
+
+ ----------------------------------------------------------------------
+ -- Receive Register
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 1 Read
+ --
+ signal twi_rx_reg : std_logic_vector(7 downto 0) := (others => '0');
+
+ ----------------------------------------------------------------------
+ -- Transmit Register
+ ----------------------------------------------------------------------
+ --
+ -- IO address + 1 Write
+ --
+ signal twi_tx_reg : std_logic_vector(7 downto 0) := (others => '0');
+
+ signal Reset : std_logic; -- Reset (Software & Hardware)
+ signal RxRst : std_logic; -- Receive Reset (Software & Hardware)
+ signal TxRst : std_logic; -- Transmit Reset (Software & Hardware)
+ signal TxDbit : std_logic; -- Transmit data bit
+ signal RxDR : std_logic := '0'; -- Receive Data ready
+ signal TxIdle : std_logic; -- Transmitter idle
+ signal TxBE : std_logic := '0'; -- Transmit buffer empty
+ signal TxAck : std_logic; -- Byte transmitted to transmitter
+ --
+ signal FErr : std_logic := '0'; -- Frame error
+ signal OErr : std_logic := '0'; -- Output error
+ signal PErr : std_logic := '0'; -- Parity Error
+ --
+ signal TxIEnb : std_logic := '0'; -- Transmit interrupt enable
+ signal RxIEnb : std_logic := '0'; -- Receive interrupt enable
+ --
+ signal ReadRR : std_logic := '0'; -- Read receive buffer
+ signal WriteTR : std_logic := '0'; -- Write transmit buffer
+ signal ReadSR : std_logic := '0'; -- Read Status register
+ --
+ signal DCDState : DCD_State_Type; -- DCD Reset state sequencer
+ signal DCDDel : std_logic := '0'; -- Delayed DCD_n
+ signal DCDEdge : std_logic := '0'; -- Rising DCD_N Edge Pulse
+ signal DCDInt : std_logic := '0'; -- DCD Interrupt
+
+begin
+ -----------------------------------------------------------------------------
+ -- Instantiation of internal components
+ -----------------------------------------------------------------------------
+
+ RxDev : entity ACIA_RX port map (
+ Clk => clk,
+ RxRst => RxRst,
+ RxRd => ReadRR,
+ WdFmt => CtrlReg(4 downto 2),
+ BdFmt => CtrlReg(1 downto 0),
+ RxClk => RxC,
+ RxDat => RxD,
+ RxFErr => FErr,
+ RxOErr => OErr,
+ RxPErr => PErr,
+ RxRdy => RxDR,
+ RxDout => RecvReg
+ );
+
+ TxDev : entity ACIA_TX port map (
+ Clk => clk,
+ Reset => TxRst,
+ Wr => WriteTR,
+ Din => TxReg,
+ WdFmt => CtrlReg(4 downto 2),
+ BdFmt => CtrlReg(1 downto 0),
+ TxClk => TxC,
+ Dat => TxDbit,
+ Empty => TxIdle
+ );
+
+---------------------------------------------------------------
+-- ACIA Reset may be hardware or software
+---------------------------------------------------------------
+ ACIA_Reset : process(clk, rst)
+ begin
+ -- Asynchronous External reset
+ if rst = '1' then
+ Reset <= '1';
+ elsif falling_edge(clk) then
+ -- Synchronous Software reset
+ Reset <= CtrlReg(1) and CtrlReg(0);
+ end if;
+
+ end process;
+
+ -- Transmitter reset
+ TxRst <= Reset;
+ -- Receiver reset
+ RxRst <= Reset or DCD_n;
+
+ -----------------------------------------------------------------------------
+ -- ACIA Status Register
+ -----------------------------------------------------------------------------
+
+ ACIA_Status : process(Reset, clk)
+ begin
+ if Reset = '1' then
+ StatReg <= (others => '0');
+ elsif falling_edge(clk) then
+ StatReg(0) <= RxDR; -- Receive Data Ready
+ StatReg(1) <= TxBE and (not CTS_n); -- Transmit Buffer Empty
+ StatReg(2) <= DCDInt; -- Data Carrier Detect
+ StatReg(3) <= CTS_n; -- Clear To Send
+ StatReg(4) <= FErr; -- Framing error
+ StatReg(5) <= OErr; -- Overrun error
+ StatReg(6) <= PErr; -- Parity error
+ StatReg(7) <= (RxIEnb and RxDR) or
+ (RxIEnb and DCDInt) or
+ (TxIEnb and TxBE);
+ end if;
+ end process;
+
+
+-----------------------------------------------------------------------------
+-- ACIA Transmit Control
+-----------------------------------------------------------------------------
+
+ ACIA_Control : process(CtrlReg, TxDbit)
+ begin
+ case CtrlReg(6 downto 5) is
+ when "00" => -- Disable TX Interrupts, Assert RTS
+ TxD <= TxDbit;
+ TxIEnb <= '0';
+ when "01" => -- Enable TX interrupts, Assert RTS
+ TxD <= TxDbit;
+ TxIEnb <= '1';
+ when "10" => -- Disable Tx Interrupts, Clear RTS
+ TxD <= TxDbit;
+ TxIEnb <= '0';
+ when "11" => -- Disable Tx interrupts, Assert RTS, send break
+ TxD <= '0';
+ TxIEnb <= '0';
+ when others =>
+ null;
+ end case;
+
+ RxIEnb <= CtrlReg(7);
+ end process;
+
+ tx_process : process(clk, reset)
+ begin
+ if reset = '1' then
+ WriteTR <= '0';
+ TxAck <= '0';
+ elsif falling_edge(clk) then
+ WriteTR <= '0';
+ TxAck <= '0';
+ if TxBE = '0' and TxIdle = '1' then
+ WriteTR <= '1';
+ TxAck <= '1';
+ end if;
+ end if;
+ end process;
+
+-----------------------------------------------------------------------------
+-- Generate Read / Write strobes.
+-----------------------------------------------------------------------------
+
+ ACIA_Read_Write : process(clk, Reset)
+ begin
+ if reset = '1' then
+ CtrlReg <= (others => '0');
+ TxReg <= (others => '0');
+ ReadRR <= '0';
+ ReadSR <= '0';
+ TxBE <= '1';
+ elsif falling_edge(clk) then
+ ReadRR <= '0';
+ ReadSR <= '0';
+ if TxAck = '1' then
+ TxBE <= '1';
+ end if;
+ if cs = '1' then
+ if Addr = '0' then -- Control / Status register
+ if rw = '0' then -- write control register
+ CtrlReg <= DataIn;
+ else -- read status register
+ ReadSR <= '1';
+ end if;
+ else -- Data Register
+ if rw = '0' then -- write transmiter register
+ TxReg <= DataIn;
+ TxBE <= '0';
+ else -- read receiver register
+ ReadRR <= '1';
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+---------------------------------------------------------------
+-- Set Data Output Multiplexer
+--------------------------------------------------------------
+
+ ACIA_Data_Mux : process(Addr, RecvReg, StatReg)
+ begin
+ if Addr = '1' then
+ DataOut <= RecvReg; -- read receiver register
+ else
+ DataOut <= StatReg; -- read status register
+ end if;
+ end process;
+
+ irq <= StatReg(7);
+
+---------------------------------------------------------------
+-- Data Carrier Detect Edge rising edge detect
+---------------------------------------------------------------
+ ACIA_DCD_edge : process(reset, clk)
+ begin
+ if reset = '1' then
+ DCDEdge <= '0';
+ DCDDel <= '0';
+ elsif falling_edge(clk) then
+ DCDDel <= DCD_n;
+ DCDEdge <= DCD_n and (not DCDDel);
+ end if;
+ end process;
+
+
+---------------------------------------------------------------
+-- Data Carrier Detect Interrupt
+---------------------------------------------------------------
+-- If Data Carrier is lost, an interrupt is generated
+-- To clear the interrupt, first read the status register
+-- then read the data receive register
+
+ ACIA_DCD_Int : process(reset, clk)
+ begin
+ if reset = '1' then
+ DCDInt <= '0';
+ DCDState <= DCD_State_Idle;
+ elsif falling_edge(clk) then
+ case DCDState is
+ when DCD_State_Idle =>
+ -- DCD Edge activates interrupt
+ if DCDEdge = '1' then
+ DCDInt <= '1';
+ DCDState <= DCD_State_Int;
+ end if;
+ when DCD_State_Int =>
+ -- To reset DCD interrupt,
+ -- First read status
+ if ReadSR = '1' then
+ DCDState <= DCD_State_Reset;
+ end if;
+ when DCD_State_Reset =>
+ -- Then read receive register
+ if ReadRR = '1' then
+ DCDInt <= '0';
+ DCDState <= DCD_State_Idle;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ end process;
+
+ rts_n <= RxDR;
+
+end rtl;
+