This commit is contained in:
141
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_gpio.vhd
Normal file
141
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_gpio.vhd
Normal file
@@ -0,0 +1,141 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- MC68901 compatible multi function port core. ----
|
||||
---- ----
|
||||
---- This are the SUSKA MFP IP core's general purpose I/Os. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_GPIO is
|
||||
port ( -- System control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Asynchronous bus control:
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
|
||||
-- Data and Adresses:
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
|
||||
-- Timer controls:
|
||||
AER_4 : out bit;
|
||||
AER_3 : out bit;
|
||||
|
||||
GPIP_IN : in bit_vector(7 downto 0);
|
||||
GPIP_OUT : out bit_vector(7 downto 0);
|
||||
GPIP_OUT_EN : buffer bit_vector(7 downto 0);
|
||||
GP_INT : out bit_vector(7 downto 0)
|
||||
);
|
||||
end entity WF68901IP_GPIO;
|
||||
|
||||
architecture BEHAVIOR of WF68901IP_GPIO is
|
||||
signal GPDR : bit_vector(7 downto 0);
|
||||
signal DDR : bit_vector(7 downto 0);
|
||||
signal AER : bit_vector(7 downto 0);
|
||||
signal GPDR_I : bit_vector(7 downto 0);
|
||||
begin
|
||||
-- These two bits control the timers A and B pulse width operation and the
|
||||
-- timers A and B event count operation.
|
||||
AER_4 <= AER(4);
|
||||
AER_3 <= AER(3);
|
||||
-- This statement provides 8 XOR units setting the desired interrupt polarity.
|
||||
-- While the level control is done here, the edge triggering is provided by
|
||||
-- the interrupt control hardware. The level control is individually for each
|
||||
-- GPIP port pin. The interrupt edge trigger unit must operate in any case on
|
||||
-- the low to high transistion of the respective port pin.
|
||||
GP_INT <= AER xnor GPIP_IN;
|
||||
|
||||
GPIO_REGISTERS: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
GPDR <= (others => '0');
|
||||
DDR <= (others => '0');
|
||||
AER <= (others => '0');
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' then
|
||||
case RS is
|
||||
when "00000" => GPDR <= DATA_IN;
|
||||
when "00001" => AER <= DATA_IN;
|
||||
when "00010" => DDR <= DATA_IN;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process GPIO_REGISTERS;
|
||||
GPIP_OUT <= GPDR; -- Port outputs.
|
||||
GPIP_OUT_EN <= DDR; -- The DDR is capable to control bitwise the GPIP.
|
||||
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS <= "00010" else '0';
|
||||
DATA_OUT <= DDR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00010" else
|
||||
AER when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00001" else
|
||||
GPDR_I when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00000" else (others => '0');
|
||||
|
||||
P_GPDR: process(GPIP_IN, GPIP_OUT_EN, GPDR)
|
||||
-- Read back control: Read the port pins, if the data direction is configured as input.
|
||||
-- Read the respective GPDR register bit, if the data direction is configured as output.
|
||||
begin
|
||||
for i in 7 downto 0 loop
|
||||
if GPIP_OUT_EN(i) = '1' then -- Port is configured output.
|
||||
GPDR_I(i) <= GPDR(i);
|
||||
else
|
||||
GPDR_I(i) <= GPIP_IN(i); -- Port is configured input.
|
||||
end if;
|
||||
end loop;
|
||||
end process P_GPDR;
|
||||
end architecture BEHAVIOR;
|
||||
391
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_interrupts.vhd
Normal file
391
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_interrupts.vhd
Normal file
@@ -0,0 +1,391 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- MC68901 compatible multi function port core. ----
|
||||
---- ----
|
||||
---- This is the SUSKA MFP IP core interrupt logic file. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/06/03 WF
|
||||
-- Fixed Pending register logic.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- Fixed interrupt polarity for TA_I and TB_I.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_INTERRUPTS is
|
||||
port ( -- System control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Asynchronous bus control:
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
|
||||
-- Data and Adresses:
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
|
||||
-- Interrupt control:
|
||||
IACKn : in bit;
|
||||
IEIn : in bit;
|
||||
IEOn : out bit;
|
||||
IRQn : out bit;
|
||||
|
||||
-- Interrupt sources:
|
||||
GP_INT : in bit_vector(7 downto 0);
|
||||
|
||||
AER_4 : in bit;
|
||||
AER_3 : in bit;
|
||||
TAI : in bit;
|
||||
TBI : in bit;
|
||||
TA_PWM : in bit;
|
||||
TB_PWM : in bit;
|
||||
TIMER_A_INT : in bit;
|
||||
TIMER_B_INT : in bit;
|
||||
TIMER_C_INT : in bit;
|
||||
TIMER_D_INT : in bit;
|
||||
|
||||
RCV_ERR : in bit;
|
||||
TRM_ERR : in bit;
|
||||
RCV_BUF_F : in bit;
|
||||
TRM_BUF_E : in bit
|
||||
);
|
||||
end entity WF68901IP_INTERRUPTS;
|
||||
|
||||
architecture BEHAVIOR of WF68901IP_INTERRUPTS is
|
||||
-- Interrupt state machine:
|
||||
type INT_STATES is (SCAN, REQUEST, VECTOR_OUT);
|
||||
signal INT_STATE : INT_STATES;
|
||||
-- The registers:
|
||||
signal IERA : bit_vector(7 downto 0);
|
||||
signal IERB : bit_vector(7 downto 0);
|
||||
signal IPRA : bit_vector(7 downto 0);
|
||||
signal IPRB : bit_vector(7 downto 0);
|
||||
signal ISRA : bit_vector(7 downto 0);
|
||||
signal ISRB : bit_vector(7 downto 0);
|
||||
signal IMRA : bit_vector(7 downto 0);
|
||||
signal IMRB : bit_vector(7 downto 0);
|
||||
signal VR : bit_vector(7 downto 3);
|
||||
-- Interconnect:
|
||||
signal VECT_NUMBER : bit_vector(7 downto 0);
|
||||
signal INT_SRC : bit_vector(15 downto 0);
|
||||
signal INT_SRC_EDGE : bit_vector(15 downto 0);
|
||||
signal INT_ENA : bit_vector(15 downto 0);
|
||||
signal INT_MASK : bit_vector(15 downto 0);
|
||||
signal INT_PENDING : bit_vector(15 downto 0);
|
||||
signal INT_SERVICE : bit_vector(15 downto 0);
|
||||
signal INT_PASS : bit_vector(15 downto 0);
|
||||
signal INT_OUT : bit_vector(15 downto 0);
|
||||
signal GP_INT_4 : bit;
|
||||
signal GP_INT_3 : bit;
|
||||
begin
|
||||
-- Interrupt source for the GPI_4 and GPI_3 is normally the respective port pin.
|
||||
-- But when the timers operate in their PWM modes, the GPI_4 and GPI_3 are associated
|
||||
-- to timer A and timer B.
|
||||
-- The xor logic provides polarity control for the interrupt transition. Be aware,
|
||||
-- that the PWM signals cause an interrupt on the opposite transition like the
|
||||
-- respective GPIP port pins (with the same AER settings).
|
||||
--GP_INT_4 <= GP_INT(4) when TA_PWM = '0' else TAI xor AER_4;
|
||||
--GP_INT_3 <= GP_INT(3) when TB_PWM = '0' else TBI xor AER_3;
|
||||
GP_INT_4 <= GP_INT(4) when TA_PWM = '0' else TAI xnor AER_4; -- This should be correct.
|
||||
GP_INT_3 <= GP_INT(3) when TB_PWM = '0' else TBI xnor AER_3;
|
||||
|
||||
|
||||
-- Interrupt source priority sorted (15 = highest):
|
||||
INT_SRC <= GP_INT(7 downto 6) & TIMER_A_INT & RCV_BUF_F & RCV_ERR & TRM_BUF_E & TRM_ERR & TIMER_B_INT &
|
||||
GP_INT(5) & GP_INT_4 & TIMER_C_INT & TIMER_D_INT & GP_INT_3 & GP_INT(2 downto 0);
|
||||
|
||||
INT_ENA <= IERA & IERB;
|
||||
INT_MASK <= IMRA & IMRB;
|
||||
INT_PENDING <= IPRA & IPRB;
|
||||
INT_SERVICE <= ISRA & ISRB;
|
||||
INT_OUT <= INT_PENDING and INT_MASK; -- Masking:
|
||||
|
||||
-- Enable the daisy chain, if there is no pending interrupt and
|
||||
-- the interrupt state machine is not in service.
|
||||
IEOn <= '0' when INT_OUT = x"0000" and INT_STATE = SCAN else '1';
|
||||
|
||||
-- Interrupt request:
|
||||
IRQn <= '0' when INT_OUT /= x"0000" and INT_STATE = REQUEST else '1';
|
||||
|
||||
EDGE_ENA: process(RESETn, CLK)
|
||||
-- These are the 16 edge detectors of the 16 interrupt input sources. This
|
||||
-- process also provides the disabling or enabling via the IERA and IERB registers.
|
||||
variable LOCK : bit_vector(15 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
INT_SRC_EDGE <= x"0000";
|
||||
LOCK := x"0000";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
for i in 15 downto 0 loop
|
||||
if INT_SRC(i) = '1' and INT_ENA(i) = '1' and LOCK(i) = '0' then
|
||||
LOCK(i) := '1';
|
||||
INT_SRC_EDGE(i) <= '1';
|
||||
elsif INT_SRC(i) = '0' then
|
||||
LOCK(i) := '0';
|
||||
INT_SRC_EDGE(i) <= '0';
|
||||
else
|
||||
INT_SRC_EDGE(i) <= '0';
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process EDGE_ENA;
|
||||
|
||||
INT_REGISTERS: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
IERA <= (others => '0');
|
||||
IERB <= (others => '0');
|
||||
IPRA <= (others => '0');
|
||||
IPRB <= (others => '0');
|
||||
ISRA <= (others => '0');
|
||||
ISRB <= (others => '0');
|
||||
IMRA <= (others => '0');
|
||||
IMRB <= (others => '0');
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' then
|
||||
case RS is
|
||||
when "00011" => IERA <= DATA_IN; -- Enable A.
|
||||
when "00100" => IERB <= DATA_IN; -- Enable B.
|
||||
when "00101" =>
|
||||
-- Only a '0' can be written to the pending register.
|
||||
for i in 7 downto 0 loop
|
||||
if DATA_IN(i) = '0' then
|
||||
IPRA(i) <= '0'; -- Pending A.
|
||||
end if;
|
||||
end loop;
|
||||
when "00110" =>
|
||||
-- Only a '0' can be written to the pending register.
|
||||
for i in 7 downto 0 loop
|
||||
if DATA_IN(i) = '0' then
|
||||
IPRB(i) <= '0'; -- Pending B.
|
||||
end if;
|
||||
end loop;
|
||||
when "00111" =>
|
||||
-- Only a '0' can be written to the in service register.
|
||||
for i in 7 downto 0 loop
|
||||
if DATA_IN(i) = '0' then
|
||||
ISRA(i) <= '0'; -- In Service A.
|
||||
end if;
|
||||
end loop;
|
||||
when "01000" =>
|
||||
-- Only a '0' can be written to the in service register.
|
||||
for i in 7 downto 0 loop
|
||||
if DATA_IN(i) = '0' then
|
||||
ISRB(i) <= '0'; -- In Service B.
|
||||
end if;
|
||||
end loop;
|
||||
when "01001" => IMRA <= DATA_IN; -- Mask A.
|
||||
when "01010" => IMRB <= DATA_IN; -- Mask B.
|
||||
when "01011" => VR <= DATA_IN(7 downto 3); -- Vector register.
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- Pending register:
|
||||
-- set and clear bit logic.
|
||||
for i in 15 downto 8 loop
|
||||
if INT_SRC_EDGE(i) = '1' then
|
||||
IPRA(i-8) <= '1';
|
||||
elsif INT_ENA(i) = '0' then
|
||||
IPRA(i-8) <= '0'; -- Clear by disabling the channel.
|
||||
elsif INT_PASS(i) = '1' then
|
||||
IPRA(i-8) <= '0'; -- Clear by passing the interrupt.
|
||||
end if;
|
||||
end loop;
|
||||
for i in 7 downto 0 loop
|
||||
if INT_SRC_EDGE(i) = '1' then
|
||||
IPRB(i) <= '1';
|
||||
elsif INT_ENA(i) = '0' then
|
||||
IPRB(i) <= '0'; -- Clear by disabling the channel.
|
||||
elsif INT_PASS(i) = '1' then
|
||||
IPRB(i) <= '0'; -- Clear by passing the interrupt.
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
-- In-Service register:
|
||||
-- Set bit logic, VR(3) is the service register enable.
|
||||
for i in 15 downto 8 loop
|
||||
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
|
||||
ISRA(i-8) <= '1';
|
||||
end if;
|
||||
end loop;
|
||||
for i in 7 downto 0 loop
|
||||
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
|
||||
ISRB(i) <= '1';
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process INT_REGISTERS;
|
||||
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "00010" and RS <= "01011" else '1' when INT_STATE = VECTOR_OUT else '0';
|
||||
|
||||
DATA_OUT <= IERA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00011" else
|
||||
IERB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00100" else
|
||||
IPRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00101" else
|
||||
IPRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00110" else
|
||||
ISRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00111" else
|
||||
ISRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01000" else
|
||||
IMRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01001" else
|
||||
IMRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01010" else
|
||||
VR & "000" when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01011" else
|
||||
VECT_NUMBER when INT_STATE = VECTOR_OUT else x"00";
|
||||
|
||||
P_INT_STATE : process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
INT_STATE <= SCAN;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
case INT_STATE is
|
||||
when SCAN =>
|
||||
INT_PASS <= x"0000";
|
||||
-- Automatic End of Interrupt mode. Service register disabled.
|
||||
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
|
||||
-- vector number (VR(7 downto 4) = x"0").
|
||||
if INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '0' and IEIn = '0' then
|
||||
INT_STATE <= REQUEST; -- Non masked interrupt is pending.
|
||||
-- The following 16 are the Software end of interrupt mode. Service register enabled.
|
||||
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
|
||||
-- vector number (VR(7 downto 4) = x"0"). The interrupts are prioritized.
|
||||
elsif INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '1' and IEIn = '0' then
|
||||
if INT_OUT (15) = '1' and INT_SERVICE(15) = '0' then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (14) = '1' and INT_SERVICE(15 downto 14) = "00" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (13) = '1' and INT_SERVICE(15 downto 13) = "000" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (12) = '1' and INT_SERVICE(15 downto 12) = x"0" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (11) = '1' and INT_SERVICE(15 downto 11) = x"0" & '0' then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (10) = '1' and INT_SERVICE(15 downto 10) = x"0" & "00" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (9) = '1' and INT_SERVICE(15 downto 9) = x"0" & "000" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (8) = '1' and INT_SERVICE(15 downto 8) = x"00" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (7) = '1' and INT_SERVICE(15 downto 7) = x"00" & '0' then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (6) = '1' and INT_SERVICE(15 downto 6) = x"00" & "00" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (5) = '1' and INT_SERVICE(15 downto 5) = x"00" & "000" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (4) = '1' and INT_SERVICE(15 downto 4) = x"000" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (3) = '1' and INT_SERVICE(15 downto 3) = x"000" & '0' then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (2) = '1' and INT_SERVICE(15 downto 2) = x"000" & "00" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (1) = '1' and INT_SERVICE(15 downto 1) = x"000" & "000" then
|
||||
INT_STATE <= REQUEST;
|
||||
elsif INT_OUT (0) = '1' and INT_SERVICE(15 downto 0) = x"0000" then
|
||||
INT_STATE <= REQUEST;
|
||||
else
|
||||
INT_STATE <= SCAN; -- Wait for interrupt.
|
||||
end if;
|
||||
else
|
||||
INT_STATE <= SCAN;
|
||||
end if;
|
||||
when REQUEST =>
|
||||
if IACKn = '0' and DSn = '0' then -- Vectored interrupt mode.
|
||||
INT_STATE <= VECTOR_OUT; -- Non masked interrupt is pending.
|
||||
if INT_OUT(15) = '1' then
|
||||
INT_PASS(15) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"F"; -- GPI 7.
|
||||
elsif INT_OUT(14) = '1' then
|
||||
INT_PASS(14) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"E"; -- GPI 6.
|
||||
elsif INT_OUT(13) = '1' then
|
||||
INT_PASS(13) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"D"; -- TIMER A.
|
||||
elsif INT_OUT(12) = '1' then
|
||||
INT_PASS(12) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"C"; -- Receive buffer full.
|
||||
elsif INT_OUT(11) = '1' then
|
||||
INT_PASS(11) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"B"; -- Receiver error.
|
||||
elsif INT_OUT(10) = '1' then
|
||||
INT_PASS(10) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"A"; -- Transmit buffer empty.
|
||||
elsif INT_OUT(9) = '1' then
|
||||
INT_PASS(9) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"9"; -- Transmit error.
|
||||
elsif INT_OUT(8) = '1' then
|
||||
INT_PASS(8) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"8"; -- Timer B.
|
||||
elsif INT_OUT(7) = '1' then
|
||||
INT_PASS(7) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"7"; -- GPI 5.
|
||||
elsif INT_OUT(6) = '1' then
|
||||
INT_PASS(6) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"6"; -- GPI 4.
|
||||
elsif INT_OUT(5) = '1' then
|
||||
INT_PASS(5) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"5"; -- Timer C.
|
||||
elsif INT_OUT(4) = '1' then
|
||||
INT_PASS(4) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"4"; -- Timer D.
|
||||
elsif INT_OUT(3) = '1' then
|
||||
INT_PASS(3) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"3"; -- GPI 3.
|
||||
elsif INT_OUT(2) = '1' then
|
||||
INT_PASS(2) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"2"; -- GPI 2.
|
||||
elsif INT_OUT(1) = '1' then
|
||||
INT_PASS(1) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"1"; -- GPI 1.
|
||||
elsif INT_OUT(0) = '1' then
|
||||
INT_PASS(0) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"0"; -- GPI 0.
|
||||
end if;
|
||||
-- Polled interrupt mode: End of interrupt by writing to the pending registers.
|
||||
elsif CSn = '0' and DSn = '0' and RWn = '0' and (RS = "00101" or RS = "00110") then
|
||||
INT_STATE <= SCAN;
|
||||
else
|
||||
INT_STATE <= REQUEST; -- Wait.
|
||||
end if;
|
||||
when VECTOR_OUT =>
|
||||
INT_PASS <= x"0000";
|
||||
if DSn = '1' or IACKn = '1' then
|
||||
INT_STATE <= SCAN; -- Finished.
|
||||
else
|
||||
INT_STATE <= VECTOR_OUT; -- Wait for processor to read the vector.
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end process P_INT_STATE;
|
||||
end architecture BEHAVIOR;
|
||||
263
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_pkg.vhd
Normal file
263
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_pkg.vhd
Normal file
@@ -0,0 +1,263 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- MC68901 compatible multi function port core. ----
|
||||
---- ----
|
||||
---- This is the package file containing the component ----
|
||||
---- declarations. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
package WF68901IP_PKG is
|
||||
component WF68901IP_USART_TOP
|
||||
port ( CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
RC : in bit;
|
||||
TC : in bit;
|
||||
SI : in bit;
|
||||
SO : out bit;
|
||||
SO_EN : out bit;
|
||||
RX_ERR_INT : out bit;
|
||||
RX_BUFF_INT : out bit;
|
||||
TX_ERR_INT : out bit;
|
||||
TX_BUFF_INT : out bit;
|
||||
RRn : out bit;
|
||||
TRn : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF68901IP_USART_CTRL
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
RX_SAMPLE : in bit;
|
||||
RX_DATA : in bit_vector(7 downto 0);
|
||||
TX_DATA : out bit_vector(7 downto 0);
|
||||
SCR_OUT : out bit_vector(7 downto 0);
|
||||
BF : in bit;
|
||||
BE : in bit;
|
||||
FE : in bit;
|
||||
OE : in bit;
|
||||
UE : in bit;
|
||||
PE : in bit;
|
||||
M_CIP : in bit;
|
||||
FS_B : in bit;
|
||||
TX_END : in bit;
|
||||
CL : out bit_vector(1 downto 0);
|
||||
ST : out bit_vector(1 downto 0);
|
||||
FS_CLR : out bit;
|
||||
RSR_READ : out bit;
|
||||
TSR_READ : out bit;
|
||||
UDR_READ : out bit;
|
||||
UDR_WRITE : out bit;
|
||||
LOOPBACK : out bit;
|
||||
SDOUT_EN : out bit;
|
||||
SD_LEVEL : out bit;
|
||||
CLK_MODE : out bit;
|
||||
RE : out bit;
|
||||
TE : out bit;
|
||||
P_ENA : out bit;
|
||||
P_EOn : out bit;
|
||||
SS : out bit;
|
||||
BR : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF68901IP_USART_TX
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
SCR : in bit_vector(7 downto 0);
|
||||
TX_DATA : in bit_vector(7 downto 0);
|
||||
SDATA_OUT : out bit;
|
||||
TXCLK : in bit;
|
||||
CL : in bit_vector(1 downto 0);
|
||||
ST : in bit_vector(1 downto 0);
|
||||
TE : in bit;
|
||||
BR : in bit;
|
||||
P_ENA : in bit;
|
||||
P_EOn : in bit;
|
||||
UDR_WRITE : in bit;
|
||||
TSR_READ : in bit;
|
||||
CLK_MODE : in bit;
|
||||
TX_END : out bit;
|
||||
UE : out bit;
|
||||
BE : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF68901IP_USART_RX
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
SCR : in bit_vector(7 downto 0);
|
||||
RX_SAMPLE : out bit;
|
||||
RX_DATA : out bit_vector(7 downto 0);
|
||||
RXCLK : in bit;
|
||||
SDATA_IN : in bit;
|
||||
CL : in bit_vector(1 downto 0);
|
||||
ST : in bit_vector(1 downto 0);
|
||||
P_ENA : in bit;
|
||||
P_EOn : in bit;
|
||||
CLK_MODE : in bit;
|
||||
RE : in bit;
|
||||
FS_CLR : in bit;
|
||||
SS : in bit;
|
||||
RSR_READ : in bit;
|
||||
UDR_READ : in bit;
|
||||
M_CIP : out bit;
|
||||
FS_B : out bit;
|
||||
BF : out bit;
|
||||
OE : out bit;
|
||||
PE : out bit;
|
||||
FE : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF68901IP_INTERRUPTS
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
IACKn : in bit;
|
||||
IEIn : in bit;
|
||||
IEOn : out bit;
|
||||
IRQn : out bit;
|
||||
GP_INT : in bit_vector(7 downto 0);
|
||||
AER_4 : in bit;
|
||||
AER_3 : in bit;
|
||||
TAI : in bit;
|
||||
TBI : in bit;
|
||||
TA_PWM : in bit;
|
||||
TB_PWM : in bit;
|
||||
TIMER_A_INT : in bit;
|
||||
TIMER_B_INT : in bit;
|
||||
TIMER_C_INT : in bit;
|
||||
TIMER_D_INT : in bit;
|
||||
RCV_ERR : in bit;
|
||||
TRM_ERR : in bit;
|
||||
RCV_BUF_F : in bit;
|
||||
TRM_BUF_E : in bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF68901IP_GPIO
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
AER_4 : out bit;
|
||||
AER_3 : out bit;
|
||||
GPIP_IN : in bit_vector(7 downto 0);
|
||||
GPIP_OUT : out bit_vector(7 downto 0);
|
||||
GPIP_OUT_EN : out bit_vector(7 downto 0);
|
||||
GP_INT : out bit_vector(7 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF68901IP_TIMERS
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
XTAL1 : in bit;
|
||||
TAI : in bit;
|
||||
TBI : in bit;
|
||||
AER_4 : in bit;
|
||||
AER_3 : in bit;
|
||||
TA_PWM : out bit;
|
||||
TB_PWM : out bit;
|
||||
TAO : out bit;
|
||||
TBO : out bit;
|
||||
TCO : out bit;
|
||||
TDO : out bit;
|
||||
TIMER_A_INT : out bit;
|
||||
TIMER_B_INT : out bit;
|
||||
TIMER_C_INT : out bit;
|
||||
TIMER_D_INT : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
end WF68901IP_PKG;
|
||||
533
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_timers.vhd
Normal file
533
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_timers.vhd
Normal file
@@ -0,0 +1,533 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- MC68901 compatible multi function port core. ----
|
||||
---- ----
|
||||
---- This is the SUSKA MFP IP core timers logic file. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K7A 2006/12/28 WF
|
||||
-- The timer is modified to work on the CLK instead
|
||||
-- of XTAL1. This modification is done to provide
|
||||
-- a synchronous design.
|
||||
-- Revision 2K8A 2008/02/29 WF
|
||||
-- Fixed a serious prescaler bug.
|
||||
-- Revision 2K9A 20090620 WF
|
||||
-- Introduced timer readback registers.
|
||||
-- TIMER_x_INT is now a strobe.
|
||||
-- Minor improvements.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_TIMERS is
|
||||
port ( -- System control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Asynchronous bus control:
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
|
||||
-- Data and Adresses:
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
|
||||
-- Timers and timer control:
|
||||
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
|
||||
TAI : in bit;
|
||||
TBI : in bit;
|
||||
AER_4 : in bit;
|
||||
AER_3 : in bit;
|
||||
TA_PWM : out bit; -- Indicates, that timer A is in PWM mode (used in Interrupt logic).
|
||||
TB_PWM : out bit; -- Indicates, that timer B is in PWM mode (used in Interrupt logic).
|
||||
TAO : buffer bit;
|
||||
TBO : buffer bit;
|
||||
TCO : buffer bit;
|
||||
TDO : buffer bit;
|
||||
TIMER_A_INT : out bit;
|
||||
TIMER_B_INT : out bit;
|
||||
TIMER_C_INT : out bit;
|
||||
TIMER_D_INT : out bit
|
||||
);
|
||||
end entity WF68901IP_TIMERS;
|
||||
|
||||
architecture BEHAVIOR of WF68901IP_TIMERS is
|
||||
signal XTAL1_S : bit;
|
||||
signal XTAL_STRB : bit;
|
||||
signal TACR : bit_vector(4 downto 0); -- Timer A control register.
|
||||
signal TBCR : bit_vector(4 downto 0); -- Timer B control register.
|
||||
signal TCDCR : bit_vector(5 downto 0); -- Timer C and D control register.
|
||||
signal TADR : bit_vector(7 downto 0); -- Timer A data register.
|
||||
signal TBDR : bit_vector(7 downto 0); -- Timer B data register.
|
||||
signal TCDR : bit_vector(7 downto 0); -- Timer C data register.
|
||||
signal TDDR : bit_vector(7 downto 0); -- Timer D data register.
|
||||
signal TIMER_A : std_logic_vector(7 downto 0); -- Timer A count register.
|
||||
signal TIMER_B : std_logic_vector(7 downto 0); -- Timer B count register.
|
||||
signal TIMER_C : std_logic_vector(7 downto 0); -- Timer C count register.
|
||||
signal TIMER_D : std_logic_vector(7 downto 0); -- Timer D count register.
|
||||
signal TIMER_R_A : bit_vector(7 downto 0); -- Timer A readback register.
|
||||
signal TIMER_R_B : bit_vector(7 downto 0); -- Timer B readback register.
|
||||
signal TIMER_R_C : bit_vector(7 downto 0); -- Timer C readback register.
|
||||
signal TIMER_R_D : bit_vector(7 downto 0); -- Timer D readback register.
|
||||
signal A_CNTSTRB : bit;
|
||||
signal B_CNTSTRB : bit;
|
||||
signal C_CNTSTRB : bit;
|
||||
signal D_CNTSTRB : bit;
|
||||
signal TAI_I : bit;
|
||||
signal TBI_I : bit;
|
||||
signal TAI_STRB : bit; -- Strobe for the event counter mode.
|
||||
signal TBI_STRB : bit; -- Strobe for the event counter mode.
|
||||
signal TAO_I : bit; -- Timer A output signal.
|
||||
signal TBO_I : bit; -- Timer A output signal.
|
||||
begin
|
||||
SYNC: process
|
||||
-- This process provides a 'clean' XTAL1.
|
||||
-- Without this sync, the edge detector for
|
||||
-- XTAL_STRB does not work properly.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
XTAL1_S <= XTAL1;
|
||||
-- Polarity control for the event counter and the PWM mode:
|
||||
TAI_I <= TAI xnor AER_4;
|
||||
TBI_I <= TBI xnor AER_3;
|
||||
end process SYNC;
|
||||
|
||||
-- Output enables for timer A and timer B:
|
||||
-- The outputs are held low for asserted reset flags in the control registers TACR
|
||||
-- and TBCR but also during a write operation to these registers.
|
||||
TAO <= '0' when TACR(4) = '1' else
|
||||
'0' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "01100" else TAO_I;
|
||||
TBO <= '0' when TBCR(4) = '1' else
|
||||
'0' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "01101" else TBO_I;
|
||||
|
||||
-- Control outputs for the PWM modi of the timers A and B. These
|
||||
-- controls are used in the interrupt logic to select the interrupt
|
||||
-- sources GPIP4 or TAI repective GPIP3 or TBI.
|
||||
TA_PWM <= '1' when TACR(3 downto 0) > x"8" else '0';
|
||||
TB_PWM <= '1' when TBCR(3 downto 0) > x"8" else '0';
|
||||
|
||||
TIMER_REGISTERS: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TACR <= (others => '0');
|
||||
TBCR <= (others => '0');
|
||||
TCDCR <= (others => '0');
|
||||
-- TADR <= Do not clear during reset!
|
||||
-- TBDR <= Do not clear during reset!
|
||||
-- TCDR <= Do not clear during reset!
|
||||
-- TDDR <= Do not clear during reset!
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' then
|
||||
case RS is
|
||||
when "01100" => TACR <= DATA_IN(4 downto 0);
|
||||
when "01101" => TBCR <= DATA_IN(4 downto 0);
|
||||
when "01110" => TCDCR <= DATA_IN(6 downto 4) & DATA_IN(2 downto 0);
|
||||
when "01111" => TADR <= DATA_IN;
|
||||
when "10000" => TBDR <= DATA_IN;
|
||||
when "10001" => TCDR <= DATA_IN;
|
||||
when "10010" => TDDR <= DATA_IN;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMER_REGISTERS;
|
||||
|
||||
TIMER_READBACK : process(RESETn, CLK)
|
||||
-- This process provides the readback information for the
|
||||
-- timers A to D. The information read is the information
|
||||
-- last clocked into the timer read register when the DSn
|
||||
-- pin had last gone high prior to the current read cycle.
|
||||
variable READ_A : boolean;
|
||||
variable READ_B : boolean;
|
||||
variable READ_C : boolean;
|
||||
variable READ_D : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TIMER_R_A <= x"00";
|
||||
TIMER_R_B <= x"00";
|
||||
TIMER_R_C <= x"00";
|
||||
TIMER_R_D <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DSn = '0' and RS = "01111" then
|
||||
READ_A := true;
|
||||
elsif DSn = '0' and RS = "10000" then
|
||||
READ_B := true;
|
||||
elsif DSn = '0' and RS = "10001" then
|
||||
READ_C := true;
|
||||
elsif DSn = '0' and RS = "10010" then
|
||||
READ_D := true;
|
||||
elsif DSn = '1' and READ_A = true then
|
||||
TIMER_R_A <= To_BitVector(TIMER_A);
|
||||
READ_A := false;
|
||||
elsif DSn = '1' and READ_B = true then
|
||||
TIMER_R_B <= To_BitVector(TIMER_B);
|
||||
READ_B := false;
|
||||
elsif DSn = '1' and READ_C = true then
|
||||
TIMER_R_C <= To_BitVector(TIMER_C);
|
||||
READ_C := false;
|
||||
elsif DSn = '1' and READ_D = true then
|
||||
TIMER_R_D <= To_BitVector(TIMER_D);
|
||||
READ_D := false;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMER_READBACK;
|
||||
|
||||
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "01011" and RS <= "10010" else '0';
|
||||
DATA_OUT <= "000" & TACR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01100" else
|
||||
"000" & TBCR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01101" else
|
||||
'0' & TCDCR(5 downto 3) & '0' & TCDCR(2 downto 0) when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01110" else
|
||||
TIMER_R_A when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01111" else
|
||||
TIMER_R_B when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10000" else
|
||||
TIMER_R_C when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10001" else
|
||||
TIMER_R_D when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10010" else (others => '0');
|
||||
|
||||
XTAL_STROBE: process(RESETn, CLK)
|
||||
-- This process provides a strobe with 1 clock cycle
|
||||
-- (CLK) length after every rising edge of XTAL1.
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
XTAL_STRB <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if XTAL1_S = '1' and LOCK = false then
|
||||
XTAL_STRB <= '1';
|
||||
LOCK := true;
|
||||
elsif XTAL1_S = '0' then
|
||||
XTAL_STRB <= '0';
|
||||
LOCK := false;
|
||||
else
|
||||
XTAL_STRB <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process XTAL_STROBE;
|
||||
|
||||
TAI_STROBE: process(RESETn, CLK)
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TAI_STRB <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if TAI_I = '1' and XTAL_STRB = '1' and LOCK = false then
|
||||
LOCK := true;
|
||||
TAI_STRB <= '1';
|
||||
elsif TAI_I = '0' then
|
||||
LOCK := false;
|
||||
TAI_STRB <= '0';
|
||||
else
|
||||
TAI_STRB <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process TAI_STROBE;
|
||||
|
||||
TBI_STROBE: process(RESETn, CLK)
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TBI_STRB <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if TBI_I = '1' and XTAL_STRB = '1' and LOCK = false then
|
||||
LOCK := true;
|
||||
TBI_STRB <= '1';
|
||||
elsif TBI_I = '0' then
|
||||
LOCK := false;
|
||||
TBI_STRB <= '0';
|
||||
else
|
||||
TBI_STRB <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process TBI_STROBE;
|
||||
|
||||
PRESCALE_A: process
|
||||
-- The prescalers work even if the RESETn is asserted.
|
||||
variable PRESCALE : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
A_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - '1';
|
||||
elsif XTAL_STRB = '1' then
|
||||
case TACR(2 downto 0) is
|
||||
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
|
||||
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
|
||||
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
|
||||
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
|
||||
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
|
||||
end case;
|
||||
A_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_A;
|
||||
|
||||
PRESCALE_B: process
|
||||
-- The prescalers work even if the RESETn is asserted.
|
||||
variable PRESCALE : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
B_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - '1';
|
||||
elsif XTAL_STRB = '1' then
|
||||
case TBCR(2 downto 0) is
|
||||
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
|
||||
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
|
||||
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
|
||||
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
|
||||
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
|
||||
end case;
|
||||
B_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_B;
|
||||
|
||||
PRESCALE_C: process
|
||||
-- The prescalers work even if the RESETn is asserted.
|
||||
variable PRESCALE : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
C_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - '1';
|
||||
elsif XTAL_STRB = '1' then
|
||||
case TCDCR(5 downto 3) is
|
||||
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
|
||||
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
|
||||
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
|
||||
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
|
||||
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped.
|
||||
end case;
|
||||
C_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_C;
|
||||
|
||||
PRESCALE_D: process
|
||||
-- The prescalers work even if the RESETn is asserted.
|
||||
variable PRESCALE : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
D_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - '1';
|
||||
elsif XTAL_STRB = '1' then
|
||||
case TCDCR(2 downto 0) is
|
||||
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
|
||||
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
|
||||
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
|
||||
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
|
||||
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped.
|
||||
end case;
|
||||
D_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_D;
|
||||
|
||||
TIMERA: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TAO_I <= '0';
|
||||
TIMER_A_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_A_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "01111" and TACR(3 downto 0) = x"0" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
-- The loading works asynchronous due to the possibly low XTAL1 clock.
|
||||
TIMER_A <= To_StdLogicVector(DATA_IN);
|
||||
else
|
||||
case TACR(3 downto 0) is
|
||||
when x"0" => -- Timer is off.
|
||||
TAO_I <= '0';
|
||||
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
|
||||
if A_CNTSTRB = '1' and TIMER_A /= x"01" then -- Count.
|
||||
TIMER_A <= TIMER_A - '1';
|
||||
elsif A_CNTSTRB = '1' and TIMER_A = x"01" then -- Reload.
|
||||
TIMER_A <= To_StdLogicVector(TADR);
|
||||
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
|
||||
TIMER_A_INT <= '1';
|
||||
end if;
|
||||
when x"8" => -- Event count operation.
|
||||
if TAI_STRB = '1' and TIMER_A /= x"01" then -- Count.
|
||||
TIMER_A <= TIMER_A - '1';
|
||||
elsif TAI_STRB = '1' and TIMER_A = x"01" then -- Reload.
|
||||
TIMER_A <= To_StdLogicVector(TADR);
|
||||
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
|
||||
TIMER_A_INT <= '1';
|
||||
end if;
|
||||
when x"9" | x"A" | x"B" | x"C" | x"D" | x"E" | x"F" => -- PWM mode.
|
||||
if TAI_I = '1' and A_CNTSTRB = '1' and TIMER_A /= x"01" then -- Count.
|
||||
TIMER_A <= TIMER_A - '1';
|
||||
elsif TAI_I = '1' and A_CNTSTRB = '1' and TIMER_A = x"01" then -- Reload.
|
||||
TIMER_A <= To_StdLogicVector(TADR);
|
||||
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
|
||||
TIMER_A_INT <= '1';
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMERA;
|
||||
|
||||
TIMERB: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TBO_I <= '0';
|
||||
TIMER_B_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_B_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10000" and TBCR(3 downto 0) = x"0" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
-- The loading works asynchronous due to the possibly low XTAL1 clock.
|
||||
TIMER_B <= To_StdLogicVector(DATA_IN);
|
||||
else
|
||||
case TBCR(3 downto 0) is
|
||||
when x"0" => -- Timer is off.
|
||||
TBO_I <= '0';
|
||||
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
|
||||
if B_CNTSTRB = '1' and TIMER_B /= x"01" then -- Count.
|
||||
TIMER_B <= TIMER_B - '1';
|
||||
elsif B_CNTSTRB = '1' and TIMER_B = x"01" then -- Reload.
|
||||
TIMER_B <= To_StdLogicVector(TBDR);
|
||||
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
|
||||
TIMER_B_INT <= '1';
|
||||
end if;
|
||||
when x"8" => -- Event count operation.
|
||||
if TBI_STRB = '1' and TIMER_B /= x"01" then -- Count.
|
||||
TIMER_B <= TIMER_B - '1';
|
||||
elsif TBI_STRB = '1' and TIMER_B = x"01" then -- Reload.
|
||||
TIMER_B <= To_StdLogicVector(TBDR);
|
||||
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
|
||||
TIMER_B_INT <= '1';
|
||||
end if;
|
||||
when x"9" | x"A" | x"B" | x"C" | x"D" | x"E" | x"F" => -- PWM mode.
|
||||
if TBI_I = '1' and B_CNTSTRB = '1' and TIMER_B /= x"01" then -- Count.
|
||||
TIMER_B <= TIMER_B - '1';
|
||||
elsif TBI_I = '1' and B_CNTSTRB = '1' and TIMER_B = x"01" then -- Reload.
|
||||
TIMER_B <= To_StdLogicVector(TBDR);
|
||||
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
|
||||
TIMER_B_INT <= '1';
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMERB;
|
||||
|
||||
TIMERC: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TCO <= '0';
|
||||
TIMER_C_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_C_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10001" and TCDCR(5 downto 3) = "000" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
-- The loading works asynchronous due to the possibly low XTAL1 clock.
|
||||
TIMER_C <= To_StdLogicVector(DATA_IN);
|
||||
else
|
||||
case TCDCR(5 downto 3) is
|
||||
when "000" => -- Timer is off.
|
||||
TCO <= '0';
|
||||
when others => -- Delay counter mode.
|
||||
if C_CNTSTRB = '1' and TIMER_C /= x"01" then -- Count.
|
||||
TIMER_C <= TIMER_C - '1';
|
||||
elsif C_CNTSTRB = '1' and TIMER_C = x"01" then -- Reload.
|
||||
TIMER_C <= To_StdLogicVector(TCDR);
|
||||
TCO <= not TCO; -- Toggle the timer C output pin.
|
||||
TIMER_C_INT <= '1';
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMERC;
|
||||
|
||||
TIMERD: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TDO <= '0';
|
||||
TIMER_D_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_D_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10010" and TCDCR(2 downto 0) = "000" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
-- The loading works asynchronous due to the possibly low XTAL1 clock.
|
||||
TIMER_D <= To_StdLogicVector(DATA_IN);
|
||||
else
|
||||
case TCDCR(2 downto 0) is
|
||||
when "000" => -- Timer is off.
|
||||
TDO <= '0';
|
||||
when others => -- Delay counter mode.
|
||||
if D_CNTSTRB = '1' and TIMER_D /= x"01" then -- Count.
|
||||
TIMER_D <= TIMER_D - '1';
|
||||
elsif D_CNTSTRB = '1' and TIMER_D = x"01" then -- Reload.
|
||||
TIMER_D <= To_StdLogicVector(TDDR);
|
||||
TDO <= not TDO; -- Toggle the timer D output pin.
|
||||
TIMER_D_INT <= '1';
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMERD;
|
||||
end architecture BEHAVIOR;
|
||||
213
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_top.vhd
Normal file
213
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_top.vhd
Normal file
@@ -0,0 +1,213 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- MC68901 compatible multi function port core. ----
|
||||
---- ----
|
||||
---- This is the SUSKA MFP IP core top level file. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K7A 2006/12/28 WF
|
||||
-- The timer is modified to work on the CLK instead
|
||||
-- of XTAL1. This modification is done to provide
|
||||
-- a synchronous design.
|
||||
-- Revision 2K8B 2008/12/24 WF
|
||||
-- Rewritten this top level file as a wrapper for the top_soc file.
|
||||
--
|
||||
|
||||
use work.wf68901ip_pkg.all;
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_TOP is
|
||||
port ( -- System control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Asynchronous bus control:
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
DTACKn : out std_logic;
|
||||
|
||||
-- Data and Adresses:
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA : inout std_logic_vector(7 downto 0);
|
||||
GPIP : inout std_logic_vector(7 downto 0);
|
||||
|
||||
-- Interrupt control:
|
||||
IACKn : in bit;
|
||||
IEIn : in bit;
|
||||
IEOn : out bit;
|
||||
IRQn : out std_logic;
|
||||
|
||||
-- Timers and timer control:
|
||||
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
|
||||
TAI : in bit;
|
||||
TBI : in bit;
|
||||
TAO : out bit;
|
||||
TBO : out bit;
|
||||
TCO : out bit;
|
||||
TDO : out bit;
|
||||
|
||||
-- Serial I/O control:
|
||||
RC : in bit;
|
||||
TC : in bit;
|
||||
SI : in bit;
|
||||
SO : out std_logic;
|
||||
|
||||
-- DMA control:
|
||||
RRn : out bit;
|
||||
TRn : out bit
|
||||
);
|
||||
end entity WF68901IP_TOP;
|
||||
|
||||
architecture STRUCTURE of WF68901IP_TOP is
|
||||
component WF68901IP_TOP_SOC
|
||||
port(CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
DTACKn : out bit;
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in std_logic_vector(7 downto 0);
|
||||
DATA_OUT : out std_logic_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
GPIP_IN : in bit_vector(7 downto 0);
|
||||
GPIP_OUT : out bit_vector(7 downto 0);
|
||||
GPIP_EN : out bit_vector(7 downto 0);
|
||||
IACKn : in bit;
|
||||
IEIn : in bit;
|
||||
IEOn : out bit;
|
||||
IRQn : out bit;
|
||||
XTAL1 : in bit;
|
||||
TAI : in bit;
|
||||
TBI : in bit;
|
||||
TAO : out bit;
|
||||
TBO : out bit;
|
||||
TCO : out bit;
|
||||
TDO : out bit;
|
||||
RC : in bit;
|
||||
TC : in bit;
|
||||
SI : in bit;
|
||||
SO : out bit;
|
||||
SO_EN : out bit;
|
||||
RRn : out bit;
|
||||
TRn : out bit
|
||||
);
|
||||
end component;
|
||||
--
|
||||
signal DTACK_In : bit;
|
||||
signal IRQ_In : bit;
|
||||
signal DATA_OUT : std_logic_vector(7 downto 0);
|
||||
signal DATA_EN : bit;
|
||||
signal GPIP_IN : bit_vector(7 downto 0);
|
||||
signal GPIP_OUT : bit_vector(7 downto 0);
|
||||
signal GPIP_EN : bit_vector(7 downto 0);
|
||||
signal SO_I : bit;
|
||||
signal SO_EN : bit;
|
||||
begin
|
||||
DTACKn <= '0' when DTACK_In = '0' else 'Z'; -- Open drain.
|
||||
IRQn <= '0' when IRQ_In = '0' else 'Z'; -- Open drain.
|
||||
|
||||
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
|
||||
|
||||
GPIP_IN <= To_BitVector(GPIP);
|
||||
|
||||
P_GPIP_OUT: process(GPIP_OUT, GPIP_EN)
|
||||
begin
|
||||
for i in 7 downto 0 loop
|
||||
if GPIP_EN(i) = '1' then
|
||||
case GPIP_OUT(i) is
|
||||
when '0' => GPIP(i) <= '0';
|
||||
when others => GPIP(i) <= '1';
|
||||
end case;
|
||||
else
|
||||
GPIP(i) <= 'Z';
|
||||
end if;
|
||||
end loop;
|
||||
end process P_GPIP_OUT;
|
||||
|
||||
SO <= '0' when SO_I = '0' and SO_EN = '1' else
|
||||
'1' when SO_I = '1' and SO_EN = '1' else 'Z';
|
||||
|
||||
I_MFP: WF68901IP_TOP_SOC
|
||||
port map(CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DSn => DSn,
|
||||
CSn => CSn,
|
||||
RWn => RWn,
|
||||
DTACKn => DTACK_In,
|
||||
RS => RS,
|
||||
DATA_IN => DATA,
|
||||
DATA_OUT => DATA_OUT,
|
||||
DATA_EN => DATA_EN,
|
||||
GPIP_IN => GPIP_IN,
|
||||
GPIP_OUT => GPIP_OUT,
|
||||
GPIP_EN => GPIP_EN,
|
||||
IACKn => IACKn,
|
||||
IEIn => IEIn,
|
||||
IEOn => IEOn,
|
||||
IRQn => IRQ_In,
|
||||
XTAL1 => XTAL1,
|
||||
TAI => TAI,
|
||||
TBI => TBI,
|
||||
TAO => TAO,
|
||||
TBO => TBO,
|
||||
TCO => TCO,
|
||||
TDO => TDO,
|
||||
RC => RC,
|
||||
TC => TC,
|
||||
SI => SI,
|
||||
SO => SO_I,
|
||||
SO_EN => SO_EN,
|
||||
RRn => RRn,
|
||||
TRn => TRn
|
||||
);
|
||||
end architecture STRUCTURE;
|
||||
309
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_top_soc.vhd
Normal file
309
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_top_soc.vhd
Normal file
@@ -0,0 +1,309 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- MC68901 compatible multi function port core. ----
|
||||
---- ----
|
||||
---- This is the SUSKA MFP IP core top level file. ----
|
||||
---- Top level file for use in systems on programmable chips. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Top level file provided for SOC (systems on programmable chips).
|
||||
-- Revision 2K7A 2006/12/28 WF
|
||||
-- The timer is modified to work on the CLK instead
|
||||
-- of XTAL1. This modification is done to provide
|
||||
-- a synchronous design.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- DTACK_OUTn has now synchronous reset to meet preset requirement.
|
||||
--
|
||||
--
|
||||
|
||||
use work.wf68901ip_pkg.all;
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_TOP_SOC is
|
||||
port ( -- System control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Asynchronous bus control:
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
DTACKn : out bit;
|
||||
|
||||
-- Data and Adresses:
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in std_logic_vector(7 downto 0);
|
||||
DATA_OUT : out std_logic_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
GPIP_IN : in bit_vector(7 downto 0);
|
||||
GPIP_OUT : out bit_vector(7 downto 0);
|
||||
GPIP_EN : out bit_vector(7 downto 0);
|
||||
|
||||
-- Interrupt control:
|
||||
IACKn : in bit;
|
||||
IEIn : in bit;
|
||||
IEOn : out bit;
|
||||
IRQn : out bit;
|
||||
|
||||
-- Timers and timer control:
|
||||
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
|
||||
TAI : in bit;
|
||||
TBI : in bit;
|
||||
TAO : out bit;
|
||||
TBO : out bit;
|
||||
TCO : out bit;
|
||||
TDO : out bit;
|
||||
|
||||
-- Serial I/O control:
|
||||
RC : in bit;
|
||||
TC : in bit;
|
||||
SI : in bit;
|
||||
SO : out bit;
|
||||
SO_EN : out bit;
|
||||
|
||||
-- DMA control:
|
||||
RRn : out bit;
|
||||
TRn : out bit
|
||||
);
|
||||
end entity WF68901IP_TOP_SOC;
|
||||
|
||||
architecture STRUCTURE of WF68901IP_TOP_SOC is
|
||||
signal DATA_IN_I : bit_vector(7 downto 0);
|
||||
signal DTACK_In : bit;
|
||||
signal DTACK_LOCK : boolean;
|
||||
signal DTACK_OUTn : bit;
|
||||
signal RX_ERR_INT_I : bit;
|
||||
signal TX_ERR_INT_I : bit;
|
||||
signal RX_BUFF_INT_I : bit;
|
||||
signal TX_BUFF_INT_I : bit;
|
||||
signal DATA_OUT_USART_I : bit_vector(7 downto 0);
|
||||
signal DATA_OUT_EN_USART_I : bit;
|
||||
signal DATA_OUT_INT_I : bit_vector(7 downto 0);
|
||||
signal DATA_OUT_EN_INT_I : bit;
|
||||
signal DATA_OUT_GPIO_I : bit_vector(7 downto 0);
|
||||
signal DATA_OUT_EN_GPIO_I : bit;
|
||||
signal DATA_OUT_TIMERS_I : bit_vector(7 downto 0);
|
||||
signal DATA_OUT_EN_TIMERS_I : bit;
|
||||
signal SO_I : bit;
|
||||
signal SO_EN_I : bit;
|
||||
signal GPIP_IN_I : bit_vector(7 downto 0);
|
||||
signal GPIP_OUT_I : bit_vector(7 downto 0);
|
||||
signal GPIP_EN_I : bit_vector(7 downto 0);
|
||||
signal GP_INT_I : bit_vector(7 downto 0);
|
||||
signal TIMER_A_INT_I : bit;
|
||||
signal TIMER_B_INT_I : bit;
|
||||
signal TIMER_C_INT_I : bit;
|
||||
signal TIMER_D_INT_I : bit;
|
||||
signal IRQ_In : bit;
|
||||
signal AER_4_I : bit;
|
||||
signal AER_3_I : bit;
|
||||
signal TA_PWM_I : bit;
|
||||
signal TB_PWM_I : bit;
|
||||
begin
|
||||
-- Interrupt request (open drain):
|
||||
IRQn <= IRQ_In;
|
||||
|
||||
-- Serial data output:
|
||||
SO <= SO_I;
|
||||
SO_EN <= SO_EN_I and RESETn;
|
||||
|
||||
-- General purpose port:
|
||||
GPIP_IN_I <= GPIP_IN;
|
||||
GPIP_OUT <= GPIP_OUT_I;
|
||||
GPIP_EN <= GPIP_EN_I;
|
||||
|
||||
DATA_IN_I <= To_BitVector(DATA_IN);
|
||||
DATA_EN <= DATA_OUT_EN_USART_I or DATA_OUT_EN_INT_I or DATA_OUT_EN_GPIO_I or DATA_OUT_EN_TIMERS_I;
|
||||
-- Output data multiplexer:
|
||||
DATA_OUT <= To_StdLogicVector(DATA_OUT_USART_I) when DATA_OUT_EN_USART_I = '1' else
|
||||
To_StdLogicVector(DATA_OUT_INT_I) when DATA_OUT_EN_INT_I = '1' else
|
||||
To_StdLogicVector(DATA_OUT_GPIO_I) when DATA_OUT_EN_GPIO_I = '1' else
|
||||
To_StdLogicVector(DATA_OUT_TIMERS_I) when DATA_OUT_EN_TIMERS_I = '1' else (others => '1');
|
||||
|
||||
-- Data acknowledge handshake is provided by the following statement and the consecutive two
|
||||
-- processes. For more information refer to the M68000 family reference manual.
|
||||
DTACK_In <= '0' when CSn = '0' and DSn = '0' and RS <= "10111" else -- Read and write operation.
|
||||
'0' when IACKn = '0' and DSn = '0' and IEIn = '0' else '1'; -- Interrupt vector data acknowledge.
|
||||
|
||||
P_DTACK_LOCK: process
|
||||
-- This process releases a data acknowledge detect, one rising clock
|
||||
-- edge after the DTACK_In occured. This is necessary to ensure write
|
||||
-- data to registers for there is one rising clock edge required.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if DTACK_In = '0' then
|
||||
DTACK_LOCK <= false;
|
||||
else
|
||||
DTACK_LOCK <= true;
|
||||
end if;
|
||||
end process P_DTACK_LOCK;
|
||||
|
||||
DTACK_OUT: process
|
||||
-- The DTACKn port pin is released on the falling clock edge after the data
|
||||
-- acknowledge detect (DTACK_LOCK) is asserted. The DTACKn is deasserted
|
||||
-- immediately when there is no further register access DTACK_In = '1';
|
||||
begin
|
||||
wait until CLK = '0' and CLK' event;
|
||||
if RESETn = '0' then
|
||||
DTACK_OUTn <= '1';
|
||||
elsif DTACK_In = '1' then
|
||||
DTACK_OUTn <= '1';
|
||||
elsif DTACK_LOCK = false then
|
||||
DTACK_OUTn <= '0';
|
||||
end if;
|
||||
end process DTACK_OUT;
|
||||
DTACKn <= '0' when DTACK_OUTn = '0' else '1';
|
||||
|
||||
I_USART: WF68901IP_USART_TOP
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DSn => DSn,
|
||||
CSn => CSn,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_IN => DATA_IN_I,
|
||||
DATA_OUT => DATA_OUT_USART_I,
|
||||
DATA_OUT_EN => DATA_OUT_EN_USART_I,
|
||||
RC => RC,
|
||||
TC => TC,
|
||||
SI => SI,
|
||||
SO => SO_I,
|
||||
SO_EN => SO_EN_I,
|
||||
RX_ERR_INT => RX_ERR_INT_I,
|
||||
RX_BUFF_INT => RX_BUFF_INT_I,
|
||||
TX_ERR_INT => TX_ERR_INT_I,
|
||||
TX_BUFF_INT => TX_BUFF_INT_I,
|
||||
RRn => RRn,
|
||||
TRn => TRn
|
||||
);
|
||||
|
||||
I_INTERRUPTS: WF68901IP_INTERRUPTS
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DSn => DSn,
|
||||
CSn => CSn,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_IN => DATA_IN_I,
|
||||
DATA_OUT => DATA_OUT_INT_I,
|
||||
DATA_OUT_EN => DATA_OUT_EN_INT_I,
|
||||
IACKn => IACKn,
|
||||
IEIn => IEIn,
|
||||
IEOn => IEOn,
|
||||
IRQn => IRQ_In,
|
||||
GP_INT => GP_INT_I,
|
||||
AER_4 => AER_4_I,
|
||||
AER_3 => AER_3_I,
|
||||
TAI => TAI,
|
||||
TBI => TBI,
|
||||
TA_PWM => TA_PWM_I,
|
||||
TB_PWM => TB_PWM_I,
|
||||
TIMER_A_INT => TIMER_A_INT_I,
|
||||
TIMER_B_INT => TIMER_B_INT_I,
|
||||
TIMER_C_INT => TIMER_C_INT_I,
|
||||
TIMER_D_INT => TIMER_D_INT_I,
|
||||
RCV_ERR => RX_ERR_INT_I,
|
||||
TRM_ERR => TX_ERR_INT_I,
|
||||
RCV_BUF_F => RX_BUFF_INT_I,
|
||||
TRM_BUF_E => TX_BUFF_INT_I
|
||||
);
|
||||
|
||||
I_GPIO: WF68901IP_GPIO
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DSn => DSn,
|
||||
CSn => CSn,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_IN => DATA_IN_I,
|
||||
DATA_OUT => DATA_OUT_GPIO_I,
|
||||
DATA_OUT_EN => DATA_OUT_EN_GPIO_I,
|
||||
AER_4 => AER_4_I,
|
||||
AER_3 => AER_3_I,
|
||||
GPIP_IN => GPIP_IN_I,
|
||||
GPIP_OUT => GPIP_OUT_I,
|
||||
GPIP_OUT_EN => GPIP_EN_I,
|
||||
GP_INT => GP_INT_I
|
||||
);
|
||||
|
||||
I_TIMERS: WF68901IP_TIMERS
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DSn => DSn,
|
||||
CSn => CSn,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_IN => DATA_IN_I,
|
||||
DATA_OUT => DATA_OUT_TIMERS_I,
|
||||
DATA_OUT_EN => DATA_OUT_EN_TIMERS_I,
|
||||
XTAL1 => XTAL1,
|
||||
AER_4 => AER_4_I,
|
||||
AER_3 => AER_3_I,
|
||||
TAI => TAI,
|
||||
TBI => TBI,
|
||||
TAO => TAO,
|
||||
TBO => TBO,
|
||||
TCO => TCO,
|
||||
TDO => TDO,
|
||||
TA_PWM => TA_PWM_I,
|
||||
TB_PWM => TB_PWM_I,
|
||||
TIMER_A_INT => TIMER_A_INT_I,
|
||||
TIMER_B_INT => TIMER_B_INT_I,
|
||||
TIMER_C_INT => TIMER_C_INT_I,
|
||||
TIMER_D_INT => TIMER_D_INT_I
|
||||
);
|
||||
end architecture STRUCTURE;
|
||||
191
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_ctrl.vhd
Normal file
191
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_ctrl.vhd
Normal file
@@ -0,0 +1,191 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- This is the SUSKA MFP IP core USART control file. ----
|
||||
---- ----
|
||||
---- Control unit and status logic. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_USART_CTRL is
|
||||
port (
|
||||
-- System Control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Bus control:
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
|
||||
-- USART data register
|
||||
RX_SAMPLE : in bit;
|
||||
RX_DATA : in bit_vector(7 downto 0);
|
||||
TX_DATA : out bit_vector(7 downto 0);
|
||||
SCR_OUT : out bit_vector(7 downto 0);
|
||||
|
||||
-- USART control inputs:
|
||||
BF : in bit;
|
||||
BE : in bit;
|
||||
FE : in bit;
|
||||
OE : in bit;
|
||||
UE : in bit;
|
||||
PE : in bit;
|
||||
M_CIP : in bit;
|
||||
FS_B : in bit;
|
||||
TX_END : in bit;
|
||||
|
||||
-- USART control outputs:
|
||||
CL : out bit_vector(1 downto 0);
|
||||
ST : out bit_vector(1 downto 0);
|
||||
FS_CLR : out bit;
|
||||
UDR_WRITE : out bit;
|
||||
UDR_READ : out bit;
|
||||
RSR_READ : out bit;
|
||||
TSR_READ : out bit;
|
||||
LOOPBACK : out bit;
|
||||
SDOUT_EN : out bit;
|
||||
SD_LEVEL : out bit;
|
||||
CLK_MODE : out bit;
|
||||
RE : out bit;
|
||||
TE : out bit;
|
||||
P_ENA : out bit;
|
||||
P_EOn : out bit;
|
||||
SS : out bit;
|
||||
BR : out bit
|
||||
);
|
||||
end entity WF68901IP_USART_CTRL;
|
||||
|
||||
architecture BEHAVIOR of WF68901IP_USART_CTRL is
|
||||
signal SCR : bit_vector(7 downto 0); -- Synchronous data register.
|
||||
signal UCR : bit_vector(7 downto 1); -- USART control register.
|
||||
signal RSR : bit_vector(7 downto 0); -- Receiver status register.
|
||||
signal TSR : bit_vector(7 downto 0); -- Transmitter status register.
|
||||
signal UDR : bit_vector(7 downto 0); -- USART data register.
|
||||
begin
|
||||
USART_REGISTERS: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SCR <= (others => '0');
|
||||
UCR <= (others => '0');
|
||||
RSR <= (others => '0');
|
||||
-- TSR and UDR are not cleared during an asserted RESETn
|
||||
elsif CLK = '1' and CLK' event then
|
||||
-- Loading via receiver shift register
|
||||
-- has priority over data buss access:
|
||||
if RX_SAMPLE = '1' then
|
||||
UDR <= RX_DATA;
|
||||
elsif CSn = '0' and DSn = '0' and RWn = '0' then
|
||||
case RS is
|
||||
when "10011" => SCR <= DATA_IN;
|
||||
when "10100" => UCR <= DATA_IN(7 downto 1);
|
||||
when "10101" => RSR(1 downto 0) <= DATA_IN(1 downto 0); -- Only the two LSB are read/write.
|
||||
when "10110" => TSR(5) <= DATA_IN(5); TSR(3 downto 0) <= DATA_IN(3 downto 0);
|
||||
when "10111" => UDR <= DATA_IN;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
RSR(7 downto 2) <= BF & OE & PE & FE & FS_B & M_CIP;
|
||||
TSR(7 downto 6) <= BE & UE;
|
||||
TSR(4) <= TX_END;
|
||||
TX_DATA <= UDR;
|
||||
end if;
|
||||
end process USART_REGISTERS;
|
||||
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS >= "10011" and RS <= "10111" else '0';
|
||||
DATA_OUT <= SCR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10011" else
|
||||
UCR & '0' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10100" else
|
||||
RSR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10101" else
|
||||
TSR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10110" else
|
||||
UDR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10111" else x"00";
|
||||
|
||||
UDR_WRITE <= '1' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "10111" else '0';
|
||||
UDR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10111" else '0';
|
||||
RSR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10101" else '0';
|
||||
TSR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10110" else '0';
|
||||
FS_CLR <= '1' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "10011" else '0';
|
||||
|
||||
RE <= '1' when RSR(0) = '1' else -- Receiver enable.
|
||||
'1' when TSR(5) = '1' and TX_END = '1' else '0'; -- Auto Turnaround.
|
||||
SS <= RSR(1); -- Synchronous strip enable.
|
||||
BR <= TSR(3); -- Send break.
|
||||
TE <= TSR(0); -- Transmitter enable.
|
||||
|
||||
SCR_OUT <= SCR;
|
||||
|
||||
CLK_MODE <= UCR(7); -- Clock mode.
|
||||
CL <= UCR(6 downto 5); -- Character length.
|
||||
ST <= UCR(4 downto 3); -- Start/Stop configuration.
|
||||
P_ENA <= UCR(2); -- Parity enable.
|
||||
P_EOn <= UCR(1); -- Even or odd parity.
|
||||
|
||||
SOUT_CONFIG: process
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
-- Do not change the output configuration until the transmitter is disabled and
|
||||
-- current character has been transmitted (TX_END = '1').
|
||||
if TX_END = '1' then
|
||||
case TSR(2 downto 1) is
|
||||
when "00" => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '0';
|
||||
when "01" => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '1';
|
||||
when "10" => LOOPBACK <= '0'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
|
||||
when "11" => LOOPBACK <= '1'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
|
||||
end case;
|
||||
end if;
|
||||
end process SOUT_CONFIG;
|
||||
end architecture BEHAVIOR;
|
||||
|
||||
590
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_rx.vhd
Normal file
590
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_rx.vhd
Normal file
@@ -0,0 +1,590 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- This is the SUSKA MFP IP core USART receiver file. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- Process P_STARTBIT has now synchronous reset to meet preset requirement.
|
||||
-- Process P_SAMPLE has now synchronous reset to meet preset requirement.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_USART_RX is
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
SCR : in bit_vector(7 downto 0); -- Synchronous character.
|
||||
RX_SAMPLE : buffer bit; -- Flag indicating valid shift register data.
|
||||
RX_DATA : out bit_vector(7 downto 0); -- Received data.
|
||||
|
||||
RXCLK : in bit; -- Receiver clock.
|
||||
SDATA_IN : in bit; -- Serial data input.
|
||||
|
||||
CL : in bit_vector(1 downto 0); -- Character length.
|
||||
ST : in bit_vector(1 downto 0); -- Start and stop bit configuration.
|
||||
P_ENA : in bit; -- Parity enable.
|
||||
P_EOn : in bit; -- Even or odd parity.
|
||||
CLK_MODE : in bit; -- Clock mode configuration bit.
|
||||
RE : in bit; -- Receiver enable.
|
||||
FS_CLR : in bit; -- Clear the Found/Search flag for resynchronisation purpose.
|
||||
SS : in bit; -- Synchronous strip enable.
|
||||
UDR_READ : in bit; -- Flag indicating reading the data register.
|
||||
RSR_READ : in bit; -- Flag indicating reading the receiver status register.
|
||||
|
||||
M_CIP : out bit; -- Match/Character in progress.
|
||||
FS_B : buffer bit; -- Find/Search or Break detect flag.
|
||||
BF : out bit; -- Buffer full.
|
||||
OE : out bit; -- Overrun error.
|
||||
PE : out bit; -- Parity error.
|
||||
FE : out bit -- Framing error.
|
||||
);
|
||||
end entity WF68901IP_USART_RX;
|
||||
|
||||
architecture BEHAVIOR of WF68901IP_USART_RX is
|
||||
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
|
||||
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
|
||||
signal SDATA_DIV16 : bit;
|
||||
signal SDATA_IN_I : bit;
|
||||
signal SDATA_EDGE : bit;
|
||||
signal SHIFT_REG : bit_vector(7 downto 0);
|
||||
signal CLK_STRB : bit;
|
||||
signal CLK_2_STRB : bit;
|
||||
signal BITCNT : std_logic_vector(2 downto 0);
|
||||
signal BREAK : boolean;
|
||||
signal RDRF : bit;
|
||||
signal STARTBIT : boolean;
|
||||
begin
|
||||
BF <= RDRF; -- Buffer full = Receiver Data Register Full.
|
||||
RX_SAMPLE <= '1' when RCV_STATE = SYNC and ST /= "00" else -- Asynchronous mode:
|
||||
-- Synchronous modes:
|
||||
'1' when RCV_STATE = SYNC and ST = "00" and SS = '0' else
|
||||
'1' when RCV_STATE = SYNC and ST = "00" and SS = '1' and SHIFT_REG /= SCR else '0';
|
||||
|
||||
-- Data multiplexer for the received data:
|
||||
RX_DATA <= "000" & SHIFT_REG(7 downto 3) when RX_SAMPLE = '1' and CL = "11" else -- 5 databits.
|
||||
"00" & SHIFT_REG(7 downto 2) when RX_SAMPLE = '1' and CL = "10" else -- 6 databits.
|
||||
'0' & SHIFT_REG(7 downto 1) when RX_SAMPLE = '1' and CL = "01" else -- 6 databits.
|
||||
SHIFT_REG when RX_SAMPLE = '1' and CL = "00" else x"00"; -- 8 databits.
|
||||
|
||||
P_SAMPLE: process
|
||||
-- This process provides the 'valid transition logic' of the originally MC68901. For further
|
||||
-- details see the 'M68000 FAMILY REFERENCE MANUAL'.
|
||||
variable LOW_FLT : std_logic_vector(1 downto 0);
|
||||
variable HI_FLT : std_logic_vector(1 downto 0);
|
||||
variable CLK_LOCK : boolean;
|
||||
variable EDGE_LOCK : boolean;
|
||||
variable TIMER : std_logic_vector(2 downto 0);
|
||||
variable TIMER_LOCK : boolean;
|
||||
variable NEW_SDATA : bit;
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RESETn = '0' or RE = '0' then
|
||||
-- The reset condition assumes the SDATA_IN logic high. Otherwise
|
||||
-- one not valid SDATA_EDGE pulse occurs during system startup.
|
||||
CLK_LOCK := true;
|
||||
EDGE_LOCK := true;
|
||||
HI_FLT := "11";
|
||||
LOW_FLT := "11";
|
||||
SDATA_EDGE <= '0';
|
||||
NEW_SDATA := '1';
|
||||
-- Positive or negative edge detector for the incoming data.
|
||||
-- Any transition must be valid for at least three receiver clock
|
||||
-- cycles. The TIMER locking inhibits detecting four receiver
|
||||
-- clock cycles after a valid transition.
|
||||
elsif RXCLK = '1' and SDATA_IN = '0' and CLK_LOCK = false and LOW_FLT > "00" then
|
||||
CLK_LOCK := true;
|
||||
EDGE_LOCK := false;
|
||||
HI_FLT := "00";
|
||||
LOW_FLT := LOW_FLT - '1';
|
||||
elsif RXCLK = '1' and SDATA_IN = '1' and CLK_LOCK = false and HI_FLT < "11" then
|
||||
CLK_LOCK := true;
|
||||
EDGE_LOCK := false;
|
||||
LOW_FLT := "11";
|
||||
HI_FLT := HI_FLT + '1';
|
||||
elsif RXCLK = '1' and EDGE_LOCK = false and LOW_FLT = "00" then
|
||||
EDGE_LOCK := true;
|
||||
SDATA_EDGE <= '1'; -- Falling edge detected.
|
||||
NEW_SDATA := '0';
|
||||
elsif RXCLK = '1' and EDGE_LOCK = false and HI_FLT = "11" then
|
||||
EDGE_LOCK := true;
|
||||
SDATA_EDGE <= '1'; -- Rising edge detected.
|
||||
NEW_SDATA := '1';
|
||||
elsif RXCLK = '1' and CLK_LOCK = false then
|
||||
CLK_LOCK := true;
|
||||
SDATA_EDGE <= '0';
|
||||
elsif RXCLK = '0' then
|
||||
CLK_LOCK := false;
|
||||
end if;
|
||||
--
|
||||
if RESETn = '0' or RE = '0' then
|
||||
-- The reset condition assumes the SDATA_IN logic high. Otherwise
|
||||
-- one not valid SDATA_EDGE pulse occurs during system startup.
|
||||
TIMER := "111";
|
||||
TIMER_LOCK := true;
|
||||
SDATA_DIV16 <= '1';
|
||||
-- The timer controls the SDATA in a way, that after a detected valid
|
||||
-- Transistion, the serial data is sampled on the 8th receiver clock
|
||||
-- edge after the initial valid transition occured.
|
||||
elsif RXCLK = '1' and SDATA_EDGE = '1' and TIMER_LOCK = false then
|
||||
TIMER_LOCK := true;
|
||||
TIMER := "000"; -- Resynchronisation.
|
||||
elsif RXCLK = '1' and TIMER = "011" and TIMER_LOCK = false then
|
||||
TIMER_LOCK := true;
|
||||
SDATA_DIV16 <= NEW_SDATA; -- Scan the new data.
|
||||
TIMER := TIMER + '1'; -- Timing is active.
|
||||
elsif RXCLK = '1' and TIMER < "111" and TIMER_LOCK = false then
|
||||
TIMER_LOCK := true;
|
||||
TIMER := TIMER + '1'; -- Timing is active.
|
||||
elsif RXCLK = '0' then
|
||||
TIMER_LOCK := false;
|
||||
end if;
|
||||
end process P_SAMPLE;
|
||||
|
||||
P_START_BIT: process(CLK)
|
||||
-- This is the valid start bit logic of the original MC68901 multi function
|
||||
-- port's USART receiver.
|
||||
variable TMP : std_logic_vector(2 downto 0);
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if CLK = '1' and CLK' event then
|
||||
if RESETn = '0' then
|
||||
TMP := "000";
|
||||
LOCK := true;
|
||||
elsif RE = '0' or RCV_STATE /= IDLE then -- Start bit logic disabled.
|
||||
TMP := "000";
|
||||
LOCK := true;
|
||||
elsif SDATA_EDGE = '1' then
|
||||
TMP := "000"; -- (Re)-Initialize.
|
||||
LOCK := false; -- Start counting.
|
||||
elsif RXCLK = '1' and SDATA_IN = '0' and TMP < "111" and LOCK = false then
|
||||
LOCK := true;
|
||||
TMP := TMP + '1'; -- Count 8 low bits to declare start condition valid.
|
||||
elsif RXCLK = '0' then
|
||||
LOCK := false;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
case TMP is
|
||||
when "111" => STARTBIT <= true;
|
||||
when others => STARTBIT <= false;
|
||||
end case;
|
||||
end process P_START_BIT;
|
||||
|
||||
SDATA_IN_I <= SDATA_IN when CLK_MODE = '0' else -- Clock div by 1 mode.
|
||||
SDATA_IN when ST = "00" else SDATA_DIV16; -- Synchronous mode.
|
||||
|
||||
CLKDIV: process
|
||||
variable CLK_LOCK : boolean;
|
||||
variable STRB_LOCK : boolean;
|
||||
variable CLK_DIVCNT : std_logic_vector(4 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if CLK_MODE = '0' then -- Divider off.
|
||||
if RXCLK = '1' and STRB_LOCK = false then
|
||||
CLK_STRB <= '1';
|
||||
STRB_LOCK := true;
|
||||
elsif RXCLK = '0' then
|
||||
CLK_STRB <= '0';
|
||||
STRB_LOCK := false;
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
CLK_2_STRB <= '0'; -- No 1 1/2 stop bits in no div by 16 mode.
|
||||
elsif SDATA_EDGE = '1' then
|
||||
CLK_DIVCNT := "01100"; -- Div by 16 mode.
|
||||
CLK_STRB <= '0'; -- Default.
|
||||
CLK_2_STRB <= '0'; -- Default.
|
||||
else
|
||||
CLK_STRB <= '0'; -- Default.
|
||||
CLK_2_STRB <= '0'; -- Default.
|
||||
if CLK_DIVCNT > "00000" and RXCLK = '1' and CLK_LOCK = false then
|
||||
CLK_DIVCNT := CLK_DIVCNT - '1';
|
||||
CLK_LOCK := true;
|
||||
if CLK_DIVCNT = "01000" then
|
||||
-- This strobe is asserted at half of the clock cycle.
|
||||
-- It is used for the stop bit timing.
|
||||
CLK_2_STRB <= '1';
|
||||
end if;
|
||||
elsif CLK_DIVCNT = "00000" then
|
||||
CLK_DIVCNT := "10000"; -- Div by 16 mode.
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
end if;
|
||||
elsif RXCLK = '0' then
|
||||
CLK_LOCK := false;
|
||||
STRB_LOCK := false;
|
||||
end if;
|
||||
end if;
|
||||
end process CLKDIV;
|
||||
|
||||
SHIFTREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RE = '0' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' then
|
||||
SHIFT_REG <= SDATA_IN_I & SHIFT_REG(7 downto 1); -- Shift right.
|
||||
end if;
|
||||
end if;
|
||||
end process SHIFTREG;
|
||||
|
||||
P_M_CIP: process(RESETn, CLK)
|
||||
-- In Synchronous mode this flag indicates wether a synchronous character M_CIP = '1'
|
||||
-- or another character (M_CIP = '0') is transferred to the receive buffer.
|
||||
-- In asynchronous mode the flag indicates sampling condition.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
M_CIP <= '0';
|
||||
elsif CLK = '0' and CLK' event then
|
||||
if RE = '0' then
|
||||
M_CIP <= '0';
|
||||
elsif ST = "00" then -- Synchronous mode.
|
||||
if RCV_STATE = SYNC and SHIFT_REG = SCR and RDRF = '0' then
|
||||
M_CIP <= '1'; -- SCR transferred.
|
||||
elsif RCV_STATE = SYNC and RDRF = '0' then
|
||||
M_CIP <= '0'; -- No SCR transferred.
|
||||
end if;
|
||||
else -- Asynchronous mode.
|
||||
case RCV_STATE is
|
||||
when SAMPLE | PARITY | STOP1 | STOP2 => M_CIP <= '1'; -- Sampling.
|
||||
when others => M_CIP <= '0'; -- No Sampling.
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process P_M_CIP;
|
||||
|
||||
BREAK_DETECT: process(RESETn, CLK)
|
||||
-- A break condition occurs, if there is no STOP1 bit and the
|
||||
-- shift register contains zero data.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
BREAK <= false;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RE = '0' then
|
||||
BREAK <= false;
|
||||
elsif CLK_STRB = '1' then
|
||||
if RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG = x"00" then
|
||||
BREAK <= true; -- Break detected (empty shift register and no stop bit).
|
||||
elsif RCV_STATE = STOP1 and SDATA_IN_I = '1' then
|
||||
BREAK <= false; -- UPDATE.
|
||||
elsif RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
|
||||
BREAK <= false; -- UPDATE, but framing error.
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process BREAK_DETECT;
|
||||
|
||||
P_FS_B: process(RESETn, CLK)
|
||||
-- In the synchronous mode, this process provides the flag detecting the synchronous
|
||||
-- character. In the asynchronous mode, the flag indicates a break condition.
|
||||
variable FS_B_I : bit;
|
||||
variable FIRST_READ : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
FS_B <= '0';
|
||||
FIRST_READ := false;
|
||||
FS_B_I := '0';
|
||||
elsif CLK = '0' and CLK' event then
|
||||
if RE = '0' then
|
||||
FS_B <= '0';
|
||||
FS_B_I := '0';
|
||||
else
|
||||
if ST = "00" then -- Synchronous operation.
|
||||
if FS_CLR = '1' then
|
||||
FS_B <= '0'; -- Clear during writing to the SCR.
|
||||
elsif SHIFT_REG = SCR then
|
||||
FS_B <= '1'; -- SCR detected.
|
||||
end if;
|
||||
else -- Asynchronous operation.
|
||||
if RX_SAMPLE = '1' and BREAK = true then -- Break condition detected.
|
||||
FS_B_I := '1'; -- Update.
|
||||
elsif RX_SAMPLE = '1' then -- No break condition.
|
||||
FS_B_I := '0'; -- Update.
|
||||
elsif RSR_READ = '1' and FS_B_I = '1' then
|
||||
-- If a break condition was detected, the concerning flag is
|
||||
-- set when the valid data word in the receiver data
|
||||
-- register is read. Thereafter the break flag is reset
|
||||
-- and the break condition disappears after a second read
|
||||
-- (in time) of the receiver status register.
|
||||
if FIRST_READ = false then
|
||||
FS_B <= '1';
|
||||
FIRST_READ := true;
|
||||
else
|
||||
FS_B <= '0';
|
||||
FIRST_READ := false;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process P_FS_B;
|
||||
|
||||
P_BITCNT: process
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RCV_STATE = SAMPLE and CLK_STRB = '1' and ST /= "00" then -- Asynchronous mode.
|
||||
BITCNT <= BITCNT + '1';
|
||||
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' and ST = "00" and FS_B = '1' then -- Synchronous mode.
|
||||
BITCNT <= BITCNT + '1'; -- Count, if matched data found (FS_B = '1').
|
||||
elsif RCV_STATE /= SAMPLE then
|
||||
BITCNT <= (others => '0');
|
||||
end if;
|
||||
end process P_BITCNT;
|
||||
|
||||
BUFFER_FULL: process(RESETn, CLK)
|
||||
-- Receive data register full flag.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
RDRF <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RE = '0' then
|
||||
RDRF <= '0';
|
||||
elsif RX_SAMPLE = '1' then
|
||||
RDRF <= '1'; -- Data register is full until now!
|
||||
elsif UDR_READ = '1' then
|
||||
RDRF <= '0'; -- After reading the data register ...
|
||||
end if;
|
||||
end if;
|
||||
end process BUFFER_FULL;
|
||||
|
||||
OVERRUN: process(RESETn, CLK)
|
||||
variable OE_I : bit;
|
||||
variable FIRST_READ : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
OE_I := '0';
|
||||
OE <= '0';
|
||||
FIRST_READ := false;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RESETn = '0' then
|
||||
OE_I := '0';
|
||||
OE <= '0';
|
||||
FIRST_READ := false;
|
||||
elsif CLK_STRB = '1' and RCV_STATE = SYNC and BREAK = false then
|
||||
-- Overrun appears if RDRF is '1' in this state and there
|
||||
-- is no break condition.
|
||||
OE_I := RDRF;
|
||||
end if;
|
||||
if RSR_READ = '1' and OE_I = '1' then
|
||||
-- if an overrun was detected, the concerning flag is
|
||||
-- set when the valid data word in the receiver data
|
||||
-- register is read. Thereafter the RDRF flag is reset
|
||||
-- and the overrun disappears (OE_I goes low) after
|
||||
-- a second read (in time) of the receiver data register.
|
||||
if FIRST_READ = false then
|
||||
OE <= '1';
|
||||
FIRST_READ := true;
|
||||
else
|
||||
OE <= '0';
|
||||
FIRST_READ := false;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process OVERRUN;
|
||||
|
||||
PARITY_TEST: process(RESETn, CLK)
|
||||
variable PAR_TMP : bit;
|
||||
variable P_ERR : bit;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
PE <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RE = '0' then
|
||||
PE <= '0';
|
||||
elsif RX_SAMPLE = '1' then
|
||||
PE <= P_ERR; -- Update on load shift register to data register.
|
||||
elsif CLK_STRB = '1' then -- Sample parity on clock strobe.
|
||||
P_ERR := '0'; -- Initialise.
|
||||
if RCV_STATE = PARITY then
|
||||
for i in 1 to 7 loop
|
||||
if i = 1 then
|
||||
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
|
||||
else
|
||||
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
|
||||
end if;
|
||||
end loop;
|
||||
if P_ENA = '1' and P_EOn = '1' then -- Even parity.
|
||||
P_ERR := PAR_TMP xor SDATA_IN_I;
|
||||
elsif P_ENA = '1' and P_EOn = '0' then -- Odd parity.
|
||||
P_ERR := not PAR_TMP xor SDATA_IN_I;
|
||||
elsif P_ENA = '0' then -- No parity.
|
||||
P_ERR := '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process PARITY_TEST;
|
||||
|
||||
FRAME_ERR: process(RESETn, CLK)
|
||||
-- This module detects a framing error
|
||||
-- during stop bit 1 and stop bit 2.
|
||||
variable FE_I: bit;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
FE_I := '0';
|
||||
FE <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RE = '0' then
|
||||
FE_I := '0';
|
||||
FE <= '0';
|
||||
elsif CLK_STRB = '1' then
|
||||
if RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
|
||||
FE_I := '1';
|
||||
elsif RCV_STATE = STOP2 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
|
||||
FE_I := '1';
|
||||
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
|
||||
FE_I := '0'; -- Error resets when correct data appears.
|
||||
end if;
|
||||
end if;
|
||||
if RCV_STATE = SYNC then
|
||||
FE <= FE_I; -- Update the FE every SYNC time.
|
||||
end if;
|
||||
end if;
|
||||
end process FRAME_ERR;
|
||||
|
||||
RCV_STATEREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
RCV_STATE <= IDLE;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RE = '0' then
|
||||
RCV_STATE <= IDLE;
|
||||
else
|
||||
RCV_STATE <= RCV_NEXT_STATE;
|
||||
end if;
|
||||
end if;
|
||||
end process RCV_STATEREG;
|
||||
|
||||
RCV_STATEDEC: process(RCV_STATE, SDATA_IN_I, BITCNT, CLK_STRB, STARTBIT,
|
||||
CLK_2_STRB, ST, CLK_MODE, CL, P_ENA, SHIFT_REG)
|
||||
begin
|
||||
case RCV_STATE is
|
||||
when IDLE =>
|
||||
if ST = "00" then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Synchronous mode.
|
||||
elsif SDATA_IN_I = '0' and CLK_MODE = '0' then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
|
||||
elsif STARTBIT = true and CLK_MODE = '1' then
|
||||
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
|
||||
else
|
||||
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
|
||||
end if;
|
||||
when WAIT_START =>
|
||||
-- This state delays the sample process by one CLK_STRB pulse
|
||||
-- to eliminate the start bit.
|
||||
if CLK_STRB = '1' then
|
||||
RCV_NEXT_STATE <= SAMPLE;
|
||||
else
|
||||
RCV_NEXT_STATE <= WAIT_START;
|
||||
end if;
|
||||
when SAMPLE =>
|
||||
if CLK_STRB = '1' then
|
||||
if CL = "11" and BITCNT < "100" then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 5 data bits.
|
||||
elsif CL = "10" and BITCNT < "101" then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 6 data bits.
|
||||
elsif CL = "01" and BITCNT < "110" then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
|
||||
elsif CL = "00" and BITCNT < "111" then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
|
||||
elsif ST = "00" and P_ENA = '0' then -- Synchronous mode (no stop bits).
|
||||
RCV_NEXT_STATE <= IDLE; -- No parity check enabled.
|
||||
elsif P_ENA = '0' then
|
||||
RCV_NEXT_STATE <= STOP1; -- No parity check enabled.
|
||||
else
|
||||
RCV_NEXT_STATE <= PARITY; -- Parity enabled.
|
||||
end if;
|
||||
else
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Stay in sample mode.
|
||||
end if;
|
||||
when PARITY =>
|
||||
if CLK_STRB = '1' then
|
||||
if ST = "00" then -- Synchronous mode (no stop bits).
|
||||
RCV_NEXT_STATE <= IDLE;
|
||||
else
|
||||
RCV_NEXT_STATE <= STOP1;
|
||||
end if;
|
||||
else
|
||||
RCV_NEXT_STATE <= PARITY;
|
||||
end if;
|
||||
when STOP1 =>
|
||||
if CLK_STRB = '1' then
|
||||
if SHIFT_REG > x"00" and SDATA_IN_I = '0' then -- No Stop bit after non zero data.
|
||||
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
|
||||
elsif ST = "11" or ST = "10" then
|
||||
RCV_NEXT_STATE <= STOP2; -- More than one stop bits selected.
|
||||
else
|
||||
RCV_NEXT_STATE <= SYNC; -- One stop bit selected.
|
||||
end if;
|
||||
else
|
||||
RCV_NEXT_STATE <= STOP1;
|
||||
end if;
|
||||
when STOP2 =>
|
||||
if CLK_2_STRB = '1' and ST = "10" then
|
||||
RCV_NEXT_STATE <= SYNC; -- One and a half stop bits selected.
|
||||
elsif CLK_STRB = '1' then
|
||||
RCV_NEXT_STATE <= SYNC; -- Two stop bits selected.
|
||||
else
|
||||
RCV_NEXT_STATE <= STOP2;
|
||||
end if;
|
||||
when SYNC =>
|
||||
RCV_NEXT_STATE <= IDLE;
|
||||
end case;
|
||||
end process RCV_STATEDEC;
|
||||
end architecture BEHAVIOR;
|
||||
|
||||
238
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_top.vhd
Normal file
238
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_top.vhd
Normal file
@@ -0,0 +1,238 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- MC68901 compatible multi function port core. ----
|
||||
---- ----
|
||||
---- This is the SUSKA MFP IP core USART top level file. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
use work.wf68901ip_pkg.all;
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_USART_TOP is
|
||||
port ( -- System control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Asynchronous bus control:
|
||||
DSn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
|
||||
-- Data and Adresses:
|
||||
RS : in bit_vector(5 downto 1);
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_OUT_EN : out bit;
|
||||
|
||||
-- Serial I/O control:
|
||||
RC : in bit; -- Receiver clock.
|
||||
TC : in bit; -- Transmitter clock.
|
||||
SI : in bit; -- Serial input.
|
||||
SO : out bit; -- Serial output.
|
||||
SO_EN : out bit; -- Serial output enable.
|
||||
|
||||
-- Interrupt channels:
|
||||
RX_ERR_INT : out bit; -- Receiver errors.
|
||||
RX_BUFF_INT : out bit; -- Receiver buffer full.
|
||||
TX_ERR_INT : out bit; -- Transmitter errors.
|
||||
TX_BUFF_INT : out bit; -- Transmitter buffer empty.
|
||||
|
||||
-- DMA control:
|
||||
RRn : out bit;
|
||||
TRn : out bit
|
||||
);
|
||||
end entity WF68901IP_USART_TOP;
|
||||
|
||||
architecture STRUCTURE of WF68901IP_USART_TOP is
|
||||
signal BF_I : bit;
|
||||
signal BE_I : bit;
|
||||
signal FE_I : bit;
|
||||
signal OE_I : bit;
|
||||
signal UE_I : bit;
|
||||
signal PE_I : bit;
|
||||
signal LOOPBACK_I : bit;
|
||||
signal SD_LEVEL_I : bit;
|
||||
signal SDATA_IN_I : bit;
|
||||
signal SDATA_OUT_I : bit;
|
||||
signal RXCLK_I : bit;
|
||||
signal CLK_MODE_I : bit;
|
||||
signal SCR_I : bit_vector(7 downto 0);
|
||||
signal RX_SAMPLE_I : bit;
|
||||
signal RX_DATA_I : bit_vector(7 downto 0);
|
||||
signal TX_DATA_I : bit_vector(7 downto 0);
|
||||
signal CL_I : bit_vector(1 downto 0);
|
||||
signal ST_I : bit_vector(1 downto 0);
|
||||
signal P_ENA_I : bit;
|
||||
signal P_EOn_I : bit;
|
||||
signal RE_I : bit;
|
||||
signal TE_I : bit;
|
||||
signal FS_CLR_I : bit;
|
||||
signal SS_I : bit;
|
||||
signal M_CIP_I : bit;
|
||||
signal FS_B_I : bit;
|
||||
signal BR_I : bit;
|
||||
signal UDR_READ_I : bit;
|
||||
signal UDR_WRITE_I : bit;
|
||||
signal RSR_READ_I : bit;
|
||||
signal TSR_READ_I : bit;
|
||||
signal TX_END_I : bit;
|
||||
begin
|
||||
SO <= SDATA_OUT_I when TE_I = '1' else SD_LEVEL_I;
|
||||
-- Loopback mode:
|
||||
SDATA_IN_I <= SDATA_OUT_I when LOOPBACK_I = '1' and TE_I = '1' else -- Loopback, transmitter enabled.
|
||||
'1' when LOOPBACK_I = '1' and TE_I = '0' else SI; -- Loopback, transmitter disabled.
|
||||
|
||||
RXCLK_I <= TC when LOOPBACK_I = '1' else RC;
|
||||
RRn <= '0' when BF_I = '1' and PE_I = '0' and FE_I = '0' else '1';
|
||||
TRn <= not BE_I;
|
||||
|
||||
-- Interrupt sources:
|
||||
RX_ERR_INT <= OE_I or PE_I or FE_I or FS_B_I;
|
||||
RX_BUFF_INT <= BF_I;
|
||||
TX_ERR_INT <= UE_I or TX_END_I;
|
||||
TX_BUFF_INT <= BE_I;
|
||||
|
||||
I_USART_CTRL: WF68901IP_USART_CTRL
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DSn => DSn,
|
||||
CSn => CSn,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_IN => DATA_IN,
|
||||
DATA_OUT => DATA_OUT,
|
||||
DATA_OUT_EN => DATA_OUT_EN,
|
||||
LOOPBACK => LOOPBACK_I,
|
||||
SDOUT_EN => SO_EN,
|
||||
SD_LEVEL => SD_LEVEL_I,
|
||||
CLK_MODE => CLK_MODE_I,
|
||||
RE => RE_I,
|
||||
TE => TE_I,
|
||||
P_ENA => P_ENA_I,
|
||||
P_EOn => P_EOn_I,
|
||||
BF => BF_I,
|
||||
BE => BE_I,
|
||||
FE => FE_I,
|
||||
OE => OE_I,
|
||||
UE => UE_I,
|
||||
PE => PE_I,
|
||||
M_CIP => M_CIP_I,
|
||||
FS_B => FS_B_I,
|
||||
SCR_OUT => SCR_I,
|
||||
TX_DATA => TX_DATA_I,
|
||||
RX_SAMPLE => RX_SAMPLE_I,
|
||||
RX_DATA => RX_DATA_I,
|
||||
SS => SS_I,
|
||||
BR => BR_I,
|
||||
CL => CL_I,
|
||||
ST => ST_I,
|
||||
FS_CLR => FS_CLR_I,
|
||||
UDR_READ => UDR_READ_I,
|
||||
UDR_WRITE => UDR_WRITE_I,
|
||||
RSR_READ => RSR_READ_I,
|
||||
TSR_READ => TSR_READ_I,
|
||||
TX_END => TX_END_I
|
||||
);
|
||||
|
||||
I_USART_RECEIVE: WF68901IP_USART_RX
|
||||
port map (
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
SCR => SCR_I,
|
||||
RX_SAMPLE => RX_SAMPLE_I,
|
||||
RX_DATA => RX_DATA_I,
|
||||
CL => CL_I,
|
||||
ST => ST_I,
|
||||
P_ENA => P_ENA_I,
|
||||
P_EOn => P_EOn_I,
|
||||
CLK_MODE => CLK_MODE_I,
|
||||
RE => RE_I,
|
||||
FS_CLR => FS_CLR_I,
|
||||
SS => SS_I,
|
||||
RXCLK => RXCLK_I,
|
||||
SDATA_IN => SDATA_IN_I,
|
||||
RSR_READ => RSR_READ_I,
|
||||
UDR_READ => UDR_READ_I,
|
||||
M_CIP => M_CIP_I,
|
||||
FS_B => FS_B_I,
|
||||
BF => BF_I,
|
||||
OE => OE_I,
|
||||
PE => PE_I,
|
||||
FE => FE_I
|
||||
);
|
||||
|
||||
I_USART_TRANSMIT: WF68901IP_USART_TX
|
||||
port map (
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
SCR => SCR_I,
|
||||
TX_DATA => TX_DATA_I,
|
||||
SDATA_OUT => SDATA_OUT_I,
|
||||
TXCLK => TC,
|
||||
CL => CL_I,
|
||||
ST => ST_I,
|
||||
TE => TE_I,
|
||||
BR => BR_I,
|
||||
P_ENA => P_ENA_I,
|
||||
P_EOn => P_EOn_I,
|
||||
UDR_WRITE => UDR_WRITE_I,
|
||||
TSR_READ => TSR_READ_I,
|
||||
CLK_MODE => CLK_MODE_I,
|
||||
TX_END => TX_END_I,
|
||||
UE => UE_I,
|
||||
BE => BE_I
|
||||
);
|
||||
end architecture STRUCTURE;
|
||||
387
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_tx.vhd
Normal file
387
FalconIO_SDCard_IDE_CF/WF_MFP68901_IP/wf68901ip_usart_tx.vhd
Normal file
@@ -0,0 +1,387 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI MFP compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- This is the SUSKA MFP IP core USART transmitter file. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file 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 source 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 source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K6A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- TDRE has now synchronous reset to meet preset requirement.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF68901IP_USART_TX is
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
SCR : in bit_vector(7 downto 0); -- Synchronous character.
|
||||
TX_DATA : in bit_vector(7 downto 0); -- Normal data.
|
||||
|
||||
SDATA_OUT : out bit; -- Serial data output.
|
||||
TXCLK : in bit; -- Transmitter clock.
|
||||
|
||||
CL : in bit_vector(1 downto 0); -- Character length.
|
||||
ST : in bit_vector(1 downto 0); -- Start and stop bit configuration.
|
||||
TE : in bit; -- Transmitter enable.
|
||||
BR : in bit; -- BREAK character send enable (all '0' without stop bit).
|
||||
P_ENA : in bit; -- Parity enable.
|
||||
P_EOn : in bit; -- Even or odd parity.
|
||||
UDR_WRITE : in bit; -- Flag indicating writing the data register.
|
||||
TSR_READ : in bit; -- Flag indicating reading the transmitter status register.
|
||||
CLK_MODE : in bit; -- Transmitter clock mode.
|
||||
|
||||
TX_END : out bit; -- End of transmission flag.
|
||||
UE : out bit; -- Underrun Flag.
|
||||
BE : out bit -- Buffer empty flag.
|
||||
);
|
||||
end entity WF68901IP_USART_TX;
|
||||
|
||||
architecture BEHAVIOR of WF68901IP_USART_TX is
|
||||
type TR_STATES is (IDLE, CHECK_BREAK, LOAD_SHFT, START, SHIFTOUT, PARITY, STOP1, STOP2);
|
||||
signal TR_STATE, TR_NEXT_STATE : TR_STATES;
|
||||
signal CLK_STRB : bit;
|
||||
signal CLK_2_STRB : bit;
|
||||
signal SHIFT_REG : bit_vector(7 downto 0);
|
||||
signal BITCNT : std_logic_vector(2 downto 0);
|
||||
signal PARITY_I : bit;
|
||||
signal TDRE : bit;
|
||||
signal BREAK : bit;
|
||||
begin
|
||||
BE <= TDRE; -- Buffer empty flag.
|
||||
|
||||
-- The default condition in this statement is to ensure
|
||||
-- to cover all possibilities for example if there is a
|
||||
-- one hot decoding of the state machine with wrong states
|
||||
-- (e.g. not one of the given here).
|
||||
SDATA_OUT <= '0' when BREAK = '1' else
|
||||
'1' when TR_STATE = IDLE else
|
||||
'1' when TR_STATE = LOAD_SHFT else
|
||||
'0' when TR_STATE = START else
|
||||
SHIFT_REG(0) when TR_STATE = SHIFTOUT else
|
||||
PARITY_I when TR_STATE = PARITY else
|
||||
'1' when TR_STATE = STOP1 else
|
||||
'1' when TR_STATE = STOP2 else '1';
|
||||
|
||||
P_BREAK : process(RESETn, CLK)
|
||||
-- This process is responsible to control the BREAK signal. After the break request
|
||||
-- is asserted via BR, the break character will be sent after the current transmission has
|
||||
-- finished. The BREAK character is sent until the BR is disabled.
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
BREAK <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
-- Break is only available in the asynchronous mode (ST /= "00").
|
||||
-- The LOCK mechanism is reponsible for sending the BREAK character just once.
|
||||
if TE = '1' and BR = '1' and ST /= "00" and TR_STATE = IDLE and LOCK = false then
|
||||
BREAK <= '1'; -- Break for the case that there is no current transmission.
|
||||
LOCK := true;
|
||||
elsif BR = '1' and ST /= "00" and TR_STATE = STOP1 then
|
||||
BREAK <= '0'; -- Break character sent.
|
||||
elsif BR = '0' then
|
||||
BREAK <= '0';
|
||||
LOCK := false;
|
||||
else
|
||||
BREAK <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process P_BREAK;
|
||||
|
||||
CLKDIV: process
|
||||
variable CLK_LOCK : boolean;
|
||||
variable STRB_LOCK : boolean;
|
||||
variable CLK_DIVCNT : std_logic_vector(4 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if CLK_MODE = '0' then -- Divider off.
|
||||
if TXCLK = '0' and STRB_LOCK = false then -- Works on negative TXCLK edge.
|
||||
CLK_STRB <= '1';
|
||||
STRB_LOCK := true;
|
||||
elsif TXCLK = '1' then
|
||||
CLK_STRB <= '0';
|
||||
STRB_LOCK := false;
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
CLK_2_STRB <= '0'; -- No 1 1/2 stop bits in no div by 16 mode.
|
||||
elsif TR_STATE = IDLE then
|
||||
CLK_DIVCNT := "10000"; -- Div by 16 mode.
|
||||
CLK_STRB <= '0';
|
||||
else
|
||||
CLK_STRB <= '0'; -- Default.
|
||||
CLK_2_STRB <= '0'; -- Default.
|
||||
-- Works on negative TXCLK edge:
|
||||
if CLK_DIVCNT > "00000" and TXCLK = '0' and CLK_LOCK = false then
|
||||
CLK_DIVCNT := CLK_DIVCNT - '1';
|
||||
CLK_LOCK := true;
|
||||
if CLK_DIVCNT = "01000" then
|
||||
-- This strobe is asserted at half of the clock cycle.
|
||||
-- It is used for the stop bit timing.
|
||||
CLK_2_STRB <= '1';
|
||||
end if;
|
||||
elsif CLK_DIVCNT = "00000" then
|
||||
CLK_DIVCNT := "10000"; -- Div by 16 mode.
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
end if;
|
||||
elsif TXCLK = '1' then
|
||||
CLK_LOCK := false;
|
||||
STRB_LOCK := false;
|
||||
end if;
|
||||
end if;
|
||||
end process CLKDIV;
|
||||
|
||||
SHIFTREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if TR_STATE = LOAD_SHFT and TDRE = '1' then -- Lost data ...
|
||||
case ST is
|
||||
when "00" => -- Synchronous mode.
|
||||
SHIFT_REG <= SCR; -- Send the synchronous character.
|
||||
when others => -- Asynchronous mode.
|
||||
SHIFT_REG <= x"5A"; -- Load the shift register with a mark (underrun).
|
||||
end case;
|
||||
elsif TR_STATE = LOAD_SHFT then
|
||||
-- Load 'normal' data if there is no break condition:
|
||||
case CL is
|
||||
when "11" => SHIFT_REG <= "000" & TX_DATA(4 downto 0); -- 5 databits.
|
||||
when "10" => SHIFT_REG <= "00" & TX_DATA(5 downto 0); -- 6 databits.
|
||||
when "01" => SHIFT_REG <= '0' & TX_DATA(6 downto 0); -- 7 databits.
|
||||
when "00" => SHIFT_REG <= TX_DATA; -- 8 databits.
|
||||
end case;
|
||||
elsif TR_STATE = SHIFTOUT and CLK_STRB = '1' then
|
||||
SHIFT_REG <= '0' & SHIFT_REG(7 downto 1); -- Shift right.
|
||||
end if;
|
||||
end if;
|
||||
end process SHIFTREG;
|
||||
|
||||
P_BITCNT: process
|
||||
-- Counter for the data bits transmitted.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
|
||||
BITCNT <= BITCNT + '1';
|
||||
elsif TR_STATE /= SHIFTOUT then
|
||||
BITCNT <= "000";
|
||||
end if;
|
||||
end process P_BITCNT;
|
||||
|
||||
BUFFER_EMPTY: process
|
||||
-- Transmit data register empty flag.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RESETn = '0' then
|
||||
TDRE <= '1';
|
||||
elsif TE = '0' then
|
||||
TDRE <= '1';
|
||||
elsif TR_STATE = START and BREAK = '0' then
|
||||
-- Data has been loaded to the shift register,
|
||||
-- thus data register is free again.
|
||||
-- If the BREAK flag is enabled, the BE flag
|
||||
-- respective TDRE flag cannot be set.
|
||||
TDRE <= '1';
|
||||
elsif UDR_WRITE = '1' then
|
||||
TDRE <= '0';
|
||||
end if;
|
||||
end process BUFFER_EMPTY;
|
||||
|
||||
UNDERRUN: process(RESETn, CLK)
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
UE <= '0';
|
||||
LOCK := false;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if TE = '0' then
|
||||
UE <= '0';
|
||||
LOCK := false;
|
||||
elsif CLK_STRB = '1' and TR_STATE = START then
|
||||
-- Underrun appears if TDRE is '0' at the end of this state.
|
||||
UE <= TDRE; -- Never true for enabled BREAK flag. See alos process BUFFER_EMPTY.
|
||||
LOCK := true;
|
||||
elsif CLK_STRB = '1' then
|
||||
LOCK := false; -- Disables clearing UE one transmit clock cycle.
|
||||
elsif TSR_READ = '1' and LOCK = false then
|
||||
UE <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process UNDERRUN;
|
||||
|
||||
P_TX_END: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TX_END <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if TE = '1' then -- Transmitter enabled.
|
||||
TX_END <= '0';
|
||||
elsif TE = '0' and TR_STATE = IDLE then
|
||||
TX_END <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process P_TX_END;
|
||||
|
||||
PARITY_GEN: process
|
||||
variable PAR_TMP : bit;
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if TR_STATE = START then -- Calculate the parity during the start phase.
|
||||
for i in 1 to 7 loop
|
||||
if i = 1 then
|
||||
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
|
||||
else
|
||||
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
|
||||
end if;
|
||||
end loop;
|
||||
if P_ENA = '1' and P_EOn = '1' then -- Even parity.
|
||||
PARITY_I <= PAR_TMP;
|
||||
elsif P_ENA = '1' and P_EOn = '0' then -- Odd parity.
|
||||
PARITY_I <= not PAR_TMP;
|
||||
else -- No parity.
|
||||
PARITY_I <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process PARITY_GEN;
|
||||
|
||||
TR_STATEREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TR_STATE <= IDLE;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TR_STATE <= TR_NEXT_STATE;
|
||||
end if;
|
||||
end process TR_STATEREG;
|
||||
|
||||
TR_STATEDEC: process(TR_STATE, CLK_STRB, CLK_2_STRB, BITCNT, TDRE, BREAK, TE, ST, P_ENA, CL, BR)
|
||||
begin
|
||||
case TR_STATE is
|
||||
when IDLE =>
|
||||
-- This IDLE state is just one clock cycle and is required to give the
|
||||
-- break process time to set the BREAK flag.
|
||||
TR_NEXT_STATE <= CHECK_BREAK;
|
||||
when CHECK_BREAK =>
|
||||
if BREAK = '1' then -- Send break character.
|
||||
-- Do not load any data to the shift register, go directly
|
||||
-- to the START state.
|
||||
TR_NEXT_STATE <= START;
|
||||
-- Start enabled transmitter, if the data register is not empty.
|
||||
-- Do not send any further data for the case of an asserted BR flag.
|
||||
elsif TE = '1' and TDRE = '0' and BR = '0' then
|
||||
TR_NEXT_STATE <= LOAD_SHFT;
|
||||
else
|
||||
TR_NEXT_STATE <= IDLE; -- Go back, scan for BREAK.
|
||||
end if;
|
||||
when LOAD_SHFT =>
|
||||
TR_NEXT_STATE <= START;
|
||||
when START => -- Send the start bit.
|
||||
if CLK_STRB = '1' then
|
||||
TR_NEXT_STATE <= SHIFTOUT;
|
||||
else
|
||||
TR_NEXT_STATE <= START;
|
||||
end if;
|
||||
when SHIFTOUT =>
|
||||
if CLK_STRB = '1' then
|
||||
if BITCNT < "100" and CL = "11" then
|
||||
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 5 data bits.
|
||||
elsif BITCNT < "101" and CL = "10" then
|
||||
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 6 data bits.
|
||||
elsif BITCNT < "110" and CL = "01" then
|
||||
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 7 data bits.
|
||||
elsif BITCNT < "111" and CL = "00" then
|
||||
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 8 data bits.
|
||||
elsif P_ENA = '0' and BREAK = '1' then
|
||||
TR_NEXT_STATE <= IDLE; -- Break condition, no parity check enabled, no stop bits.
|
||||
elsif P_ENA = '0' and ST = "00" then
|
||||
TR_NEXT_STATE <= IDLE; -- Synchronous mode, no parity check enabled.
|
||||
elsif P_ENA = '0' then
|
||||
TR_NEXT_STATE <= STOP1; -- Asynchronous mode, no parity check enabled.
|
||||
else
|
||||
TR_NEXT_STATE <= PARITY; -- Parity enabled.
|
||||
end if;
|
||||
else
|
||||
TR_NEXT_STATE <= SHIFTOUT;
|
||||
end if;
|
||||
when PARITY =>
|
||||
if CLK_STRB = '1' then
|
||||
if ST = "00" then -- Synchronous mode (no stop bits).
|
||||
TR_NEXT_STATE <= IDLE;
|
||||
elsif BREAK = '1' then -- No stop bits during break condition.
|
||||
TR_NEXT_STATE <= IDLE;
|
||||
else
|
||||
TR_NEXT_STATE <= STOP1;
|
||||
end if;
|
||||
else
|
||||
TR_NEXT_STATE <= PARITY;
|
||||
end if;
|
||||
when STOP1 =>
|
||||
if CLK_STRB = '1' and (ST = "11" or ST = "10") then
|
||||
TR_NEXT_STATE <= STOP2; -- More than one stop bits selected.
|
||||
elsif CLK_STRB = '1' then
|
||||
TR_NEXT_STATE <= IDLE; -- One stop bits selected.
|
||||
else
|
||||
TR_NEXT_STATE <= STOP1;
|
||||
end if;
|
||||
when STOP2 =>
|
||||
if CLK_2_STRB = '1' and ST = "10" then
|
||||
TR_NEXT_STATE <= IDLE; -- One and a half stop bits selected.
|
||||
elsif CLK_STRB = '1' then
|
||||
TR_NEXT_STATE <= IDLE; -- Two stop bits detected.
|
||||
else
|
||||
TR_NEXT_STATE <= STOP2;
|
||||
end if;
|
||||
end case;
|
||||
end process TR_STATEDEC;
|
||||
end architecture BEHAVIOR;
|
||||
|
||||
Reference in New Issue
Block a user