forked from Firebee/FPGA_Config
Sync with Fredi's source tree 18/04/2017
Blitter work.
This commit is contained in:
@@ -1,391 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- 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 = '0' 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;
|
||||
@@ -1,239 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- ATARI IP Core peripheral Add-On ----
|
||||
---- ----
|
||||
---- This file is part of the FPGA-ATARI project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- This hardware provides an interface to connect to a SD-Card. ----
|
||||
---- ----
|
||||
---- This interface is based on the project 'SatanDisk' of ----
|
||||
---- Miroslav Nohaj 'Jookie'. The code is an interpretation of ----
|
||||
---- the original code, written in VERILOG. It is provided for ----
|
||||
---- the use in a system on programmable chips (SOPC). ----
|
||||
---- ----
|
||||
---- Timing: Use a clock frequency of 16MHz for this component. ----
|
||||
---- Use the same clock frequency for the connected AVR ----
|
||||
---- microcontroller. ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2007 - 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 ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- This hardware works with the original ATARI ----
|
||||
---- hard dik driver. ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2K7A 2007/01/05 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF_SD_CARD is
|
||||
port (
|
||||
-- System:
|
||||
RESETn : in bit;
|
||||
CLK : in bit; -- 16MHz, see above.
|
||||
|
||||
-- ACSI section:
|
||||
ACSI_A1 : in bit;
|
||||
ACSI_CSn : in bit;
|
||||
ACSI_ACKn : in bit;
|
||||
ACSI_INTn : out bit;
|
||||
ACSI_DRQn : out bit;
|
||||
ACSI_D_IN : in std_logic_vector(7 downto 0);
|
||||
ACSI_D_OUT : out std_logic_vector(7 downto 0);
|
||||
ACSI_D_EN : out bit;
|
||||
|
||||
-- Microcontroller interface:
|
||||
MC_DO : in bit;
|
||||
MC_PIO_DMAn : in bit;
|
||||
MC_RWn : in bit;
|
||||
MC_CLR_CMD : in bit;
|
||||
MC_DONE : out bit;
|
||||
MC_GOT_CMD : out bit;
|
||||
MC_D_IN : in std_logic_vector(7 downto 0);
|
||||
MC_D_OUT : out std_logic_vector(7 downto 0);
|
||||
MC_D_EN : out bit
|
||||
);
|
||||
end WF_SD_CARD;
|
||||
|
||||
architecture BEHAVIOR of WF_SD_CARD is
|
||||
signal DATA_REG : std_logic_vector(7 downto 0);
|
||||
signal D0_REG : bit;
|
||||
signal INT_REG : bit;
|
||||
signal DRQ_REG : bit;
|
||||
signal DONE_REG : bit;
|
||||
signal GOT_CMD_REG : bit;
|
||||
signal HOLD : bit;
|
||||
signal PREV_CSn : bit;
|
||||
signal PREV_ACKn : bit;
|
||||
begin
|
||||
MC_D_OUT <= DATA_REG when MC_RWn = '0' and DONE_REG = '1' else (others => '0');
|
||||
MC_D_EN <= '1' when MC_RWn = '0' and DONE_REG = '1' else '0';
|
||||
ACSI_D_OUT <= DATA_REG when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else (others => '0');
|
||||
-- ???:
|
||||
--ACSI_D_EN <= '1' when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else '0';
|
||||
ACSI_D_EN <= '0';
|
||||
ACSI_INTn <= INT_REG;
|
||||
ACSI_DRQn <= DRQ_REG;
|
||||
MC_DONE <= DONE_REG;
|
||||
MC_GOT_CMD <= GOT_CMD_REG;
|
||||
|
||||
P_DATA: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
DATA_REG <= (others => '0');
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if D0_REG = '0' and MC_DO = '1' and MC_RWn = '1' then
|
||||
DATA_REG <= MC_D_IN; -- Read from AVR to ACSI.
|
||||
end if;
|
||||
--
|
||||
if PREV_CSn = '0' and ACSI_CSn = '0' and MC_RWn = '0' and DONE_REG = '0' then
|
||||
DATA_REG <= ACSI_D_IN; -- Write from ACSI to AVR.
|
||||
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and MC_RWn = '0' and DONE_REG = '0' then
|
||||
DATA_REG <= ACSI_D_IN; -- Write from ACSI to AVR.
|
||||
end if;
|
||||
end if;
|
||||
end process P_DATA;
|
||||
|
||||
P_SYNC: process
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
PREV_CSn <= ACSI_CSn;
|
||||
PREV_ACKn <= ACSI_ACKn;
|
||||
end process P_SYNC;
|
||||
|
||||
P_INT_DRQ: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
INT_REG <= '1'; -- No interrupt.
|
||||
DRQ_REG <= '1'; -- No data request.
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if D0_REG = '0' and MC_DO = '1' and MC_PIO_DMAn = '1' then -- Positive MC_DO edge.
|
||||
INT_REG <= '0'; -- Release an interrupt.
|
||||
DRQ_REG <= '1';
|
||||
elsif D0_REG = '0' and MC_DO = '1' then
|
||||
INT_REG <= '1';
|
||||
DRQ_REG <= '0'; -- Release a data request.
|
||||
end if;
|
||||
--
|
||||
if MC_CLR_CMD = '1' then -- Clear done.
|
||||
INT_REG <= '1'; -- Restore INT_REG.
|
||||
DRQ_REG <= '1'; -- Restore DRQ_REG.
|
||||
end if;
|
||||
--
|
||||
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
|
||||
if ACSI_CSn = '0' then
|
||||
INT_REG <= '1';
|
||||
end if;
|
||||
--
|
||||
if ACSI_ACKn = '0' then
|
||||
DRQ_REG <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process P_INT_DRQ;
|
||||
|
||||
P_HOLD: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
HOLD <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
|
||||
HOLD <= '1';
|
||||
elsif PREV_CSn = '1' and ACSI_CSn = '1' then -- If signal is high.
|
||||
HOLD <= '0';
|
||||
elsif PREV_ACKn = '1' and ACSI_ACKn = '1' then -- If signal is high.
|
||||
HOLD <= '0';
|
||||
elsif PREV_CSn = '0' and ACSI_CSn = '1' then -- Rising edge.
|
||||
HOLD <= '1';
|
||||
elsif PREV_ACKn = '0' and ACSI_ACKn = '1' then -- Rising edge.
|
||||
HOLD <= '1';
|
||||
elsif MC_CLR_CMD = '1' then -- Clear done.
|
||||
HOLD <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process P_HOLD;
|
||||
|
||||
P_DONE: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
DONE_REG <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
|
||||
DONE_REG <= '1';
|
||||
elsif MC_CLR_CMD = '1' then -- Clear done.
|
||||
DONE_REG <= '0';
|
||||
elsif D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
|
||||
DONE_REG <= '0';
|
||||
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
|
||||
DONE_REG <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process P_DONE;
|
||||
|
||||
P_DO_REG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
D0_REG <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
|
||||
D0_REG <= MC_DO;
|
||||
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
|
||||
D0_REG <= MC_DO;
|
||||
end if;
|
||||
end if;
|
||||
end process P_DO_REG;
|
||||
|
||||
P_GOT_CMD: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
GOT_CMD_REG <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
-- ?? ACSI_CSn doppelt!
|
||||
--if PREV_CSn = '0' and ACSI_CSn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
|
||||
GOT_CMD_REG <= '1'; -- If command was received.
|
||||
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
|
||||
GOT_CMD_REG <= '1'; -- If command was received.
|
||||
elsif MC_CLR_CMD = '1' then -- Clear done.
|
||||
GOT_CMD_REG <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process P_GOT_CMD;
|
||||
end architecture BEHAVIOR;
|
||||
@@ -1,214 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- 6850 compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- UART 6850 compatible IP core ----
|
||||
---- ----
|
||||
---- 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.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- CTRL_REG has now synchronous reset to meet preset requirements.
|
||||
-- Process P_DCD has now synchronous reset to meet preset requirements.
|
||||
-- IRQ_In has now synchronous reset to meet preset requirement.
|
||||
-- Revision 2K9B 2009/12/24 WF
|
||||
-- Fixed the interrupt logic.
|
||||
-- Introduced a minor RTSn correction.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF6850IP_CTRL_STATUS is
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
RESETn : in bit;
|
||||
|
||||
CS : in bit_vector(2 downto 0); -- Active if "011".
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
|
||||
-- Status register stuff:
|
||||
RDRF : in bit; -- Receive data register full.
|
||||
TDRE : in bit; -- Transmit data register empty.
|
||||
DCDn : in bit; -- Data carrier detect.
|
||||
CTSn : in bit; -- Clear to send.
|
||||
FE : in bit; -- Framing error.
|
||||
OVR : in bit; -- Overrun error.
|
||||
PE : in bit; -- Parity error.
|
||||
|
||||
-- Control register stuff:
|
||||
MCLR : buffer bit; -- Master clear (high active).
|
||||
RTSn : out bit; -- Request to send.
|
||||
CDS : out bit_vector(1 downto 0); -- Clock control.
|
||||
WS : out bit_vector(2 downto 0); -- Word select.
|
||||
TC : out bit_vector(1 downto 0); -- Transmit control.
|
||||
IRQn : buffer bit -- Interrupt request.
|
||||
);
|
||||
end entity WF6850IP_CTRL_STATUS;
|
||||
|
||||
architecture BEHAVIOR of WF6850IP_CTRL_STATUS is
|
||||
signal CTRL_REG : bit_vector(7 downto 0);
|
||||
signal STATUS_REG : bit_vector(7 downto 0);
|
||||
signal RIE : bit;
|
||||
signal CTS_In : bit;
|
||||
signal DCD_In : bit;
|
||||
signal DCD_FLAGn : bit;
|
||||
begin
|
||||
CTS_In <= CTSn;
|
||||
DCD_In <= DCDn; -- immer 0
|
||||
|
||||
STATUS_REG(7) <= not IRQn;
|
||||
STATUS_REG(6) <= PE;
|
||||
STATUS_REG(5) <= OVR;
|
||||
STATUS_REG(4) <= FE;
|
||||
STATUS_REG(3) <= CTS_In; -- Reflexion of the input pin.
|
||||
STATUS_REG(2) <= DCD_FLAGn;
|
||||
STATUS_REG(1) <= TDRE and not CTS_In; -- No TDRE for CTSn = '1'.
|
||||
STATUS_REG(0) <= RDRF and not DCD_In; -- DCDn = '1' indicates empty.
|
||||
|
||||
DATA_OUT <= STATUS_REG when CS = "011" and RWn = '1' and RS = '0' else (others => '0');
|
||||
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' else '0';
|
||||
|
||||
MCLR <= '1' when CTRL_REG(1 downto 0) = "11" else '0';
|
||||
RTSn <= '0' when CTRL_REG(6 downto 5) /= "10" else '1';
|
||||
|
||||
CDS <= CTRL_REG(1 downto 0);
|
||||
WS <= CTRL_REG(4 downto 2);
|
||||
TC <= CTRL_REG(6 downto 5);
|
||||
RIE <= CTRL_REG(7);
|
||||
|
||||
P_IRQ: process(CLK)
|
||||
variable irq_v : std_logic_vector(3 downto 0);
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RESETn = '0' or MCLR = '1' then
|
||||
irq_v := x"0";
|
||||
IRQn <= '1';
|
||||
else
|
||||
-- Transmitter interrupt:
|
||||
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" then
|
||||
if irq_v = x"F" then
|
||||
irq_v := irq_v + 1;
|
||||
end if;
|
||||
-- Receiver interrupts:
|
||||
elsif RDRF = '1' and RIE = '1' then
|
||||
if irq_v < 15 then
|
||||
irq_v := irq_v + 1;
|
||||
end if;
|
||||
-- Overrun
|
||||
elsif OVR = '1' and RIE = '1' then
|
||||
if irq_v < 15 then
|
||||
irq_v := irq_v + 1;
|
||||
end if;
|
||||
else
|
||||
if irq_v > 0 then
|
||||
irq_v := irq_v - 1;
|
||||
end if;
|
||||
end if;
|
||||
if irq_v < 8 then
|
||||
IRQn <= '1';
|
||||
else
|
||||
IRQn <= '0';
|
||||
end if;
|
||||
-- The reset of the IRQ status flag:
|
||||
-- Clear by writing to the transmit data register.
|
||||
-- Clear by reading the receive data register.
|
||||
end if;
|
||||
end if;
|
||||
end process P_IRQ;
|
||||
|
||||
CONTROL: process(CLK)
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RESETn = '0' then
|
||||
CTRL_REG <= "01000000";
|
||||
elsif CS = "011" and RWn = '0' and RS = '0' then
|
||||
CTRL_REG <= DATA_IN;
|
||||
end if;
|
||||
end if;
|
||||
end process CONTROL;
|
||||
|
||||
P_DCD: process(CLK)
|
||||
-- This process is some kind of tricky. Refer to the MC6850 data
|
||||
-- sheet for more information.
|
||||
variable READ_LOCK : boolean;
|
||||
variable DCD_RELEASE : boolean;
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RESETn = '0' then
|
||||
DCD_FLAGn <= '0'; -- This interrupt source must initialise low.
|
||||
READ_LOCK := true;
|
||||
DCD_RELEASE := false;
|
||||
elsif MCLR = '1' then
|
||||
DCD_FLAGn <= DCD_In;
|
||||
READ_LOCK := true;
|
||||
elsif DCD_In = '1' then
|
||||
DCD_FLAGn <= '1';
|
||||
elsif CS = "011" and RWn = '1' and RS = '0' then
|
||||
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
|
||||
elsif CS = "011" and RWn = '1' and RS = '1' and READ_LOCK = false then
|
||||
-- Clear if receiver status register read access.
|
||||
-- After data register has ben read and READ_LOCK again.
|
||||
DCD_RELEASE := true;
|
||||
READ_LOCK := true;
|
||||
DCD_FLAGn <= DCD_In;
|
||||
elsif DCD_In = '0' and DCD_RELEASE = true then
|
||||
DCD_FLAGn <= '0';
|
||||
DCD_RELEASE := false;
|
||||
end if;
|
||||
end if;
|
||||
end process P_DCD;
|
||||
end architecture BEHAVIOR;
|
||||
|
||||
@@ -1,419 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- 6850 compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- UART 6850 compatible IP core ----
|
||||
---- ----
|
||||
---- 6850's receiver unit. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- 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 WF6850IP_RECEIVE is
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
MCLR : in bit;
|
||||
|
||||
CS : in bit_vector(2 downto 0);
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
|
||||
WS : in bit_vector(2 downto 0);
|
||||
CDS : in bit_vector(1 downto 0);
|
||||
|
||||
RXCLK : in bit;
|
||||
RXDATA : in bit;
|
||||
|
||||
RDRF : buffer bit;
|
||||
OVR : out bit;
|
||||
PE : out bit;
|
||||
FE : out bit
|
||||
);
|
||||
end entity WF6850IP_RECEIVE;
|
||||
|
||||
architecture BEHAVIOR of WF6850IP_RECEIVE is
|
||||
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
|
||||
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
|
||||
signal RXDATA_I : bit;
|
||||
signal RXDATA_S : bit;
|
||||
signal DATA_REG : bit_vector(7 downto 0);
|
||||
signal SHIFT_REG : bit_vector(7 downto 0);
|
||||
signal CLK_STRB : bit;
|
||||
signal BITCNT : std_logic_vector(2 downto 0);
|
||||
begin
|
||||
P_SAMPLE: process
|
||||
-- This filter provides a synchronisation to the system
|
||||
-- clock, even for random baud rates of the received data
|
||||
-- stream.
|
||||
variable FLT_TMP : integer range 0 to 2;
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
--
|
||||
RXDATA_I <= RXDATA;
|
||||
--
|
||||
if RXDATA_I = '1' and FLT_TMP < 2 then
|
||||
FLT_TMP := FLT_TMP + 1;
|
||||
elsif RXDATA_I = '1' then
|
||||
RXDATA_S <= '1';
|
||||
elsif RXDATA_I = '0' and FLT_TMP > 0 then
|
||||
FLT_TMP := FLT_TMP - 1;
|
||||
elsif RXDATA_I = '0' then
|
||||
RXDATA_S <= '0';
|
||||
end if;
|
||||
end process P_SAMPLE;
|
||||
|
||||
CLKDIV: process
|
||||
variable CLK_LOCK : boolean;
|
||||
variable STRB_LOCK : boolean;
|
||||
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if CDS = "00" 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;
|
||||
elsif RCV_STATE = IDLE then
|
||||
-- Preset the CLKDIV with the start delays.
|
||||
if CDS = "01" then
|
||||
CLK_DIVCNT := "0001000"; -- Half of div by 16 mode.
|
||||
elsif CDS = "10" then
|
||||
CLK_DIVCNT := "0100000"; -- Half of div by 64 mode.
|
||||
end if;
|
||||
CLK_STRB <= '0';
|
||||
else
|
||||
if CLK_DIVCNT > "0000000" and RXCLK = '1' and CLK_LOCK = false then
|
||||
CLK_DIVCNT := CLK_DIVCNT - '1';
|
||||
CLK_STRB <= '0';
|
||||
CLK_LOCK := true;
|
||||
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
|
||||
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
|
||||
--
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
|
||||
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
elsif RXCLK = '0' then
|
||||
CLK_LOCK := false;
|
||||
STRB_LOCK := false;
|
||||
CLK_STRB <= '0';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process CLKDIV;
|
||||
|
||||
DATAREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
DATA_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if MCLR = '1' then
|
||||
DATA_REG <= x"00";
|
||||
elsif RCV_STATE = SYNC and WS(2) = '0' and RDRF = '0' then -- 7 bit data.
|
||||
-- Transfer from shift- to data register only if
|
||||
-- data register is empty (RDRF = '0').
|
||||
DATA_REG <= '0' & SHIFT_REG(7 downto 1);
|
||||
elsif RCV_STATE = SYNC and WS(2) = '1' and RDRF = '0' then -- 8 bit data.
|
||||
-- Transfer from shift- to data register only if
|
||||
-- data register is empty (RDRF = '0').
|
||||
DATA_REG <= SHIFT_REG;
|
||||
end if;
|
||||
end if;
|
||||
end process DATAREG;
|
||||
DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' and E = '1' else (others => '0');
|
||||
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' and E = '1' else '0';
|
||||
|
||||
SHIFTREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if MCLR = '1' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' then
|
||||
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 downto 1); -- Shift right.
|
||||
end if;
|
||||
end if;
|
||||
end process SHIFTREG;
|
||||
|
||||
P_BITCNT: process
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
|
||||
BITCNT <= BITCNT + '1';
|
||||
elsif RCV_STATE /= SAMPLE then
|
||||
BITCNT <= (others => '0');
|
||||
end if;
|
||||
end process P_BITCNT;
|
||||
|
||||
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 MCLR = '1' then
|
||||
FE_I := '0';
|
||||
FE <= '0';
|
||||
elsif CLK_STRB = '1' then
|
||||
if RCV_STATE = STOP1 and RXDATA_S = '0' then
|
||||
FE_I := '1';
|
||||
elsif RCV_STATE = STOP2 and RXDATA_S = '0' 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;
|
||||
|
||||
OVERRUN: process(RESETn, CLK)
|
||||
variable OVR_I : bit;
|
||||
variable FIRST_READ : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
OVR_I := '0';
|
||||
OVR <= '0';
|
||||
FIRST_READ := false;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if MCLR = '1' then
|
||||
OVR_I := '0';
|
||||
OVR <= '0';
|
||||
FIRST_READ := false;
|
||||
elsif CLK_STRB = '1' and RCV_STATE = STOP1 then
|
||||
-- Overrun appears if RDRF is '1' in this state.
|
||||
OVR_I := RDRF;
|
||||
end if;
|
||||
if CS = "011" and RWn = '1' and RS = '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 (OVR_I goes low) after
|
||||
-- a second read (in time) of the receiver data register.
|
||||
if FIRST_READ = false then
|
||||
if OVR_I = '1' then
|
||||
OVR <= '1';
|
||||
OVR_I := '0';
|
||||
FIRST_READ := true;
|
||||
else
|
||||
OVR <= '0';
|
||||
end if;
|
||||
end if;
|
||||
else
|
||||
FIRST_READ := false;
|
||||
end if;
|
||||
end if;
|
||||
end process OVERRUN;
|
||||
|
||||
PARITY_TEST: process(RESETn, CLK)
|
||||
variable PAR_TMP : bit;
|
||||
variable PE_I : bit;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
PE <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if MCLR = '1' then
|
||||
PE <= '0';
|
||||
elsif CLK_STRB = '1' then -- Sample parity on clock strobe.
|
||||
PE_I := '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 WS = "000" or WS = "010" or WS = "110" then -- Even parity.
|
||||
PE_I := PAR_TMP xor RXDATA_S;
|
||||
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
|
||||
PE_I := not PAR_TMP xor RXDATA_S;
|
||||
else -- No parity for WS = "100" and WS = "101".
|
||||
PE_I := '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
-- Transmit the parity flag together with the data
|
||||
-- In other words: no parity to the status register
|
||||
-- when RDRF inhibits the data transfer to the
|
||||
-- receiver data register.
|
||||
if RCV_STATE = SYNC and RDRF = '0' then
|
||||
PE <= PE_I;
|
||||
elsif CS = "011" and RWn = '1' and RS = '1' then
|
||||
PE <= '0'; -- Clear when reading the data register.
|
||||
end if;
|
||||
end if;
|
||||
end process PARITY_TEST;
|
||||
|
||||
P_RDRF: process(RESETn, CLK)
|
||||
-- Receive data register full flag.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
RDRF <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if MCLR = '1' then
|
||||
RDRF <= '0';
|
||||
elsif RCV_STATE = SYNC then
|
||||
RDRF <= '1'; -- Data register is full until now!
|
||||
elsif CS = "011" and RWn = '1' and RS = '1' then
|
||||
RDRF <= '0'; -- After reading the data register ...
|
||||
end if;
|
||||
end if;
|
||||
end process P_RDRF;
|
||||
|
||||
RCV_STATEREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
RCV_STATE <= IDLE;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if MCLR = '1' then
|
||||
RCV_STATE <= IDLE;
|
||||
else
|
||||
RCV_STATE <= RCV_NEXT_STATE;
|
||||
end if;
|
||||
end if;
|
||||
end process RCV_STATEREG;
|
||||
|
||||
RCV_STATEDEC: process(RCV_STATE, RXDATA_S, CDS, WS, BITCNT, CLK_STRB)
|
||||
begin
|
||||
case RCV_STATE is
|
||||
when IDLE =>
|
||||
if RXDATA_S = '0' and CDS = "00" then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
|
||||
elsif RXDATA_S = '0' and CDS = "01" then
|
||||
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
|
||||
elsif RXDATA_S = '0' and CDS = "10" then
|
||||
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 64 mode.
|
||||
else
|
||||
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
|
||||
end if;
|
||||
when WAIT_START =>
|
||||
if CLK_STRB = '1' then
|
||||
if RXDATA_S = '0' then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Start condition in no div by 1 modes.
|
||||
else
|
||||
RCV_NEXT_STATE <= IDLE; -- No valid start condition, go back.
|
||||
end if;
|
||||
else
|
||||
RCV_NEXT_STATE <= WAIT_START; -- Stay.
|
||||
end if;
|
||||
when SAMPLE =>
|
||||
if CLK_STRB = '1' then
|
||||
if BITCNT < "110" and WS(2) = '0' then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
|
||||
elsif BITCNT < "111" and WS(2) = '1' then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
|
||||
elsif WS = "100" or WS = "101" 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
|
||||
RCV_NEXT_STATE <= STOP1;
|
||||
else
|
||||
RCV_NEXT_STATE <= PARITY;
|
||||
end if;
|
||||
when STOP1 =>
|
||||
if CLK_STRB = '1' then
|
||||
if RXDATA_S = '0' then
|
||||
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
|
||||
elsif WS = "000" or WS = "001" or WS = "100" then
|
||||
RCV_NEXT_STATE <= STOP2; -- Two 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_STRB = '1' then
|
||||
RCV_NEXT_STATE <= SYNC;
|
||||
else
|
||||
RCV_NEXT_STATE <= STOP2;
|
||||
end if;
|
||||
when SYNC =>
|
||||
RCV_NEXT_STATE <= IDLE;
|
||||
end case;
|
||||
end process RCV_STATEDEC;
|
||||
end architecture BEHAVIOR;
|
||||
|
||||
@@ -1,425 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- 6850 compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- UART 6850 compatible IP core ----
|
||||
---- ----
|
||||
---- 6850's receiver unit. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- 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 WF6850IP_RECEIVE is
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
RESETn : in bit;
|
||||
MCLR : in bit;
|
||||
|
||||
CS : in bit_vector(2 downto 0);
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
|
||||
WS : in bit_vector(2 downto 0);
|
||||
CDS : in bit_vector(1 downto 0);
|
||||
|
||||
RXCLK : in bit;
|
||||
RXDATA : in bit;
|
||||
|
||||
RDRF : buffer bit;
|
||||
OVR : out bit;
|
||||
PE : out bit;
|
||||
FE : out bit
|
||||
);
|
||||
end entity WF6850IP_RECEIVE;
|
||||
|
||||
architecture BEHAVIOR of WF6850IP_RECEIVE is
|
||||
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
|
||||
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
|
||||
signal RXDATA_I : bit;
|
||||
signal RXDATA_S : bit;
|
||||
signal DATA_REG : bit_vector(7 downto 0);
|
||||
signal SHIFT_REG : bit_vector(7 downto 0);
|
||||
signal CLK_STRB : bit;
|
||||
signal BITCNT : std_logic_vector(2 downto 0);
|
||||
begin
|
||||
P_SAMPLE: process(CLK)
|
||||
-- This filter provides a synchronisation to the system
|
||||
-- clock, even for random baud rates of the received data
|
||||
-- stream.
|
||||
variable FLT_TMP : integer range 0 to 2;
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
--
|
||||
RXDATA_I <= RXDATA;
|
||||
--
|
||||
if RXDATA_I = '1' and FLT_TMP < 2 then
|
||||
FLT_TMP := FLT_TMP + 1;
|
||||
elsif RXDATA_I = '1' then
|
||||
RXDATA_S <= '1';
|
||||
elsif RXDATA_I = '0' and FLT_TMP > 0 then
|
||||
FLT_TMP := FLT_TMP - 1;
|
||||
elsif RXDATA_I = '0' then
|
||||
RXDATA_S <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process P_SAMPLE;
|
||||
|
||||
CLKDIV: process(CLK)
|
||||
variable CLK_LOCK : boolean;
|
||||
variable STRB_LOCK : boolean;
|
||||
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if CDS = "00" 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;
|
||||
elsif RCV_STATE = IDLE then
|
||||
-- Preset the CLKDIV with the start delays.
|
||||
if CDS = "01" then
|
||||
CLK_DIVCNT := "0001000"; -- Half of div by 16 mode.
|
||||
elsif CDS = "10" then
|
||||
CLK_DIVCNT := "0100000"; -- Half of div by 64 mode.
|
||||
end if;
|
||||
CLK_STRB <= '0';
|
||||
else
|
||||
if CLK_DIVCNT > "0000000" and RXCLK = '1' and CLK_LOCK = false then
|
||||
CLK_DIVCNT := CLK_DIVCNT - '1';
|
||||
CLK_STRB <= '0';
|
||||
CLK_LOCK := true;
|
||||
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
|
||||
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
|
||||
--
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
|
||||
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
elsif RXCLK = '0' then
|
||||
CLK_LOCK := false;
|
||||
STRB_LOCK := false;
|
||||
CLK_STRB <= '0';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process CLKDIV;
|
||||
|
||||
DATAREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' or MCLR = '1' then
|
||||
DATA_REG <= x"00";
|
||||
else
|
||||
if rising_edge(CLK) then
|
||||
if RCV_STATE = SYNC and WS(2) = '0' and RDRF = '0' then -- 7 bit data.
|
||||
-- Transfer from shift- to data register only if
|
||||
-- data register is empty (RDRF = '0').
|
||||
DATA_REG <= '0' & SHIFT_REG(7 downto 1);
|
||||
elsif RCV_STATE = SYNC and WS(2) = '1' and RDRF = '0' then -- 8 bit data.
|
||||
-- Transfer from shift- to data register only if
|
||||
-- data register is empty (RDRF = '0').
|
||||
DATA_REG <= SHIFT_REG;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process DATAREG;
|
||||
DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' else (others => '0');
|
||||
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' else '0';
|
||||
|
||||
SHIFTREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' or MCLR = '1' then
|
||||
SHIFT_REG <= x"00";
|
||||
else
|
||||
if rising_edge(CLK) then
|
||||
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
|
||||
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 downto 1); -- Shift right.
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process SHIFTREG;
|
||||
|
||||
P_BITCNT: process(CLK)
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
|
||||
BITCNT <= BITCNT + '1';
|
||||
elsif RCV_STATE /= SAMPLE then
|
||||
BITCNT <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process P_BITCNT;
|
||||
|
||||
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';
|
||||
else
|
||||
if rising_edge(CLK) then
|
||||
if MCLR = '1' then
|
||||
FE_I := '0';
|
||||
FE <= '0';
|
||||
elsif CLK_STRB = '1' then
|
||||
if RCV_STATE = STOP1 and RXDATA_S = '0' then
|
||||
FE_I := '1';
|
||||
elsif RCV_STATE = STOP2 and RXDATA_S = '0' 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 if;
|
||||
end process FRAME_ERR;
|
||||
|
||||
OVERRUN: process(RESETn, CLK)
|
||||
variable OVR_I : bit;
|
||||
variable FIRST_READ : boolean;
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RESETn = '0' or MCLR = '1' then
|
||||
OVR_I := '0';
|
||||
OVR <= '0';
|
||||
FIRST_READ := false;
|
||||
else
|
||||
if CLK_STRB = '1' and RCV_STATE = STOP1 then
|
||||
-- Overrun appears if RDRF is '1' in this state.
|
||||
OVR_I := RDRF;
|
||||
end if;
|
||||
if CS = "011" and RWn = '1' and RS = '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 (OVR_I goes low) after
|
||||
-- a second read (in time) of the receiver data register.
|
||||
if FIRST_READ = false then
|
||||
if OVR_I = '1' then
|
||||
OVR <= '1';
|
||||
OVR_I := '0';
|
||||
FIRST_READ := true;
|
||||
else
|
||||
OVR <= '0';
|
||||
end if;
|
||||
end if;
|
||||
else
|
||||
FIRST_READ := false;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process OVERRUN;
|
||||
|
||||
PARITY_TEST: process(RESETn,MCLR,CLK)
|
||||
variable PAR_TMP : bit;
|
||||
variable PE_I : bit;
|
||||
begin
|
||||
if RESETn = '0' or MCRL = '1' then
|
||||
PE <= '0';
|
||||
else
|
||||
if rising_edge(CLK) then
|
||||
if CLK_STRB = '1' then -- Sample parity on clock strobe.
|
||||
PE_I := '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 WS = "000" or WS = "010" or WS = "110" then -- Even parity.
|
||||
PE_I := PAR_TMP xor RXDATA_S;
|
||||
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
|
||||
PE_I := not PAR_TMP xor RXDATA_S;
|
||||
else -- No parity for WS = "100" and WS = "101".
|
||||
PE_I := '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
-- Transmit the parity flag together with the data
|
||||
-- In other words: no parity to the status register
|
||||
-- when RDRF inhibits the data transfer to the
|
||||
-- receiver data register.
|
||||
if RCV_STATE = SYNC and RDRF = '0' then
|
||||
PE <= PE_I;
|
||||
elsif CS = "011" and RWn = '1' and RS = '1' then
|
||||
PE <= '0'; -- Clear when reading the data register.
|
||||
end if;
|
||||
end if;
|
||||
end process PARITY_TEST;
|
||||
|
||||
P_RDRF: process(RESETn, CLK)
|
||||
-- Receive data register full flag.
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RESETn = '0' or MCLR = '1' then
|
||||
RDRF <= '0';
|
||||
else
|
||||
if RCV_STATE = SYNC then
|
||||
RDRF <= '1'; -- Data register is full until now!
|
||||
end if;
|
||||
if CS = "011" and RWn = '1' and RS = '1' then
|
||||
RDRF <= '0'; -- when reading the data register ...
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process P_RDRF;
|
||||
|
||||
RCV_STATEREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
RCV_STATE <= IDLE;
|
||||
else
|
||||
if rising_edge(CLK) then
|
||||
if MCLR = '1' then
|
||||
RCV_STATE <= IDLE;
|
||||
else
|
||||
RCV_STATE <= RCV_NEXT_STATE;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process RCV_STATEREG;
|
||||
|
||||
RCV_STATEDEC: process(RCV_STATE, RXDATA_S, CDS, WS, BITCNT, CLK_STRB)
|
||||
begin
|
||||
case RCV_STATE is
|
||||
when IDLE =>
|
||||
if RXDATA_S = '0' and CDS = "00" then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
|
||||
elsif RXDATA_S = '0' and CDS = "01" then
|
||||
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
|
||||
elsif RXDATA_S = '0' and CDS = "10" then
|
||||
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 64 mode.
|
||||
else
|
||||
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
|
||||
end if;
|
||||
when WAIT_START =>
|
||||
if CLK_STRB = '1' then
|
||||
if RXDATA_S = '0' then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Start condition in no div by 1 modes.
|
||||
else
|
||||
RCV_NEXT_STATE <= IDLE; -- No valid start condition, go back.
|
||||
end if;
|
||||
else
|
||||
RCV_NEXT_STATE <= WAIT_START; -- Stay.
|
||||
end if;
|
||||
when SAMPLE =>
|
||||
if CLK_STRB = '1' then
|
||||
if BITCNT < "110" and WS(2) = '0' then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
|
||||
elsif BITCNT < "111" and WS(2) = '1' then
|
||||
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
|
||||
elsif WS = "100" or WS = "101" 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
|
||||
RCV_NEXT_STATE <= STOP1;
|
||||
else
|
||||
RCV_NEXT_STATE <= PARITY;
|
||||
end if;
|
||||
when STOP1 =>
|
||||
if CLK_STRB = '1' then
|
||||
if RXDATA_S = '0' then
|
||||
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
|
||||
elsif WS = "000" or WS = "001" or WS = "100" then
|
||||
RCV_NEXT_STATE <= STOP2; -- Two 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_STRB = '1' then
|
||||
RCV_NEXT_STATE <= SYNC;
|
||||
else
|
||||
RCV_NEXT_STATE <= STOP2;
|
||||
end if;
|
||||
when SYNC =>
|
||||
RCV_NEXT_STATE <= IDLE;
|
||||
end case;
|
||||
end process RCV_STATEDEC;
|
||||
end architecture BEHAVIOR;
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- 6850 compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- UART 6850 compatible IP core ----
|
||||
---- ----
|
||||
---- This is the 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 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF6850IP_TOP_SOC is
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
CS2n, CS1, CS0 : in bit;
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
|
||||
DATA_IN : in std_logic_vector(7 downto 0);
|
||||
DATA_OUT : out std_logic_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
|
||||
TXCLK : in bit;
|
||||
RXCLK : in bit;
|
||||
RXDATA : in bit;
|
||||
CTSn : in bit;
|
||||
DCDn : in bit;
|
||||
|
||||
IRQn : out bit;
|
||||
TXDATA : out bit;
|
||||
RTSn : out bit
|
||||
);
|
||||
end entity WF6850IP_TOP_SOC;
|
||||
|
||||
architecture STRUCTURE of WF6850IP_TOP_SOC is
|
||||
component WF6850IP_CTRL_STATUS
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
CS : in bit_vector(2 downto 0);
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
RDRF : in bit;
|
||||
TDRE : in bit;
|
||||
DCDn : in bit;
|
||||
CTSn : in bit;
|
||||
FE : in bit;
|
||||
OVR : in bit;
|
||||
PE : in bit;
|
||||
MCLR : out bit;
|
||||
RTSn : out bit;
|
||||
CDS : out bit_vector(1 downto 0);
|
||||
WS : out bit_vector(2 downto 0);
|
||||
TC : out bit_vector(1 downto 0);
|
||||
IRQn : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF6850IP_RECEIVE
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
MCLR : in bit;
|
||||
CS : in bit_vector(2 downto 0);
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
DATA_OUT : out bit_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
WS : in bit_vector(2 downto 0);
|
||||
CDS : in bit_vector(1 downto 0);
|
||||
RXCLK : in bit;
|
||||
RXDATA : in bit;
|
||||
RDRF : out bit;
|
||||
OVR : out bit;
|
||||
PE : out bit;
|
||||
FE : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF6850IP_TRANSMIT
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
MCLR : in bit;
|
||||
CS : in bit_vector(2 downto 0);
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
CTSn : in bit;
|
||||
TC : in bit_vector(1 downto 0);
|
||||
WS : in bit_vector(2 downto 0);
|
||||
CDS : in bit_vector(1 downto 0);
|
||||
TXCLK : in bit;
|
||||
TDRE : out bit;
|
||||
TXDATA : out bit
|
||||
);
|
||||
end component;
|
||||
signal DATA_IN_I : bit_vector(7 downto 0);
|
||||
signal DATA_RX : bit_vector(7 downto 0);
|
||||
signal DATA_RX_EN : bit;
|
||||
signal DATA_CTRL : bit_vector(7 downto 0);
|
||||
signal DATA_CTRL_EN : bit;
|
||||
signal RDRF_I : bit;
|
||||
signal TDRE_I : bit;
|
||||
signal FE_I : bit;
|
||||
signal OVR_I : bit;
|
||||
signal PE_I : bit;
|
||||
signal MCLR_I : bit;
|
||||
signal CDS_I : bit_vector(1 downto 0);
|
||||
signal WS_I : bit_vector(2 downto 0);
|
||||
signal TC_I : bit_vector(1 downto 0);
|
||||
signal IRQ_In : bit;
|
||||
begin
|
||||
DATA_IN_I <= To_BitVector(DATA_IN);
|
||||
DATA_EN <= DATA_RX_EN or DATA_CTRL_EN;
|
||||
DATA_OUT <= To_StdLogicVector(DATA_RX) when DATA_RX_EN = '1' else
|
||||
To_StdLogicVector(DATA_CTRL) when DATA_CTRL_EN = '1' else (others => '0');
|
||||
|
||||
IRQn <= '0' when IRQ_In = '0' else '1';
|
||||
|
||||
I_UART_CTRL_STATUS: WF6850IP_CTRL_STATUS
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
CS(2) => CS2n,
|
||||
CS(1) => CS1,
|
||||
CS(0) => CS0,
|
||||
E => E,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_IN => DATA_IN_I,
|
||||
DATA_OUT => DATA_CTRL,
|
||||
DATA_EN => DATA_CTRL_EN,
|
||||
RDRF => RDRF_I,
|
||||
TDRE => TDRE_I,
|
||||
DCDn => DCDn,
|
||||
CTSn => CTSn,
|
||||
FE => FE_I,
|
||||
OVR => OVR_I,
|
||||
PE => PE_I,
|
||||
MCLR => MCLR_I,
|
||||
RTSn => RTSn,
|
||||
CDS => CDS_I,
|
||||
WS => WS_I,
|
||||
TC => TC_I,
|
||||
IRQn => IRQ_In
|
||||
);
|
||||
|
||||
I_UART_RECEIVE: WF6850IP_RECEIVE
|
||||
port map (
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
MCLR => MCLR_I,
|
||||
CS(2) => CS2n,
|
||||
CS(1) => CS1,
|
||||
CS(0) => CS0,
|
||||
E => E,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_OUT => DATA_RX,
|
||||
DATA_EN => DATA_RX_EN,
|
||||
WS => WS_I,
|
||||
CDS => CDS_I,
|
||||
RXCLK => RXCLK,
|
||||
RXDATA => RXDATA,
|
||||
RDRF => RDRF_I,
|
||||
OVR => OVR_I,
|
||||
PE => PE_I,
|
||||
FE => FE_I
|
||||
);
|
||||
|
||||
I_UART_TRANSMIT: WF6850IP_TRANSMIT
|
||||
port map (
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
MCLR => MCLR_I,
|
||||
CS(2) => CS2n,
|
||||
CS(1) => CS1,
|
||||
CS(0) => CS0,
|
||||
E => E,
|
||||
RWn => RWn,
|
||||
RS => RS,
|
||||
DATA_IN => DATA_IN_I,
|
||||
CTSn => CTSn,
|
||||
TC => TC_I,
|
||||
WS => WS_I,
|
||||
CDS => CDS_I,
|
||||
TDRE => TDRE_I,
|
||||
TXCLK => TXCLK,
|
||||
TXDATA => TXDATA
|
||||
);
|
||||
end architecture STRUCTURE;
|
||||
@@ -1,338 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- 6850 compatible IP Core ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- UART 6850 compatible IP core ----
|
||||
---- ----
|
||||
---- 6850's transmitter unit. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- 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 2K8B 2008/11/01 WF
|
||||
-- Fixed the T_DRE process concerning the TDRE <= '1' setting.
|
||||
-- Thanks to Lyndon Amsdon finding the bug.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF6850IP_TRANSMIT is
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
RESETn : in bit;
|
||||
MCLR : in bit;
|
||||
|
||||
CS : in bit_vector(2 downto 0);
|
||||
E : in bit;
|
||||
RWn : in bit;
|
||||
RS : in bit;
|
||||
|
||||
DATA_IN : in bit_vector(7 downto 0);
|
||||
|
||||
CTSn : in bit;
|
||||
|
||||
TC : in bit_vector(1 downto 0);
|
||||
WS : in bit_vector(2 downto 0);
|
||||
CDS : in bit_vector(1 downto 0);
|
||||
|
||||
TXCLK : in bit;
|
||||
|
||||
TDRE : buffer bit;
|
||||
TXDATA : out bit
|
||||
);
|
||||
end entity WF6850IP_TRANSMIT;
|
||||
|
||||
architecture BEHAVIOR of WF6850IP_TRANSMIT is
|
||||
type TR_STATES is (IDLE, LOAD_SHFT, START, SHIFTOUT, PARITY, STOP1, STOP2);
|
||||
signal TR_STATE, TR_NEXT_STATE : TR_STATES;
|
||||
signal CLK_STRB : bit;
|
||||
signal DATA_REG : bit_vector(7 downto 0);
|
||||
signal SHIFT_REG : bit_vector(7 downto 0);
|
||||
signal BITCNT : std_logic_vector(2 downto 0);
|
||||
signal PARITY_I : bit;
|
||||
begin
|
||||
-- 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).
|
||||
TXDATA <= '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';
|
||||
|
||||
CLKDIV: process
|
||||
variable CLK_LOCK : boolean;
|
||||
variable STRB_LOCK : boolean;
|
||||
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if CDS = "00" 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;
|
||||
elsif TR_STATE = IDLE then
|
||||
-- preset the CLKDIV with the start delays
|
||||
if CDS = "01" then
|
||||
CLK_DIVCNT := "0010000"; -- div by 16 mode
|
||||
elsif CDS = "10" then
|
||||
CLK_DIVCNT := "1000000"; -- div by 64 mode
|
||||
end if;
|
||||
CLK_STRB <= '0';
|
||||
else
|
||||
-- Works on negative TXCLK edge:
|
||||
if CLK_DIVCNT > "0000000" and TXCLK = '0' and CLK_LOCK = false then
|
||||
CLK_DIVCNT := CLK_DIVCNT - '1';
|
||||
CLK_STRB <= '0';
|
||||
CLK_LOCK := true;
|
||||
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
|
||||
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
|
||||
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
|
||||
if STRB_LOCK = false then
|
||||
STRB_LOCK := true;
|
||||
CLK_STRB <= '1';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
elsif TXCLK = '1' then
|
||||
CLK_LOCK := false;
|
||||
STRB_LOCK := false;
|
||||
CLK_STRB <= '0';
|
||||
else
|
||||
CLK_STRB <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process CLKDIV;
|
||||
|
||||
DATAREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
DATA_REG <= x"00";
|
||||
elsif rising_edge(CLK) then
|
||||
if MCLR = '1' then
|
||||
DATA_REG <= x"00";
|
||||
elsif WS(2) = '0' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
|
||||
DATA_REG <= '0' & DATA_IN(6 downto 0); -- 7 bit data mode.
|
||||
elsif WS(2) = '1' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
|
||||
DATA_REG <= DATA_IN; -- 8 bit data mode.
|
||||
end if;
|
||||
end if;
|
||||
end process DATAREG;
|
||||
|
||||
SHIFTREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif rising_edge(CLK) then
|
||||
if MCLR = '1' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif TR_STATE = LOAD_SHFT and TDRE = '0' then
|
||||
-- If during LOAD_SHIFT the transmitter data register
|
||||
-- is empty (TDRE = '1') the shift register will not
|
||||
-- be loaded. When additionally TC = "11", the break
|
||||
-- character (zero data and no stop bits) is sent.
|
||||
SHIFT_REG <= DATA_REG;
|
||||
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(CLK)
|
||||
-- Counter for the data bits transmitted.
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
|
||||
BITCNT <= BITCNT + '1';
|
||||
elsif TR_STATE /= SHIFTOUT then
|
||||
BITCNT <= "000";
|
||||
end if;
|
||||
end if;
|
||||
end process P_BITCNT;
|
||||
|
||||
P_TDRE: process(RESETn, CLK)
|
||||
-- Transmit data register empty flag.
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if RESETn = '0' or MCLR = '1' then
|
||||
TDRE <= '1';
|
||||
else
|
||||
if TR_NEXT_STATE = START and TR_STATE /= START then
|
||||
-- Data has been loaded to shift register, thus data register is free again.
|
||||
-- Thanks to Lyndon Amsdon for finding a bug here. The TDRE is set to one once
|
||||
-- entering the state now.
|
||||
TDRE <= '1';
|
||||
end if;
|
||||
if CS = "011" and RWn = '0' and RS = '1' then
|
||||
TDRE <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process P_TDRE;
|
||||
|
||||
PARITY_GEN: process(CLK)
|
||||
variable PAR_TMP : bit;
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
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 WS = "000" or WS = "010" or WS = "110" then -- Even parity.
|
||||
PARITY_I <= PAR_TMP;
|
||||
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
|
||||
PARITY_I <= not PAR_TMP;
|
||||
else -- No parity for WS = "100" and WS = "101".
|
||||
PARITY_I <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process PARITY_GEN;
|
||||
|
||||
TR_STATEREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TR_STATE <= IDLE;
|
||||
else
|
||||
if rising_edge(CLK) then
|
||||
if MCLR = '1' then
|
||||
TR_STATE <= IDLE;
|
||||
else
|
||||
TR_STATE <= TR_NEXT_STATE;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process TR_STATEREG;
|
||||
|
||||
TR_STATEDEC: process(TR_STATE, CLK_STRB, TC, BITCNT, WS, TDRE, CTSn)
|
||||
begin
|
||||
case TR_STATE is
|
||||
when IDLE =>
|
||||
if TDRE = '1' and TC = "11" then
|
||||
TR_NEXT_STATE <= LOAD_SHFT;
|
||||
elsif TDRE = '0' and CTSn = '0' then -- Start if data register is not empty.
|
||||
TR_NEXT_STATE <= LOAD_SHFT;
|
||||
else
|
||||
TR_NEXT_STATE <= IDLE;
|
||||
end if;
|
||||
when LOAD_SHFT =>
|
||||
TR_NEXT_STATE <= START;
|
||||
when START =>
|
||||
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 < "110" and WS(2) = '0' then
|
||||
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 7 data bits.
|
||||
elsif BITCNT < "111" and WS(2) = '1' then
|
||||
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 8 data bits.
|
||||
elsif WS = "100" or WS = "101" then
|
||||
if TDRE = '1' and TC = "11" then
|
||||
-- Break condition, do not send a stop bit.
|
||||
TR_NEXT_STATE <= IDLE;
|
||||
else
|
||||
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
|
||||
end if;
|
||||
else
|
||||
TR_NEXT_STATE <= PARITY; -- Parity enabled.
|
||||
end if;
|
||||
else
|
||||
TR_NEXT_STATE <= SHIFTOUT;
|
||||
end if;
|
||||
when PARITY =>
|
||||
if CLK_STRB = '1' then
|
||||
if TDRE = '1' and TC = "11" then
|
||||
-- Break condition, do not send a stop bit.
|
||||
TR_NEXT_STATE <= IDLE;
|
||||
else
|
||||
TR_NEXT_STATE <= STOP1; -- No parity check enabled.
|
||||
end if;
|
||||
else
|
||||
TR_NEXT_STATE <= PARITY;
|
||||
end if;
|
||||
when STOP1 =>
|
||||
if CLK_STRB = '1' and (WS = "000" or WS = "001" or WS = "100") then
|
||||
TR_NEXT_STATE <= STOP2; -- Two 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_STRB = '1' then
|
||||
TR_NEXT_STATE <= IDLE;
|
||||
else
|
||||
TR_NEXT_STATE <= STOP2;
|
||||
end if;
|
||||
end case;
|
||||
end process TR_STATEDEC;
|
||||
end architecture BEHAVIOR;
|
||||
|
||||
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.vhd.bak
Normal file
202
FPGA_by_Fredi/FalconIO_SDCard_IDE_CF/dcfifo1.vhd.bak
Normal file
@@ -0,0 +1,202 @@
|
||||
-- megafunction wizard: %LPM_FIFO+%
|
||||
-- GENERATION: STANDARD
|
||||
-- VERSION: WM1.0
|
||||
-- MODULE: dcfifo_mixed_widths
|
||||
|
||||
-- ============================================================
|
||||
-- File Name: dcfifo1.vhd
|
||||
-- Megafunction Name(s):
|
||||
-- dcfifo_mixed_widths
|
||||
--
|
||||
-- Simulation Library Files(s):
|
||||
-- altera_mf
|
||||
-- ============================================================
|
||||
-- ************************************************************
|
||||
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
--
|
||||
-- 9.1 Build 222 10/21/2009 SJ Web Edition
|
||||
-- ************************************************************
|
||||
|
||||
|
||||
--Copyright (C) 1991-2009 Altera Corporation
|
||||
--Your use of Altera Corporation's design tools, logic functions
|
||||
--and other software and tools, and its AMPP partner logic
|
||||
--functions, and any output files from any of the foregoing
|
||||
--(including device programming or simulation files), and any
|
||||
--associated documentation or information are expressly subject
|
||||
--to the terms and conditions of the Altera Program License
|
||||
--Subscription Agreement, Altera MegaCore Function License
|
||||
--Agreement, or other applicable license agreement, including,
|
||||
--without limitation, that your use is for the sole purpose of
|
||||
--programming logic devices manufactured by Altera and sold by
|
||||
--Altera or its authorized distributors. Please refer to the
|
||||
--applicable agreement for further details.
|
||||
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.all;
|
||||
|
||||
ENTITY dcfifo1 IS
|
||||
PORT
|
||||
(
|
||||
aclr : IN STD_LOGIC := '0';
|
||||
data : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
|
||||
rdclk : IN STD_LOGIC ;
|
||||
rdreq : IN STD_LOGIC ;
|
||||
wrclk : IN STD_LOGIC ;
|
||||
wrreq : IN STD_LOGIC ;
|
||||
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
|
||||
wrusedw : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
|
||||
);
|
||||
END dcfifo1;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dcfifo1 IS
|
||||
|
||||
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0);
|
||||
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (7 DOWNTO 0);
|
||||
|
||||
|
||||
|
||||
COMPONENT dcfifo_mixed_widths
|
||||
GENERIC (
|
||||
intended_device_family : STRING;
|
||||
lpm_numwords : NATURAL;
|
||||
lpm_showahead : STRING;
|
||||
lpm_type : STRING;
|
||||
lpm_width : NATURAL;
|
||||
lpm_widthu : NATURAL;
|
||||
lpm_widthu_r : NATURAL;
|
||||
lpm_width_r : NATURAL;
|
||||
overflow_checking : STRING;
|
||||
rdsync_delaypipe : NATURAL;
|
||||
underflow_checking : STRING;
|
||||
use_eab : STRING;
|
||||
write_aclr_synch : STRING;
|
||||
wrsync_delaypipe : NATURAL
|
||||
);
|
||||
PORT (
|
||||
wrclk : IN STD_LOGIC ;
|
||||
rdreq : IN STD_LOGIC ;
|
||||
wrusedw : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
|
||||
aclr : IN STD_LOGIC ;
|
||||
rdclk : IN STD_LOGIC ;
|
||||
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
|
||||
wrreq : IN STD_LOGIC ;
|
||||
data : IN STD_LOGIC_VECTOR (15 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
BEGIN
|
||||
wrusedw <= sub_wire0(3 DOWNTO 0);
|
||||
q <= sub_wire1(7 DOWNTO 0);
|
||||
|
||||
dcfifo_mixed_widths_component : dcfifo_mixed_widths
|
||||
GENERIC MAP (
|
||||
intended_device_family => "Cyclone III",
|
||||
lpm_numwords => 16,
|
||||
lpm_showahead => "OFF",
|
||||
lpm_type => "dcfifo",
|
||||
lpm_width => 16,
|
||||
lpm_widthu => 4,
|
||||
lpm_widthu_r => 5,
|
||||
lpm_width_r => 8,
|
||||
overflow_checking => "ON",
|
||||
rdsync_delaypipe => 5,
|
||||
underflow_checking => "ON",
|
||||
use_eab => "ON",
|
||||
write_aclr_synch => "OFF",
|
||||
wrsync_delaypipe => 5
|
||||
)
|
||||
PORT MAP (
|
||||
wrclk => wrclk,
|
||||
rdreq => rdreq,
|
||||
aclr => aclr,
|
||||
rdclk => rdclk,
|
||||
wrreq => wrreq,
|
||||
data => data,
|
||||
wrusedw => sub_wire0,
|
||||
q => sub_wire1
|
||||
);
|
||||
|
||||
|
||||
|
||||
END SYN;
|
||||
|
||||
-- ============================================================
|
||||
-- CNX file retrieval info
|
||||
-- ============================================================
|
||||
-- Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
|
||||
-- Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
|
||||
-- Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: Clock NUMERIC "4"
|
||||
-- Retrieval info: PRIVATE: Depth NUMERIC "16"
|
||||
-- Retrieval info: PRIVATE: Empty NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: Full NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
-- Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: Optimize NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
-- Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: UsedW NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: Width NUMERIC "16"
|
||||
-- Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: diff_widths NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: output_width NUMERIC "8"
|
||||
-- Retrieval info: PRIVATE: rsEmpty NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: rsFull NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: wsFull NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: wsUsedW NUMERIC "1"
|
||||
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
-- Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "16"
|
||||
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
|
||||
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
|
||||
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"
|
||||
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "4"
|
||||
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "5"
|
||||
-- Retrieval info: CONSTANT: LPM_WIDTH_R NUMERIC "8"
|
||||
-- Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
|
||||
-- Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "5"
|
||||
-- Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
|
||||
-- Retrieval info: CONSTANT: USE_EAB STRING "ON"
|
||||
-- Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
|
||||
-- Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "5"
|
||||
-- Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr
|
||||
-- Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]
|
||||
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
|
||||
-- Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk
|
||||
-- Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
|
||||
-- Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk
|
||||
-- Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
|
||||
-- Retrieval info: USED_PORT: wrusedw 0 0 4 0 OUTPUT NODEFVAL wrusedw[3..0]
|
||||
-- Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0
|
||||
-- Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
|
||||
-- Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
|
||||
-- Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
|
||||
-- Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
|
||||
-- Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
|
||||
-- Retrieval info: CONNECT: wrusedw 0 0 4 0 @wrusedw 0 0 4 0
|
||||
-- Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
|
||||
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.vhd TRUE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.inc FALSE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.cmp TRUE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1.bsf TRUE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_inst.vhd FALSE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_waveforms.html FALSE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo1_wave*.jpg FALSE
|
||||
-- Retrieval info: LIB_FILE: altera_mf
|
||||
Reference in New Issue
Block a user