Sync with Fredi's source tree 18/04/2017

Blitter work.
This commit is contained in:
David Gálvez
2018-04-09 17:23:44 +02:00
parent b2d17efff1
commit 343ede8328
55 changed files with 2659 additions and 4429 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View 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