This commit is contained in:
aschi54
2010-12-27 13:20:36 +00:00
commit 1b6b1201a2
427 changed files with 91737 additions and 0 deletions

View File

@@ -0,0 +1,971 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 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.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Tue Sep 08 16:24:20 2009
library work;
use work.FalconIO_SDCard_IDE_CF_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
-- Entity Declaration
-- Entity Declaration
ENTITY FalconIO_SDCard_IDE_CF IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
CLK33M : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
CLK2M : IN STD_LOGIC;
CLK500k : IN STD_LOGIC;
nFB_CS1 : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
nFB_BURST : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
LP_BUSY : IN STD_LOGIC;
nACSI_DRQ : IN STD_LOGIC;
nACSI_INT : IN STD_LOGIC;
nSCSI_DRQ : IN STD_LOGIC;
nSCSI_MSG : IN STD_LOGIC;
MIDI_IN : IN STD_LOGIC;
RxD : IN STD_LOGIC;
CTS : IN STD_LOGIC;
RI : IN STD_LOGIC;
DCD : IN STD_LOGIC;
AMKB_RX : IN STD_LOGIC;
PIC_AMKB_RX : IN STD_LOGIC;
IDE_RDY : IN STD_LOGIC;
IDE_INT : IN STD_LOGIC;
WP_CS_CARD : IN STD_LOGIC;
nINDEX : IN STD_LOGIC;
TRACK00 : IN STD_LOGIC;
nRD_DATA : IN STD_LOGIC;
nDCHG : IN STD_LOGIC;
SD_DATA0 : IN STD_LOGIC;
SD_DATA1 : IN STD_LOGIC;
SD_DATA2 : IN STD_LOGIC;
SD_CARD_DEDECT : IN STD_LOGIC;
SD_WP : IN STD_LOGIC;
nDACK0 : IN STD_LOGIC;
nFB_WR : INOUT STD_LOGIC;
WP_CF_CARD : IN STD_LOGIC;
nWP : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
nRSTO : IN STD_LOGIC;
HD_DD : IN STD_LOGIC;
nSCSI_C_D : IN STD_LOGIC;
nSCSI_I_O : IN STD_LOGIC;
CLK2M4576 : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
VSYNC : IN STD_LOGIC;
HSYNC : IN STD_LOGIC;
DSP_INT : IN STD_LOGIC;
nBLANK : IN STD_LOGIC;
FDC_CLK : IN STD_LOGIC;
FB_ALE : IN STD_LOGIC;
ACP_CONF : IN STD_LOGIC_VECTOR(31 downto 24);
nIDE_CS1 : OUT STD_LOGIC;
nIDE_CS0 : OUT STD_LOGIC;
LP_STR : OUT STD_LOGIC;
LP_DIR : OUT STD_LOGIC;
nACSI_ACK : OUT STD_LOGIC;
nACSI_RESET : OUT STD_LOGIC;
nACSI_CS : OUT STD_LOGIC;
ACSI_DIR : OUT STD_LOGIC;
ACSI_A1 : OUT STD_LOGIC;
nSCSI_ACK : OUT STD_LOGIC;
nSCSI_ATN : OUT STD_LOGIC;
SCSI_DIR : OUT STD_LOGIC;
SD_CLK : OUT STD_LOGIC;
YM_QA : OUT STD_LOGIC;
YM_QC : OUT STD_LOGIC;
YM_QB : OUT STD_LOGIC;
nSDSEL : OUT STD_LOGIC;
STEP : OUT STD_LOGIC;
MOT_ON : OUT STD_LOGIC;
nRP_LDS : OUT STD_LOGIC;
nRP_UDS : OUT STD_LOGIC;
nROM4 : OUT STD_LOGIC;
nROM3 : OUT STD_LOGIC;
nCF_CS1 : OUT STD_LOGIC;
nCF_CS0 : OUT STD_LOGIC;
nIDE_RD : INOUT STD_LOGIC;
nIDE_WR : INOUT STD_LOGIC;
AMKB_TX : OUT STD_LOGIC;
IDE_RES : OUT STD_LOGIC;
DTR : OUT STD_LOGIC;
RTS : OUT STD_LOGIC;
TxD : OUT STD_LOGIC;
MIDI_OLR : OUT STD_LOGIC;
MIDI_TLR : OUT STD_LOGIC;
nDREQ0 : OUT STD_LOGIC;
DSA_D : OUT STD_LOGIC;
nMFP_INT : OUT STD_LOGIC;
FALCON_IO_TA : OUT STD_LOGIC;
STEP_DIR : OUT STD_LOGIC;
WR_DATA : OUT STD_LOGIC;
WR_GATE : OUT STD_LOGIC;
DMA_DRQ : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
LP_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
ACSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_PAR : INOUT STD_LOGIC;
nSCSI_SEL : INOUT STD_LOGIC;
nSCSI_BUSY : INOUT STD_LOGIC;
nSCSI_RST : INOUT STD_LOGIC;
SD_CD_DATA3 : INOUT STD_LOGIC;
SD_CDM_D1 : INOUT STD_LOGIC
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END FalconIO_SDCard_IDE_CF;
-- Architecture Body
ARCHITECTURE FalconIO_SDCard_IDE_CF_architecture OF FalconIO_SDCard_IDE_CF IS
-- system
signal SYS_CLK : STD_LOGIC;
signal RESETn : STD_LOGIC;
signal FB_B0 : STD_LOGIC; -- UPPER BYT BEI 16BIT BUS
signal FB_B1 : STD_LOGIC; -- LOWER BYT BEI 16BIT BUS
signal BYT : STD_LOGIC; -- WENN BYT -> 1
signal LONG : STD_LOGIC; -- WENN -> 1
-- KEYBOARD MIDI
signal ACIA_CS_I : STD_LOGIC;
signal IRQ_KEYBDn : STD_LOGIC;
signal IRQ_MIDIn : STD_LOGIC;
signal KEYB_RxD : STD_LOGIC;
signal AMKB_REG : STD_LOGIC_VECTOR(4 downto 0);
signal MIDI_OUT : STD_LOGIC;
signal DATA_OUT_ACIA_I : STD_LOGIC_VECTOR(7 downto 0);
signal DATA_OUT_ACIA_II : STD_LOGIC_VECTOR(7 downto 0);
-- MFP
signal MFP_CS : STD_LOGIC;
signal MFP_INTACK : STD_LOGIC;
signal LDS : STD_LOGIC;
signal DTACK_OUT_MFPn : STD_LOGIC;
signal IRQ_ACIAn : STD_LOGIC;
signal DINTn : STD_LOGIC;
signal DATA_OUT_MFP : STD_LOGIC_VECTOR(7 downto 0);
signal TDO : STD_LOGIC;
-- SOUND
signal SNDCS : STD_LOGIC;
signal SNDCS_I : STD_LOGIC;
signal SNDIR_I : STD_LOGIC;
signal LP_DIR_X : STD_LOGIC;
signal DA_OUT_X : STD_LOGIC_VECTOR(7 downto 0);
signal LP_D_X : STD_LOGIC_VECTOR(7 downto 0);
-- DIV
signal SUB_BUS : STD_LOGIC; -- SUB BUS MIT ROM-PORT, CF UND IDE
signal ROM_CS : STD_LOGIC;
-- DMA UND FLOPPY
signal DMA_DATEN_CS : STD_LOGIC;
signal DMA_MODUS_CS : STD_LOGIC;
signal DMA_MODUS : STD_LOGIC_VECTOR(15 downto 0);
signal WDC_BSL_CS : STD_LOGIC;
signal WDC_BSL : STD_LOGIC_VECTOR(1 DOWNTO 0);
signal HD_DD_OUT : STD_LOGIC;
signal FDCS_In : STD_LOGIC;
signal CA0 : STD_LOGIC;
signal CA1 : STD_LOGIC;
signal CA2 : STD_LOGIC;
signal FDINT : STD_LOGIC;
signal FDRQ : STD_LOGIC;
signal CD_OUT_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal CD_IN_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_TOP_CS : STD_LOGIC;
signal DMA_TOP : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_HIGH_CS : STD_LOGIC;
signal DMA_HIGH : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_MID_CS : STD_LOGIC;
signal DMA_MID : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_LOW_CS : STD_LOGIC;
signal DMA_LOW : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_DIRM_CS : STD_LOGIC;
signal DMA_ADR_CS : STD_LOGIC;
signal DMA_STATUS : STD_LOGIC_VECTOR(2 downto 0);
signal DMA_DIR_OLD : STD_LOGIC;
signal DMA_BYT_CNT_CS : STD_LOGIC;
signal DMA_BYT_CNT : STD_LOGIC_VECTOR(31 downto 0);
signal CLR_FIFO : STD_LOGIC;
signal DMA_DRQ_I : STD_LOGIC;
signal DMA_DRQ_REG : STD_LOGIC_VECTOR(1 downto 0);
signal DMA_DRQQ : STD_LOGIC;
signal DMA_DRQ_Q : STD_LOGIC;
signal RDF_DOUT : STD_LOGIC_VECTOR(31 downto 0);
signal RDF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal RDF_RDE : STD_LOGIC;
signal RDF_WRE : STD_LOGIC;
signal RDF_DIN : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal WRF_RDE : STD_LOGIC;
signal WRF_WRE : STD_LOGIC;
signal nFDC_WR : STD_LOGIC;
type FCF_STATES is( FCF_IDLE, FCF_T0, FCF_T1, FCF_T2, FCF_T3, FCF_T6, FCF_T7);
signal FCF_STATE : FCF_STATES;
signal NEXT_FCF_STATE : FCF_STATES;
signal DMA_REQ : STD_LOGIC;
signal FDC_CS : STD_LOGIC;
signal FCF_CS : STD_LOGIC;
signal FCF_APH : STD_LOGIC;
signal DMA_AZ_CS : STD_LOGIC;
signal DMA_ACTIV : STD_LOGIC;
signal DMA_ACTIV_NEW : STD_LOGIC;
signal FDC_OUT : STD_LOGIC_VECTOR(7 downto 0);
-- SCSI
signal SCSI_CS : STD_LOGIC;
signal SCSI_CSn : STD_LOGIC;
signal SCSI_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal nSCSI_DACK : STD_LOGIC;
signal SCSI_DRQ : STD_LOGIC;
signal SCSI_INT : STD_LOGIC;
signal DB_OUTn : STD_LOGIC_VECTOR(7 downto 0);
signal DB_EN : STD_LOGIC;
signal DBP_OUTn : STD_LOGIC;
signal DBP_EN : STD_LOGIC;
signal RST_OUTn : STD_LOGIC;
signal RST_EN : STD_LOGIC;
signal BSY_OUTn : STD_LOGIC;
signal BSY_EN : STD_LOGIC;
signal SEL_OUTn : STD_LOGIC;
signal SEL_EN : STD_LOGIC;
-- IDE
signal nnIDE_RES : STD_LOGIC;
signal IDE_CF_CS : STD_LOGIC;
signal IDE_CF_TA : STD_LOGIC;
signal NEXT_nIDE_RD : STD_LOGIC;
signal NEXT_nIDE_WR : STD_LOGIC;
type CMD_STATES is( IDLE, T1, T6, T7);
signal CMD_STATE : CMD_STATES;
signal NEXT_CMD_STATE : CMD_STATES;
BEGIN
LONG <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '0' else '0';
BYT <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
FB_B0 <= '1' when FB_ADR(0) = '0' or BYT = '0' else '0';
FB_B1 <= '1' when FB_ADR(0) = '1' or BYT = '0' else '0';
FALCON_IO_TA <= '1' when SNDCS = '1' or DTACK_OUT_MFPn = '0' or ACIA_CS_I = '1' or DMA_MODUS_CS ='1'
or DMA_ADR_CS = '1' or DMA_DIRM_CS = '1' or DMA_BYT_CNT_CS = '1' or FCF_CS = '1' or IDE_CF_TA = '1' else '0';
SUB_BUS <= '1' when nFB_WR = '1' and ROM_CS = '1' ELSE
'1' when nFB_WR = '1' and IDE_CF_CS = '1' ELSE
'1' when nFB_WR = '0' and nIDE_WR = '0' ELSE '0';
nRP_UDS <= '0' when SUB_BUS = '1' and FB_B0 = '1' else '1';
nRP_LDS <= '0' when SUB_BUS = '1' and FB_B1 = '1' else '1';
nDREQ0 <= '0';
----------------------------------------------------------------------------
-- SD
----------------------------------------------------------------------------
SD_CLK <= 'Z';
SD_CD_DATA3 <= 'Z';
SD_CDM_D1 <= 'Z';
----------------------------------------------------------------------------
-- IDE
----------------------------------------------------------------------------
CMD_REG: process(nRSTO, MAIN_CLK, CMD_STATE, NEXT_CMD_STATE)
begin
if nRSTO = '0' then
CMD_STATE <= IDLE;
elsif rising_edge(MAIN_CLK) then
CMD_STATE <= NEXT_CMD_STATE; -- go to next
nIDE_RD <= NEXT_nIDE_RD; -- go to next
nIDE_WR <= NEXT_nIDE_WR; -- go to next
else
CMD_STATE <= CMD_STATE; -- halten
nIDE_RD <= nIDE_RD; -- halten
nIDE_WR <= nIDE_WR; -- halten
end if;
end process CMD_REG;
CMD_DECODER: process(CMD_STATE, NEXT_CMD_STATE, NEXT_nIDE_RD, NEXT_nIDE_WR, IDE_RDY, IDE_CF_TA)
begin
case CMD_STATE is
when IDLE =>
IDE_CF_TA <= '0';
if IDE_CF_CS = '1' then
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T1;
else
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end if;
when T1 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
when T6 =>
IF IDE_RDY = '1' then
IDE_CF_TA <= '1';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= T7;
else
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
end if;
when T7 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end case;
end process CMD_DECODER;
IDE_RES <= not nnIDE_RES and nRSTO;
IDE_CF_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 7) = x"0" else '0'; -- FFF0'0000/80
nCF_CS0 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"0" else -- FFFO'0000-FFF0'001F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"2" else '1'; -- FFFO'0040-FFF0'005F
nCF_CS1 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"1" else -- FFF0'0020-FFF0'003F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"3" else '1'; -- FFFO'0060-FFF0'007F
nIDE_CS0 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"2" else -- FFF0'0040-FFF0'005F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"0" else '1'; -- FFFO'0000-FFF0'001F
nIDE_CS1 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"3" else -- FFF0'0060-FFF0'007F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"1" else '1'; -- FFFO'0020-FFF0'003F
-----------------------------------------------------------------------------------------------------------------------------------------
-- ACSI, SCSI UND FLOPPY WD1772
-------------------------------------------------------------------------------------------------------------------------------------------
-- daten read fifo
RDF: dcfifo0
port map(
aclr => CLR_FIFO,
data => RDF_DIN,
rdclk => MAIN_CLK,
rdreq => RDF_RDE,
wrclk => FDC_CLK,
wrreq => RDF_WRE,
q => RDF_DOUT,
wrusedw => RDF_AZ
);
FCF_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"0020110" and LONG = '1' else '0'; -- F002'0110 LONG ONLY
FCF_APH <= '1' when FB_ALE = '1' and FB_AD(31 downto 0) = x"F0020110" and LONG = '1' else '0'; -- ADRESSPHASE F0020110 LONG ONLY
RDF_RDE <= '1' when FCF_APH = '1' and nFB_WR = '1' else '0'; -- AKTIVIEREN IN ADRESSPHASE
FB_AD <= RDF_DOUT(7 downto 0) & RDF_DOUT(15 downto 8) & RDF_DOUT(23 downto 16) & RDF_DOUT(31 downto 24) when FCF_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
RDF_DIN <= CD_OUT_FDC when DMA_MODUS(7) = '1' else SCSI_DOUT;
-- daten write fifo
WRF: dcfifo1
port map(
aclr => CLR_FIFO,
data => FB_AD(7 downto 0) & FB_AD(15 downto 8) & FB_AD(23 downto 16) & FB_AD(31 downto 24),
rdclk => FDC_CLK,
rdreq => WRF_RDE,
wrclk => MAIN_CLK,
wrreq => WRF_WRE,
q => WRF_DOUT,
rdusedw => WRF_AZ
);
CD_IN_FDC <= WRF_DOUT when DMA_ACTIV = '1' and DMA_MODUS(8) = '1' else FB_AD(23 downto 16); -- BEI DMA WRITE <-FIFO SONST <-FB
DMA_AZ_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"002010C" else '0'; -- F002'010C LONG
FB_AD <= DMA_DRQ_Q & DMA_DRQ_REG & IDE_INT & FDINT & SCSI_INT & RDF_AZ & "0" & DMA_STATUS & "00" & WRF_AZ when DMA_AZ_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
DMA_DRQ_Q <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- FIFO WRITE: GENAU 1 MAIN_CLK -------------------------------------------------------------------------
process(MAIN_CLK, nRSTO, WRF_WRE, nFB_WR, FCF_APH)
begin
if nRSTO = '0' THEN
WRF_WRE <= '0';
elsif rising_edge(MAIN_CLK) then
IF FCF_APH = '1' and nFB_WR = '0' then
WRF_WRE <= '1';
else
WRF_WRE <= '0';
end if;
else
WRF_WRE <= WRF_WRE;
end if;
END PROCESS;
FCF_REG: process(nRSTO, FDC_CLK, FCF_STATE, NEXT_FCF_STATE, DMA_ACTIV)
begin
if nRSTO = '0' then
FCF_STATE <= FCF_IDLE;
DMA_ACTIV <= '0';
elsif rising_edge(FDC_CLK) then
FCF_STATE <= NEXT_FCF_STATE; -- go to next
DMA_ACTIV <= DMA_ACTIV_NEW;
else
FCF_STATE <= FCF_STATE; -- halten
DMA_ACTIV <= DMA_ACTIV;
end if;
end process FCF_REG;
FDC_REG: process(nRSTO, FDC_CLK, FDC_OUT, FDCS_In, CD_OUT_FDC)
begin
if nRSTO = '0' then
FDC_OUT <= x"00";
elsif rising_edge(FDC_CLK) and FDCS_In = '0' then
FDC_OUT <= CD_OUT_FDC; -- set
else
FDC_OUT <= FDC_OUT; -- halten
end if;
end process FDC_REG;
DMA_REQ <= '1' when ((DMA_DRQ_I = '1' and DMA_MODUS(7) = '1') or (SCSI_DRQ = '1' and DMA_MODUS(7) = '0')) and DMA_STATUS(1) = '1' and DMA_MODUS(6) = '0' and CLR_FIFO = '0' else '0';
FDC_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and FB_B1 = '1' else '0';
SCSI_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and FB_B1 = '1' else '0';
FCF_DECODER: process(FCF_STATE, NEXT_FCF_STATE, DMA_REQ,FDC_CS, RDF_WRE, WRF_RDE, SCSI_DRQ, nSCSI_DACK, DMA_MODUS, DMA_ACTIV, FDCS_In,SCSI_CS, SCSI_CSn)
begin
case FCF_STATE is
when FCF_IDLE =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
if DMA_REQ = '1' or FDC_CS = '1' or SCSI_CS = '1' then
DMA_ACTIV_NEW <= DMA_REQ;
NEXT_FCF_STATE <= FCF_T0;
else
DMA_ACTIV_NEW <= '0';
NEXT_FCF_STATE <= FCF_IDLE;
end if;
when FCF_T0 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= DMA_REQ;
WRF_RDE <= DMA_MODUS(8) and DMA_REQ; -- WRITE -> READ FROM FIFO
if DMA_REQ = '0' and DMA_ACTIV = '1' THEN -- spike?
NEXT_FCF_STATE <= FCF_IDLE; -- ja -> zum start
else
NEXT_FCF_STATE <= FCF_T1;
end if;
when FCF_T1 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T2;
when FCF_T2 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T3;
when FCF_T3 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T6;
when FCF_T6 =>
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
RDF_WRE <= not DMA_MODUS(8) and DMA_ACTIV; -- READ -> WRITE IN FIFO
NEXT_FCF_STATE <= FCF_T7;
when FCF_T7 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= '0';
if FDC_CS = '1' and DMA_REQ = '0' then
NEXT_FCF_STATE <= FCF_T7;
else
NEXT_FCF_STATE <= FCF_IDLE;
end if;
end case;
end process FCF_DECODER;
I_FDC: WF1772IP_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
CSn => FDCS_In,
RWn => nFDC_WR,
A1 => CA2,
A0 => CA1,
DATA_IN => CD_IN_FDC,
DATA_OUT => CD_OUT_FDC,
-- DATA_EN => CD_EN_FDC,
RDn => nRD_DATA,
TR00n => TRACK00,
IPn => nINDEX,
WPRTn => nWP,
DDEn => '0', -- Fixed to MFM.
HDTYPE => HD_DD_OUT,
MO => MOT_ON,
WG => WR_GATE,
WD => WR_DATA,
STEP => STEP,
DIRC => STEP_DIR,
DRQ => DMA_DRQ_I,
INTRQ => FDINT
);
DMA_DATEN_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C302" else '0'; -- F8604/2
DMA_MODUS_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C303" else '0'; -- F8606/2
WDC_BSL_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C307" else '0'; -- F860E/2
HD_DD_OUT <= HD_DD WHEN ACP_CONF(29) = '0' ELSE WDC_BSL(0);
nFDC_WR <= (not DMA_MODUS(8)) when DMA_ACTIV = '1' else nFB_WR;
CA0 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(0);
CA1 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(1);
CA2 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(2);
FB_AD(23 downto 16) <= "0000" & (not DMA_STATUS(1)) & "0" & WDC_BSL(1) & HD_DD when WDC_BSL_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 24) <= "00000000" when DMA_DATEN_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= FDC_OUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and nFB_OE = '0' else
SCSI_DOUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and nFB_OE = '0' else
DMA_BYT_CNT(16 downto 9) when DMA_DATEN_CS = '1' and DMA_MODUS(4) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
--- WDC BSL REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, WDC_BSL_CS, WDC_BSL, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
WDC_BSL <= "00";
elsif rising_edge(MAIN_CLK) and WDC_BSL_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
WDC_BSL(1 DOWNTO 0) <= FB_AD(25 DOWNTO 24);
else
WDC_BSL(1 DOWNTO 0) <= WDC_BSL(1 DOWNTO 0);
end if;
end if;
END PROCESS;
--- DMA MODUS REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
DMA_MODUS <= x"0000";
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
DMA_MODUS(15 downto 8) <= FB_AD(31 downto 24);
else
DMA_MODUS(15 downto 8) <= DMA_MODUS(15 downto 8);
end if;
IF FB_B1 = '1' THEN
DMA_MODUS(7 downto 0) <= FB_AD(23 downto 16);
else
DMA_MODUS(7 downto 0) <= DMA_MODUS(7 downto 0);
end if;
else
DMA_MODUS <= DMA_MODUS;
end if;
END PROCESS;
-- BYT COUNTER, SECTOR COUNTER ----------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_DATEN_CS, DMA_BYT_CNT_CS, DMA_BYT_CNT, nFB_WR, FB_B0, FB_B1, DMA_MODUS, CLR_FIFO)
begin
if nRSTO = '0' or CLR_FIFO = '1' THEN
DMA_BYT_CNT <= x"00000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_DATEN_CS = '1' and nFB_WR = '0' and DMA_MODUS(4) = '1' and FB_B1 = '1' then
DMA_BYT_CNT(31 downto 17) <= "000000000000000";
DMA_BYT_CNT(16 downto 9) <= FB_AD(23 downto 16);
DMA_BYT_CNT(8 downto 0) <= "000000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_BYT_CNT_CS = '1' then
DMA_BYT_CNT <= FB_AD;
else
DMA_BYT_CNT <= DMA_BYT_CNT;
end if;
END PROCESS;
--------------------------------------------------------------------
FB_AD(31 downto 16) <= "0000000000000" & DMA_STATUS when DMA_MODUS_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
DMA_STATUS(0) <= '1'; -- DMA OK
DMA_STATUS(1) <= '1' when DMA_BYT_CNT /= 0 and DMA_BYT_CNT(31) = '0' else '0'; -- WENN byts UND NICHT MINUS
DMA_STATUS(2) <= '0' when DMA_DRQ_I = '1' or SCSI_DRQ = '1' else '0';
DMA_DRQQ <= '1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '0' and RDF_AZ > 15 and DMA_MODUS(6) = '0' else
'1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '1' and WRF_AZ < 512 and DMA_MODUS(6) = '0' else '0';
DMA_DRQ <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- DMA REQUEST: SPIKES AUSFILTERN ------------------------------------------
process(FDC_CLK, nRSTO, DMA_DRQ_REG)
begin
if nRSTO = '0' THEN
DMA_DRQ_REG <= "00";
elsif rising_edge(FDC_CLK) then
DMA_DRQ_REG(0) <= DMA_DRQQ;
DMA_DRQ_REG(1) <= DMA_DRQ_REG(0) and DMA_DRQQ;
else
DMA_DRQ_REG <= DMA_DRQ_REG;
end if;
END PROCESS;
-- DMA ADRESSE ------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_TOP_CS, DMA_TOP, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_TOP <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_TOP_CS = '1' or DMA_ADR_CS = '1') then
DMA_TOP <= FB_AD(31 downto 24);
else
DMA_TOP <= DMA_TOP;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_HIGH_CS, DMA_HIGH, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_HIGH <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_HIGH_CS = '1' or DMA_ADR_CS = '1') then
DMA_HIGH <= FB_AD(23 downto 16);
else
DMA_HIGH <= DMA_HIGH;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_MID_CS, DMA_MID, nFB_WR)
begin
DMA_MID <= DMA_MID;
if nRSTO = '0' THEN
DMA_MID <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_MID_CS = '1' then
DMA_MID <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_MID <= FB_AD(15 downto 8);
end if;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_LOW_CS, DMA_LOW, nFB_WR)
begin
DMA_LOW <= DMA_LOW;
if nRSTO = '0' THEN
DMA_LOW <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_LOW_CS = '1'then
DMA_LOW <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_LOW <= FB_AD(7 downto 0);
end if;
end if;
END PROCESS;
--------------------------------------------------------------------------------------------
DMA_TOP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B0 = '1' else '0'; -- F8608/2
DMA_HIGH_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B1 = '1' else '0'; -- F8609/2
DMA_MID_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C305" and FB_B1 = '1' else '0'; -- F860B/2
DMA_LOW_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C306" and FB_B1 = '1' else '0'; -- F860D/2
FB_AD(31 downto 24) <= DMA_TOP when DMA_TOP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_HIGH when DMA_HIGH_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_MID when DMA_MID_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_LOW when DMA_LOW_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
-- DIRECTZUGRIFF
DMA_DIRM_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20100" else '0'; -- F002'0100 WORD
DMA_ADR_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20104" else '0'; -- F002'0104 LONG
DMA_BYT_CNT_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20108" else '0'; -- F002'0108 LONG
FB_AD <= DMA_TOP & DMA_HIGH & DMA_MID & DMA_LOW when DMA_ADR_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= DMA_MODUS when DMA_DIRM_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD <= DMA_BYT_CNT when DMA_BYT_CNT_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
-- DMA RW TOGGLE ------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, DMA_DIR_OLD)
begin
if nRSTO = '0' THEN
DMA_DIR_OLD <= '0';
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '0' then
DMA_DIR_OLD <= DMA_MODUS(8);
else
DMA_DIR_OLD <= DMA_DIR_OLD;
end if;
END PROCESS;
CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
-- SCSI ----------------------------------------------------------------------------------
I_SCSI: WF5380_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
ADR => CA2 & CA1 & CA0,
DATA_IN => CD_IN_FDC,
DATA_OUT => SCSI_DOUT,
--DATA_EN : out bit;
-- Bus and DMA controls:
CSn => '1', --SCSI_CSn, ABGESCHALTET
RDn => (not nFDC_WR) or (not SCSI_CS),
WRn => nFDC_WR or (not SCSI_CS),
EOPn => '1',
DACKn => nSCSI_DACK,
DRQ => SCSI_DRQ,
INT => SCSI_INT,
-- READY =>
-- SCSI bus:
DB_INn => SCSI_D,
DB_OUTn => DB_OUTn,
DB_EN => DB_EN,
DBP_INn => SCSI_PAR,
DBP_OUTn => DBP_OUTn,
DBP_EN => DBP_EN, -- wenn 1 dann output
RST_INn => nSCSI_RST,
RST_OUTn => RST_OUTn,
RST_EN => RST_EN,
BSY_INn => nSCSI_BUSY,
BSY_OUTn => BSY_OUTn,
BSY_EN => BSY_EN,
SEL_INn => nSCSI_SEL,
SEL_OUTn => SEL_OUTn,
SEL_EN => SEL_EN,
ACK_INn => '1',
ACK_OUTn => nSCSI_ACK,
-- ACK_EN => ACK_EN,
ATN_INn => '1',
ATN_OUTn => nSCSI_ATN,
-- ATN_EN => ATN_EN,
REQ_INn => nSCSI_DRQ,
-- REQ_OUTn => REQ_OUTn,
-- REQ_EN => REQ_EN,
IOn_IN => nSCSI_I_O,
-- IOn_OUT => IOn_OUT,
-- IO_EN => IO_EN,
CDn_IN => nSCSI_C_D,
-- CDn_OUT => CDn_OUT,
-- CD_EN => CD_EN,
MSG_INn => nSCSI_MSG
-- MSG_OUTn => MSG_OUTn,
-- MSG_EN => MSG_EN
);
-- SCSI ACSI ---------------------------------------------------------------
SCSI_D <= DB_OUTn when DB_EN = '1' else "ZZZZZZZZ";
SCSI_DIR <= '1'; --'0' when DB_EN = '1' else '1'; --ABGESCHALTET
SCSI_PAR <= DBP_OUTn when DBP_EN = '1' else 'Z';
nSCSI_RST <= RST_OUTn when RST_EN = '1' else 'Z';
nSCSI_BUSY <= BSY_OUTn when BSY_EN = '1' else 'Z';
nSCSI_SEL <= SEL_OUTn when SEL_EN = '1' else 'Z';
ACSI_DIR <= '0';
ACSI_D <= "ZZZZZZZZ";
nACSI_CS <= '1';
ACSI_A1 <= CA1;
nACSI_RESET <= nRSTO;
nACSI_ACK <= '1';
----------------------------------------------------------------------------
-- ROM-PORT TA KOMMT FROM DEFAULT TA = 16 BUSCYCLEN = 500ns
----------------------------------------------------------------------------
ROM_CS <= '1' when nFB_CS1 = '0' and nFB_WR = '1' and FB_ADR(19 downto 17) = x"5" else '0'; -- FFF A'0000/2'0000
nROM4 <= '0' when ROM_CS = '1' and FB_ADR(16) = '0' else '1';
nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
----------------------------------------------------------------------------
-- ACIA KEYBOARD
----------------------------------------------------------------------------
I_ACIA_KEYBOARD: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => FB_ADR(2),
CS1 => '1',
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_I,
-- DATA_EN => DATA_EN_ACIA_I,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => KEYB_RxD,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_KEYBDn,
TXDATA => AMKB_TX
--RTSn => -- Not used.
);
ACIA_CS_I <= '1' when nFB_CS1 = '0'and FB_ADR(19 downto 3) = x"1FF80" else '0'; -- FFC00-FFC07 FFC00/8
KEYB_RxD <= '1' when AMKB_REG(3) = '1' or PIC_AMKB_RX = '0' else '0'; -- TASTATUR DATEN VOM PIC(PS2) OR NORMAL
FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0' and nFB_OE = '0' else "ZZZZZZZZ";
-- AMKB_TX: SPIKES AUSFILTERN ------------------------------------------
process(CLK2M, AMKB_RX, AMKB_REG)
begin
if rising_edge(CLK2M) then
IF AMKB_RX = '0' THEN
IF AMKB_REG < 16 THEN
AMKB_REG <= "00000";
ELSE
AMKB_REG <= AMKB_REG - 1;
END IF;
ELSE
IF AMKB_REG > 15 THEN
AMKB_REG <= "11111";
ELSE
AMKB_REG <= AMKB_REG + 1;
END IF;
END IF;
ELSE
AMKB_REG <= AMKB_REG;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- ACIA MIDI
----------------------------------------------------------------------------
I_ACIA_MIDI: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => '0',
CS1 => FB_ADR(2),
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_II,
-- DATA_EN => DATA_EN_ACIA_II,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => MIDI_IN,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_MIDIn,
TXDATA => MIDI_OUT
--RTSn => -- Not used.
);
MIDI_TLR <= MIDI_OUT;
MIDI_OLR <= MIDI_OUT;
FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
----------------------------------------------------------------------------
-- MFP
----------------------------------------------------------------------------
I_MFP: WF68901IP_TOP_SOC
port map(
-- System control:
CLK => MAIN_CLK,
RESETn => nRSTO,
-- Asynchronous bus control:
DSn => not LDS,
CSn => not MFP_CS,
RWn => nFB_WR,
DTACKn => DTACK_OUT_MFPn,
-- Data and Adresses:
RS => FB_ADR(5 downto 1),
DATA_IN => FB_AD(23 downto 16),
DATA_OUT => DATA_OUT_MFP,
-- DATA_EN => DATA_EN_MFP,
GPIP_IN(7) => not DMA_DRQ_Q,
GPIP_IN(6) => not RI,
GPIP_IN(5) => DINTn,
GPIP_IN(4) => IRQ_ACIAn,
GPIP_IN(3) => DSP_INT,
GPIP_IN(2) => not CTS,
GPIP_IN(1) => not DCD,
GPIP_IN(0) => LP_BUSY,
-- GPIP_OUT =>, -- Not used; all GPIPs are direction input.
-- GPIP_EN =>, -- Not used; all GPIPs are direction input.
-- Interrupt control:
IACKn => not MFP_INTACK,
IEIn => '0',
-- IEOn =>, -- Not used.
IRQn => nMFP_INT,
-- Timers and timer control:
XTAL1 => CLK2M4576,
TAI => '0',
TBI => nBLANK,
-- TAO =>,
-- TBO =>,
-- TCO =>,
TDO => TDO,
-- Serial I/O control:
RC => TDO,
TC => TDO,
SI => RxD,
SO => TxD
-- SO_EN => MFP_SO_EN
-- DMA control:
-- RRn =>,
-- TRn =>
);
MFP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3FE8" else '0'; -- FFA00/40
MFP_INTACK <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20000" else '0'; --F002'0000
LDS <= '1' when MFP_CS = '1' or MFP_INTACK = '1' else '0';
FB_AD(23 downto 16) <= DATA_OUT_MFP when MFP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 10) <= "0000000000000000000000" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(9 downto 2) <= DATA_OUT_MFP when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(1 downto 0) <= "00" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZ";
DINTn <= '0' when IDE_INT = '1' AND ACP_CONF(28) = '1' else
'0' when FDINT = '1' else
'0' when SCSI_INT = '1' AND ACP_CONF(28) = '1' else '1';
-- TASTATUR UND KEYBOARD INTERRUPT: SPIKES AUSFILTERN ------------------------------------------
process(MAIN_CLK,nRSTO,IRQ_ACIAn,IRQ_KEYBDn,IRQ_MIDIn)
begin
if nRSTO = '0' THEN
IRQ_ACIAn <= '1';
elsif rising_edge(MAIN_CLK) then
IRQ_ACIAn <= IRQ_KEYBDn and IRQ_MIDIn;
else
IRQ_ACIAn <= IRQ_ACIAn;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- Sound
----------------------------------------------------------------------------
I_SOUND: WF2149IP_TOP_SOC
port map(
SYS_CLK => MAIN_CLK,
RESETn => nRSTO,
WAV_CLK => CLK2M,
SELn => '1',
BDIR => SNDIR_I,
BC2 => '1',
BC1 => SNDCS_I,
A9n => '0',
A8 => '1',
DA_IN => FB_AD(31 downto 24),
DA_OUT => DA_OUT_X,
IO_A_IN => x"00", -- All port pins are dedicated outputs.
IO_A_OUT(7) => nnIDE_RES,
IO_A_OUT(6) => LP_DIR_X,
IO_A_OUT(5) => LP_STR,
IO_A_OUT(4) => DTR,
IO_A_OUT(3) => RTS,
-- IO_A_OUT(2) => FDD_D1SEL,
IO_A_OUT(1) => DSA_D,
IO_A_OUT(0) => nSDSEL,
-- IO_A_EN =>, -- Not required.
IO_B_IN => LP_D,
IO_B_OUT => LP_D_X,
-- IO_B_EN => IO_B_EN,
OUT_A => YM_QA,
OUT_B => YM_QB,
OUT_C => YM_QC
);
SNDCS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 2) = x"3E200" else '0'; -- 8800-8803 F8800/4
SNDCS_I <= '1' when SNDCS = '1' and FB_ADR (1 downto 1) = "0" else '0';
SNDIR_I <= '1' when SNDCS = '1' and nFB_WR = '0' else '0';
FB_AD(31 downto 24) <= DA_OUT_X when SNDCS_I = '1' and nFB_OE = '0' else "ZZZZZZZZ";
LP_D <= LP_D_X when LP_DIR_X = '0' else "ZZZZZZZZ";
LP_DIR <= LP_DIR_X;
END FalconIO_SDCard_IDE_CF_architecture;

View File

@@ -0,0 +1,971 @@
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2008 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.
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
-- Created on Tue Sep 08 16:24:20 2009
library work;
use work.FalconIO_SDCard_IDE_CF_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
-- Entity Declaration
-- Entity Declaration
ENTITY FalconIO_SDCard_IDE_CF IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
CLK33M : IN STD_LOGIC;
MAIN_CLK : IN STD_LOGIC;
CLK2M : IN STD_LOGIC;
CLK500k : IN STD_LOGIC;
nFB_CS1 : IN STD_LOGIC;
FB_SIZE0 : IN STD_LOGIC;
FB_SIZE1 : IN STD_LOGIC;
nFB_BURST : IN STD_LOGIC;
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
LP_BUSY : IN STD_LOGIC;
nACSI_DRQ : IN STD_LOGIC;
nACSI_INT : IN STD_LOGIC;
nSCSI_DRQ : IN STD_LOGIC;
nSCSI_MSG : IN STD_LOGIC;
MIDI_IN : IN STD_LOGIC;
RxD : IN STD_LOGIC;
CTS : IN STD_LOGIC;
RI : IN STD_LOGIC;
DCD : IN STD_LOGIC;
AMKB_RX : IN STD_LOGIC;
PIC_AMKB_RX : IN STD_LOGIC;
IDE_RDY : IN STD_LOGIC;
IDE_INT : IN STD_LOGIC;
WP_CS_CARD : IN STD_LOGIC;
nINDEX : IN STD_LOGIC;
TRACK00 : IN STD_LOGIC;
nRD_DATA : IN STD_LOGIC;
nDCHG : IN STD_LOGIC;
SD_DATA0 : IN STD_LOGIC;
SD_DATA1 : IN STD_LOGIC;
SD_DATA2 : IN STD_LOGIC;
SD_CARD_DEDECT : IN STD_LOGIC;
SD_WP : IN STD_LOGIC;
nDACK0 : IN STD_LOGIC;
nFB_WR : INOUT STD_LOGIC;
WP_CF_CARD : IN STD_LOGIC;
nWP : IN STD_LOGIC;
nFB_CS2 : IN STD_LOGIC;
nRSTO : IN STD_LOGIC;
HD_DD : IN STD_LOGIC;
nSCSI_C_D : IN STD_LOGIC;
nSCSI_I_O : IN STD_LOGIC;
CLK2M4576 : IN STD_LOGIC;
nFB_OE : IN STD_LOGIC;
VSYNC : IN STD_LOGIC;
HSYNC : IN STD_LOGIC;
DSP_INT : IN STD_LOGIC;
nBLANK : IN STD_LOGIC;
FDC_CLK : IN STD_LOGIC;
FB_ALE : IN STD_LOGIC;
ACP_CONF : IN STD_LOGIC_VECTOR(31 downto 24);
nIDE_CS1 : OUT STD_LOGIC;
nIDE_CS0 : OUT STD_LOGIC;
LP_STR : OUT STD_LOGIC;
LP_DIR : OUT STD_LOGIC;
nACSI_ACK : OUT STD_LOGIC;
nACSI_RESET : OUT STD_LOGIC;
nACSI_CS : OUT STD_LOGIC;
ACSI_DIR : OUT STD_LOGIC;
ACSI_A1 : OUT STD_LOGIC;
nSCSI_ACK : OUT STD_LOGIC;
nSCSI_ATN : OUT STD_LOGIC;
SCSI_DIR : OUT STD_LOGIC;
SD_CLK : OUT STD_LOGIC;
YM_QA : OUT STD_LOGIC;
YM_QC : OUT STD_LOGIC;
YM_QB : OUT STD_LOGIC;
nSDSEL : OUT STD_LOGIC;
STEP : OUT STD_LOGIC;
MOT_ON : OUT STD_LOGIC;
nRP_LDS : OUT STD_LOGIC;
nRP_UDS : OUT STD_LOGIC;
nROM4 : OUT STD_LOGIC;
nROM3 : OUT STD_LOGIC;
nCF_CS1 : OUT STD_LOGIC;
nCF_CS0 : OUT STD_LOGIC;
nIDE_RD : INOUT STD_LOGIC;
nIDE_WR : INOUT STD_LOGIC;
AMKB_TX : OUT STD_LOGIC;
IDE_RES : OUT STD_LOGIC;
DTR : OUT STD_LOGIC;
RTS : OUT STD_LOGIC;
TxD : OUT STD_LOGIC;
MIDI_OLR : OUT STD_LOGIC;
MIDI_TLR : OUT STD_LOGIC;
nDREQ0 : OUT STD_LOGIC;
DSA_D : OUT STD_LOGIC;
nMFP_INT : OUT STD_LOGIC;
FALCON_IO_TA : OUT STD_LOGIC;
STEP_DIR : OUT STD_LOGIC;
WR_DATA : OUT STD_LOGIC;
WR_GATE : OUT STD_LOGIC;
DMA_DRQ : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
LP_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
ACSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SCSI_PAR : INOUT STD_LOGIC;
nSCSI_SEL : INOUT STD_LOGIC;
nSCSI_BUSY : INOUT STD_LOGIC;
nSCSI_RST : INOUT STD_LOGIC;
SD_CD_DATA3 : INOUT STD_LOGIC;
SD_CDM_D1 : INOUT STD_LOGIC
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END FalconIO_SDCard_IDE_CF;
-- Architecture Body
ARCHITECTURE FalconIO_SDCard_IDE_CF_architecture OF FalconIO_SDCard_IDE_CF IS
-- system
signal SYS_CLK : STD_LOGIC;
signal RESETn : STD_LOGIC;
signal FB_B0 : STD_LOGIC; -- UPPER BYT BEI 16BIT BUS
signal FB_B1 : STD_LOGIC; -- LOWER BYT BEI 16BIT BUS
signal BYT : STD_LOGIC; -- WENN BYT -> 1
signal LONG : STD_LOGIC; -- WENN -> 1
-- KEYBOARD MIDI
signal ACIA_CS_I : STD_LOGIC;
signal IRQ_KEYBDn : STD_LOGIC;
signal IRQ_MIDIn : STD_LOGIC;
signal KEYB_RxD : STD_LOGIC;
signal AMKB_REG : STD_LOGIC_VECTOR(4 downto 0);
signal MIDI_OUT : STD_LOGIC;
signal DATA_OUT_ACIA_I : STD_LOGIC_VECTOR(7 downto 0);
signal DATA_OUT_ACIA_II : STD_LOGIC_VECTOR(7 downto 0);
-- MFP
signal MFP_CS : STD_LOGIC;
signal MFP_INTACK : STD_LOGIC;
signal LDS : STD_LOGIC;
signal DTACK_OUT_MFPn : STD_LOGIC;
signal IRQ_ACIAn : STD_LOGIC;
signal DINTn : STD_LOGIC;
signal DATA_OUT_MFP : STD_LOGIC_VECTOR(7 downto 0);
signal TDO : STD_LOGIC;
-- SOUND
signal SNDCS : STD_LOGIC;
signal SNDCS_I : STD_LOGIC;
signal SNDIR_I : STD_LOGIC;
signal LP_DIR_X : STD_LOGIC;
signal DA_OUT_X : STD_LOGIC_VECTOR(7 downto 0);
signal LP_D_X : STD_LOGIC_VECTOR(7 downto 0);
-- DIV
signal SUB_BUS : STD_LOGIC; -- SUB BUS MIT ROM-PORT, CF UND IDE
signal ROM_CS : STD_LOGIC;
-- DMA UND FLOPPY
signal DMA_DATEN_CS : STD_LOGIC;
signal DMA_MODUS_CS : STD_LOGIC;
signal DMA_MODUS : STD_LOGIC_VECTOR(15 downto 0);
signal WDC_BSL_CS : STD_LOGIC;
signal WDC_BSL : STD_LOGIC_VECTOR(1 DOWNTO 0);
signal HD_DD_OUT : STD_LOGIC;
signal FDCS_In : STD_LOGIC;
signal CA0 : STD_LOGIC;
signal CA1 : STD_LOGIC;
signal CA2 : STD_LOGIC;
signal FDINT : STD_LOGIC;
signal FDRQ : STD_LOGIC;
signal CD_OUT_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal CD_IN_FDC : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_TOP_CS : STD_LOGIC;
signal DMA_TOP : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_HIGH_CS : STD_LOGIC;
signal DMA_HIGH : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_MID_CS : STD_LOGIC;
signal DMA_MID : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_LOW_CS : STD_LOGIC;
signal DMA_LOW : STD_LOGIC_VECTOR(7 downto 0);
signal DMA_DIRM_CS : STD_LOGIC;
signal DMA_ADR_CS : STD_LOGIC;
signal DMA_STATUS : STD_LOGIC_VECTOR(2 downto 0);
signal DMA_DIR_OLD : STD_LOGIC;
signal DMA_BYT_CNT_CS : STD_LOGIC;
signal DMA_BYT_CNT : STD_LOGIC_VECTOR(31 downto 0);
signal CLR_FIFO : STD_LOGIC;
signal DMA_DRQ_I : STD_LOGIC;
signal DMA_DRQ_REG : STD_LOGIC_VECTOR(1 downto 0);
signal DMA_DRQQ : STD_LOGIC;
signal DMA_DRQ_Q : STD_LOGIC;
signal RDF_DOUT : STD_LOGIC_VECTOR(31 downto 0);
signal RDF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal RDF_RDE : STD_LOGIC;
signal RDF_WRE : STD_LOGIC;
signal RDF_DIN : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal WRF_AZ : STD_LOGIC_VECTOR(9 downto 0);
signal WRF_RDE : STD_LOGIC;
signal WRF_WRE : STD_LOGIC;
signal nFDC_WR : STD_LOGIC;
type FCF_STATES is( FCF_IDLE, FCF_T0, FCF_T1, FCF_T2, FCF_T3, FCF_T6, FCF_T7);
signal FCF_STATE : FCF_STATES;
signal NEXT_FCF_STATE : FCF_STATES;
signal DMA_REQ : STD_LOGIC;
signal FDC_CS : STD_LOGIC;
signal FCF_CS : STD_LOGIC;
signal FCF_APH : STD_LOGIC;
signal DMA_AZ_CS : STD_LOGIC;
signal DMA_ACTIV : STD_LOGIC;
signal DMA_ACTIV_NEW : STD_LOGIC;
signal FDC_OUT : STD_LOGIC_VECTOR(7 downto 0);
-- SCSI
signal SCSI_CS : STD_LOGIC;
signal SCSI_CSn : STD_LOGIC;
signal SCSI_DOUT : STD_LOGIC_VECTOR(7 downto 0);
signal nSCSI_DACK : STD_LOGIC;
signal SCSI_DRQ : STD_LOGIC;
signal SCSI_INT : STD_LOGIC;
signal DB_OUTn : STD_LOGIC_VECTOR(7 downto 0);
signal DB_EN : STD_LOGIC;
signal DBP_OUTn : STD_LOGIC;
signal DBP_EN : STD_LOGIC;
signal RST_OUTn : STD_LOGIC;
signal RST_EN : STD_LOGIC;
signal BSY_OUTn : STD_LOGIC;
signal BSY_EN : STD_LOGIC;
signal SEL_OUTn : STD_LOGIC;
signal SEL_EN : STD_LOGIC;
-- IDE
signal nnIDE_RES : STD_LOGIC;
signal IDE_CF_CS : STD_LOGIC;
signal IDE_CF_TA : STD_LOGIC;
signal NEXT_nIDE_RD : STD_LOGIC;
signal NEXT_nIDE_WR : STD_LOGIC;
type CMD_STATES is( IDLE, T1, T6, T7);
signal CMD_STATE : CMD_STATES;
signal NEXT_CMD_STATE : CMD_STATES;
BEGIN
LONG <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '0' else '0';
BYT <= '1' when FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
FB_B0 <= '1' when FB_ADR(0) = '0' or BYT = '0' else '0';
FB_B1 <= '1' when FB_ADR(0) = '1' or BYT = '0' else '0';
FALCON_IO_TA <= '1' when SNDCS = '1' or DTACK_OUT_MFPn = '0' or ACIA_CS_I = '1' or DMA_MODUS_CS ='1'
or DMA_ADR_CS = '1' or DMA_DIRM_CS = '1' or DMA_BYT_CNT_CS = '1' or FCF_CS = '1' or IDE_CF_TA = '1' else '0';
SUB_BUS <= '1' when nFB_WR = '1' and ROM_CS = '1' ELSE
'1' when nFB_WR = '1' and IDE_CF_CS = '1' ELSE
'1' when nFB_WR = '0' and nIDE_WR = '0' ELSE '0';
nRP_UDS <= '0' when SUB_BUS = '1' and FB_B0 = '1' else '1';
nRP_LDS <= '0' when SUB_BUS = '1' and FB_B1 = '1' else '1';
nDREQ0 <= '0';
----------------------------------------------------------------------------
-- SD
----------------------------------------------------------------------------
SD_CLK <= 'Z';
SD_CD_DATA3 <= 'Z';
SD_CDM_D1 <= 'Z';
----------------------------------------------------------------------------
-- IDE
----------------------------------------------------------------------------
CMD_REG: process(nRSTO, MAIN_CLK, CMD_STATE, NEXT_CMD_STATE)
begin
if nRSTO = '0' then
CMD_STATE <= IDLE;
elsif rising_edge(MAIN_CLK) then
CMD_STATE <= NEXT_CMD_STATE; -- go to next
nIDE_RD <= NEXT_nIDE_RD; -- go to next
nIDE_WR <= NEXT_nIDE_WR; -- go to next
else
CMD_STATE <= CMD_STATE; -- halten
nIDE_RD <= nIDE_RD; -- halten
nIDE_WR <= nIDE_WR; -- halten
end if;
end process CMD_REG;
CMD_DECODER: process(CMD_STATE, NEXT_CMD_STATE, NEXT_nIDE_RD, NEXT_nIDE_WR, IDE_RDY, IDE_CF_TA)
begin
case CMD_STATE is
when IDLE =>
IDE_CF_TA <= '0';
if IDE_CF_CS = '1' then
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T1;
else
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end if;
when T1 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
when T6 =>
IF IDE_RDY = '1' then
IDE_CF_TA <= '1';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= T7;
else
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= not nFB_WR;
NEXT_nIDE_WR <= nFB_WR;
NEXT_CMD_STATE <= T6;
end if;
when T7 =>
IDE_CF_TA <= '0';
NEXT_nIDE_RD <= '1';
NEXT_nIDE_WR <= '1';
NEXT_CMD_STATE <= IDLE;
end case;
end process CMD_DECODER;
IDE_RES <= not nnIDE_RES and nRSTO;
IDE_CF_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 7) = x"0" else '0'; -- FFF0'0000/80
nCF_CS0 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"0" else -- FFFO'0000-FFF0'001F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"2" else '1'; -- FFFO'0040-FFF0'005F
nCF_CS1 <= '0' when ACP_CONF(31) = '0' and FB_ADR(19 downto 5) = x"1" else -- FFF0'0020-FFF0'003F
'0' when ACP_CONF(31) = '1' and FB_ADR(19 downto 5) = x"3" else '1'; -- FFFO'0060-FFF0'007F
nIDE_CS0 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"2" else -- FFF0'0040-FFF0'005F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"0" else '1'; -- FFFO'0000-FFF0'001F
nIDE_CS1 <= '0' when ACP_CONF(30) = '0' and FB_ADR(19 downto 5) = x"3" else -- FFF0'0060-FFF0'007F
'0' when ACP_CONF(30) = '1' and FB_ADR(19 downto 5) = x"1" else '1'; -- FFFO'0020-FFF0'003F
-----------------------------------------------------------------------------------------------------------------------------------------
-- ACSI, SCSI UND FLOPPY WD1772
-------------------------------------------------------------------------------------------------------------------------------------------
-- daten read fifo
RDF: dcfifo0
port map(
aclr => CLR_FIFO,
data => RDF_DIN,
rdclk => MAIN_CLK,
rdreq => RDF_RDE,
wrclk => FDC_CLK,
wrreq => RDF_WRE,
q => RDF_DOUT,
wrusedw => RDF_AZ
);
FCF_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"0020110" and LONG = '1' else '0'; -- F002'0110 LONG ONLY
FCF_APH <= '1' when FB_ALE = '1' and FB_AD(31 downto 0) = x"F0020110" and LONG = '1' else '0'; -- ADRESSPHASE F0020110 LONG ONLY
RDF_RDE <= '1' when FCF_APH = '1' and nFB_WR = '1' else '0'; -- AKTIVIEREN IN ADRESSPHASE
FB_AD <= RDF_DOUT(7 downto 0) & RDF_DOUT(15 downto 8) & RDF_DOUT(23 downto 16) & RDF_DOUT(31 downto 24) when FCF_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
RDF_DIN <= CD_OUT_FDC when DMA_MODUS(7) = '1' else SCSI_DOUT;
-- daten write fifo
WRF: dcfifo1
port map(
aclr => CLR_FIFO,
data => FB_AD(7 downto 0) & FB_AD(15 downto 8) & FB_AD(23 downto 16) & FB_AD(31 downto 24),
rdclk => FDC_CLK,
rdreq => WRF_RDE,
wrclk => MAIN_CLK,
wrreq => WRF_WRE,
q => WRF_DOUT,
rdusedw => WRF_AZ
);
CD_IN_FDC <= WRF_DOUT when DMA_ACTIV = '1' and DMA_MODUS(8) = '1' else FB_AD(23 downto 16); -- BEI DMA WRITE <-FIFO SONST <-FB
DMA_AZ_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"002010C" else '0'; -- F002'010C LONG
FB_AD <= DMA_DRQ_Q & DMA_DRQ_REG & IDE_INT & FDINT & SCSI_INT & RDF_AZ & "0" & DMA_STATUS & "00" & WRF_AZ when DMA_AZ_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
DMA_DRQ_Q <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- FIFO WRITE: GENAU 1 MAIN_CLK -------------------------------------------------------------------------
process(MAIN_CLK, nRSTO, WRF_WRE, nFB_WR, FCF_APH)
begin
if nRSTO = '0' THEN
WRF_WRE <= '0';
elsif rising_edge(MAIN_CLK) then
IF FCF_APH = '1' and nFB_WR = '0' then
WRF_WRE <= '1';
else
WRF_WRE <= '0';
end if;
else
WRF_WRE <= WRF_WRE;
end if;
END PROCESS;
FCF_REG: process(nRSTO, FDC_CLK, FCF_STATE, NEXT_FCF_STATE, DMA_ACTIV)
begin
if nRSTO = '0' then
FCF_STATE <= FCF_IDLE;
DMA_ACTIV <= '0';
elsif rising_edge(FDC_CLK) then
FCF_STATE <= NEXT_FCF_STATE; -- go to next
DMA_ACTIV <= DMA_ACTIV_NEW;
else
FCF_STATE <= FCF_STATE; -- halten
DMA_ACTIV <= DMA_ACTIV;
end if;
end process FCF_REG;
FDC_REG: process(nRSTO, FDC_CLK, FDC_OUT, FDCS_In, CD_OUT_FDC)
begin
if nRSTO = '0' then
FDC_OUT <= x"00";
elsif rising_edge(FDC_CLK) and FDCS_In = '0' then
FDC_OUT <= CD_OUT_FDC; -- set
else
FDC_OUT <= FDC_OUT; -- halten
end if;
end process FDC_REG;
DMA_REQ <= '1' when ((DMA_DRQ_I = '1' and DMA_MODUS(7) = '1') or (SCSI_DRQ = '1' and DMA_MODUS(7) = '0')) and DMA_STATUS(1) = '1' and DMA_MODUS(6) = '0' and CLR_FIFO = '0' else '0';
FDC_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and FB_B1 = '1' else '0';
SCSI_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and FB_B1 = '1' else '0';
FCF_DECODER: process(FCF_STATE, NEXT_FCF_STATE, DMA_REQ,FDC_CS, RDF_WRE, WRF_RDE, SCSI_DRQ, nSCSI_DACK, DMA_MODUS, DMA_ACTIV, FDCS_In,SCSI_CS, SCSI_CSn)
begin
case FCF_STATE is
when FCF_IDLE =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
if DMA_REQ = '1' or FDC_CS = '1' or SCSI_CS = '1' then
DMA_ACTIV_NEW <= DMA_REQ;
NEXT_FCF_STATE <= FCF_T0;
else
DMA_ACTIV_NEW <= '0';
NEXT_FCF_STATE <= FCF_IDLE;
end if;
when FCF_T0 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= DMA_REQ;
WRF_RDE <= DMA_MODUS(8) and DMA_REQ; -- WRITE -> READ FROM FIFO
if DMA_REQ = '0' and DMA_ACTIV = '1' THEN -- spike?
NEXT_FCF_STATE <= FCF_IDLE; -- ja -> zum start
else
NEXT_FCF_STATE <= FCF_T1;
end if;
when FCF_T1 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T2;
when FCF_T2 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T3;
when FCF_T3 =>
RDF_WRE <= '0';
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
NEXT_FCF_STATE <= FCF_T6;
when FCF_T6 =>
WRF_RDE <= '0';
DMA_ACTIV_NEW <= DMA_ACTIV;
SCSI_CSn <= not SCSI_CS;
FDCS_In <= DMA_MODUS(4) or DMA_MODUS(3);
nSCSI_DACK <= DMA_MODUS(7) and DMA_ACTIV;
RDF_WRE <= not DMA_MODUS(8) and DMA_ACTIV; -- READ -> WRITE IN FIFO
NEXT_FCF_STATE <= FCF_T7;
when FCF_T7 =>
SCSI_CSn <= '1';
FDCS_In <= '1';
RDF_WRE <= '0';
WRF_RDE <= '0';
nSCSI_DACK <= '1';
DMA_ACTIV_NEW <= '0';
if FDC_CS = '1' and DMA_REQ = '0' then
NEXT_FCF_STATE <= FCF_T7;
else
NEXT_FCF_STATE <= FCF_IDLE;
end if;
end case;
end process FCF_DECODER;
I_FDC: WF1772IP_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
CSn => FDCS_In,
RWn => nFDC_WR,
A1 => CA2,
A0 => CA1,
DATA_IN => CD_IN_FDC,
DATA_OUT => CD_OUT_FDC,
-- DATA_EN => CD_EN_FDC,
RDn => nRD_DATA,
TR00n => TRACK00,
IPn => nINDEX,
WPRTn => nWP,
DDEn => '0', -- Fixed to MFM.
HDTYPE => HD_DD_OUT,
MO => MOT_ON,
WG => WR_GATE,
WD => WR_DATA,
STEP => STEP,
DIRC => STEP_DIR,
DRQ => DMA_DRQ_I,
INTRQ => FDINT
);
DMA_DATEN_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C302" else '0'; -- F8604/2
DMA_MODUS_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C303" else '0'; -- F8606/2
WDC_BSL_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C307" else '0'; -- F860E/2
HD_DD_OUT <= HD_DD WHEN ACP_CONF(29) = '0' ELSE WDC_BSL(0);
nFDC_WR <= (not DMA_MODUS(8)) when DMA_ACTIV = '1' else nFB_WR;
CA0 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(0);
CA1 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(1);
CA2 <= '1' when DMA_ACTIV = '1' ELSE DMA_MODUS(2);
FB_AD(23 downto 16) <= "0000" & (not DMA_STATUS(1)) & "0" & WDC_BSL(1) & HD_DD when WDC_BSL_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 24) <= "00000000" when DMA_DATEN_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= FDC_OUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "00" and nFB_OE = '0' else
SCSI_DOUT when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and nFB_OE = '0' else
DMA_BYT_CNT(16 downto 9) when DMA_DATEN_CS = '1' and DMA_MODUS(4) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
--- WDC BSL REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, WDC_BSL_CS, WDC_BSL, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
WDC_BSL <= "00";
elsif rising_edge(MAIN_CLK) and WDC_BSL_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
WDC_BSL(1 DOWNTO 0) <= FB_AD(25 DOWNTO 24);
else
WDC_BSL(1 DOWNTO 0) <= WDC_BSL(1 DOWNTO 0);
end if;
end if;
END PROCESS;
--- DMA MODUS REGISTER -------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, nFB_WR, FB_B0, FB_B1)
begin
if nRSTO = '0' THEN
DMA_MODUS <= x"0000";
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '1' and nFB_WR = '0' then
IF FB_B0 = '1' THEN
DMA_MODUS(15 downto 8) <= FB_AD(31 downto 24);
else
DMA_MODUS(15 downto 8) <= DMA_MODUS(15 downto 8);
end if;
IF FB_B1 = '1' THEN
DMA_MODUS(7 downto 0) <= FB_AD(23 downto 16);
else
DMA_MODUS(7 downto 0) <= DMA_MODUS(7 downto 0);
end if;
else
DMA_MODUS <= DMA_MODUS;
end if;
END PROCESS;
-- BYT COUNTER, SECTOR COUNTER ----------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_DATEN_CS, DMA_BYT_CNT_CS, DMA_BYT_CNT, nFB_WR, FB_B0, FB_B1, DMA_MODUS, CLR_FIFO)
begin
if nRSTO = '0' or CLR_FIFO = '1' THEN
DMA_BYT_CNT <= x"00000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_DATEN_CS = '1' and nFB_WR = '0' and DMA_MODUS(4) = '1' and FB_B1 = '1' then
DMA_BYT_CNT(31 downto 17) <= "000000000000000";
DMA_BYT_CNT(16 downto 9) <= FB_AD(23 downto 16);
DMA_BYT_CNT(8 downto 0) <= "000000000";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and DMA_BYT_CNT_CS = '1' then
DMA_BYT_CNT <= FB_AD;
else
DMA_BYT_CNT <= DMA_BYT_CNT;
end if;
END PROCESS;
--------------------------------------------------------------------
FB_AD(31 downto 16) <= "0000000000000" & DMA_STATUS when DMA_MODUS_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
DMA_STATUS(0) <= '1'; -- DMA OK
DMA_STATUS(1) <= '1' when DMA_BYT_CNT /= 0 and DMA_BYT_CNT(31) = '0' else '0'; -- WENN byts UND NICHT MINUS
DMA_STATUS(2) <= '0' when DMA_DRQ_I = '1' or SCSI_DRQ = '1' else '0';
DMA_DRQQ <= '1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '0' and RDF_AZ > 15 and DMA_MODUS(6) = '0' else
'1' when DMA_STATUS(1) = '1' and DMA_MODUS(8) = '1' and WRF_AZ < 512 and DMA_MODUS(6) = '0' else '0';
DMA_DRQ <= '1' when DMA_DRQ_REG = "11" and DMA_MODUS(6) = '0' else '0';
-- DMA REQUEST: SPIKES AUSFILTERN ------------------------------------------
process(FDC_CLK, nRSTO, DMA_DRQ_REG)
begin
if nRSTO = '0' THEN
DMA_DRQ_REG <= "00";
elsif rising_edge(FDC_CLK) then
DMA_DRQ_REG(0) <= DMA_DRQQ;
DMA_DRQ_REG(1) <= DMA_DRQ_REG(0) and DMA_DRQQ;
else
DMA_DRQ_REG <= DMA_DRQ_REG;
end if;
END PROCESS;
-- DMA ADRESSE ------------------------------------------------------
process(MAIN_CLK, nRSTO, DMA_TOP_CS, DMA_TOP, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_TOP <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_TOP_CS = '1' or DMA_ADR_CS = '1') then
DMA_TOP <= FB_AD(31 downto 24);
else
DMA_TOP <= DMA_TOP;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_HIGH_CS, DMA_HIGH, nFB_WR, DMA_ADR_CS)
begin
if nRSTO = '0' THEN
DMA_HIGH <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' and (DMA_HIGH_CS = '1' or DMA_ADR_CS = '1') then
DMA_HIGH <= FB_AD(23 downto 16);
else
DMA_HIGH <= DMA_HIGH;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_MID_CS, DMA_MID, nFB_WR)
begin
DMA_MID <= DMA_MID;
if nRSTO = '0' THEN
DMA_MID <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_MID_CS = '1' then
DMA_MID <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_MID <= FB_AD(15 downto 8);
end if;
end if;
END PROCESS;
process(MAIN_CLK, nRSTO, DMA_LOW_CS, DMA_LOW, nFB_WR)
begin
DMA_LOW <= DMA_LOW;
if nRSTO = '0' THEN
DMA_LOW <= x"00";
elsif rising_edge(MAIN_CLK) and nFB_WR = '0' then
if DMA_LOW_CS = '1'then
DMA_LOW <= FB_AD(23 downto 16);
elsif DMA_ADR_CS = '1' then
DMA_LOW <= FB_AD(7 downto 0);
end if;
end if;
END PROCESS;
--------------------------------------------------------------------------------------------
DMA_TOP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B0 = '1' else '0'; -- F8608/2
DMA_HIGH_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C304" and FB_B1 = '1' else '0'; -- F8609/2
DMA_MID_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C305" and FB_B1 = '1' else '0'; -- F860B/2
DMA_LOW_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 1) = x"7C306" and FB_B1 = '1' else '0'; -- F860D/2
FB_AD(31 downto 24) <= DMA_TOP when DMA_TOP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_HIGH when DMA_HIGH_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_MID when DMA_MID_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(23 downto 16) <= DMA_LOW when DMA_LOW_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
-- DIRECTZUGRIFF
DMA_DIRM_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20100" else '0'; -- F002'0100 WORD
DMA_ADR_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20104" else '0'; -- F002'0104 LONG
DMA_BYT_CNT_CS <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20108" else '0'; -- F002'0108 LONG
FB_AD <= DMA_TOP & DMA_HIGH & DMA_MID & DMA_LOW when DMA_ADR_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= DMA_MODUS when DMA_DIRM_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD <= DMA_BYT_CNT when DMA_BYT_CNT_CS = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
-- DMA RW TOGGLE ------------------------------------------
process(MAIN_CLK, nRSTO, DMA_MODUS_CS, DMA_MODUS, DMA_DIR_OLD)
begin
if nRSTO = '0' THEN
DMA_DIR_OLD <= '0';
elsif rising_edge(MAIN_CLK) and DMA_MODUS_CS = '0' then
DMA_DIR_OLD <= DMA_MODUS(8);
else
DMA_DIR_OLD <= DMA_DIR_OLD;
end if;
END PROCESS;
CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
-- SCSI ----------------------------------------------------------------------------------
I_SCSI: WF5380_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
ADR => CA2 & CA1 & CA0,
DATA_IN => CD_IN_FDC,
DATA_OUT => SCSI_DOUT,
--DATA_EN : out bit;
-- Bus and DMA controls:
CSn => '1', --SCSI_CSn, ABGESCHALTET
RDn => (not nFDC_WR) or (not SCSI_CS),
WRn => nFDC_WR or (not SCSI_CS),
EOPn => '1',
DACKn => nSCSI_DACK,
DRQ => SCSI_DRQ,
INT => SCSI_INT,
-- READY =>
-- SCSI bus:
DB_INn => SCSI_D,
DB_OUTn => DB_OUTn,
DB_EN => DB_EN,
DBP_INn => SCSI_PAR,
DBP_OUTn => DBP_OUTn,
DBP_EN => DBP_EN, -- wenn 1 dann output
RST_INn => nSCSI_RST,
RST_OUTn => RST_OUTn,
RST_EN => RST_EN,
BSY_INn => nSCSI_BUSY,
BSY_OUTn => BSY_OUTn,
BSY_EN => BSY_EN,
SEL_INn => nSCSI_SEL,
SEL_OUTn => SEL_OUTn,
SEL_EN => SEL_EN,
ACK_INn => '1',
ACK_OUTn => nSCSI_ACK,
-- ACK_EN => ACK_EN,
ATN_INn => '1',
ATN_OUTn => nSCSI_ATN,
-- ATN_EN => ATN_EN,
REQ_INn => nSCSI_DRQ,
-- REQ_OUTn => REQ_OUTn,
-- REQ_EN => REQ_EN,
IOn_IN => nSCSI_I_O,
-- IOn_OUT => IOn_OUT,
-- IO_EN => IO_EN,
CDn_IN => nSCSI_C_D,
-- CDn_OUT => CDn_OUT,
-- CD_EN => CD_EN,
MSG_INn => nSCSI_MSG
-- MSG_OUTn => MSG_OUTn,
-- MSG_EN => MSG_EN
);
-- SCSI ACSI ---------------------------------------------------------------
SCSI_D <= DB_OUTn when DB_EN = '1' else "ZZZZZZZZ";
SCSI_DIR <= '1'; --'0' when DB_EN = '1' else '1'; --ABGESCHALTET
SCSI_PAR <= DBP_OUTn when DBP_EN = '1' else 'Z';
nSCSI_RST <= RST_OUTn when RST_EN = '1' else 'Z';
nSCSI_BUSY <= BSY_OUTn when BSY_EN = '1' else 'Z';
nSCSI_SEL <= SEL_OUTn when SEL_EN = '1' else 'Z';
ACSI_DIR <= '0';
ACSI_D <= "ZZZZZZZZ";
nACSI_CS <= '1';
ACSI_A1 <= CA1;
nACSI_RESET <= nRSTO;
nACSI_ACK <= '1';
----------------------------------------------------------------------------
-- ROM-PORT TA KOMMT FROM DEFAULT TA = 16 BUSCYCLEN = 500ns
----------------------------------------------------------------------------
ROM_CS <= '1' when nFB_CS1 = '0' and nFB_WR = '1' and FB_ADR(19 downto 17) = x"5" else '0'; -- FFF A'0000/2'0000
nROM4 <= '0' when ROM_CS = '1' and FB_ADR(16) = '0' else '1';
nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
----------------------------------------------------------------------------
-- ACIA KEYBOARD
----------------------------------------------------------------------------
I_ACIA_KEYBOARD: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => FB_ADR(2),
CS1 => '1',
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_I,
-- DATA_EN => DATA_EN_ACIA_I,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => KEYB_RxD,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_KEYBDn,
TXDATA => AMKB_TX
--RTSn => -- Not used.
);
ACIA_CS_I <= '1' when nFB_CS1 = '0'and FB_ADR(19 downto 3) = x"1FF80" else '0'; -- FFC00-FFC07 FFC00/8
KEYB_RxD <= '1' when AMKB_REG(3) = '1' or PIC_AMKB_RX = '0' else '0'; -- TASTATUR DATEN VOM PIC(PS2) OR NORMAL
FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0' and nFB_OE = '0' else "ZZZZZZZZ";
-- AMKB_TX: SPIKES AUSFILTERN ------------------------------------------
process(CLK2M, AMKB_RX, AMKB_REG)
begin
if rising_edge(CLK2M) then
IF AMKB_RX = '0' THEN
IF AMKB_REG < 16 THEN
AMKB_REG <= "00000";
ELSE
AMKB_REG <= AMKB_REG - 1;
END IF;
ELSE
IF AMKB_REG > 15 THEN
AMKB_REG <= "11111";
ELSE
AMKB_REG <= AMKB_REG + 1;
END IF;
END IF;
ELSE
AMKB_REG <= AMKB_REG;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- ACIA MIDI
----------------------------------------------------------------------------
I_ACIA_MIDI: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
CS2n => '0',
CS1 => FB_ADR(2),
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_OUT => DATA_OUT_ACIA_II,
-- DATA_EN => DATA_EN_ACIA_II,
TXCLK => CLK500k,
RXCLK => CLK500k,
RXDATA => MIDI_IN,
CTSn => '0',
DCDn => '0',
IRQn => IRQ_MIDIn,
TXDATA => MIDI_OUT
--RTSn => -- Not used.
);
MIDI_TLR <= MIDI_OUT;
MIDI_OLR <= MIDI_OUT;
FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
----------------------------------------------------------------------------
-- MFP
----------------------------------------------------------------------------
I_MFP: WF68901IP_TOP_SOC
port map(
-- System control:
CLK => MAIN_CLK,
RESETn => nRSTO,
-- Asynchronous bus control:
DSn => not LDS,
CSn => not MFP_CS,
RWn => nFB_WR,
DTACKn => DTACK_OUT_MFPn,
-- Data and Adresses:
RS => FB_ADR(5 downto 1),
DATA_IN => FB_AD(23 downto 16),
DATA_OUT => DATA_OUT_MFP,
-- DATA_EN => DATA_EN_MFP,
GPIP_IN(7) => not DMA_DRQ_Q,
GPIP_IN(6) => not RI,
GPIP_IN(5) => DINTn,
GPIP_IN(4) => IRQ_ACIAn,
GPIP_IN(3) => DSP_INT,
GPIP_IN(2) => not CTS,
GPIP_IN(1) => not DCD,
GPIP_IN(0) => LP_BUSY,
-- GPIP_OUT =>, -- Not used; all GPIPs are direction input.
-- GPIP_EN =>, -- Not used; all GPIPs are direction input.
-- Interrupt control:
IACKn => not MFP_INTACK,
IEIn => '0',
-- IEOn =>, -- Not used.
IRQn => nMFP_INT,
-- Timers and timer control:
XTAL1 => CLK2M4576,
TAI => '0',
TBI => nBLANK,
-- TAO =>,
-- TBO =>,
-- TCO =>,
TDO => TDO,
-- Serial I/O control:
RC => TDO,
TC => TDO,
SI => RxD,
SO => TxD
-- SO_EN => MFP_SO_EN
-- DMA control:
-- RRn =>,
-- TRn =>
);
MFP_CS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3FE8" else '0'; -- FFA00/40
MFP_INTACK <= '1' when nFB_CS2 = '0' and FB_ADR(26 downto 0) = x"20000" else '0'; --F002'0000
LDS <= '1' when MFP_CS = '1' or MFP_INTACK = '1' else '0';
FB_AD(23 downto 16) <= DATA_OUT_MFP when MFP_CS = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(31 downto 10) <= "0000000000000000000000" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZZZZZZZ";
FB_AD(9 downto 2) <= DATA_OUT_MFP when MFP_INTACK = '1' and nFB_OE = '0' else "ZZZZZZZZ";
FB_AD(1 downto 0) <= "00" when MFP_INTACK = '1' and nFB_OE = '0' else "ZZ";
DINTn <= '0' when IDE_INT = '1' AND ACP_CONFIG[28] = '1' else
'0' when FDINT = '1' else
'0' when SCSI_INT = '1' AND ACP_CONFIG[28] = '1' else '1';
-- TASTATUR UND KEYBOARD INTERRUPT: SPIKES AUSFILTERN ------------------------------------------
process(MAIN_CLK,nRSTO,IRQ_ACIAn,IRQ_KEYBDn,IRQ_MIDIn)
begin
if nRSTO = '0' THEN
IRQ_ACIAn <= '1';
elsif rising_edge(MAIN_CLK) then
IRQ_ACIAn <= IRQ_KEYBDn and IRQ_MIDIn;
else
IRQ_ACIAn <= IRQ_ACIAn;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- Sound
----------------------------------------------------------------------------
I_SOUND: WF2149IP_TOP_SOC
port map(
SYS_CLK => MAIN_CLK,
RESETn => nRSTO,
WAV_CLK => CLK2M,
SELn => '1',
BDIR => SNDIR_I,
BC2 => '1',
BC1 => SNDCS_I,
A9n => '0',
A8 => '1',
DA_IN => FB_AD(31 downto 24),
DA_OUT => DA_OUT_X,
IO_A_IN => x"00", -- All port pins are dedicated outputs.
IO_A_OUT(7) => nnIDE_RES,
IO_A_OUT(6) => LP_DIR_X,
IO_A_OUT(5) => LP_STR,
IO_A_OUT(4) => DTR,
IO_A_OUT(3) => RTS,
-- IO_A_OUT(2) => FDD_D1SEL,
IO_A_OUT(1) => DSA_D,
IO_A_OUT(0) => nSDSEL,
-- IO_A_EN =>, -- Not required.
IO_B_IN => LP_D,
IO_B_OUT => LP_D_X,
-- IO_B_EN => IO_B_EN,
OUT_A => YM_QA,
OUT_B => YM_QB,
OUT_C => YM_QC
);
SNDCS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 2) = x"3E200" else '0'; -- 8800-8803 F8800/4
SNDCS_I <= '1' when SNDCS = '1' and FB_ADR (1 downto 1) = "0" else '0';
SNDIR_I <= '1' when SNDCS = '1' and nFB_WR = '0' else '0';
FB_AD(31 downto 24) <= DA_OUT_X when SNDCS_I = '1' and nFB_OE = '0' else "ZZZZZZZZ";
LP_D <= LP_D_X when LP_DIR_X = '0' else "ZZZZZZZZ";
LP_DIR <= LP_DIR_X;
END FalconIO_SDCard_IDE_CF_architecture;

View File

@@ -0,0 +1,406 @@
----------------------------------------------------------------------
---- ----
---- Atari Coldfire IP Core ----
---- ----
---- This file is part of the Atari Coldfire project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 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
-- 1.0 Initial Release, 20090925.
--
library ieee;
use ieee.std_logic_1164.all;
package FalconIO_SDCard_IDE_CF_PKG is
component WF25915IP_TOP_V1_SOC -- GLUE.
port (
-- Clock system:
GL_CLK : in std_logic; -- Originally 8MHz.
GL_CLK_016 : in std_logic; -- One sixteenth of GL_CLK.
-- Core address select:
GL_ROMSEL_FC_E0n : in std_logic;
EN_RAM_14MB : in std_logic;
-- Adress decoder outputs:
GL_ROM_6n : out std_logic; -- STE.
GL_ROM_5n : out std_logic; -- STE.
GL_ROM_4n : out std_logic; -- ST.
GL_ROM_3n : out std_logic; -- ST.
GL_ROM_2n : out std_logic;
GL_ROM_1n : out std_logic;
GL_ROM_0n : out std_logic;
GL_ACIACS : out std_logic;
GL_MFPCSn : out std_logic;
GL_SNDCSn : out std_logic;
GL_FCSn : out std_logic;
GL_STE_SNDCS : out std_logic; -- STE: Sound chip select.
GL_STE_SNDIR : out std_logic; -- STE: Data flow direction control.
GL_STE_RTCCSn : out std_logic; --STE only.
GL_STE_RTC_WRn : out std_logic; --STE only.
GL_STE_RTC_RDn : out std_logic; --STE only.
-- 6800 peripheral control,
GL_VPAn : out std_logic;
GL_VMAn : in std_logic;
GL_DMA_SYNC : in std_logic;
GL_DEVn : out std_logic;
GL_RAMn : out std_logic;
GL_DMAn : out std_logic;
-- Interrupt system:
-- Comment out GL_AVECn for CPUs which do not provide the VMAn signal.
GL_AVECn : out std_logic;
GL_STE_FDINT : in std_logic; -- Floppy disk interrupt; STE only.
GL_STE_HDINTn : in std_logic; -- Hard disk interrupt; STE only.
GL_MFPINTn : in std_logic; -- ST.
GL_STE_EINT3n : in std_logic; --STE only.
GL_STE_EINT5n : in std_logic; --STE only.
GL_STE_EINT7n : in std_logic; --STE only.
GL_STE_DINTn : out std_logic; -- Disk interrupt (floppy or hard disk); STE only.
GL_IACKn : out std_logic; -- ST.
GL_STE_IPL2n : out std_logic; --STE only.
GL_STE_IPL1n : out std_logic; --STE only.
GL_STE_IPL0n : out std_logic; --STE only.
-- Video timing:
GL_BLANKn : out std_logic;
GL_DE : out std_logic;
GL_MULTISYNC : in std_logic_vector(3 downto 2);
GL_VIDEO_HIMODE : out std_logic;
GL_HSYNC_INn : in std_logic;
GL_HSYNC_OUTn : out std_logic;
GL_VSYNC_INn : in std_logic;
GL_VSYNC_OUTn : out std_logic;
GL_SYNC_OUT_EN : out std_logic;
-- Bus arstd_logicration control:
GL_RDY_INn : in std_logic;
GL_RDY_OUTn : out std_logic;
GL_BRn : out std_logic;
GL_BGIn : in std_logic;
GL_BGOn : out std_logic;
GL_BGACK_INn : in std_logic;
GL_BGACK_OUTn : out std_logic;
-- Adress and data bus:
GL_ADDRESS : in std_logic_vector(23 downto 1);
-- ST: put the data bus to 1 downto 0.
-- STE: put the data out bus to 15 downto 0.
GL_DATA_IN : in std_logic_vector(7 downto 0);
GL_DATA_OUT : out std_logic_vector(15 downto 0);
GL_DATA_EN : out std_logic;
-- Asynchronous bus control:
GL_RWn_IN : in std_logic;
GL_RWn_OUT : out std_logic;
GL_AS_INn : in std_logic;
GL_AS_OUTn : out std_logic;
GL_UDS_INn : in std_logic;
GL_UDS_OUTn : out std_logic;
GL_LDS_INn : in std_logic;
GL_LDS_OUTn : out std_logic;
GL_DTACK_INn : in std_logic;
GL_DTACK_OUTn : out std_logic;
GL_CTRL_EN : out std_logic;
-- System control:
GL_RESETn : in std_logic;
GL_BERRn : out std_logic;
-- Processor function codes:
GL_FC : in std_logic_vector(2 downto 0);
-- STE enhancements:
GL_STE_FDDS : out std_logic; -- Floppy type select (HD or DD).
GL_STE_FCCLK : out std_logic; -- Floppy controller clock select.
GL_STE_JOY_RHn : out std_logic; -- Read only FF9202 high byte.
GL_STE_JOY_RLn : out std_logic; -- Read only FF9202 low byte.
GL_STE_JOY_WL : out std_logic; -- Write only FF9202 low byte.
GL_STE_JOY_WEn : out std_logic; -- Write only FF9202 output enable.
GL_STE_BUTTONn : out std_logic; -- Read only FF9000 low byte.
GL_STE_PAD0Xn : in std_logic; -- Counter input for the Paddle 0X.
GL_STE_PAD0Yn : in std_logic; -- Counter input for the Paddle 0Y.
GL_STE_PAD1Xn : in std_logic; -- Counter input for the Paddle 1X.
GL_STE_PAD1Yn : in std_logic; -- Counter input for the Paddle 1Y.
GL_STE_PADRSTn : out std_logic; -- Paddle monoflops reset.
GL_STE_PENn : in std_logic; -- Input of the light pen.
GL_STE_SCCn : out std_logic; -- Select signal for the STE or TT SCC chip.
GL_STE_CPROGn : out std_logic -- Select signal for the STE's cache processor.
);
end component WF25915IP_TOP_V1_SOC;
component WF5380_TOP_SOC
port (
CLK : in std_logic;
RESETn : in std_logic;
ADR : in std_logic_vector(2 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
CSn : in std_logic;
RDn : in std_logic;
WRn : in std_logic;
EOPn : in std_logic;
DACKn : in std_logic;
DRQ : out std_logic;
INT : out std_logic;
READY : out std_logic;
DB_INn : in std_logic_vector(7 downto 0);
DB_OUTn : out std_logic_vector(7 downto 0);
DB_EN : out std_logic;
DBP_INn : in std_logic;
DBP_OUTn : out std_logic;
DBP_EN : out std_logic;
RST_INn : in std_logic;
RST_OUTn : out std_logic;
RST_EN : out std_logic;
BSY_INn : in std_logic;
BSY_OUTn : out std_logic;
BSY_EN : out std_logic;
SEL_INn : in std_logic;
SEL_OUTn : out std_logic;
SEL_EN : out std_logic;
ACK_INn : in std_logic;
ACK_OUTn : out std_logic;
ACK_EN : out std_logic;
ATN_INn : in std_logic;
ATN_OUTn : out std_logic;
ATN_EN : out std_logic;
REQ_INn : in std_logic;
REQ_OUTn : out std_logic;
REQ_EN : out std_logic;
IOn_IN : in std_logic;
IOn_OUT : out std_logic;
IO_EN : out std_logic;
CDn_IN : in std_logic;
CDn_OUT : out std_logic;
CD_EN : out std_logic;
MSG_INn : in std_logic;
MSG_OUTn : out std_logic;
MSG_EN : out std_logic
);
end component WF5380_TOP_SOC;
component WF1772IP_TOP_SOC -- FDC.
port (
CLK : in std_logic; -- 16MHz clock!
RESETn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
A1, A0 : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
RDn : in std_logic;
TR00n : in std_logic;
IPn : in std_logic;
WPRTn : in std_logic;
DDEn : in std_logic;
HDTYPE : in std_logic; -- '0' = DD disks, '1' = HD disks.
MO : out std_logic;
WG : out std_logic;
WD : out std_logic;
STEP : out std_logic;
DIRC : out std_logic;
DRQ : out std_logic;
INTRQ : out std_logic
);
end component WF1772IP_TOP_SOC;
component WF68901IP_TOP_SOC -- MFP.
port ( -- System control:
CLK : in std_logic;
RESETn : in std_logic;
-- Asynchronous bus control:
DSn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
DTACKn : out std_logic;
-- Data and Adresses:
RS : in std_logic_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
GPIP_IN : in std_logic_vector(7 downto 0);
GPIP_OUT : out std_logic_vector(7 downto 0);
GPIP_EN : out std_logic_vector(7 downto 0);
-- Interrupt control:
IACKn : in std_logic;
IEIn : in std_logic;
IEOn : out std_logic;
IRQn : out std_logic;
-- Timers and timer control:
XTAL1 : in std_logic; -- Use an oszillator instead of a quartz.
TAI : in std_logic;
TBI : in std_logic;
TAO : out std_logic;
TBO : out std_logic;
TCO : out std_logic;
TDO : out std_logic;
-- Serial I/O control:
RC : in std_logic;
TC : in std_logic;
SI : in std_logic;
SO : out std_logic;
SO_EN : out std_logic;
-- DMA control:
RRn : out std_logic;
TRn : out std_logic
);
end component WF68901IP_TOP_SOC;
component WF2149IP_TOP_SOC -- Sound.
port(
SYS_CLK : in std_logic; -- Read the inforation in the header!
RESETn : in std_logic;
WAV_CLK : in std_logic; -- Read the inforation in the header!
SELn : in std_logic;
BDIR : in std_logic;
BC2, BC1 : in std_logic;
A9n, A8 : in std_logic;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out std_logic;
IO_A_IN : in std_logic_vector(7 downto 0);
IO_A_OUT : out std_logic_vector(7 downto 0);
IO_A_EN : out std_logic;
IO_B_IN : in std_logic_vector(7 downto 0);
IO_B_OUT : out std_logic_vector(7 downto 0);
IO_B_EN : out std_logic;
OUT_A : out std_logic; -- Analog (PWM) outputs.
OUT_B : out std_logic;
OUT_C : out std_logic
);
end component WF2149IP_TOP_SOC;
component WF6850IP_TOP_SOC -- ACIA.
port (
CLK : in std_logic;
RESETn : in std_logic;
CS2n, CS1, CS0 : in std_logic;
E : in std_logic;
RWn : in std_logic;
RS : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
TXCLK : in std_logic;
RXCLK : in std_logic;
RXDATA : in std_logic;
CTSn : in std_logic;
DCDn : in std_logic;
IRQn : out std_logic;
TXDATA : out std_logic;
RTSn : out std_logic
);
end component WF6850IP_TOP_SOC;
component WF_SD_CARD
port (
RESETn : in std_logic;
CLK : in std_logic;
ACSI_A1 : in std_logic;
ACSI_CSn : in std_logic;
ACSI_ACKn : in std_logic;
ACSI_INTn : out std_logic;
ACSI_DRQn : out std_logic;
ACSI_D_IN : in std_logic_vector(7 downto 0);
ACSI_D_OUT : out std_logic_vector(7 downto 0);
ACSI_D_EN : out std_logic;
MC_DO : in std_logic;
MC_PIO_DMAn : in std_logic;
MC_RWn : in std_logic;
MC_CLR_CMD : in std_logic;
MC_DONE : out std_logic;
MC_GOT_CMD : out std_logic;
MC_D_IN : in std_logic_vector(7 downto 0);
MC_D_OUT : out std_logic_vector(7 downto 0);
MC_D_EN : out std_logic
);
end component WF_SD_CARD;
component dcfifo0
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component dcfifo0;
component dcfifo1
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (31 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);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component;
end FalconIO_SDCard_IDE_CF_PKG;

View File

@@ -0,0 +1,406 @@
----------------------------------------------------------------------
---- ----
---- Atari Coldfire IP Core ----
---- ----
---- This file is part of the Atari Coldfire project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 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
-- 1.0 Initial Release, 20090925.
--
library ieee;
use ieee.std_logic_1164.all;
package FalconIO_SDCard_IDE_CF_PKG is
component WF25915IP_TOP_V1_SOC -- GLUE.
port (
-- Clock system:
GL_CLK : in std_logic; -- Originally 8MHz.
GL_CLK_016 : in std_logic; -- One sixteenth of GL_CLK.
-- Core address select:
GL_ROMSEL_FC_E0n : in std_logic;
EN_RAM_14MB : in std_logic;
-- Adress decoder outputs:
GL_ROM_6n : out std_logic; -- STE.
GL_ROM_5n : out std_logic; -- STE.
GL_ROM_4n : out std_logic; -- ST.
GL_ROM_3n : out std_logic; -- ST.
GL_ROM_2n : out std_logic;
GL_ROM_1n : out std_logic;
GL_ROM_0n : out std_logic;
GL_ACIACS : out std_logic;
GL_MFPCSn : out std_logic;
GL_SNDCSn : out std_logic;
GL_FCSn : out std_logic;
GL_STE_SNDCS : out std_logic; -- STE: Sound chip select.
GL_STE_SNDIR : out std_logic; -- STE: Data flow direction control.
GL_STE_RTCCSn : out std_logic; --STE only.
GL_STE_RTC_WRn : out std_logic; --STE only.
GL_STE_RTC_RDn : out std_logic; --STE only.
-- 6800 peripheral control,
GL_VPAn : out std_logic;
GL_VMAn : in std_logic;
GL_DMA_SYNC : in std_logic;
GL_DEVn : out std_logic;
GL_RAMn : out std_logic;
GL_DMAn : out std_logic;
-- Interrupt system:
-- Comment out GL_AVECn for CPUs which do not provide the VMAn signal.
GL_AVECn : out std_logic;
GL_STE_FDINT : in std_logic; -- Floppy disk interrupt; STE only.
GL_STE_HDINTn : in std_logic; -- Hard disk interrupt; STE only.
GL_MFPINTn : in std_logic; -- ST.
GL_STE_EINT3n : in std_logic; --STE only.
GL_STE_EINT5n : in std_logic; --STE only.
GL_STE_EINT7n : in std_logic; --STE only.
GL_STE_DINTn : out std_logic; -- Disk interrupt (floppy or hard disk); STE only.
GL_IACKn : out std_logic; -- ST.
GL_STE_IPL2n : out std_logic; --STE only.
GL_STE_IPL1n : out std_logic; --STE only.
GL_STE_IPL0n : out std_logic; --STE only.
-- Video timing:
GL_BLANKn : out std_logic;
GL_DE : out std_logic;
GL_MULTISYNC : in std_logic_vector(3 downto 2);
GL_VIDEO_HIMODE : out std_logic;
GL_HSYNC_INn : in std_logic;
GL_HSYNC_OUTn : out std_logic;
GL_VSYNC_INn : in std_logic;
GL_VSYNC_OUTn : out std_logic;
GL_SYNC_OUT_EN : out std_logic;
-- Bus arstd_logicration control:
GL_RDY_INn : in std_logic;
GL_RDY_OUTn : out std_logic;
GL_BRn : out std_logic;
GL_BGIn : in std_logic;
GL_BGOn : out std_logic;
GL_BGACK_INn : in std_logic;
GL_BGACK_OUTn : out std_logic;
-- Adress and data bus:
GL_ADDRESS : in std_logic_vector(23 downto 1);
-- ST: put the data bus to 1 downto 0.
-- STE: put the data out bus to 15 downto 0.
GL_DATA_IN : in std_logic_vector(7 downto 0);
GL_DATA_OUT : out std_logic_vector(15 downto 0);
GL_DATA_EN : out std_logic;
-- Asynchronous bus control:
GL_RWn_IN : in std_logic;
GL_RWn_OUT : out std_logic;
GL_AS_INn : in std_logic;
GL_AS_OUTn : out std_logic;
GL_UDS_INn : in std_logic;
GL_UDS_OUTn : out std_logic;
GL_LDS_INn : in std_logic;
GL_LDS_OUTn : out std_logic;
GL_DTACK_INn : in std_logic;
GL_DTACK_OUTn : out std_logic;
GL_CTRL_EN : out std_logic;
-- System control:
GL_RESETn : in std_logic;
GL_BERRn : out std_logic;
-- Processor function codes:
GL_FC : in std_logic_vector(2 downto 0);
-- STE enhancements:
GL_STE_FDDS : out std_logic; -- Floppy type select (HD or DD).
GL_STE_FCCLK : out std_logic; -- Floppy controller clock select.
GL_STE_JOY_RHn : out std_logic; -- Read only FF9202 high byte.
GL_STE_JOY_RLn : out std_logic; -- Read only FF9202 low byte.
GL_STE_JOY_WL : out std_logic; -- Write only FF9202 low byte.
GL_STE_JOY_WEn : out std_logic; -- Write only FF9202 output enable.
GL_STE_BUTTONn : out std_logic; -- Read only FF9000 low byte.
GL_STE_PAD0Xn : in std_logic; -- Counter input for the Paddle 0X.
GL_STE_PAD0Yn : in std_logic; -- Counter input for the Paddle 0Y.
GL_STE_PAD1Xn : in std_logic; -- Counter input for the Paddle 1X.
GL_STE_PAD1Yn : in std_logic; -- Counter input for the Paddle 1Y.
GL_STE_PADRSTn : out std_logic; -- Paddle monoflops reset.
GL_STE_PENn : in std_logic; -- Input of the light pen.
GL_STE_SCCn : out std_logic; -- Select signal for the STE or TT SCC chip.
GL_STE_CPROGn : out std_logic -- Select signal for the STE's cache processor.
);
end component WF25915IP_TOP_V1_SOC;
component WF5380_TOP_SOC
port (
CLK : in std_logic;
RESETn : in std_logic;
ADR : in std_logic_vector(2 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
CSn : in std_logic;
RDn : in std_logic;
WRn : in std_logic;
EOPn : in std_logic;
DACKn : in std_logic;
DRQ : out std_logic;
INT : out std_logic;
READY : out std_logic;
DB_INn : in std_logic_vector(7 downto 0);
DB_OUTn : out std_logic_vector(7 downto 0);
DB_EN : out std_logic;
DBP_INn : in std_logic;
DBP_OUTn : out std_logic;
DBP_EN : out std_logic;
RST_INn : in std_logic;
RST_OUTn : out std_logic;
RST_EN : out std_logic;
BSY_INn : in std_logic;
BSY_OUTn : out std_logic;
BSY_EN : out std_logic;
SEL_INn : in std_logic;
SEL_OUTn : out std_logic;
SEL_EN : out std_logic;
ACK_INn : in std_logic;
ACK_OUTn : out std_logic;
ACK_EN : out std_logic;
ATN_INn : in std_logic;
ATN_OUTn : out std_logic;
ATN_EN : out std_logic;
REQ_INn : in std_logic;
REQ_OUTn : out std_logic;
REQ_EN : out std_logic;
IOn_IN : in std_logic;
IOn_OUT : out std_logic;
IO_EN : out std_logic;
CDn_IN : in std_logic;
CDn_OUT : out std_logic;
CD_EN : out std_logic;
MSG_INn : in std_logic;
MSG_OUTn : out std_logic;
MSG_EN : out std_logic
);
end component WF5380_TOP_SOC;
component WF1772IP_TOP_SOC -- FDC.
port (
CLK : in std_logic; -- 16MHz clock!
RESETn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
A1, A0 : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
RDn : in std_logic;
TR00n : in std_logic;
IPn : in std_logic;
WPRTn : in std_logic;
DDEn : in std_logic;
HDTYPE : in std_logic; -- '0' = DD disks, '1' = HD disks.
MO : out std_logic;
WG : out std_logic;
WD : out std_logic;
STEP : out std_logic;
DIRC : out std_logic;
DRQ : out std_logic;
INTRQ : out std_logic
);
end component WF1772IP_TOP_SOC;
component WF68901IP_TOP_SOC -- MFP.
port ( -- System control:
CLK : in std_logic;
RESETn : in std_logic;
-- Asynchronous bus control:
DSn : in std_logic;
CSn : in std_logic;
RWn : in std_logic;
DTACKn : out std_logic;
-- Data and Adresses:
RS : in std_logic_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
GPIP_IN : in std_logic_vector(7 downto 0);
GPIP_OUT : out std_logic_vector(7 downto 0);
GPIP_EN : out std_logic_vector(7 downto 0);
-- Interrupt control:
IACKn : in std_logic;
IEIn : in std_logic;
IEOn : out std_logic;
IRQn : out std_logic;
-- Timers and timer control:
XTAL1 : in std_logic; -- Use an oszillator instead of a quartz.
TAI : in std_logic;
TBI : in std_logic;
TAO : out std_logic;
TBO : out std_logic;
TCO : out std_logic;
TDO : out std_logic;
-- Serial I/O control:
RC : in std_logic;
TC : in std_logic;
SI : in std_logic;
SO : out std_logic;
SO_EN : out std_logic;
-- DMA control:
RRn : out std_logic;
TRn : out std_logic
);
end component WF68901IP_TOP_SOC;
component WF2149IP_TOP_SOC -- Sound.
port(
SYS_CLK : in std_logic; -- Read the inforation in the header!
RESETn : in std_logic;
WAV_CLK : in std_logic; -- Read the inforation in the header!
SELn : in std_logic;
BDIR : in std_logic;
BC2, BC1 : in std_logic;
A9n, A8 : in std_logic;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out std_logic;
IO_A_IN : in std_logic_vector(7 downto 0);
IO_A_OUT : out std_logic_vector(7 downto 0);
IO_A_EN : out std_logic;
IO_B_IN : in std_logic_vector(7 downto 0);
IO_B_OUT : out std_logic_vector(7 downto 0);
IO_B_EN : out std_logic;
OUT_A : out std_logic; -- Analog (PWM) outputs.
OUT_B : out std_logic;
OUT_C : out std_logic
);
end component WF2149IP_TOP_SOC;
component WF6850IP_TOP_SOC -- ACIA.
port (
CLK : in std_logic;
RESETn : in std_logic;
CS2n, CS1, CS0 : in std_logic;
E : in std_logic;
RWn : in std_logic;
RS : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out std_logic;
TXCLK : in std_logic;
RXCLK : in std_logic;
RXDATA : in std_logic;
CTSn : in std_logic;
DCDn : in std_logic;
IRQn : out std_logic;
TXDATA : out std_logic;
RTSn : out std_logic
);
end component WF6850IP_TOP_SOC;
component WF_SD_CARD
port (
RESETn : in std_logic;
CLK : in std_logic;
ACSI_A1 : in std_logic;
ACSI_CSn : in std_logic;
ACSI_ACKn : in std_logic;
ACSI_INTn : out std_logic;
ACSI_DRQn : out std_logic;
ACSI_D_IN : in std_logic_vector(7 downto 0);
ACSI_D_OUT : out std_logic_vector(7 downto 0);
ACSI_D_EN : out std_logic;
MC_DO : in std_logic;
MC_PIO_DMAn : in std_logic;
MC_RWn : in std_logic;
MC_CLR_CMD : in std_logic;
MC_DONE : out std_logic;
MC_GOT_CMD : out std_logic;
MC_D_IN : in std_logic_vector(7 downto 0);
MC_D_OUT : out std_logic_vector(7 downto 0);
MC_D_EN : out std_logic
);
end component WF_SD_CARD;
component dcfifo0
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (5 DOWNTO 0)
);
end component dcfifo0;
component dcfifo1
PORT (
aclr : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (31 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);
rdusedw : OUT STD_LOGIC_VECTOR (5 DOWNTO 0)
);
end component;
end FalconIO_SDCard_IDE_CF_PKG;

View File

@@ -0,0 +1,631 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the 5380's system controller. ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 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 2K9A 2009/06/20 WF
-- Initial Release.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_CONTROL is
port (
-- System controls:
CLK : in bit;
RESETn : in bit; -- System reset.
-- System controls:
BSY_INn : in bit; -- SCSI BSY_INn bit.
BSY_OUTn : out bit; -- SCSI BSY_INn bit.
DATA_EN : out bit; -- Enable the SCSI data lines.
SEL_INn : in bit; -- SCSI SEL_INn bit.
ARB_EN : in bit; -- Arbitration enable.
BSY_DISn : in bit; -- BSY monitoring enable.
RSTn : in bit; -- SCSI reset.
ARB : out bit; -- Arbitration flag.
AIP : out bit; -- Arbitration in progress flag.
LA : out bit; -- Lost arbitration flag.
ACK_INn : in bit;
ACK_OUTn : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
DACKn : in bit; -- Data acknowledge.
READY : out bit;
DRQ : out bit; -- Data request.
TARG : in bit; -- Target mode indicator.
BLK : in bit; -- Block mode indicator.
PINT_EN : in bit; -- Parity interrupt enable.
SPER : in bit; -- Parity error.
SER_ID : in bit; -- SER matches ODR bits.
RPI : in bit; -- Reset interrupts.
DMA_EN : in bit; -- DMA mode enable.
SDS : in bit; -- Start DMA send, write only.
SDT : in bit; -- Start DMA target receive, write only.
SDI : in bit; -- Start DMA initiator receive, write only.
EOP_EN : in bit; -- EOP interrupt enable.
EOPn : in bit; -- End of process indicator.
PHSM : in bit; -- Phase match flag.
INT : out bit; -- Interrupt.
IDR_WR : out bit; -- Write input data register during DMA.
ODR_WR : out bit; -- Write output data register, during DMA.
CHK_PAR : out bit; -- Check Parity during DMA operation.
BSY_ERR : out bit; -- Busy monitoring error.
DMA_SND : out bit; -- Indicates direction of target DMA.
DMA_ACTIVE : out bit -- DMA is active.
);
end entity WF5380_CONTROL;
architecture BEHAVIOUR of WF5380_CONTROL is
type CTRL_STATES is (IDLE, WAIT_800ns, WAIT_2200ns, DMA_SEND, DMA_TARG_RCV, DMA_INIT_RCV);
type DMA_STATES is (IDLE, DMA_STEP_1, DMA_STEP_2, DMA_STEP_3, DMA_STEP_4);
signal CTRL_STATE : CTRL_STATES;
signal NEXT_CTRL_STATE : CTRL_STATES;
signal DMA_STATE : DMA_STATES;
signal NEXT_DMA_STATE : DMA_STATES;
signal BUS_FREE : bit;
signal DELAY_800ns : boolean;
signal DELAY_2200ns : boolean;
signal DMA_ACTIVE_I : bit;
signal EOP_In : bit;
begin
IN_BUFFER: process
-- This buffer shall prevent some signals against
-- setup hold effects and thus the state machine
-- against unpredictable behaviour.
begin
wait until CLK = '1' and CLK' event;
EOP_In <= EOPn;
end process IN_BUFFER;
STATE_REGISTERS: process(RESETn, CLK)
-- This is the controller's state machine register.
variable BSY_LOCK : boolean;
begin
if RESETn = '0' then
CTRL_STATE <= IDLE;
DMA_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if RSTn = '0' then -- SCSI reset.
CTRL_STATE <= IDLE;
DMA_STATE <= IDLE;
else
CTRL_STATE <= NEXT_CTRL_STATE;
DMA_STATE <= NEXT_DMA_STATE;
end if;
--
if DMA_EN = '0' then
DMA_STATE <= IDLE;
end if;
end if;
end process STATE_REGISTERS;
CTRL_DECODER: process(CTRL_STATE, ARB_EN, BUS_FREE, DELAY_800ns, SEL_INn, DMA_ACTIVE_I, SDS, SDT, SDI)
-- This is the controller's state machine decoder.
variable BSY_LOCK : boolean;
begin
-- Defaults.
DMA_SND <= '0';
--
case CTRL_STATE is
when IDLE =>
if ARB_EN = '1' and BUS_FREE = '1' then
NEXT_CTRL_STATE <= WAIT_800ns;
else
NEXT_CTRL_STATE <= IDLE;
end if;
when WAIT_800ns =>
if DELAY_800ns = true then
NEXT_CTRL_STATE <= WAIT_2200ns;
else
NEXT_CTRL_STATE <= WAIT_800ns;
end if;
when WAIT_2200ns =>
-- In this state the delay is provided by the
-- microprocessor and is at least 2.2us. The
-- delay is released by deasserting SELn.
if SEL_INn = '1' and SDS = '1' then
NEXT_CTRL_STATE <= DMA_SEND;
elsif SEL_INn = '1' and SDT = '1' then
NEXT_CTRL_STATE <= DMA_TARG_RCV;
elsif SEL_INn = '1' and SDI = '1' then
NEXT_CTRL_STATE <= DMA_INIT_RCV;
else
NEXT_CTRL_STATE <= WAIT_2200ns;
end if;
when DMA_SEND =>
if DMA_ACTIVE_I = '0' then
NEXT_CTRL_STATE <= IDLE;
else
NEXT_CTRL_STATE <= DMA_SEND;
end if;
--
DMA_SND <= '1';
when DMA_TARG_RCV =>
if DMA_ACTIVE_I = '0' then
NEXT_CTRL_STATE <= IDLE;
else
NEXT_CTRL_STATE <= DMA_TARG_RCV;
end if;
when DMA_INIT_RCV =>
if DMA_ACTIVE_I = '0' then
NEXT_CTRL_STATE <= IDLE;
else
NEXT_CTRL_STATE <= DMA_INIT_RCV;
end if;
end case;
end process CTRL_DECODER;
DMA_DECODER: process(CTRL_STATE, DMA_STATE, TARG, BLK, DACKn, REQ_INn, ACK_INn)
-- This is the DMA state machine decoder.
begin
-- Defaults:
IDR_WR <= '0';
ODR_WR <= '0';
CHK_PAR <= '0';
--
case DMA_STATE is
when IDLE =>
if CTRL_STATE = DMA_SEND then
NEXT_DMA_STATE <= DMA_STEP_1;
elsif CTRL_STATE = DMA_INIT_RCV then
NEXT_DMA_STATE <= DMA_STEP_1;
elsif CTRL_STATE = DMA_TARG_RCV then
NEXT_DMA_STATE <= DMA_STEP_1;
else
NEXT_DMA_STATE <= IDLE;
end if;
when DMA_STEP_1 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for REQn asserted.
IDR_WR <= '1';
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for REQn asserted.
IDR_WR <= '1';
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
ODR_WR <= '1';
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for ACKn asserted.
IDR_WR <= '1';
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for ACKn asserted.
IDR_WR <= '1';
else
NEXT_DMA_STATE <= DMA_STEP_1;
end if;
when DMA_STEP_2 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for REQn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for REQn deasserted.
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for ACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for ACKn deasserted.
else
NEXT_DMA_STATE <= DMA_STEP_2;
end if;
when DMA_STEP_3 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait REQn asserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and REQ_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait REQn asserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait ACKn asserted.
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' and ACK_INn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait ACKn asserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and DACKn = '0' then
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
CHK_PAR <= '1';
else
NEXT_DMA_STATE <= DMA_STEP_3;
end if;
when DMA_STEP_4 =>
-- Initiator modes:
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait REQn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and REQ_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait REQn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
-- Target modes:
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait ACKn deasserted.
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' and ACK_INn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait ACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and DACKn = '1' then
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
else
NEXT_DMA_STATE <= DMA_STEP_4;
end if;
end case;
end process DMA_DECODER;
P_REQn: process(DMA_STATE, CTRL_STATE, TARG, BLK)
-- This logic controls the REQn output in target mode.
begin
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '0' then
REQ_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
REQ_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' then
REQ_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
REQ_OUTn <= '0';
else
REQ_OUTn <= '1';
end if;
end process P_REQn;
P_ACKn: process(DMA_STATE, CTRL_STATE, TARG, BLK)
-- This logic controls the ACKn output in initiator mode.
begin
if DMA_STATE = DMA_STEP_2 and CTRL_STATE = DMA_INIT_RCV and BLK = '0' then
ACK_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_2 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
ACK_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_4 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' then
ACK_OUTn <= '0';
elsif DMA_STATE = DMA_STEP_4 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' then
ACK_OUTn <= '0';
else
ACK_OUTn <= '1';
end if;
end process P_ACKn;
P_READY: process(DMA_STATE, CTRL_STATE, TARG, BLK)
-- This logic controls the READY output in initiator and target block mode.
begin
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
READY <= '1';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
READY <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' then
READY <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
READY <= '1';
else
READY <= '0';
end if;
end process P_READY;
P_DRQ: process(RESETn, CLK)
-- This flip flop controls the DRQ flag during all initiator and all target modes
-- for both block mode and non block mode operation.
variable LOCK : boolean;
begin
if RESETn = '0' then
DRQ <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
-- Initiator modes:
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and LOCK = false then
DRQ <= '1';
LOCK := true;
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
DRQ <= '1';
LOCK := true;
-- Target modes:
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
DRQ <= '1';
LOCK := true;
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '0' then
DRQ <= '1';
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
DRQ <= '1';
LOCK := true;
elsif DACKn = '0' and LOCK = false then
DRQ <= '0';
elsif EOPn = '0' and DACKn = '0' then
DRQ <= '0';
LOCK := false;
end if;
end if;
end process P_DRQ;
P_BUSFREE: process(RESETn, CLK)
-- This is the logic for the bus free signal.
-- A bus free is valid if the BSY_INn signal is
-- at least 437.5ns inactive ans SEL_INn is inactive.
-- The delay are 7 clock cycles of 16MHz.
variable TMP : std_logic_vector(2 downto 0);
begin
if RESETn = '0' then
BUS_FREE <= '0';
TMP := "000";
elsif CLK = '1' and CLK' event then
if BSY_INn = '1' and TMP < x"111" then
TMP := TMP + '1';
elsif BSY_INn = '0' then
TMP := "000";
end if;
--
if RSTn = '0' then -- SCSI reset.
BUS_FREE <= '0';
elsif SEL_INn = '1' and TMP = "111" then
BUS_FREE <= '1';
else
BUS_FREE <= '0';
end if;
end if;
end process P_BUSFREE;
DELAY_800: process(RESETn, CLK)
-- This is the delay of 812.5ns.
-- It is derived from 13 16MHz clock cycles.
variable TMP : std_logic_vector(3 downto 0);
begin
if RESETn = '0' then
DELAY_800ns <= false;
TMP := x"0";
elsif CLK = '1' and CLK' event then
if CTRL_STATE /= WAIT_800ns then
TMP := x"0";
elsif TMP <= x"D" then
TMP := TMP + '1';
end if;
--
if TMP = x"D" then
DELAY_800ns <= true;
else
DELAY_800ns <= false;
end if;
end if;
end process DELAY_800;
P_ARB: process(RESETn, CLK)
-- This flip flop controls the ARB flag read back
-- by the microcontroller.
begin
if RESETn = '0' then
ARB <= '0';
elsif CLK = '1' and CLK' event then
if CTRL_STATE /= WAIT_800ns and NEXT_CTRL_STATE = WAIT_800ns then
ARB <= '1';
elsif ARB_EN = '0' then
ARB <= '0';
end if;
end if;
end process P_ARB;
P_AIP: process(RESETn, CLK)
-- This flip flop controls the AIP flag read back
-- by the microcontroller.
begin
if RESETn = '0' then
AIP <= '0';
elsif CLK = '1' and CLK' event then
if CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
AIP <= '1';
elsif ARB_EN = '0' then
AIP <= '0';
end if;
end if;
end process P_AIP;
P_BSY: process
-- This flip flop controls the BSYn output
-- to the SCSI bus.
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
BSY_OUTn <= '1';
elsif CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
BSY_OUTn <= '0';
elsif ARB_EN = '0' then
BSY_OUTn <= '1';
end if;
end process P_BSY;
P_DATA_EN: process(RESETn, CLK)
-- This flip flop controls the data enable
-- of the SCSI bus.
begin
if RESETn = '0' then
DATA_EN <= '0';
elsif CLK = '1' and CLK' event then
if CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
DATA_EN <= '1';
elsif ARB_EN = '0' then
DATA_EN <= '0';
end if;
end if;
end process P_DATA_EN;
P_LA: process(RESETn, CLK)
-- This flip flop controls the LA
-- (lost arbitration) flag.
begin
if RESETn = '0' then
LA <= '0';
elsif CLK = '1' and CLK' event then
if (CTRL_STATE = WAIT_800ns or CTRL_STATE = WAIT_2200ns) and SEL_INn = '0' then
LA <= '1';
elsif ARB_EN = '0' then
LA <= '0';
end if;
end if;
end process P_LA;
P_DMA_ACTIVE: process(RESETn, CLK, DMA_ACTIVE_I)
-- This is the Flip Flop indicating if there is DMA
-- operation.
begin
if RESETn = '0' then
DMA_ACTIVE_I <= '0';
elsif CLK = '1' and CLK' event then
if DMA_EN = '1' and SDS = '1' then
DMA_ACTIVE_I <= '1'; -- Start DMA send.
elsif DMA_EN = '1' and SDT = '1' then
DMA_ACTIVE_I <= '1'; -- Start DMA target receive.
elsif DMA_EN = '1' and SDI = '1' then
DMA_ACTIVE_I <= '1'; -- Start DMA initiator receive.
elsif DMA_EN = '0' then
DMA_ACTIVE_I <= '0'; -- Halt DMA via DMA flag in MR2.
elsif EOP_In = '0' then
DMA_ACTIVE_I <= '0'; -- Halt DMA via EOPn.
elsif PHSM = '0' then
DMA_ACTIVE_I <= '0'; -- Halt DMA via phase mismatch.
end if;
end if;
--
DMA_ACTIVE <= DMA_ACTIVE_I;
end process P_DMA_ACTIVE;
INTERRUPTS: process(RESETn, CLK)
-- This is the logic for all DP5380's interrupt sources.
-- A busy interrupt occurs if the BSY_INn signal is at
-- least 437.5ns inactive. The delay are 7 clock cycles
-- of 16MHz. This logic also provides the respective
-- error flags for the BSR.
variable TMP : std_logic_vector(2 downto 0);
begin
if RESETn = '0' then
INT <= '0';
BSY_ERR <= '0';
TMP := "000";
elsif CLK = '1' and CLK' event then
if SPER = '1' and PINT_EN = '1' then
INT <= '1'; -- Parity interrupt.
elsif RPI = '0' then -- Reset interrupts.
INT <= '0';
end if;
--
if EOP_In = '0' and CTRL_STATE = DMA_SEND then
BSY_ERR <= '1'; -- End of DMA error.
elsif EOP_In = '0' and CTRL_STATE = DMA_TARG_RCV then
BSY_ERR <= '1'; -- End of DMA error.
elsif EOP_In = '0' and CTRL_STATE = DMA_INIT_RCV then
BSY_ERR <= '1'; -- End of DMA error.
elsif DMA_EN = '0' then -- Reset error.
INT <= '0';
end if;
--
if EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_SEND then
INT <= '1'; -- End of DMA interrupt.
elsif EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_TARG_RCV then
INT <= '1'; -- End of DMA interrupt.
elsif EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_INIT_RCV then
INT <= '1'; -- End of DMA interrupt.
elsif DMA_EN = '0' then -- Reset interrupt.
INT <= '0';
end if;
--
if PHSM = '0' then
INT <= '1'; -- Phase mismatch interrupt.
elsif DMA_EN = '0' then -- Reset interrupts.
INT <= '0';
end if;
--
if SEL_INn = '0' and BSY_INn = '1' and SER_ID = '1' then
INT <= '1'; -- (Re)Selection interrupt.
elsif RPI = '1' then -- Reset interrupts.
INT <= '0';
end if;
--
if BSY_INn = '1' and TMP < x"111" then
TMP := TMP + '1'; -- Bus settle delay.
elsif BSY_INn = '0' then
TMP := "000";
end if;
--
if BSY_DISn = '1' and BSY_INn = '1' and TMP = x"111" then
INT <= '1'; -- Busy monitoring interrupt.
BSY_ERR <= '1';
elsif RPI = '1' then -- Reset interrupts.
INT <= '0';
BSY_ERR <= '0';
end if;
--
end if;
end process INTERRUPTS;
end BEHAVIOUR;

View File

@@ -0,0 +1,139 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the package file of the ip core. ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 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 2K9A 2009/06/20 WF
-- Initial Release.
library ieee;
use ieee.std_logic_1164.all;
package WF5380_PKG is
component WF5380_REGISTERS
port (
CLK : in bit;
RESETn : in bit;
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
CSn : in bit;
RDn : in bit;
WRn : in bit;
RSTn : in bit;
RST : out bit;
ARB_EN : out bit;
DMA_ACTIVE : in bit;
DMA_EN : out bit;
BSY_DISn : out bit;
EOP_EN : out bit;
PINT_EN : out bit;
SPER : out bit;
TARG : out bit;
BLK : out bit;
DMA_DIS : in bit;
IDR_WR : in bit;
ODR_WR : in bit;
CHK_PAR : in bit;
AIP : in bit;
ARB : in bit;
LA : in bit;
CSD : in bit_vector(7 downto 0);
CSB : in bit_vector(7 downto 0);
BSR : in bit_vector(7 downto 0);
ODR_OUT : out bit_vector(7 downto 0);
ICR_OUT : out bit_vector(7 downto 0);
TCR_OUT : out bit_vector(3 downto 0);
SER_OUT : out bit_vector(7 downto 0);
SDS : out bit;
SDT : out bit;
SDI : out bit;
RPI : out bit
);
end component;
component WF5380_CONTROL
port (
CLK : in bit;
RESETn : in bit;
BSY_INn : in bit;
BSY_OUTn : out bit;
DATA_EN : out bit;
SEL_INn : in bit;
ARB_EN : in bit;
BSY_DISn : in bit;
RSTn : in bit;
ARB : out bit;
AIP : out bit;
LA : out bit;
ACK_INn : in bit;
ACK_OUTn : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
DACKn : in bit;
READY : out bit;
DRQ : out bit;
TARG : in bit;
BLK : in bit;
PINT_EN : in bit;
SPER : in bit;
SER_ID : in bit;
RPI : in bit;
DMA_EN : in bit;
SDS : in bit;
SDT : in bit;
SDI : in bit;
EOP_EN : in bit;
EOPn : in bit;
PHSM : in bit;
INT : out bit;
IDR_WR : out bit;
ODR_WR : out bit;
CHK_PAR : out bit;
BSY_ERR : out bit;
DMA_SND : out bit;
DMA_ACTIVE : out bit
);
end component;
end WF5380_PKG;

View File

@@ -0,0 +1,265 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the 5380's register model. ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Register description (for more information see the DP5380 ----
---- data sheet: ----
---- ODR (address 0) Output data register, write only. ----
---- CSD (address 0) Current SCSI data, read only. ----
---- ICR (address 1) Initiator command register, read/write. ----
---- MR2 (address 2) Mode register 2, read/write. ----
---- TCR (address 3) Target command register, read/write. ----
---- SER (address 4) Select enable register, write only. ----
---- CSB (address 4) Current SCSI bus status, read only. ----
---- BSR (address 5) Start DMA send, write only. ----
---- SDS (address 5) Bus and status, read only. ----
---- SDT (address 6) Start DMA target receive, write only. ----
---- IDR (address 6) Input data register, read only. ----
---- SDI (address 7) Start DMA initiator recive, write only. ----
---- RPI (address 7) Reset parity / interrupts, read only. ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 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 2K9A 2009/06/20 WF
-- Initial Release.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_REGISTERS is
port (
-- System controls:
CLK : in bit;
RESETn : in bit; -- System reset.
-- Address and data:
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
-- Bus and DMA controls:
CSn : in bit;
RDn : in bit;
WRn : in bit;
-- Core controls:
RSTn : in bit; -- SCSI reset.
RST : out bit; -- Programmed SCSI reset.
ARB_EN : out bit; -- Arbitration enable.
DMA_ACTIVE : in bit; -- DMA is running.
DMA_EN : out bit; -- DMA mode enable.
BSY_DISn : out bit; -- BSY monitoring enable.
EOP_EN : out bit; -- EOP interrupt enable.
PINT_EN : out bit; -- Parity interrupt enable.
SPER : out bit; -- Parity error.
TARG : out bit; -- Target mode.
BLK : out bit; -- Block DMA mode.
DMA_DIS : in bit; -- Reset the DMA_EN by this signal.
IDR_WR : in bit; -- Write input data register during DMA.
ODR_WR : in bit; -- Write output data register, during DMA.
CHK_PAR : in bit; -- Check Parity during DMA operation.
AIP : in bit; -- Arbitration in progress.
ARB : in bit; -- Arbitration.
LA : in bit; -- Lost arbitration.
CSD : in bit_vector(7 downto 0); -- SCSI data.
CSB : in bit_vector(7 downto 0); -- Current SCSI bus status.
BSR : in bit_vector(7 downto 0); -- Bus and status.
ODR_OUT : out bit_vector(7 downto 0); -- This is the ODR register.
ICR_OUT : out bit_vector(7 downto 0); -- This is the ICR register.
TCR_OUT : out bit_vector(3 downto 0); -- This is the TCR register.
SER_OUT : out bit_vector(7 downto 0); -- This is the SER register.
SDS : out bit; -- Start DMA send, write only.
SDT : out bit; -- Start DMA target receive, write only.
SDI : out bit; -- Start DMA initiator receive, write only.
RPI : out bit
);
end entity WF5380_REGISTERS;
architecture BEHAVIOUR of WF5380_REGISTERS is
signal ICR : bit_vector(7 downto 0); -- Initiator command register, read/write.
signal IDR : bit_vector(7 downto 0); -- Input data register.
signal MR2 : bit_vector(7 downto 0); -- Mode register 2, read/write.
signal ODR : bit_vector(7 downto 0); -- Output data register, write only.
signal SER : bit_vector(7 downto 0); -- Select enable register, write only.
signal TCR : bit_vector(3 downto 0); -- Target command register, read/write.
begin
REGISTERS: process(RESETn, CLK)
-- This process reflects all registers in the 5380.
variable BSY_LOCK : boolean;
begin
if RESETn = '0' then
ODR <= (others => '0');
ICR <= (others => '0');
MR2 <= (others => '0');
TCR <= (others => '0');
SER <= (others => '0');
BSY_LOCK := false;
elsif CLK = '1' and CLK' event then
if RSTn = '0' then -- SCSI reset.
ODR <= (others => '0');
ICR(6 downto 0) <= (others => '0');
MR2(7) <= '0';
MR2(5 downto 0) <= (others => '0');
TCR <= (others => '0');
SER <= (others => '0');
BSY_LOCK := false;
elsif ADR = "000" and CSn = '0' and WRn = '0' then
ODR <= DATA_IN;
elsif ADR = "001" and CSn = '0' and WRn = '0' then
ICR <= DATA_IN;
elsif ADR = "010" and CSn = '0' and WRn = '0' then
MR2 <= DATA_IN;
elsif ADR = "011" and CSn = '0' and WRn = '0' then
TCR <= DATA_IN(3 downto 0);
elsif ADR = "100" and CSn = '0' and WRn = '0' then
SER <= DATA_IN;
end if;
--
if ODR_WR = '1' then
ODR <= DATA_IN;
end if;
--
-- This reset function is edge triggered on the 'Monitor Busy'
-- MR2(2).
if MR2(2) = '1' and BSY_LOCK = false then
ICR(5 downto 0) <= "000000";
BSY_LOCK := true;
elsif MR2(2) = '0' then
BSY_LOCK := false;
end if;
--
if DMA_DIS = '1' then
MR2(1) <= '0';
end if;
end if;
end process REGISTERS;
IDR_REGISTER: process(RESETn, CLK)
begin
if RESETn = '0' then
IDR <= x"00";
elsif CLK = '1' and CLK' event then
if RSTn = '0' or ICR(7) = '1' then
IDR <= x"00"; -- SCSI reset.
elsif IDR_WR = '1' then
IDR <= CSD;
end if;
end if;
end process IDR_REGISTER;
PARITY: process(RESETn, CLK)
-- This is the parity generating logic with it's related
-- error generation.
variable PAR_VAR : bit;
variable LOCK : boolean;
begin
if RESETn = '0' then
SPER <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
-- Parity checked during 'Read from CSD'
-- (registered I/O and selection/reselection):
if ADR = "000" and CSn = '0' and RDn = '0' and LOCK = false then
for i in 1 to 7 loop
PAR_VAR := CSD(i) xor CSD(i-1);
end loop;
SPER <= not PAR_VAR;
LOCK := true;
end if;
--
-- Parity checking during DMA operation:
if DMA_ACTIVE = '1' and CHK_PAR = '1' then
for i in 1 to 7 loop
PAR_VAR := IDR(i) xor IDR(i-1);
end loop;
SPER <= not PAR_VAR;
LOCK := true;
end if;
--
-- Reset parity flag:
if MR2(5) <= '0' then -- MR2(5) = PCHK (disabled).
SPER <= '0';
elsif ADR = "111" and CSn = '0' and RDn = '0' then -- Reset parity/interrupts.
SPER <= '0';
LOCK := false;
end if;
end if;
end process PARITY;
DATA_EN <= '1' when ADR < "101" and CSn = '0' and WRn = '0' else '0';
SDS <= '1' when ADR = "101" and CSn = '0' and WRn = '0' else '0';
SDT <= '1' when ADR = "110" and CSn = '0' and WRn = '0' else '0';
SDI <= '1' when ADR = "111" and CSn = '0' and WRn = '0' else '0';
ICR_OUT <= ICR;
TCR_OUT <= TCR;
SER_OUT <= SER;
ODR_OUT <= ODR;
ARB_EN <= MR2(0);
DMA_EN <= MR2(1);
BSY_DISn <= MR2(2);
EOP_EN <= MR2(3);
PINT_EN <= MR2(4);
TARG <= MR2(6);
BLK <= MR2(7);
RST <= ICR(7);
-- Readback, unused bit positions are read back zero.
DATA_OUT <= CSD when ADR = "000" and CSn = '0' and RDn = '0' else -- Current SCSI data.
ICR(7) & AIP & LA & ICR(4 downto 0) when ADR = "001" and CSn = '0' and RDn = '0' else
MR2 when ADR = "010" and CSn = '0' and RDn = '0' else
x"0" & TCR when ADR = "011" and CSn = '0' and RDn = '0' else
CSB when ADR = "100" and CSn = '0' and RDn = '0' else -- Current SCSI bus status.
BSR when ADR = "101" and CSn = '0' and RDn = '0' else -- Bus and status.
IDR when ADR = "110" and CSn = '0' and RDn = '0' else x"00"; -- Input data register.
RPI <= '1' when ADR = "111" and CSn = '0' and RDn = '0' else '0'; -- Reset parity/interrupts.
end BEHAVIOUR;

View File

@@ -0,0 +1,300 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- Some remarks to the required input clock: ----
---- This core is provided for a 16MHz input clock. To use other ----
---- frequencies, it is necessary to modify the following proces- ----
---- ses in the control file section: ----
---- P_BUSFREE, DELAY_800, INTERRUPTS. ----
---- ----
---- This file is the top level file without tree state buses for ----
---- use in 'systems on chip' designs. ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 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 2K9A 2009/06/20 WF
-- Initial Release.
--
library work;
use work.wf5380_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_TOP_SOC is
port (
-- System controls:
CLK : in bit; -- Use a 16MHz Clock.
RESETn : in bit;
-- Address and data:
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
-- Bus and DMA controls:
CSn : in bit;
RDn : in bit;
WRn : in bit;
EOPn : in bit;
DACKn : in bit;
DRQ : out bit;
INT : out bit;
READY : out bit;
-- SCSI bus:
DB_INn : in bit_vector(7 downto 0);
DB_OUTn : out bit_vector(7 downto 0);
DB_EN : out bit;
DBP_INn : in bit;
DBP_OUTn : out bit;
DBP_EN : out bit;
RST_INn : in bit;
RST_OUTn : out bit;
RST_EN : out bit;
BSY_INn : in bit;
BSY_OUTn : out bit;
BSY_EN : out bit;
SEL_INn : in bit;
SEL_OUTn : out bit;
SEL_EN : out bit;
ACK_INn : in bit;
ACK_OUTn : out bit;
ACK_EN : out bit;
ATN_INn : in bit;
ATN_OUTn : out bit;
ATN_EN : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
REQ_EN : out bit;
IOn_IN : in bit;
IOn_OUT : out bit;
IO_EN : out bit;
CDn_IN : in bit;
CDn_OUT : out bit;
CD_EN : out bit;
MSG_INn : in bit;
MSG_OUTn : out bit;
MSG_EN : out bit
);
end entity WF5380_TOP_SOC;
architecture STRUCTURE of WF5380_TOP_SOC is
signal ACK_OUT_CTRLn : bit;
signal AIP : bit;
signal ARB : bit;
signal ARB_EN : bit;
signal BLK : bit;
signal BSR : bit_vector(7 downto 0);
signal BSY_DISn : bit;
signal BSY_ERR : bit;
signal BSY_OUT_CTRLn : bit;
signal CHK_PAR : bit;
signal CSD : bit_vector(7 downto 0);
signal CSB : bit_vector(7 downto 0);
signal DATA_EN_CTRL : bit;
signal DB_EN_I : bit;
signal DMA_ACTIVE : bit;
signal DMA_EN : bit;
signal DMA_DIS : bit;
signal DMA_SND : bit;
signal DRQ_I : bit;
signal EDMA : bit;
signal EOP_EN : bit;
signal ICR : bit_vector(7 downto 0);
signal IDR_WR : bit;
signal INT_I : bit;
signal LA : bit;
signal ODR : bit_vector(7 downto 0);
signal ODR_WR : bit;
signal PCHK : bit;
signal PHSM : bit;
signal PINT_EN : bit;
signal REQ_OUT_CTRLn : bit;
signal RPI : bit;
signal RST : bit;
signal SDI : bit;
signal SDS : bit;
signal SDT : bit;
signal SER : bit_vector(7 downto 0);
signal SER_ID : bit;
signal SPER : bit;
signal TARG : bit;
signal TCR : bit_vector(3 downto 0);
begin
EDMA <= '1' when EOPn = '0' and DACKn = '0' and RDn = '0' else
'1' when EOPn = '0' and DACKn = '0' and WRn = '0' else '0';
PHSM <= '1' when DMA_ACTIVE = '0' else -- Always true, if there is no DMA.
'1' when DMA_ACTIVE = '1' and REQ_INn = '0' and CDn_In = TCR(1) and IOn_IN = TCR(0) and MSG_INn = TCR(2) else '0'; -- Phasematch.
DMA_DIS <= '1' when DMA_ACTIVE = '1' and BSY_INn = '1' else '0';
SER_ID <= '1' when SER /= x"00" and SER = not CSD else '0';
DRQ <= DRQ_I;
INT <= INT_I;
-- Pay attention: the SCSI bus is driven with inverted signals.
ACK_OUTn <= ACK_OUT_CTRLn when DMA_ACTIVE = '1' else not ICR(4); -- Valid in initiator mode.
REQ_OUTn <= REQ_OUT_CTRLn when DMA_ACTIVE = '1' else not TCR(3); -- Valid in Target mode.
BSY_OUTn <= '0' when BSY_OUT_CTRLn = '0' and TARG = '0' else -- Valid in initiator mode.
'0' when ICR(3) = '1' else '1';
ATN_OUTn <= not ICR(1); -- Valid in initiator mode.
SEL_OUTn <= not ICR(2); -- Valid in initiator mode.
IOn_OUT <= not TCR(0); -- Valid in Target mode.
CDn_OUT <= not TCR(1); -- Valid in Target mode.
MSG_OUTn <= not TCR(2); -- Valid in Target mode.
RST_OUTn <= not RST;
DB_OUTn <= not ODR;
DBP_OUTn <= not SPER;
CSD <= not DB_INn;
CSB <= not RST_INn & not BSY_INn & not REQ_INn & not MSG_INn & not CDn_IN & not IOn_IN & not SEL_INn & not DBP_INn;
BSR <= EDMA & DRQ_I & SPER & INT_I & PHSM & BSY_ERR & not ATN_INn & not ACK_INn;
-- Hi impedance control:
ATN_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
SEL_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
BSY_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
ACK_EN <= '1' when TARG = '0' else '0'; -- Initiator mode.
IO_EN <= '1' when TARG = '1' else '0'; -- Target mode.
CD_EN <= '1' when TARG = '1' else '0'; -- Target mode.
MSG_EN <= '1' when TARG = '1' else '0'; -- Target mode.
REQ_EN <= '1' when TARG = '1' else '0'; -- Target mode.
RST_EN <= '1' when RST = '1' else '0'; -- Open drain control.
-- Data enables:
DB_EN_I <= '1' when DATA_EN_CTRL = '1' else -- During Arbitration.
'1' when ICR(0) = '1' and TARG = '1' and DMA_SND = '1' else -- Target 'Send' mode.
'1' when ICR(0) = '1' and TARG = '0' and IOn_IN = '0' and PHSM = '1' else
'1' when ICR(6) = '1' else '0'; -- Test mode enable.
DB_EN <= DB_EN_I;
DBP_EN <= DB_EN_I;
I_REGISTERS: WF5380_REGISTERS
port map(
CLK => CLK,
RESETn => RESETn,
ADR => ADR,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
CSn => CSn,
RDn => RDn,
WRn => WRn,
RSTn => RST_INn,
RST => RST,
ARB_EN => ARB_EN,
DMA_ACTIVE => DMA_ACTIVE,
DMA_EN => DMA_EN,
BSY_DISn => BSY_DISn,
EOP_EN => EOP_EN,
PINT_EN => PINT_EN,
SPER => SPER,
TARG => TARG,
BLK => BLK,
DMA_DIS => DMA_DIS,
IDR_WR => IDR_WR,
ODR_WR => ODR_WR,
CHK_PAR => CHK_PAR,
AIP => AIP,
ARB => ARB,
LA => LA,
CSD => CSD,
CSB => CSB,
BSR => BSR,
ODR_OUT => ODR,
ICR_OUT => ICR,
TCR_OUT => TCR,
SER_OUT => SER,
SDS => SDS,
SDT => SDT,
SDI => SDI,
RPI => RPI
);
I_CONTROL: WF5380_CONTROL
port map(
CLK => CLK,
RESETn => RESETn,
BSY_INn => BSY_INn,
BSY_OUTn => BSY_OUT_CTRLn,
DATA_EN => DATA_EN_CTRL,
SEL_INn => SEL_INn,
ARB_EN => ARB_EN,
BSY_DISn => BSY_DISn,
RSTn => RST_INn,
ARB => ARB,
AIP => AIP,
LA => LA,
ACK_INn => ACK_INn,
ACK_OUTn => ACK_OUT_CTRLn,
REQ_INn => REQ_INn,
REQ_OUTn => REQ_OUT_CTRLn,
DACKn => DACKn,
READY => READY,
DRQ => DRQ_I,
TARG => TARG,
BLK => BLK,
PINT_EN => PINT_EN,
SPER => SPER,
SER_ID => SER_ID,
RPI => RPI,
DMA_EN => DMA_EN,
SDS => SDS,
SDT => SDT,
SDI => SDI,
EOP_EN => EOP_EN,
EOPn => EOPn,
PHSM => PHSM,
INT => INT_I,
IDR_WR => IDR_WR,
ODR_WR => ODR_WR,
CHK_PAR => CHK_PAR,
BSY_ERR => BSY_ERR,
DMA_SND => DMA_SND,
DMA_ACTIVE => DMA_ACTIVE
);
end STRUCTURE;

View File

@@ -0,0 +1,275 @@
----------------------------------------------------------------------
---- ----
---- WF5380 IP Core ----
---- ----
---- Description: ----
---- This model provides an asynchronous SCSI interface compa- ----
---- tible to the DP5380 from National Semiconductor and others. ----
---- ----
---- This file is the top level file with tree state buses. ----
---- ----
---- ----
---- ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 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 2K9A 2009/06/20 WF
-- Initial Release.
--
library work;
use work.wf5380_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF5380_TOP is
port (
-- System controls:
CLK : in bit;
RESETn : in bit;
-- Address and data:
ADR : in std_logic_vector(2 downto 0);
DATA : inout std_logic_vector(7 downto 0);
-- Bus and DMA controls:
CSn : in bit;
RDn : in bit;
WRn : in bit;
EOPn : in bit;
DACKn : in bit;
DRQ : out bit;
INT : out bit;
READY : out bit;
-- SCSI bus:
DBn : inout std_logic_vector(7 downto 0);
DBPn : inout std_logic;
RSTn : inout std_logic;
BSYn : inout std_logic;
SELn : inout std_logic;
ACKn : inout std_logic;
ATNn : inout std_logic;
REQn : inout std_logic;
IOn : inout std_logic;
CDn : inout std_logic;
MSGn : inout std_logic
);
end entity WF5380_TOP;
architecture STRUCTURE of WF5380_TOP is
component WF5380_TOP_SOC
port (
-- System controls:
CLK : in bit;
RESETn : in bit;
ADR : in bit_vector(2 downto 0);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
CSn : in bit;
RDn : in bit;
WRn : in bit;
EOPn : in bit;
DACKn : in bit;
DRQ : out bit;
INT : out bit;
READY : out bit;
DB_INn : in bit_vector(7 downto 0);
DB_OUTn : out bit_vector(7 downto 0);
DB_EN : out bit;
DBP_INn : in bit;
DBP_OUTn : out bit;
DBP_EN : out bit;
RST_INn : in bit;
RST_OUTn : out bit;
RST_EN : out bit;
BSY_INn : in bit;
BSY_OUTn : out bit;
BSY_EN : out bit;
SEL_INn : in bit;
SEL_OUTn : out bit;
SEL_EN : out bit;
ACK_INn : in bit;
ACK_OUTn : out bit;
ACK_EN : out bit;
ATN_INn : in bit;
ATN_OUTn : out bit;
ATN_EN : out bit;
REQ_INn : in bit;
REQ_OUTn : out bit;
REQ_EN : out bit;
IOn_IN : in bit;
IOn_OUT : out bit;
IO_EN : out bit;
CDn_IN : in bit;
CDn_OUT : out bit;
CD_EN : out bit;
MSG_INn : in bit;
MSG_OUTn : out bit;
MSG_EN : out bit
);
end component;
--
signal ADR_IN : bit_vector(2 downto 0);
signal DATA_IN : bit_vector(7 downto 0);
signal DATA_OUT : bit_vector(7 downto 0);
signal DATA_EN : bit;
signal DB_INn : bit_vector(7 downto 0);
signal DB_OUTn : bit_vector(7 downto 0);
signal DB_EN : bit;
signal DBP_INn : bit;
signal DBP_OUTn : bit;
signal DBP_EN : bit;
signal RST_INn : bit;
signal RST_OUTn : bit;
signal RST_EN : bit;
signal BSY_INn : bit;
signal BSY_OUTn : bit;
signal BSY_EN : bit;
signal SEL_INn : bit;
signal SEL_OUTn : bit;
signal SEL_EN : bit;
signal ACK_INn : bit;
signal ACK_OUTn : bit;
signal ACK_EN : bit;
signal ATN_INn : bit;
signal ATN_OUTn : bit;
signal ATN_EN : bit;
signal REQ_INn : bit;
signal REQ_OUTn : bit;
signal REQ_EN : bit;
signal IOn_IN : bit;
signal IOn_OUT : bit;
signal IO_EN : bit;
signal CDn_IN : bit;
signal CDn_OUT : bit;
signal CD_EN : bit;
signal MSG_INn : bit;
signal MSG_OUTn : bit;
signal MSG_EN : bit;
begin
ADR_IN <= To_BitVector(ADR);
DATA_IN <= To_BitVector(DATA);
DATA <= To_StdLogicVector(DATA_OUT) when DATA_EN = '1' else (others => 'Z');
DB_INn <= To_BitVector(DBn);
DBn <= To_StdLogicVector(DB_OUTn) when DB_EN = '1' else (others => 'Z');
DBP_INn <= To_Bit(DBPn);
RST_INn <= To_Bit(RSTn);
BSY_INn <= To_Bit(BSYn);
SEL_INn <= To_Bit(SELn);
ACK_INn <= To_Bit(ACKn);
ATN_INn <= To_Bit(ATNn);
REQ_INn <= To_Bit(REQn);
IOn_IN <= To_Bit(IOn);
CDn_IN <= To_Bit(CDn);
MSG_INn <= To_Bit(MSGn);
DBPn <= '1' when DBP_OUTn = '1' and DBP_EN = '1' else
'0' when DBP_OUTn = '0' and DBP_EN = '1' else 'Z';
RSTn <= '1' when RST_OUTn = '1' and RST_EN = '1'else
'0' when RST_OUTn = '0' and RST_EN = '1' else 'Z';
BSYn <= '1' when BSY_OUTn = '1' and BSY_EN = '1' else
'0' when BSY_OUTn = '0' and BSY_EN = '1' else 'Z';
SELn <= '1' when SEL_OUTn = '1' and SEL_EN = '1' else
'0' when SEL_OUTn = '0' and SEL_EN = '1' else 'Z';
ACKn <= '1' when ACK_OUTn = '1' and ACK_EN = '1' else
'0' when ACK_OUTn = '0' and ACK_EN = '1' else 'Z';
ATNn <= '1' when ATN_OUTn = '1' and ATN_EN = '1' else
'0' when ATN_OUTn = '0' and ATN_EN = '1' else 'Z';
REQn <= '1' when REQ_OUTn = '1' and REQ_EN = '1' else
'0' when REQ_OUTn = '0' and REQ_EN = '1' else 'Z';
IOn <= '1' when IOn_OUT = '1' and IO_EN = '1' else
'0' when IOn_OUT = '0' and IO_EN = '1' else 'Z';
CDn <= '1' when CDn_OUT = '1' and CD_EN = '1' else
'0' when CDn_OUT = '0' and CD_EN = '1' else 'Z';
MSGn <= '1' when MSG_OUTn = '1' and MSG_EN = '1' else
'0' when MSG_OUTn = '0' and MSG_EN = '1' else 'Z';
I_5380: WF5380_TOP_SOC
port map(
CLK => CLK,
RESETn => RESETn,
ADR => ADR_IN,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
CSn => CSn,
RDn => RDn,
WRn => WRn,
EOPn => EOPn,
DACKn => DACKn,
DRQ => DRQ,
INT => INT,
READY => READY,
DB_INn => DB_INn,
DB_OUTn => DB_OUTn,
DB_EN => DB_EN,
DBP_INn => DBP_INn,
DBP_OUTn => DBP_OUTn,
DBP_EN => DBP_EN,
RST_INn => RST_INn,
RST_OUTn => RST_OUTn,
RST_EN => RST_EN,
BSY_INn => BSY_INn,
BSY_OUTn => BSY_OUTn,
BSY_EN => BSY_EN,
SEL_INn => SEL_INn,
SEL_OUTn => SEL_OUTn,
SEL_EN => SEL_EN,
ACK_INn => ACK_INn,
ACK_OUTn => ACK_OUTn,
ACK_EN => ACK_EN,
ATN_INn => ATN_INn,
ATN_OUTn => ATN_OUTn,
ATN_EN => ATN_EN,
REQ_INn => REQ_INn,
REQ_OUTn => REQ_OUTn,
REQ_EN => REQ_EN,
IOn_IN => IOn_IN,
IOn_OUT => IOn_OUT,
IO_EN => IO_EN,
CDn_IN => CDn_IN,
CDn_OUT => CDn_OUT,
CD_EN => CD_EN,
MSG_INn => MSG_INn,
MSG_OUTn => MSG_OUTn,
MSG_EN => MSG_EN
);
end STRUCTURE;

View File

@@ -0,0 +1,253 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- Address mark detector file. This part detects the address ----
---- mark in the incoming data stream in FM and also in MFM mode ----
---- and provides therewith synchronisation information for the ----
---- control state machine and for the data separator in the ----
---- transceiver unit. ----
---- ----
------------------------------- Some theory -------------------------------------
---- Frequency modulation FM: ----
---- The frequency modulation works as follows: ----
---- 1. every first pulse of the clock and data line is a clock. ----
---- 2. every second pulse is a data. ----
---- 3. a logic 1 is represented by two consecutive pulses (clock and data). ----
---- 4. a logic 0 is represented by one clock pulse and no data pulse. ----
---- 5. Hence there are a maximum of two pulses per data bit. ----
---- 6. one clock and one data pulse come together in one bit cell. ----
---- 7. the duration of a bit cell in FM is 4 microseconds. ----
---- 8. an ID address mark is represented as data FE with clock C7. ----
---- 9. a DATA address mark is represented as data FB with clock C7. ----
---- Examples: ----
---- Binary data 1 1 0 0 1 0 1 1 is represented in FM as follows: ----
---- 1111101011101111 ----
---- the FE data 1 1 1 1 1 1 1 0 is represented as follows: ----
---- 1111111111111110 ----
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
---- results: 1111010101111110 this is the ID address mark. ----
---- the FB data 1 1 1 1 1 0 1 1 is represented as follows: ----
---- 1111111111101111 ----
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
---- results: 1111010101101111 this is the DATA address mark. ----
---- the F8 data 1 1 1 1 1 0 0 0 is represented as follows: ----
---- 1111111111101010 ----
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
---- results: 1111010101101010 this is the deleted DATA mark. ----
---- ----
---- ----
---- Modified frequency modulation MFM: ----
---- The modified frequency modulation works as follows: ----
---- 1. every first pulse of the clock and data line is a clock. ----
---- 2. every second pulse is a data. ----
---- 3. a logic 1 is represented by no clock but a data pulse. ----
---- 4. a logic 0 is represented by a clock pulse and no data pulse if ----
---- following a 0. ----
---- 5. a logic 0 is represented by no pulse if following a 1. ----
---- 6. Hence there are a maximum of one pulse per data bit. ----
---- 7. one clock and one data pulse form together one bit cell. ----
---- 8. the duration of a bit cell in MFM is 2 microseconds. ----
---- 9. an address mark sync is represented as data A1 with missing clock ----
---- pulse between bit 4 and 5. ----
---- Examples: ----
---- Binary data FE 1 1 1 1 1 1 1 0 is represented in MFM as follows: ----
---- 0101010101010100 this is the ID address mark. ----
---- Binary data FB 1 1 1 1 1 0 1 1 is represented in MFM as follows: ----
---- 0101010101000101 this is the DATA address mark. ----
---- Binary data F8 1 1 1 1 1 0 0 0 is represented in MFM as follows: ----
---- 0101010101001010 this is the deleted DATA address mark. ----
---- the A1 data 1 0 1 0 0 0 0 1 is represented as follows: ----
---- 0100010010101001 ----
---- with the missing clock pulse between bits 4 and 5 there results: ----
---- results: 0100010010001001 this is the address mark sync. ----
---- ----
---- Both MFM and FM are during read and write shifted with most significant ----
---- bit (MSB) first. During the FM address marks are written without a ----
---- SYNC pulse the MFM coded data requires a synchronisation (A1 with ----
---- missing clock pulse because at the beginning of the data stream it is ----
---- not defined wether a clock pulse or a data pulse appears first. In FM ----
---- coding the first pulse is in any case a clock pulse. ----
---------------------------------------------------------------------------------
---- ----
---- 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 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 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 WF1772IP_AM_DETECTOR is
port(
-- System control
CLK : in bit;
RESETn : in bit;
-- Controls:
DDEn : in bit;
-- Serial data and clock:
DATA : in bit;
DATA_STRB : in bit;
-- Address mark detector:
ID_AM : out bit; -- ID address mark strobe.
DATA_AM : out bit; -- Data address mark strobe.
DDATA_AM : out bit -- Deleted data address mark strobe.
);
end WF1772IP_AM_DETECTOR;
architecture BEHAVIOR of WF1772IP_AM_DETECTOR is
signal SHIFT : bit_vector(15 downto 0);
signal SYNC : boolean;
signal ID_AM_I : bit;
signal DATA_AM_I : bit;
signal DDATA_AM_I : bit;
begin
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT <= (others => '0');
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
-- MSB first leads to a shift left operation.
SHIFT <= SHIFT(14 downto 0) & DATA;
elsif DDEn = '0' and SHIFT = "0100010010001001" then -- This is the synchronisation in MFM.
SHIFT <= (others => '0');
end if;
end if;
end process SHIFTREG;
MFM_SYNCLOCK: process(RESETn, CLK)
-- The SYNC pulse is generated in MFM mode only when the sync character
-- appears in the shift register (A1 sync mark, see file header).
-- After the sync character is detected, the sync time counter is loaded
-- with a value of 17. During counting the following 17 read clock pulses
-- down, the SYNC is true. After exactly 16 pulses the address mark is
-- detected if the pattern in the shift register fits one of the address
-- marks. The address mark pulses are valid for one read clock cycle until
-- SYNC goes low again. This mechanism is used to detect the correct address
-- marks in the MFM data stream during the type III read track command.
-- This is an improvement over the original WD1772 chip.
variable TMP : std_logic_vector(4 downto 0);
begin
if RESETn = '0' then
TMP := "00000";
elsif CLK = '1' and CLK' event then
if SHIFT = "0100010010001001" and DDEn = '0' then
TMP := "10001"; -- Load sync time counter.
elsif DATA_STRB = '1' and TMP > "00000" then
TMP := TMP - '1';
end if;
end if;
case TMP is
when "00000" => SYNC <= false;
when others => SYNC <= true;
end case;
end process MFM_SYNCLOCK;
-- The addressmark is nominally valid for one data pulse cycle (1us, 2us, 4us).
-- The pulse is shorter due to the fact that the detected address marks change the
-- state of the control state machine and so clear the address mark shift register...
ID_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101111110" else
'1' when DDEn = '0' and SHIFT = "0101010101010100" and SYNC = true else '0';
DATA_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101101111" else
-- Normal data address mark...
'1' when DDEn = '0' and SHIFT = "0101010101000101" and SYNC = true else '0';
DDATA_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101101010" else
-- ... and deleted address mark in MFM mode:
'1' when DDEn = '0' and SHIFT = "0101010101001010" and SYNC = true else '0';
ADRMARK_STROBES: process(RESETn, CLK)
-- ... nevertheless The controller and the transceiver require ID address mark strobes
-- and DATA address mark strobes. Therefore this process provides these strobe
-- signals independant of any 'feedbacks' like pulse shortening by the controller
-- state machine itself.
variable ID_AM_LOCK, DATA_AM_LOCK, DDATA_AM_LOCK : boolean;
begin
if RESETn = '0' then
ID_AM_LOCK := false;
DATA_AM_LOCK := false;
ID_AM <= '0';
DATA_AM <= '0';
elsif CLK = '1' and CLK' event then
-- ID address mark:
if ID_AM_I = '1' and ID_AM_LOCK = false then
ID_AM <= '1';
ID_AM_LOCK := true;
elsif ID_AM_I = '0' then
ID_AM <= '0';
ID_AM_LOCK := false;
else
ID_AM <= '0';
end if;
-- Data address mark:
if DATA_AM_I = '1' and DATA_AM_LOCK = false then
DATA_AM <= '1';
DATA_AM_LOCK := true;
elsif DATA_AM_I = '0' then
DATA_AM <= '0';
DATA_AM_LOCK := false;
else
DATA_AM <= '0';
end if;
-- Deleted data address mark:
if DDATA_AM_I = '1' and DDATA_AM_LOCK = false then
DDATA_AM <= '1';
DDATA_AM_LOCK := true;
elsif DDATA_AM_I = '0' then
DDATA_AM <= '0';
DDATA_AM_LOCK := false;
else
DDATA_AM <= '0';
end if;
end if;
end process ADRMARK_STROBES;
end architecture BEHAVIOR;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- The CRC cyclic redundancy checker unit. Further description ----
---- see below. ----
---- ----
---- Working principle of the CRC generator and verify unit: ----
---- During read operation: ----
---- The CRC generator is switched on via after the detection of ----
---- the address ID of the data ID mark. The CRC generation last ----
---- in case of the address ID until the lenght byte is read. ----
---- In case of generation after the data address mark the CRC ----
---- generator is activated until the last data byte is read. ----
---- The number of data bytes to be read depends on the LENGHT ----
---- information in the header file. After generation of the CRC ----
---- the CRC_GEN is switched off and the VERIFY procedure begins ----
---- by activating CRC_VERIFY. The previously generated CRC is ----
---- then compared (serially) with the two consecutive read CRC ----
---- bytes. The CRC error appeas, when the comparision fails. ----
---- During write operation: ----
---- The CRC generator is switched on via after the detection of ----
---- the address ID of the data ID mark. The CRC generation last ----
---- in case of the address ID until the lenght byte is read. ----
---- In case of generation after the data address mark the CRC ----
---- generator is activated until the last data byte is read. ----
---- The number of data bytes to be read depends on the LENGHT ----
---- information in the header file. After the generation of the ----
---- two CRC bytes, the write out process begins by activating ----
---- CRC_SHFTOUT. The CRC data appears in this case serially on ----
---- the CRC_SDOUT. ----
---- ----
---- 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 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- CRC_SHIFT has now synchronous reset to meeet preset behaviour.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_CRC_LOGIC is
port(
-- System control
CLK : in bit;
RESETn : in bit;
DISK_RWn : in bit;
-- Preset controls:
DDEn : in bit;
ID_AM : in bit;
DATA_AM : in Bit;
DDATA_AM : in Bit;
-- CRC unit:
SD : in bit; -- Serial data input.
CRC_STRB : in bit; -- Data strobe.
CRC_2_DISK : in bit; -- Forces the unit to flush the CRC remainder.
CRC_PRES : in bit; -- Presets the CRC unit during write to disk.
CRC_SDOUT : out bit; -- Serial data output.
CRC_ERR : out bit -- Indicates CRC error.
);
end WF1772IP_CRC_LOGIC;
architecture BEHAVIOR of WF1772IP_CRC_LOGIC is
signal CRC_SHIFT : bit_vector(15 downto 0);
begin
P_CRC: process
-- The shift register is initialised with appropriate values in HD or DD mode.
-- In theory the shift register should be preset to ones. Due to a latency of one byte
-- in FM mode or 4 bytes in MFM mode it is necessary to preset the shift register with
-- the CRC values of this ID address mark, data address mark and the A1 sync bytes. The
-- latency is caused by the addressmark detector which needs one or 4 byte time(s) for
-- detection. The CRC unit therefore starts with every detection of an address mark and
-- ends if the CRC unit is flushed.
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
CRC_SHIFT <= (others => '1');
elsif CRC_2_DISK = '1' then
if CRC_STRB = '1' then
CRC_SHIFT <= CRC_SHIFT(14 downto 0) & '0';
end if;
elsif CRC_PRES = '1' then -- Preset during write sector or write track command.
CRC_SHIFT <= x"FFFF";
elsif DDEn = '1' and ID_AM = '1' then -- DD mode and ID address mark detected.
CRC_SHIFT <= x"EF21"; -- The CRC-CCITT for data x"FE" is x"EF21"
elsif DDEn = '1' and DATA_AM = '1' then -- DD mode and data address mark detected.
CRC_SHIFT <= x"BF84"; -- The CRC-CCITT for data x"FB" is x"BF84"
elsif DDEn = '1' and DDATA_AM = '1' then -- DD mode and deleted data address mark detected.
CRC_SHIFT <= x"8FE7"; -- The CRC-CCITT for data x"F8" is x"8FE7"
elsif DDEn = '0' and ID_AM = '1' then -- HD mode and ID address mark detected.
CRC_SHIFT <= x"B230"; -- The CRC-CCITT for data x"A1A1A1FE" is x"B230"
elsif DDEn = '0' and DATA_AM = '1' then -- HD mode and data address mark detected.
CRC_SHIFT <= x"E295"; -- The CRC-CCITT for data x"A1A1A1FB" is x"E295"
elsif DDEn = '0' and DDATA_AM = '1' then -- HD mode and deleted data address mark detected.
CRC_SHIFT <= x"D2F6"; -- The CRC-CCITT for data x"A1A1A1F8" is x"D2F6"
elsif CRC_STRB = '1' then
-- CRC-CCITT (xFFFF):
-- the polynomial is G(x) = x^16 + x^12 + x^5 + 1
-- In this mode the CRC is encoded. In read from disk mode, the encoding works as CRC
-- verification. In this operating condition the ID or the data field is compared
-- against the CRC checksum. if there are no errors, the shift register's value is
-- x"0000" after the last bit of the checksum is shifted in. In write to disk mode the
-- CRC linear feedback shift register (lfsr) works to generate the CRC remainder of the
-- ID or data field.
CRC_SHIFT <= CRC_SHIFT(14 downto 12) & (CRC_SHIFT(15) xor CRC_SHIFT(11) xor SD) &
CRC_SHIFT(10 downto 5) & (CRC_SHIFT(15) xor CRC_SHIFT(4) xor SD) &
CRC_SHIFT(3 downto 0) & (CRC_SHIFT(15) xor SD);
end if;
end process P_CRC;
CRC_SDOUT <= CRC_SHIFT(15);
CRC_ERR <= '0' when CRC_SHIFT = x"0000" else '1';
end architecture BEHAVIOR;

View File

@@ -0,0 +1,426 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- The digital PLL is responsible to detect the incoming serial ----
---- data stream and provide a system clock synchronous signal ----
---- containing the data and clock information. ----
---- To understand how the code works in detail refer to the free ----
---- US patent no. 4,780,844. ----
---- ----
---- Attention: The settings for TOP and BOTTOM, which control ----
---- the PLL frequency and for PHASE_CORR which control the PLL ----
---- phase are rather critical for a good read condition! To test ----
---- the PLL in the WD1772 compatible core do the following: ----
---- Sample on an oscilloscope on one channel the falling edge of ----
---- the RDn pulse and on the other channel the PLL_DSTRB. The ----
---- RDn must be located exactly between the PLL_DSTRB pulses. ----
---- Otherwise, the parameters TOP, BOTTOM and PHASE_CORR have to ----
---- be optimized. ----
---- ----
---- 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 2006A 2006/06/03 WF
-- Initial Release: the MFM portion for HD and DD floppies is tested.
-- The FM mode (DDEn = '1') is not completely tested due to lack of FM
-- drives.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K7B 2006/12/29 WF
-- Introduced several improvements based on a very good examination
-- of the pll code by Jean Louis-Guerin.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K8B 2008/12/24 WF
-- Improvement of the INPORT process.
-- Bugfix of the FREQ_AMOUNT counter: now stops if its value is zero.
-- Several changes concerning the PLL parameters to improve the
-- stability of the PLL.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_DIGITAL_PLL is
generic(
-- The valid range of the period counter of the PLL is given by the TOP and BOTTOM
-- limits. The counter range is therefore BOTTOM <= counter value <= TOP.
-- The generic PHASE_CORR is responsible fo the center setting of PLL_DSTRB concerning
-- the RDn period.
-- The nominal frequency setting is 128. So it is recommended to use TOP and BOTTOM
-- settings symmetrically around 128. If TOP = BOTTOM = 128, the frequency control
-- is disabled. TOP + PHASE_CORR may not exceed a value of 255. BOTTOM - PHASE_CORR
-- may not drop below zero.
TOP : integer range 0 to 255 := 152; -- +18.0%
BOTTOM : integer range 0 to 255 := 104; -- -18.0%
PHASE_CORR : integer range 0 to 128 := 75
);
port(
-- System control
CLK : in bit; -- 16MHz clock.
RESETn : in bit;
-- Controls
DDEn : in bit; -- Double density enable.
HDTYPE : in bit; -- This control is '1' when HD disks are inserted.
DISK_RWn : in bit; -- Read write control.
-- Data and clock lines
RDn : in bit; -- Read signal from the disk.
PLL_D : out bit; -- Synchronous read signal.
PLL_DSTRB : out bit -- Read strobe.
);
end WF1772IP_DIGITAL_PLL;
architecture BEHAVIOR of WF1772IP_DIGITAL_PLL is
signal RD_In : bit;
signal UP, DOWN : bit;
signal PHASE_DECREASE : bit;
signal PHASE_INCREASE : bit;
signal HI_STOP, LOW_STOP : bit;
signal PER_CNT : std_logic_vector(7 downto 0);
signal ADDER_IN : std_logic_vector(7 downto 0);
signal ADDER_MSBs : bit_vector(2 downto 0);
signal RD_PULSE : bit;
signal ROLL_OVER : bit;
signal HISTORY_REG : bit_vector(1 downto 0);
signal ERROR_HISTORY : integer range 0 to 2;
begin
INPORT: process
-- This process is necessary due to the poor quality of the rising
-- edge of RDn. Let it work on the negative clock edge.
begin
wait until CLK = '0' and CLK' event;
RD_In <= RDn;
end process INPORT;
EDGEDETECT: process(RESETn, CLK)
-- This process forms a falling edge detector for the incoming
-- data read port. The output (RD_PULSE) goes high for exactly
-- one clock period after the RDn is low and the positive
-- clock edge is detected.
variable LOCK : boolean;
begin
if RESETn = '0' then
RD_PULSE <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
if DISK_RWn = '0' then -- Disable detector in write mode.
RD_PULSE <= '0';
elsif RD_In = '0' and LOCK = false then
RD_PULSE <= '1'; -- READ_PULSE is inverted against RDn
LOCK := true;
elsif RD_In = '1' then
LOCK := false;
RD_PULSE <= '0';
else
RD_PULSE <= '0';
end if;
end if;
end process EDGEDETECT;
PERIOD_CNT: process(RESETn, CLK)
-- This process provides the nominal variable added to the adder. To achieve a good
-- settling time of the PLL in all cases, the period counter is controlled via the DDEn
-- and HDTYPE flags respective to its added value. Be aware, that in case of adding "10"
-- or "11", the TOP value may be exceeded or the period counter may drop below the BOTTOM
-- value. The higher the value added, the faster will be the settling time of phase locked
-- loop .
begin
if RESETn = '0' then
PER_CNT <= "10000000"; -- Initial value is 128.
elsif CLK = '1' and CLK' event then
if UP = '1' then
PER_CNT <= PER_CNT + '1';
elsif DOWN = '1' then
PER_CNT <= PER_CNT - '1';
end if;
end if;
end process PERIOD_CNT;
HI_STOP <= '1' when PER_CNT >= TOP else '0';
LOW_STOP <= '1' when PER_CNT <= BOTTOM else '0';
ADDER_IN <= -- This DISK_RWn = '0' implementation keeps the last phase information
-- of the PLL in read from disk mode. It should be a good solution concer-
-- ning alternative read write cycles.
"10000000" when DISK_RWn = '0' else -- Nominal value for write to disk.
PER_CNT + PHASE_CORR when PHASE_INCREASE = '1' else -- Phase lags.
PER_CNT - PHASE_CORR when PHASE_DECREASE = '1' else -- Phase leeds.
PER_CNT; -- No phase correction;
ADDER: process(RESETn, CLK, DDEn, HDTYPE)
-- Clock adjustment: The clock cycle is 62.5ns for the 16MHz system clock.
-- The offset (LSBs) of the adder input is chosen to be conform with the required
-- rollover period in the different DDEn and HDTYPE modi as follows:
-- With a nominal adder input term of 128:
-- The adder rolls over every 4us for DDEn = 1 and HDTYPE = 0.
-- The adder rolls over every 2us for DDEn = 1 and HDTYPE = 1.
-- The adder rolls over every 2us for DDEn = 0 and HDTYPE = 0.
-- The adder rolls over every 1us for DDEn = 0 and HDTYPE = 1.
-- The given times are the half of a data period time in MFM or FM.
variable ADDER_DATA : std_logic_vector(12 downto 0);
begin
if RESETn = '0' then
ADDER_DATA := (others => '0');
elsif CLK = '1' and CLK' event then
ADDER_DATA := ADDER_DATA + ADDER_IN;
end if;
--
case DDEn & HDTYPE is
when "01" => -- MFM mode using HD disks, results in 1us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(10 downto 8));
when "00" => -- MFM mode using DD disks, results in 2us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(11 downto 9));
when "11" => -- FM mode using HD disks, results in 2us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(11 downto 9));
when "10" => -- FM mode using DD disks, results in 4us inspection period:
ADDER_MSBs <= To_BitVector(ADDER_DATA(12 downto 10));
end case;
end process ADDER;
ROLLOVER: process(RESETn, CLK)
-- This process forms a falling edge detector for the detection
-- of the adder's rollover time. The output goes low for exactly
-- one clock period after the rollover is detected and the positive
-- clock edge appears.
variable LOCK : boolean;
begin
if RESETn = '0' then
ROLL_OVER <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
if ADDER_MSBs /= "111" and LOCK = false then
ROLL_OVER <= '1';
LOCK := true;
elsif ADDER_MSBs = "111" then
LOCK := false;
ROLL_OVER <= '0';
else
ROLL_OVER <= '0';
end if;
end if;
end process ROLLOVER;
PLL_DSTRB <= ROLL_OVER;
DATA_FLIP_FLOP: process(RESETn, CLK, RD_PULSE)
-- This flip-flop is responsible for 'catching' the read pulses of the
-- serial data input.
begin
if RESETn = '0' then
PLL_D <= '0'; -- Asynchronous reset.
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' then
PLL_D <= '1'; -- Read pulse detected.
elsif ROLL_OVER = '1' then
PLL_D <= '0';
end if;
end if;
end process DATA_FLIP_FLOP;
WIN_HISTORY: process(RESETn, CLK)
begin
if RESETn = '0' then
HISTORY_REG <= "00";
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' then
HISTORY_REG <= ADDER_MSBs(2) & HISTORY_REG(1);
end if;
end if;
end process WIN_HISTORY;
-- Error history:
-- This signal indicates the number of consequtive levels of the adder's
-- MSB and the history register as shown in the following table. The default
-- setting of 0 was added to compile with the Xilinx ISE.
ERROR_HISTORY <= 2 when ADDER_MSBs(2) = '0' and HISTORY_REG = "00" else -- Speed strongly up.
1 when ADDER_MSBs(2) = '0' and HISTORY_REG = "01" else -- Speed up.
0 when ADDER_MSBs(2) = '0' and HISTORY_REG = "10" else -- o.k.
0 when ADDER_MSBs(2) = '0' and HISTORY_REG = "11" else -- Now adjusted.
0 when ADDER_MSBs(2) = '1' and HISTORY_REG = "00" else -- Now adjusted.
0 when ADDER_MSBs(2) = '1' and HISTORY_REG = "01" else -- o.k.
1 when ADDER_MSBs(2) = '1' and HISTORY_REG = "10" else -- Slow down.
2 when ADDER_MSBs(2) = '1' and HISTORY_REG = "11" else 0; -- Slow strongly down.
FREQUENCY_DECODER: process(RESETn, CLK, HI_STOP, LOW_STOP)
-- The frequency decoder controls the period of the data inspection window respective to the
-- ERROR_HISTORY for the 11 bit adder is as follows:
-- ERROR_HISTORY = 0:
-- -> no correction necessary <-
-- ERROR_HISTORY = 1:
-- MSBs input: 7 6 5 4 3 2 1 0
-- Correction output: -3 -2 -1 0 0 +1 +2 +3
-- ERROR_HISTORY = 2:
-- MSBs input: 7 6 5 4 3 2 1 0
-- Correction output: -4 -3 -2 -1 +1 +2 +3 +4
-- The most significant bit of the FREQ_AMOUNT controls incrementation or decrementation
-- of the adder (0 is up).
variable FREQ_AMOUNT: std_logic_vector(3 downto 0);
begin
if RESETn = '0' then
FREQ_AMOUNT := "0000";
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' then -- Load the frequency amount register.
case ERROR_HISTORY is
when 2 =>
case ADDER_MSBs is
when "000" => FREQ_AMOUNT := "0100";
when "001" => FREQ_AMOUNT := "0011";
when "010" => FREQ_AMOUNT := "0010";
when "011" => FREQ_AMOUNT := "0001";
when "100" => FREQ_AMOUNT := "1001";
when "101" => FREQ_AMOUNT := "1010";
when "110" => FREQ_AMOUNT := "1011";
when "111" => FREQ_AMOUNT := "1100";
end case;
when 1 =>
case ADDER_MSBs is
when "000" => FREQ_AMOUNT := "0011";
when "001" => FREQ_AMOUNT := "0010";
when "010" => FREQ_AMOUNT := "0001";
when "011" => FREQ_AMOUNT := "0000";
when "100" => FREQ_AMOUNT := "1000";
when "101" => FREQ_AMOUNT := "1001";
when "110" => FREQ_AMOUNT := "1010";
when "111" => FREQ_AMOUNT := "1011";
end case;
when others =>
FREQ_AMOUNT := "0000";
end case;
elsif FREQ_AMOUNT(2 downto 0) > "000" then
FREQ_AMOUNT := FREQ_AMOUNT - '1'; -- Modify the frequency amount register.
end if;
end if;
--
if FREQ_AMOUNT(3) = '0' and FREQ_AMOUNT(2 downto 0) /= "000" and HI_STOP = '0' then
-- FREQ_AMOUNT(3) = '0' means Frequency is too low. Count up when counter is not at HI_STOP.
UP <= '1';
DOWN <= '0';
elsif FREQ_AMOUNT(3) = '1' and FREQ_AMOUNT (2 downto 0) /= "000" and LOW_STOP = '0' then
-- FREQ_AMOUNT(3) = '1' means Frequency is too high. Count down when counter is not at LOW_STOP.
UP <= '0';
DOWN <= '1';
else
UP <= '0';
DOWN <= '0';
end if;
end process FREQUENCY_DECODER;
PHASE_DECODER: process(RESETn, CLK)
-- The phase decoder depends on the value of ADDER_MSBs. If the phase leeds, the most significant bit
-- of PHASE_AMOUNT indicates with a '0', that the next rollover should appear earlier. In case of a
-- phase lag, the next rollover should come later (indicated by a '1' of the most significant bit of
-- PHASE_AMOUNT).
-- This implementation gives the freedom to adjust the phase amount individually for every mode
-- depending on DDEn and HDTYPE.
variable PHASE_AMOUNT: std_logic_vector(5 downto 0);
begin
if RESETn = '0' then
PHASE_AMOUNT := "000000";
elsif CLK = '1' and CLK' event then
if RD_PULSE = '1' and DDEn = '1' and HDTYPE = '0' then -- FM mode, single density.
case ADDER_MSBs is -- Multiplier: 4.
when "000" => PHASE_AMOUNT := "010000";
when "001" => PHASE_AMOUNT := "001101";
when "010" => PHASE_AMOUNT := "001000";
when "011" => PHASE_AMOUNT := "000100";
when "100" => PHASE_AMOUNT := "100100";
when "101" => PHASE_AMOUNT := "101000";
when "110" => PHASE_AMOUNT := "101100";
when "111" => PHASE_AMOUNT := "110000";
end case;
elsif RD_PULSE = '1' and DDEn = '1' and HDTYPE = '1' then -- FM mode, double density
case ADDER_MSBs is -- Multiplier: 2.
when "000" => PHASE_AMOUNT := "001000";
when "001" => PHASE_AMOUNT := "000110";
when "010" => PHASE_AMOUNT := "000100";
when "011" => PHASE_AMOUNT := "000010";
when "100" => PHASE_AMOUNT := "100010";
when "101" => PHASE_AMOUNT := "100100";
when "110" => PHASE_AMOUNT := "100110";
when "111" => PHASE_AMOUNT := "101000";
end case;
elsif RD_PULSE = '1' and DDEn = '0' and HDTYPE = '0' then -- MFM mode, single density
case ADDER_MSBs is -- Multiplier: 2.
when "000" => PHASE_AMOUNT := "000110";
when "001" => PHASE_AMOUNT := "000100";
when "010" => PHASE_AMOUNT := "000011";
when "011" => PHASE_AMOUNT := "000010";
when "100" => PHASE_AMOUNT := "100010";
when "101" => PHASE_AMOUNT := "100011";
when "110" => PHASE_AMOUNT := "100100";
when "111" => PHASE_AMOUNT := "100110";
end case;
elsif RD_PULSE = '1' and DDEn = '0' and HDTYPE = '1' then -- MFM mode, double density.
case ADDER_MSBs is -- Multiplier: 1.
when "000" => PHASE_AMOUNT := "000100";
when "001" => PHASE_AMOUNT := "000011";
when "010" => PHASE_AMOUNT := "000010";
when "011" => PHASE_AMOUNT := "000001";
when "100" => PHASE_AMOUNT := "100001";
when "101" => PHASE_AMOUNT := "100010";
when "110" => PHASE_AMOUNT := "100011";
when "111" => PHASE_AMOUNT := "100100";
end case;
else -- Modify phase amount register:
if PHASE_AMOUNT(4 downto 0) > x"0" then
PHASE_AMOUNT := PHASE_AMOUNT - 1;
end if;
end if;
end if;
--
if PHASE_AMOUNT(5) = '0' and PHASE_AMOUNT(4 downto 0) > x"0" then
-- PHASE_AMOUNT(5) = '0' means, that the phase leeds.
PHASE_INCREASE <= '1'; -- Speed phase up, accelerate next rollover.
PHASE_DECREASE <= '0';
elsif PHASE_AMOUNT(5) = '1' and PHASE_AMOUNT(4 downto 0) > x"0" then
-- PHASE_AMOUNT(5) = '1' means, that the phase lags.
PHASE_INCREASE <= '0';
PHASE_DECREASE <= '1'; -- Speed phase down, delay of next rollover.
else
PHASE_INCREASE <= '0';
PHASE_DECREASE <= '0';
end if;
end process PHASE_DECODER;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,232 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- This is the package file containing the component ----
---- declarations. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Removed CRC_BUSY.
library ieee;
use ieee.std_logic_1164.all;
package WF1772IP_PKG is
-- component declarations:
component WF1772IP_AM_DETECTOR
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
DATA : in bit;
DATA_STRB : in bit;
ID_AM : out bit;
DATA_AM : out bit;
DDATA_AM : out bit
);
end component;
component WF1772IP_CONTROL
port(
CLK : in bit;
RESETn : in bit;
A1, A0 : in bit;
RWn : in bit;
CSn : in bit;
DDEn : in bit;
DR : in bit_vector(7 downto 0);
CMD : in std_logic_vector(7 downto 0);
DSR : in std_logic_vector(7 downto 0);
TR : in std_logic_vector(7 downto 0);
SR : in std_logic_vector(7 downto 0);
MO : out bit;
WR_PR : out bit;
SPINUP_RECTYPE : out bit;
SEEK_RNF : out bit;
CRC_ERRFLAG : out bit;
LOST_DATA_TR00 : out bit;
DRQ : out bit;
DRQ_IPn : out bit;
BUSY : out bit;
AM_2_DISK : out bit;
ID_AM : in bit;
DATA_AM : in bit;
DDATA_AM : in bit;
CRC_ERR : in bit;
CRC_PRES : out bit;
TR_PRES : out bit;
TR_CLR : out bit;
TR_INC : out bit;
TR_DEC : out bit;
SR_LOAD : out bit;
SR_INC : out bit;
TRACK_NR : out std_logic_vector(7 downto 0);
DR_CLR : out bit;
DR_LOAD : out bit;
SHFT_LOAD_SD : out bit;
SHFT_LOAD_ND : out bit;
CRC_2_DISK : out bit;
DSR_2_DISK : out bit;
FF_2_DISK : out bit;
PRECOMP_EN : out bit;
DATA_STRB : in bit;
DISK_RWn : out bit;
WPRTn : in bit;
TRACK00n : in bit;
IPn : in bit;
DIRC : out bit;
STEP : out bit;
WG : out bit;
INTRQ : out bit
);
end component;
component WF1772IP_CRC_LOGIC
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
DISK_RWn : in bit;
ID_AM : in bit;
DATA_AM : in bit;
DDATA_AM : in bit;
SD : in bit;
CRC_STRB : in bit;
CRC_2_DISK : in bit;
CRC_PRES : in bit;
CRC_SDOUT : out bit;
CRC_ERR : out bit
);
end component;
component WF1772IP_DIGITAL_PLL
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
HDTYPE : in bit;
DISK_RWn : in bit;
RDn : in bit;
PLL_D : out bit;
PLL_DSTRB : out bit
);
end component;
component WF1772IP_REGISTERS
port(
CLK : in bit;
RESETn : in bit;
CSn : in bit;
ADR : in bit_vector(1 downto 0);
RWn : in bit;
DATA_IN : in std_logic_vector (7 downto 0);
DATA_OUT : out std_logic_vector (7 downto 0);
DATA_EN : out bit;
CMD : out std_logic_vector(7 downto 0);
SR : out std_logic_vector(7 downto 0);
TR : out std_logic_vector(7 downto 0);
DSR : out std_logic_vector(7 downto 0);
DR : out bit_vector(7 downto 0);
SD_R : in bit;
DATA_STRB : in bit;
DR_CLR : in bit;
DR_LOAD : in bit;
TR_PRES : in bit;
TR_CLR : in bit;
TR_INC : in bit;
TR_DEC : in bit;
TRACK_NR : in std_logic_vector(7 downto 0);
SR_LOAD : in bit;
SR_INC : in bit;
SHFT_LOAD_SD : in bit;
SHFT_LOAD_ND : in bit;
MOTOR_ON : in bit;
WRITE_PROTECT : in bit;
SPINUP_RECTYPE : in bit;
SEEK_RNF : in bit;
CRC_ERRFLAG : in bit;
LOST_DATA_TR00 : in bit;
DRQ : in bit;
DRQ_IPn : in bit;
BUSY : in bit;
DDEn : in bit
);
end component;
component WF1772IP_TRANSCEIVER
port(
CLK : in bit;
RESETn : in bit;
DDEn : in bit;
HDTYPE : in bit;
ID_AM : in bit;
DATA_AM : in bit;
DDATA_AM : in bit;
SHFT_LOAD_SD : in bit;
DR : in bit_vector(7 downto 0);
PRECOMP_EN : in bit;
AM_TYPE : in bit;
AM_2_DISK : in bit;
CRC_2_DISK : in bit;
DSR_2_DISK : in bit;
FF_2_DISK : in bit;
SR_SDOUT : in std_logic;
CRC_SDOUT : in bit;
WRn : out bit;
PLL_DSTRB : in bit;
PLL_D : in bit;
WDATA : out bit;
DATA_STRB : out bit;
SD_R : out bit
);
end component;
end WF1772IP_PKG;

View File

@@ -0,0 +1,264 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- This file models all the five WD1772 registers: DATA-, ----
---- COMMAND-, SECTOR-, TRACK- and STATUS register as also the ----
---- shift register. ----
---- ----
---- ----
---- 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 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 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 WF1772IP_REGISTERS is
port(
-- System control:
CLK : in bit;
RESETn : in bit;
-- Bus interface:
CSn : in bit;
ADR : in bit_vector(1 downto 0);
RWn : in bit;
DATA_IN : in std_logic_vector (7 downto 0);
DATA_OUT : out std_logic_vector (7 downto 0);
DATA_EN : out bit;
-- FDC data:
CMD : out std_logic_vector(7 downto 0); -- Command register.
SR : out std_logic_vector(7 downto 0); -- Sector register.
TR : out std_logic_vector(7 downto 0); -- Track register.
DSR : out std_logic_vector(7 downto 0); -- Data shift register.
DR : out bit_vector(7 downto 0); -- Data register.
-- Serial data and clock strobes (in and out):
DATA_STRB : in bit; -- Strobe for the incoming data.
SD_R : in bit; -- Serial data input.
-- DATA register control:
DR_CLR : in bit; -- Clear.
DR_LOAD : in bit; -- LOAD.
-- Track register controls:
TR_PRES : in bit; -- Set x"FF".
TR_CLR : in bit; -- Clear.
TR_INC : in bit; -- Increment.
TR_DEC : in bit; -- Decrement.
-- Sector register control:
TRACK_NR : in std_logic_vector(7 downto 0);
SR_LOAD : in bit; -- Load.
SR_INC : in bit; -- Increment.
-- Shift register control:
SHFT_LOAD_SD : in bit;
SHFT_LOAD_ND : in bit;
-- Status register stuff
MOTOR_ON : in bit;
WRITE_PROTECT : in bit;
SPINUP_RECTYPE : in bit; -- Disk is on speed / data mark status.
SEEK_RNF : in bit; -- Seek error / record not found status flag.
CRC_ERRFLAG : in bit; -- CRC status flag.
LOST_DATA_TR00 : in bit;
DRQ : in bit;
DRQ_IPn : in bit;
BUSY : in bit;
-- Others:
DDEn : in bit
);
end WF1772IP_REGISTERS;
architecture BEHAVIOR of WF1772IP_REGISTERS is
-- Remark: In the original data sheet 'WD17X-00' there is the following statement:
-- "After any register is written to, the same register cannot be read from until
-- 16us in MFM or 32us in FMMM have elapsed." If this is a hint for a hardware read
-- lock ... this lock is not implemented in this code.
signal SHIFT_REG : std_logic_vector(7 downto 0);
signal DATA_REG : std_logic_vector(7 downto 0);
signal COMMAND_REG : std_logic_vector(7 downto 0);
signal SECTOR_REG : std_logic_vector(7 downto 0);
signal TRACK_REG : std_logic_vector(7 downto 0);
signal STATUS_REG : bit_vector(7 downto 0);
signal SD_R_I : std_logic;
begin
-- Type conversion To_Std_Logic:
SD_R_I <= '1' when SD_R = '1' else '0';
P_SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if SHFT_LOAD_ND = '1' then
SHIFT_REG <= DATA_REG; -- Load data register stuff.
elsif SHFT_LOAD_SD = '1' and DDEn = '1' then
SHIFT_REG <= DATA_REG; -- Normal data in FM mode.
elsif SHFT_LOAD_SD = '1' and DDEn = '0' then -- MFM mode:
case DATA_REG is
when x"F5" => SHIFT_REG <= x"A1"; -- Special character.
when x"F6" => SHIFT_REG <= x"C2"; -- Special character.
when others => SHIFT_REG <= DATA_REG; -- Normal MFM data.
end case;
elsif DATA_STRB = '1' then -- Shift left during read from disk or write to disk.
SHIFT_REG <= SHIFT_REG(6 downto 0) & SD_R_I; -- for write operation SD_R_I is a dummy.
end if;
end if;
end process P_SHIFTREG;
DSR <= SHIFT_REG;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "11" and RWn = '0' then
DATA_REG <= DATA_IN; -- Write bus data to register
elsif DR_LOAD = '1' and DRQ = '0' then
DATA_REG <= SHIFT_REG; -- Correct data loaded to shift register.
elsif DR_LOAD = '1' and DRQ = '1' then
DATA_REG <= x"00"; -- Dummy byte due to lost data loaded to shift register.
elsif DR_CLR = '1' then
DATA_REG <= (others => '0');
end if;
end if;
end process DATAREG;
-- Data register buffered for further data processing.
DR <= To_BitVector(DATA_REG);
SECTORREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SECTOR_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "10" and RWn = '0' and BUSY = '0' then
SECTOR_REG <= DATA_IN; -- Write to register when device is not busy.
elsif SR_LOAD = '1' then
-- Load the track number to the sector register in the type III command
-- 'Read Address'.
SECTOR_REG <= TRACK_NR;
elsif SR_INC = '1' then
SECTOR_REG <= SECTOR_REG + '1';
end if;
end if;
end process SECTORREG;
SR <= SECTOR_REG;
TRACKREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TRACK_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "01" and RWn = '0' and BUSY = '0' then
TRACK_REG <= DATA_IN; -- Write to register when device is busy.
elsif TR_PRES = '1' then
TRACK_REG <= (others => '1'); -- Preset the track register.
elsif TR_CLR = '1' then
TRACK_REG <= (others => '0'); -- Reset the track register.
elsif TR_INC = '1' then
TRACK_REG <= TRACK_REG + '1'; -- Increment register contents.
elsif TR_DEC = '1' then
TRACK_REG <= TRACK_REG - '1'; -- Decrement register contents.
end if;
end if;
end process TRACKREG;
TR <= TRACK_REG;
COMMANDREG: process(RESETn, CLK)
-- The command register is write only.
begin
if RESETn = '0' then
COMMAND_REG <= x"00";
elsif CLK = '1' and CLK' event then
if CSn = '0' and ADR = "00" and RWn = '0' and BUSY = '0' then
COMMAND_REG <= DATA_IN; -- Write to register when device is not busy.
-- Write 'force interrupt' to register even when device is busy:
elsif CSn = '0' and ADR = "00" and RWn = '0' and DATA_IN(7 downto 4) = x"D" then
COMMAND_REG <= DATA_IN;
end if;
end if;
end process COMMANDREG;
CMD <= COMMAND_REG;
STATUSREG: process(RESETn, CLK)
-- The status register is read only to the data bus.
begin
-- Status register wiring:
if RESETn = '0' then
STATUS_REG <= x"00";
elsif CLK = '1' and CLK' event then
STATUS_REG(7) <= MOTOR_ON;
STATUS_REG(6) <= WRITE_PROTECT;
STATUS_REG(5) <= SPINUP_RECTYPE;
STATUS_REG(4) <= SEEK_RNF;
STATUS_REG(3) <= CRC_ERRFLAG;
STATUS_REG(2) <= LOST_DATA_TR00;
STATUS_REG(1) <= DRQ_IPn;
STATUS_REG(0) <= BUSY;
end if;
end process STATUSREG;
-- Read from track, sector or data register:
-- The register data after writing to the track register is valid at least
-- after 32us in FM mode and after 16us in MFM mode.
-- Read from status register. This register is read only:
-- Be aware, that the status register data bits 7 to 1 after writing
-- the command regsiter are valid at least after 64us in FM mode or 32us in MFM mode and
-- the bit 0 (BUSY) is valid after 48us in FM mode or 24us in MFM mode.
DATA_OUT <= TRACK_REG when CSn = '0' and ADR = "01" and RWn = '1' else
SECTOR_REG when CSn = '0' and ADR = "10" and RWn = '1' else
DATA_REG when CSn = '0' and ADR = "11" and RWn = '1' else
To_StdLogicVector(STATUS_REG) when CSn = '0' and ADR = "00" and RWn = '1' else (others => '0');
DATA_EN <= '1' when CSn = '0' and RWn = '1' else '0';
end architecture BEHAVIOR;

View File

@@ -0,0 +1,154 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- This is the top level file. ----
---- ----
---- ----
---- To Do: ----
---- - Test of the FM portion of the code (if there is any need). ----
---- - Test of the read track command. ----
---- - Test of the read address command. ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2006A 2006/06/03 WF
-- Initial Release: the MFM portion for HD and DD floppies is tested.
-- The FM mode (DDEn = '1') is not completely tested due to the lack
-- of FM drives.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Fixed the polarity of the precompensation flag.
-- The flag is no active '0'. Thanks to Jorma
-- Oksanen for the information.
-- Revision 2K7B 2006/12/29 WF
-- Introduced several improvements based on a very good examination
-- of the pll code by Jean Louis-Guerin.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
library work;
use work.WF1772IP_PKG.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_TOP is
port (
CLK : in bit; -- 16MHz clock!
MRn : in bit;
CSn : in bit;
RWn : in bit;
A1, A0 : in bit;
DATA : inout std_logic_vector(7 downto 0);
RDn : in bit;
TR00n : in bit;
IPn : in bit;
WPRTn : in bit;
DDEn : in bit;
HDTYPE : in bit; -- '0' = DD disks, '1' = HD disks.
MO : out bit;
WG : out bit;
WD : out bit;
STEP : out bit;
DIRC : out bit;
DRQ : out bit;
INTRQ : out bit
);
end entity WF1772IP_TOP;
architecture STRUCTURE of WF1772IP_TOP is
component WF1772IP_TOP_SOC
port (
CLK : in bit;
RESETn : in bit;
CSn : in bit;
RWn : in bit;
A1, A0 : in bit;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
RDn : in bit;
TR00n : in bit;
IPn : in bit;
WPRTn : in bit;
DDEn : in bit;
HDTYPE : in bit;
MO : out bit;
WG : out bit;
WD : out bit;
STEP : out bit;
DIRC : out bit;
DRQ : out bit;
INTRQ : out bit
);
end component;
signal DATA_OUT : std_logic_vector(7 downto 0);
signal DATA_EN : bit;
begin
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
I_1772: WF1772IP_TOP_SOC
port map(
CLK => CLK,
RESETn => MRn,
CSn => CSn,
RWn => RWn,
A1 => A1,
A0 => A0,
DATA_IN => DATA,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
RDn => RDn,
TR00n => TR00n,
IPn => IPn,
WPRTn => WPRTn,
DDEn => DDEn,
HDTYPE => HDTYPE,
MO => MO,
WG => WG,
WD => WD,
STEP => STEP,
DIRC => DIRC,
DRQ => DRQ,
INTRQ => INTRQ
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,333 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- Top level file for use in systems on programmable chips. ----
---- ----
---- ----
---- To Do: ----
---- - Test of the FM portion of the code (if there is any need). ----
---- - Test of the read track command. ----
---- - Test of the read address command. ----
---- ----
---- 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 2006A 2006/06/03 WF
-- Initial Release: the MFM portion for HD and DD floppies is tested.
-- The FM mode (DDEn = '1') is not completely tested due to the lack
-- of FM drives.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Fixed the polarity of the precompensation flag.
-- The flag is no active '0'. Thanks to Jorma Oksanen for the information.
-- Top level file provided for SOC (systems on programmable chips).
-- Revision 2K7B 2006/12/29 WF
-- Introduced several improvements based on a very good examination
-- of the pll code by Jean Louis-Guerin.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K8B 2008/12/24 WF
-- Bugfixes in the controller due to hanging state machine.
-- Removed CRC_BUSY.
--
library work;
use work.WF1772IP_PKG.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_TOP_SOC is
port (
CLK : in bit; -- 16MHz clock!
RESETn : in bit;
CSn : in bit;
RWn : in bit;
A1, A0 : in bit;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
RDn : in bit;
TR00n : in bit;
IPn : in bit;
WPRTn : in bit;
DDEn : in bit;
HDTYPE : in bit; -- '0' = DD disks, '1' = HD disks.
MO : out bit;
WG : out bit;
WD : out bit;
STEP : out bit;
DIRC : out bit;
DRQ : out bit;
INTRQ : out bit
);
end entity WF1772IP_TOP_SOC;
architecture STRUCTURE of WF1772IP_TOP_SOC is
signal DATA_OUT_REG : std_logic_vector(7 downto 0);
signal DATA_EN_REG : bit;
signal CMD_I : std_logic_vector(7 downto 0);
signal DR_I : bit_vector(7 downto 0);
signal DSR_I : std_logic_vector(7 downto 0);
signal TR_I : std_logic_vector(7 downto 0);
signal SR_I : std_logic_vector(7 downto 0);
signal ID_AM_I : bit;
signal DATA_AM_I : bit;
signal DDATA_AM_I : bit;
signal AM_TYPE_I : bit;
signal AM_2_DISK_I : bit;
signal DATA_STRB_I : bit;
signal BUSY_I : bit;
signal DRQ_I : bit;
signal DRQ_IPn_I : bit;
signal LD_TR00_I : bit;
signal SP_RT_I : bit;
signal SEEK_RNF_I : bit;
signal WR_PR_I : bit;
signal MO_I : bit;
signal PLL_DSTRB_I : bit;
signal PLL_D_I : bit;
signal CRC_SD_I : bit;
signal CRC_ERR_I : bit;
signal CRC_PRES_I : bit;
signal CRC_ERRFLAG_I : bit;
signal SD_R_I : bit;
signal CRC_SDOUT_I : bit;
signal SHFT_LOAD_SD_I : bit;
signal SHFT_LOAD_ND_I : bit;
signal WR_In : bit;
signal TR_PRES_I : bit;
signal TR_CLR_I : bit;
signal TR_INC_I : bit;
signal TR_DEC_I : bit;
signal SR_LOAD_I : bit;
signal SR_INC_I : bit;
signal DR_CLR_I : bit;
signal DR_LOAD_I : bit;
signal TRACK_NR_I : std_logic_vector(7 downto 0);
signal CRC_2_DISK_I : bit;
signal DSR_2_DISK_I : bit;
signal FF_2_DISK_I : bit;
signal PRECOMP_EN_I : bit;
signal DISK_RWn_I : bit;
signal WDATA_I : bit;
begin
-- Three state data bus:
DATA_OUT <= DATA_OUT_REG when DATA_EN_REG = '1' else (others => '0');
DATA_EN <= DATA_EN_REG;
-- Some signals copied to the outputs:
WD <= not WR_In;
MO <= MO_I;
DRQ <= DRQ_I;
-- Write deleted data address mark in MFM mode in 'Write Sector' command in
-- case of asserted command bit 0.
AM_TYPE_I <= '0' when CMD_I(7 downto 5) = "101" and CMD_I(0) = '1' else '1';
-- The CRC unit is used during read from disk and write to disk.
-- This is the data multiplexer for the data stream to encode.
CRC_SD_I <= SD_R_I when DISK_RWn_I = '1' else WDATA_I;
I_CONTROL: WF1772IP_CONTROL
port map(
CLK => CLK,
RESETn => RESETn,
A1 => A0,
A0 => A1,
RWn => RWn,
CSn => CSn,
DDEn => DDEn,
DR => DR_I,
CMD => CMD_I,
DSR => DSR_I,
TR => TR_I,
SR => SR_I,
MO => MO_I,
WR_PR => WR_PR_I,
SPINUP_RECTYPE => SP_RT_I,
SEEK_RNF => SEEK_RNF_I,
CRC_ERRFLAG => CRC_ERRFLAG_I,
LOST_DATA_TR00 => LD_TR00_I,
DRQ => DRQ_I,
DRQ_IPn => DRQ_IPn_I,
BUSY => BUSY_I,
AM_2_DISK => AM_2_DISK_I,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I,
CRC_ERR => CRC_ERR_I,
CRC_PRES => CRC_PRES_I,
TR_PRES => TR_PRES_I,
TR_CLR => TR_CLR_I,
TR_INC => TR_INC_I,
TR_DEC => TR_DEC_I,
SR_LOAD => SR_LOAD_I,
SR_INC => SR_INC_I,
TRACK_NR => TRACK_NR_I,
DR_CLR => DR_CLR_I,
DR_LOAD => DR_LOAD_I,
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
SHFT_LOAD_ND => SHFT_LOAD_ND_I,
CRC_2_DISK => CRC_2_DISK_I,
DSR_2_DISK => DSR_2_DISK_I,
FF_2_DISK => FF_2_DISK_I,
PRECOMP_EN => PRECOMP_EN_I,
DATA_STRB => DATA_STRB_I,
DISK_RWn => DISK_RWn_I,
WPRTn => WPRTn,
TRACK00n => TR00n,
IPn => IPn,
DIRC => DIRC,
STEP => STEP,
WG => WG,
INTRQ => INTRQ
);
I_REGISTERS: WF1772IP_REGISTERS
port map(
CLK => CLK,
RESETn => RESETn,
CSn => CSn,
ADR(1) => A1,
ADR(0) => A0,
RWn => RWn,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT_REG,
DATA_EN => DATA_EN_REG,
CMD => CMD_I,
TR => TR_I,
SR => SR_I,
DSR => DSR_I,
DR => DR_I,
SD_R => SD_R_I,
DATA_STRB => DATA_STRB_I,
DR_CLR => DR_CLR_I,
DR_LOAD => DR_LOAD_I,
TR_PRES => TR_PRES_I,
TR_CLR => TR_CLR_I,
TR_INC => TR_INC_I,
TR_DEC => TR_DEC_I,
TRACK_NR => TRACK_NR_I,
SR_LOAD => SR_LOAD_I,
SR_INC => SR_INC_I,
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
SHFT_LOAD_ND => SHFT_LOAD_ND_I,
MOTOR_ON => MO_I,
WRITE_PROTECT => WR_PR_I,
SPINUP_RECTYPE => SP_RT_I,
SEEK_RNF => SEEK_RNF_I,
CRC_ERRFLAG => CRC_ERRFLAG_I,
LOST_DATA_TR00 => LD_TR00_I,
DRQ => DRQ_I,
DRQ_IPn => DRQ_IPn_I,
BUSY => BUSY_I,
DDEn => DDEn
);
I_DIGITAL_PLL: WF1772IP_DIGITAL_PLL
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
HDTYPE => HDTYPE,
DISK_RWn => DISK_RWn_I,
RDn => RDn,
PLL_D => PLL_D_I,
PLL_DSTRB => PLL_DSTRB_I
);
I_AM_DETECTOR: WF1772IP_AM_DETECTOR
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
DATA => PLL_D_I,
DATA_STRB => PLL_DSTRB_I,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I
);
I_CRC_LOGIC: WF1772IP_CRC_LOGIC
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
DISK_RWn => DISK_RWn_I,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I,
SD => CRC_SD_I,
CRC_STRB => DATA_STRB_I,
CRC_2_DISK => CRC_2_DISK_I,
CRC_PRES => CRC_PRES_I,
CRC_SDOUT => CRC_SDOUT_I,
CRC_ERR => CRC_ERR_I
);
I_TRANSCEIVER: WF1772IP_TRANSCEIVER
port map(
CLK => CLK,
RESETn => RESETn,
DDEn => DDEn,
HDTYPE => HDTYPE,
ID_AM => ID_AM_I,
DATA_AM => DATA_AM_I,
DDATA_AM => DDATA_AM_I,
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
DR => DR_I,
PRECOMP_EN => PRECOMP_EN_I,
AM_TYPE => AM_TYPE_I,
AM_2_DISK => AM_2_DISK_I,
CRC_2_DISK => CRC_2_DISK_I,
DSR_2_DISK => DSR_2_DISK_I,
FF_2_DISK => FF_2_DISK_I,
SR_SDOUT => DSR_I(7),
CRC_SDOUT => CRC_SDOUT_I,
WRn => WR_In,
WDATA => WDATA_I,
PLL_DSTRB => PLL_DSTRB_I,
PLL_D => PLL_D_I,
DATA_STRB => DATA_STRB_I,
SD_R => SD_R_I
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,517 @@
----------------------------------------------------------------------
---- ----
---- WD1772 compatible floppy disk controller IP Core. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Floppy disk controller with all features of the Western ----
---- Digital WD1772-02 controller. ----
---- ----
---- The transceiver unit contains on the one hand the receiver ----
---- part which strips off the clock signal from the data stream ----
---- and on the other hand the transmitter unit which provides in ----
---- the different modes (FM and MFM) all functions which are ----
---- necessary to send data, CRC bytes, 'FF', '00' or the address ----
---- marks. ----
---- ----
---- ----
---- 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 2006A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/05 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- MFM_In and MASK_SHFT have now synchronous reset to meet preset requirement.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF1772IP_TRANSCEIVER is
port(
-- System control
CLK : in bit; -- must be 16MHz
RESETn : in bit;
-- Data and Control:
HDTYPE : in bit; -- Floppy type HD or DD.
DDEn : in bit; -- Double density select (FM or MFM).
ID_AM : in bit; -- ID addressmark strobe.
DATA_AM : in Bit; -- Data addressmark strobe.
DDATA_AM : in Bit; -- Deleted data addressmark strobe.
SHFT_LOAD_SD : in bit; -- Indication for shift register load time.
DR : in bit_vector(7 downto 0); -- Content of the data register.
-- Data strobes:
PLL_DSTRB : in bit; -- Clock strobe for RD serial data input.
DATA_STRB : buffer bit;
-- Data strobe and data for the CRC during write operation:
WDATA : buffer bit;
-- Encoder (logic to disk):
PRECOMP_EN : in bit; -- control signal for MFM write precompensation.
AM_TYPE : in bit; -- Write deleted address mark in MFM mode when 0.
AM_2_DISK : in bit;
DSR_2_DISK : in bit;
FF_2_DISK : in bit;
CRC_2_DISK : in bit;
SR_SDOUT : in std_logic; -- encoder's data input from the shift register (serial).
CRC_SDOUT : in bit; -- encoder's data input from the CRC unit (serial).
WRn : out bit; -- write output for the MFM drive containing clock and data.
-- Decoder (disk to logic):
PLL_D : in bit; -- Serial data input.
SD_R : out bit -- Serial (decoded) data output.
);
end WF1772IP_TRANSCEIVER;
architecture BEHAVIOR of WF1772IP_TRANSCEIVER is
type MFM_STATES is (A_00, B_01, C_10);
type PRECOMP_VALUES is (EARLY, NOMINAL, LATE);
type DEC_STATES is (CLK_PHASE, DATA_PHASE);
signal MFM_STATE : MFM_STATES;
signal NEXT_MFM_STATE : MFM_STATES;
signal PRECOMP : PRECOMP_VALUES;
signal DEC_STATE : DEC_STATES;
signal NEXT_DEC_STATE : DEC_STATES;
signal FM_In : bit;
signal CLKMASK : bit; -- Control for suppression of FM clock transitions.
signal MFM_10_STRB : bit;
signal MFM_01_STRB : bit;
signal WR_CNT : std_logic_vector(3 downto 0);
signal MFM_In : bit;
signal AM_SHFT : bit_vector(31 downto 0);
begin
-- ####################### encoder stuff ###########################
ADRMARK: process(RESETn, CLK)
-- This process provides the address mark data for both FM and MFM in
-- write to disk mode. In FM only one byte is written where in MFM
-- 3 sync bytes x"A1" and one data address mark is written.
-- In this process only the data address mark is provided. The only way
-- writing the ID address mark is the write track command.
begin
if RESETn = '0' then
AM_SHFT <= (others => '0');
elsif CLK = '1' and CLK' event then
if AM_2_DISK = '1' and DATA_STRB = '1' then
AM_SHFT <= AM_SHFT (30 downto 0) & '0'; -- Shift out.
elsif AM_2_DISK = '0' and DDEn = '1' and AM_TYPE = '0' then -- FM mode.
AM_SHFT <= x"F8000000"; -- Load deleted FM address mark.
elsif AM_2_DISK = '0' and DDEn = '1' and AM_TYPE = '1' then -- FM mode.
AM_SHFT <= x"FB000000"; -- Load normal FM address mark.
elsif AM_2_DISK = '0' and DDEn = '0' and AM_TYPE = '0' then -- MFM mode deleted data mark.
AM_SHFT <= x"A1A1A1F8"; -- Load MFM syncs and address mark.
elsif AM_2_DISK = '0' and DDEn = '0' and AM_TYPE = '1' then -- Default: MFM mode normal data mark.
AM_SHFT <= x"A1A1A1FB"; -- Load MFM syncs and address mark.
end if;
end if;
end process ADRMARK;
-- Input multiplexer:
WDATA <= AM_SHFT(31) when AM_2_DISK = '1' else -- Address mark data data.
To_Bit(SR_SDOUT) when DSR_2_DISK = '1' else -- Shift register data.
CRC_SDOUT when CRC_2_DISK = '1' else -- CRC data.
'1' when FF_2_DISK = '1' else '0'; -- Write zeros is default.
-- Output multiplexer:
WRn <= '0' when FM_In = '0' and DDEn = '1' else -- FM portion.
'0' when MFM_In = '0' and DDEn = '0' else '1'; -- MFM portion and default.
CLK_MASK: process(CLK)
-- This part of software controls the suppression of the clock pulses
-- during transmission of several FM special characters. During writing
-- 'normal' data to the disk, only 8 mask bits of the shift register are
-- used. During writing MFM sync and address mark bits, the register is
-- used with 32 mask bits.
variable MASK_SHFT : bit_vector(23 downto 0);
variable LOCK : boolean;
begin
if CLK = '1' and CLK' event then
if RESETn = '0' then
MASK_SHFT := (others => '1');
LOCK := false;
-- Load the mask shift register just in time when the shift register is
-- loaded with valid data from the data register.
elsif SHFT_LOAD_SD = '1' and DDEn = '1' then -- FM mode.
case DR is
when x"F8" | x"F9" | x"FA" | x"FB" | x"FE" => MASK_SHFT := x"C7FFFF";
when x"FC" => MASK_SHFT := x"D7FFFF";
when x"F5" | x"F6" => MASK_SHFT := (others => '0'); -- Not allowed.
when others => MASK_SHFT := x"FFFFFF"; -- Normal data.
end case;
elsif SHFT_LOAD_SD = '1' and DDEn = '0' then -- MFM mode.
case DR is
when x"F5" => MASK_SHFT := x"FBFFFF"; -- Suppress clock pulse between bits 4 and 5.
when x"F6" => MASK_SHFT := x"F7FFFF"; -- Suppress clock pulse between bits 3 and 4.
when others => MASK_SHFT := x"FFFFFF"; -- Normal data.
end case;
elsif AM_2_DISK = '1' and DDEn = '1' and LOCK = false then -- FM mode.
MASK_SHFT := x"C7FFFF"; -- Load just once per AM_2_DISK rising edge.
LOCK := true;
elsif AM_2_DISK = '1' and DDEn = '0' and LOCK = false then -- MFM mode.
MASK_SHFT := x"FBFBFB"; -- Three syncs with suppressed clock pulse then transparent mask.
LOCK := true;
elsif DATA_STRB = '1' then -- shift as long as transmission is active
-- The Shift register is shifted left. After shifting the clockmasks out it is
-- transparent due to the '1's filled up from the left.
MASK_SHFT := MASK_SHFT(22 downto 0) & '1'; -- Shift left.
elsif AM_2_DISK = '0' then
LOCK := false; -- Release the lock after address mark has been written.
end if;
end if;
CLKMASK <= MASK_SHFT(23);
end process CLK_MASK;
FM_ENCODER: process (RESETn, DATA_STRB, CLK)
-- For DD type floppies the data rate is 125kBps. Therefore there are 128 16-MHz clocks cycles
-- per FM bit.
-- For HD type floppies the data rate is 250kBps. Therefore there are 64 16-MHz clocks cycles
-- per FM bit.
-- The FM write pulse width is 1.375us for DD and 0.750us HD type floppies.
-- This process provides the FM encoded signal. The first pulse is in any case the clock
-- pulse and the second pulse is due to data. The FM encoding is very simple and therefore
-- self explaining.
variable CNT : std_logic_vector(7 downto 0);
begin
if RESETn = '0' then
FM_In <= '1';
CNT := x"00";
elsif CLK = '1' and CLK' event then
-- In case of HD type floppies the counter reaches a value of b"0100000"
-- In case of DD type floppies the counter reaches a value of b"1000000"
if DATA_STRB = '1' then
CNT := x"00";
else
CNT := CNT + '1';
end if;
-- The flux reversal pulses are centered between the DATA_STRB pulses.
-- In detail: the clock pulse appears in the middle of the first half
-- of the DATA_STRB period and the data pulse appears in the middle of
-- the second half.
case HDTYPE is
when '0' => -- DD type floppies:
if CNT > "00010101" and CNT <= "00101011" then
FM_In <= not CLKMASK; -- FM clock.
elsif CNT > "01010101" and CNT <= "01101011" then
FM_In <= not WDATA; -- FM data.
else
FM_In <= '1';
end if;
when '1' => -- HD type floppies:
if CNT > "00001010" and CNT <= "00010110" then
FM_In <= not CLKMASK; -- FM clock.
elsif CNT > "00101010" and CNT <= "00110110" then
FM_In <= not WDATA; -- FM data.
else
FM_In <= '1';
end if;
end case;
end if;
end process FM_ENCODER;
MFM_ENCODE_REG: process(RESETn, CLK)
-- This process is the first portion of the more complicated MFM encoder. It can be interpreted
-- as a Moore machine. This part is the current state register.
begin
if RESETn = '0' then
MFM_STATE <= A_00;
elsif CLK = '1' and CLK' event then
MFM_STATE <= NEXT_MFM_STATE;
end if;
end process MFM_ENCODE_REG;
MFM_ENCODE_LOGIC: process(MFM_STATE, WDATA, DATA_STRB)
-- Rules for Encoding:
-- transitions are never located at the mid point of a 'zero'.
-- transistions are always located at the mid point of a '1'.
-- no transitions at the borders of a '1'.
-- transitions appear between two adjacent 'zeros'.
-- states are as follows:
-- A_00: idle state, no transition.
-- B_01: transistion between the MFM clock edges.
-- C_10: transition on the leading MFM clock edges.
-- The timing of the MFM output is done in the process MFM_WR_OUT.
begin
case MFM_STATE is
when A_00 =>
if WDATA = '0' and DATA_STRB = '1' then
NEXT_MFM_STATE <= C_10;
elsif WDATA = '1' and DATA_STRB = '1' then
NEXT_MFM_STATE <= B_01;
else
NEXT_MFM_STATE <= A_00; -- Stay, if there is no strobe.
end if;
when C_10 =>
if WDATA = '0' and DATA_STRB = '1' then
NEXT_MFM_STATE <= C_10;
elsif WDATA = '1' and DATA_STRB = '1' then
NEXT_MFM_STATE <= B_01;
else
NEXT_MFM_STATE <= C_10; -- Stay, if there is no strobe.
end if;
when B_01 =>
if WDATA = '0' and DATA_STRB = '1' then
NEXT_MFM_STATE <= A_00;
elsif WDATA = '1' and DATA_STRB = '1' then
NEXT_MFM_STATE <= B_01;
else
NEXT_MFM_STATE <= B_01; -- Stay, if there is no strobe.
end if;
end case;
end process MFM_ENCODE_LOGIC;
MFM_PRECOMPENSATION: process(RESETn, CLK)
-- The write pattern is adjusted in the MFM write timing process as follows:
-- after DATA_STRB (the duty cycle of this strobe is exactly one CLK) the
-- incoming data is bufferd in WRITEPATTERN. After the following DATA_STRB
-- the WDATA is shifted through WRITEPATTERN. After further DATA_STRBs the
-- WRITEPATTERN consists of previous, current and next WDATA like this:
-- WRITEPATTERN(3) is the second previous WDATA.
-- WRITEPATTERN(2) is the previous WDATA.
-- WRITEPATTERN(1) is the current WDATA to be sent.
-- WRITEPATTERN(0) is the next WDATA to be sent.
variable WRITEPATTERN : bit_vector(3 downto 0);
begin
if RESETn = '0' then
PRECOMP <= NOMINAL;
WRITEPATTERN := "0000";
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
WRITEPATTERN := WRITEPATTERN(2 downto 0) & WDATA; -- shift left
end if;
if PRECOMP_EN = '0' then
PRECOMP <= NOMINAL; -- no precompensation
else
case WRITEPATTERN is
when "1110" | "0110" => PRECOMP <= EARLY;
when "1011" | "0011" => PRECOMP <= LATE;
when "0001" => PRECOMP <= EARLY;
when "1000" => PRECOMP <= LATE;
when others => PRECOMP <= NOMINAL;
end case;
end if;
end if;
end process MFM_PRECOMPENSATION;
MFM_STROBES: process (RESETn, DATA_STRB, CLK)
-- For the MFM frequency is 250 kBps for DD type floppies, there are 64
-- 16 MHz clock cycles per MFM bit and for HD type floppies, which have
-- 500 kBps there are 32 16MHz clock pulses for one MFM bit.
-- The MFM state machine (Moore) switches on the DATA_STRB.
-- During one cycle there are the two further strobes MFM_10_STRB and
-- MFM_01_STRB which control the MFM output in the process MFM_WR_OUT.
-- The strobes are centered in the middle of the first half and in the
-- middle of the second half of the DATA_STRB cycle.
variable CNT : std_logic_vector(5 downto 0);
begin
if RESETn = '0' then
CNT := "000000";
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
CNT := (others => '0');
else
CNT := CNT + '1';
end if;
if HDTYPE = '1' then
case CNT is
-- encoder timing for MFM and HD type floppies.
when "000100" => MFM_10_STRB <= '1'; MFM_01_STRB <= '0'; -- Pulse centered in the first half.
when "010100" => MFM_10_STRB <= '0'; MFM_01_STRB <= '1'; -- Pulse centered in the second half.
when others => MFM_10_STRB <= '0'; MFM_01_STRB <= '0';
end case;
else
case CNT is
-- encoder timing for MFM and DD type floppies.
when "001010" => MFM_10_STRB <= '1'; MFM_01_STRB <= '0'; -- Pulse centered in the first half.
when "101000" => MFM_10_STRB <= '0'; MFM_01_STRB <= '1'; -- Pulse centered in the second half.
when others => MFM_10_STRB <= '0'; MFM_01_STRB <= '0';
end case;
end if;
end if;
end process MFM_STROBES;
-- MFM_WR_TIMING generates the timing for the write pulses which are
-- required by a MFM device like floppy disk drive. The pulse timing
-- meets the timing of the MFM data with pulse width of 700ns +/- 100ns
-- depending on write precompensation.
-- The original WD1772 (CLK = 8MHz) data timing was as follows:
-- The output is asserted as long as CNT is active; in detail
-- this are 4,5; 5,5 or 6,5 CLK cycles depending on the write
-- precompensation.
-- The new design which works with a 16MHz clock requires the following
-- timing: 9; 11 or 13 CLK cycles depending on the writeprecompensation
-- for DD floppies and 5; 6 or 7 CLK cycles depending on the write
-- precompensation for HD floppies.
-- To meet the timing requirements of half clocks
-- the WRn is controlled by the following three processes where the one
-- syncs on the positive clock edge and the other on the negative.
-- For more information on the WTn timing see the datasheet of the
-- WD177x floppy disc controller.
MFM_WR_TIMING: process(RESETn, CLK)
variable CLKMASK_MFM : bit;
begin
if RESETn = '0' then
WR_CNT <= x"F";
elsif CLK = '1' and CLK' event then
if DATA_STRB = '1' then
-- The CLKMASK_MFM is synchronised to DATA_STRB. This brings one strobe latency.
-- The timing in connection with the data is correct because the MFM encoder state machine
-- causes the data to be 1 DATA_STRB late too.
CLKMASK_MFM := CLKMASK;
end if;
if MFM_STATE = C_10 and MFM_10_STRB = '1' and CLKMASK_MFM = '1' then
WR_CNT <= x"0";
elsif MFM_STATE = B_01 and MFM_01_STRB = '1' then
WR_CNT <= x"0";
elsif WR_CNT < x"F" then
WR_CNT <= WR_CNT + '1';
end if;
end if;
end process MFM_WR_TIMING;
MFM_WR_OUT: process
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
MFM_In <= '1';
else
case HDTYPE is
when '1' => -- HD type.
if PRECOMP = EARLY and WR_CNT > x"0" and WR_CNT <= x"9" then
MFM_In <= '0'; -- 9,0 clock cycles for WRn --> early timing
elsif PRECOMP = NOMINAL and WR_CNT > x"0" and WR_CNT <= x"8" then
MFM_In <= '0'; -- 8,0 clock cycles for WRn --> nominal timing
elsif PRECOMP = LATE and WR_CNT > x"0" and WR_CNT <= x"7" then
MFM_In <= '0'; -- 7,0 clock cycles for WRn --> late timing
else
MFM_In <= '1';
end if;
when '0' => -- DD type.
if PRECOMP = EARLY and WR_CNT > x"0" and WR_CNT <= x"D" then
MFM_In <= '0'; -- 13,0 clock cycles for WRn --> early timing
elsif PRECOMP = NOMINAL and WR_CNT > x"0" and WR_CNT <= x"B" then
MFM_In <= '0'; -- 11,0 clock cycles for WRn --> nominal timing
elsif PRECOMP = LATE and WR_CNT > x"0" and WR_CNT <= x"9" then
MFM_In <= '0'; -- 9,0 clock cycles for WRn --> late timing
else
MFM_In <= '1';
end if;
end case;
end if;
end process MFM_WR_OUT;
-- ####################### Decoder stuff ###########################
-- The decoding of the serial FM or MFM encoded data stream
-- is done in the following two processes (Moore machine).
-- The decoder works in principle like a simple toggle Flip-Flop.
-- It is important to synchronise it in a way, that the clock
-- pulses are separated from the data pulses. The principle
-- works for both FM and MFM data due to the digital phase
-- locked loop, which delivers the serial data and the clock
-- strobe. In general this decoder can be understood as the
-- data separator where the digital phase locked loop provides
-- the FM or the MFM decoding. The data separation lives from
-- the fact, that FM and also MFM encoded signals consist of a
-- mixture of alternating data and clock pulses.
-- FM works as follows:
-- every first pulse of the FM signal is a clock pulse and every
-- second pulse is a logic '1' of the data. A missing second
-- pulse represents a logic '0' of the data.
-- MFM works as follows:
-- every first pulse of the MFM signal is a clock pulse. The coding
-- principle causes clock pulses to be absent in some conditions.
-- Every second pulse is a logic '1' of the data. A missing second
-- pulse represents a logic '0' of the data.
-- So FM and MFM compared, the data is represented directly by the
-- second pulses and the data separator has to look only for these.
-- The missing MFM clock pulses do not cause a problem because the
-- digital PLL used in conjunction with this data separator fills
-- up the clock pulses and delivers a PLL_DSTRB containing aequidistant
-- clock strobes and data strobes.
DEC_REG: process(RESETn, CLK)
begin
if RESETn = '0' then
DEC_STATE <= CLK_PHASE;
elsif CLK = '1' and CLK' event then
DEC_STATE <= NEXT_DEC_STATE;
end if;
end process DEC_REG;
DEC_LOGIC: process(DEC_STATE, ID_AM, DATA_AM, DDATA_AM, PLL_DSTRB, PLL_D)
begin
case DEC_STATE is
when CLK_PHASE =>
if PLL_DSTRB = '1' then
NEXT_DEC_STATE <= DATA_PHASE;
else
NEXT_DEC_STATE <= CLK_PHASE;
end if;
DATA_STRB <= '0'; -- Inactive during clock pulse time.
SD_R <= '0'; -- Inactive during clock pulse time.
when DATA_PHASE =>
if ID_AM = '1' or DATA_AM = '1' or DDATA_AM = '1' then
-- Here the state machine is synchronised
-- to separate data and clock pulses correctly.
NEXT_DEC_STATE <= CLK_PHASE;
elsif PLL_DSTRB = '1' then
NEXT_DEC_STATE <= CLK_PHASE;
else
NEXT_DEC_STATE <= DATA_PHASE;
end if;
-- During the data phase valid data appears at SD.
-- The data is valid during DATA_STRB.
DATA_STRB <= PLL_DSTRB;
SD_R <= PLL_D;
end case;
end process DEC_LOGIC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,141 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This are the SUSKA MFP IP core's general purpose I/Os. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_GPIO is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Timer controls:
AER_4 : out bit;
AER_3 : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_OUT_EN : buffer bit_vector(7 downto 0);
GP_INT : out bit_vector(7 downto 0)
);
end entity WF68901IP_GPIO;
architecture BEHAVIOR of WF68901IP_GPIO is
signal GPDR : bit_vector(7 downto 0);
signal DDR : bit_vector(7 downto 0);
signal AER : bit_vector(7 downto 0);
signal GPDR_I : bit_vector(7 downto 0);
begin
-- These two bits control the timers A and B pulse width operation and the
-- timers A and B event count operation.
AER_4 <= AER(4);
AER_3 <= AER(3);
-- This statement provides 8 XOR units setting the desired interrupt polarity.
-- While the level control is done here, the edge triggering is provided by
-- the interrupt control hardware. The level control is individually for each
-- GPIP port pin. The interrupt edge trigger unit must operate in any case on
-- the low to high transistion of the respective port pin.
GP_INT <= AER xnor GPIP_IN;
GPIO_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
GPDR <= (others => '0');
DDR <= (others => '0');
AER <= (others => '0');
elsif CLK = '1' and CLK' event then
if CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "00000" => GPDR <= DATA_IN;
when "00001" => AER <= DATA_IN;
when "00010" => DDR <= DATA_IN;
when others => null;
end case;
end if;
end if;
end process GPIO_REGISTERS;
GPIP_OUT <= GPDR; -- Port outputs.
GPIP_OUT_EN <= DDR; -- The DDR is capable to control bitwise the GPIP.
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS <= "00010" else '0';
DATA_OUT <= DDR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00010" else
AER when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00001" else
GPDR_I when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00000" else (others => '0');
P_GPDR: process(GPIP_IN, GPIP_OUT_EN, GPDR)
-- Read back control: Read the port pins, if the data direction is configured as input.
-- Read the respective GPDR register bit, if the data direction is configured as output.
begin
for i in 7 downto 0 loop
if GPIP_OUT_EN(i) = '1' then -- Port is configured output.
GPDR_I(i) <= GPDR(i);
else
GPDR_I(i) <= GPIP_IN(i); -- Port is configured input.
end if;
end loop;
end process P_GPDR;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,391 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core interrupt logic file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/06/03 WF
-- Fixed Pending register logic.
-- Revision 2K9A 2009/06/20 WF
-- Fixed interrupt polarity for TA_I and TB_I.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_INTERRUPTS is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Interrupt control:
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
-- Interrupt sources:
GP_INT : in bit_vector(7 downto 0);
AER_4 : in bit;
AER_3 : in bit;
TAI : in bit;
TBI : in bit;
TA_PWM : in bit;
TB_PWM : in bit;
TIMER_A_INT : in bit;
TIMER_B_INT : in bit;
TIMER_C_INT : in bit;
TIMER_D_INT : in bit;
RCV_ERR : in bit;
TRM_ERR : in bit;
RCV_BUF_F : in bit;
TRM_BUF_E : in bit
);
end entity WF68901IP_INTERRUPTS;
architecture BEHAVIOR of WF68901IP_INTERRUPTS is
-- Interrupt state machine:
type INT_STATES is (SCAN, REQUEST, VECTOR_OUT);
signal INT_STATE : INT_STATES;
-- The registers:
signal IERA : bit_vector(7 downto 0);
signal IERB : bit_vector(7 downto 0);
signal IPRA : bit_vector(7 downto 0);
signal IPRB : bit_vector(7 downto 0);
signal ISRA : bit_vector(7 downto 0);
signal ISRB : bit_vector(7 downto 0);
signal IMRA : bit_vector(7 downto 0);
signal IMRB : bit_vector(7 downto 0);
signal VR : bit_vector(7 downto 3);
-- Interconnect:
signal VECT_NUMBER : bit_vector(7 downto 0);
signal INT_SRC : bit_vector(15 downto 0);
signal INT_SRC_EDGE : bit_vector(15 downto 0);
signal INT_ENA : bit_vector(15 downto 0);
signal INT_MASK : bit_vector(15 downto 0);
signal INT_PENDING : bit_vector(15 downto 0);
signal INT_SERVICE : bit_vector(15 downto 0);
signal INT_PASS : bit_vector(15 downto 0);
signal INT_OUT : bit_vector(15 downto 0);
signal GP_INT_4 : bit;
signal GP_INT_3 : bit;
begin
-- Interrupt source for the GPI_4 and GPI_3 is normally the respective port pin.
-- But when the timers operate in their PWM modes, the GPI_4 and GPI_3 are associated
-- to timer A and timer B.
-- The xor logic provides polarity control for the interrupt transition. Be aware,
-- that the PWM signals cause an interrupt on the opposite transition like the
-- respective GPIP port pins (with the same AER settings).
--GP_INT_4 <= GP_INT(4) when TA_PWM = '0' else TAI xor AER_4;
--GP_INT_3 <= GP_INT(3) when TB_PWM = '0' else TBI xor AER_3;
GP_INT_4 <= GP_INT(4) when TA_PWM = '0' else TAI xnor AER_4; -- This should be correct.
GP_INT_3 <= GP_INT(3) when TB_PWM = '0' else TBI xnor AER_3;
-- Interrupt source priority sorted (15 = highest):
INT_SRC <= GP_INT(7 downto 6) & TIMER_A_INT & RCV_BUF_F & RCV_ERR & TRM_BUF_E & TRM_ERR & TIMER_B_INT &
GP_INT(5) & GP_INT_4 & TIMER_C_INT & TIMER_D_INT & GP_INT_3 & GP_INT(2 downto 0);
INT_ENA <= IERA & IERB;
INT_MASK <= IMRA & IMRB;
INT_PENDING <= IPRA & IPRB;
INT_SERVICE <= ISRA & ISRB;
INT_OUT <= INT_PENDING and INT_MASK; -- Masking:
-- Enable the daisy chain, if there is no pending interrupt and
-- the interrupt state machine is not in service.
IEOn <= '0' when INT_OUT = x"0000" and INT_STATE = SCAN else '1';
-- Interrupt request:
IRQn <= '0' when INT_OUT /= x"0000" and INT_STATE = REQUEST else '1';
EDGE_ENA: process(RESETn, CLK)
-- These are the 16 edge detectors of the 16 interrupt input sources. This
-- process also provides the disabling or enabling via the IERA and IERB registers.
variable LOCK : bit_vector(15 downto 0);
begin
if RESETn = '0' then
INT_SRC_EDGE <= x"0000";
LOCK := x"0000";
elsif CLK = '1' and CLK' event then
for i in 15 downto 0 loop
if INT_SRC(i) = '1' and INT_ENA(i) = '1' and LOCK(i) = '0' then
LOCK(i) := '1';
INT_SRC_EDGE(i) <= '1';
elsif INT_SRC(i) = '0' then
LOCK(i) := '0';
INT_SRC_EDGE(i) <= '0';
else
INT_SRC_EDGE(i) <= '0';
end if;
end loop;
end if;
end process EDGE_ENA;
INT_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
IERA <= (others => '0');
IERB <= (others => '0');
IPRA <= (others => '0');
IPRB <= (others => '0');
ISRA <= (others => '0');
ISRB <= (others => '0');
IMRA <= (others => '0');
IMRB <= (others => '0');
elsif CLK = '1' and CLK' event then
if CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "00011" => IERA <= DATA_IN; -- Enable A.
when "00100" => IERB <= DATA_IN; -- Enable B.
when "00101" =>
-- Only a '0' can be written to the pending register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
IPRA(i) <= '0'; -- Pending A.
end if;
end loop;
when "00110" =>
-- Only a '0' can be written to the pending register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
IPRB(i) <= '0'; -- Pending B.
end if;
end loop;
when "00111" =>
-- Only a '0' can be written to the in service register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
ISRA(i) <= '0'; -- In Service A.
end if;
end loop;
when "01000" =>
-- Only a '0' can be written to the in service register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
ISRB(i) <= '0'; -- In Service B.
end if;
end loop;
when "01001" => IMRA <= DATA_IN; -- Mask A.
when "01010" => IMRB <= DATA_IN; -- Mask B.
when "01011" => VR <= DATA_IN(7 downto 3); -- Vector register.
when others => null;
end case;
end if;
-- Pending register:
-- set and clear bit logic.
for i in 15 downto 8 loop
if INT_SRC_EDGE(i) = '1' then
IPRA(i-8) <= '1';
elsif INT_ENA(i) = '0' then
IPRA(i-8) <= '0'; -- Clear by disabling the channel.
elsif INT_PASS(i) = '1' then
IPRA(i-8) <= '0'; -- Clear by passing the interrupt.
end if;
end loop;
for i in 7 downto 0 loop
if INT_SRC_EDGE(i) = '1' then
IPRB(i) <= '1';
elsif INT_ENA(i) = '0' then
IPRB(i) <= '0'; -- Clear by disabling the channel.
elsif INT_PASS(i) = '1' then
IPRB(i) <= '0'; -- Clear by passing the interrupt.
end if;
end loop;
-- In-Service register:
-- Set bit logic, VR(3) is the service register enable.
for i in 15 downto 8 loop
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
ISRA(i-8) <= '1';
end if;
end loop;
for i in 7 downto 0 loop
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
ISRB(i) <= '1';
end if;
end loop;
end if;
end process INT_REGISTERS;
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "00010" and RS <= "01011" else '1' when INT_STATE = VECTOR_OUT else '0';
DATA_OUT <= IERA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00011" else
IERB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00100" else
IPRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00101" else
IPRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00110" else
ISRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00111" else
ISRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01000" else
IMRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01001" else
IMRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01010" else
VR & "000" when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01011" else
VECT_NUMBER when INT_STATE = VECTOR_OUT else x"00";
P_INT_STATE : process(RESETn, CLK)
begin
if RESETn = '0' then
INT_STATE <= SCAN;
elsif CLK = '1' and CLK' event then
case INT_STATE is
when SCAN =>
INT_PASS <= x"0000";
-- Automatic End of Interrupt mode. Service register disabled.
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
-- vector number (VR(7 downto 4) = x"0").
if INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '0' and IEIn = '0' then
INT_STATE <= REQUEST; -- Non masked interrupt is pending.
-- The following 16 are the Software end of interrupt mode. Service register enabled.
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
-- vector number (VR(7 downto 4) = x"0"). The interrupts are prioritized.
elsif INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '1' and IEIn = '0' then
if INT_OUT (15) = '1' and INT_SERVICE(15) = '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (14) = '1' and INT_SERVICE(15 downto 14) = "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (13) = '1' and INT_SERVICE(15 downto 13) = "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (12) = '1' and INT_SERVICE(15 downto 12) = x"0" then
INT_STATE <= REQUEST;
elsif INT_OUT (11) = '1' and INT_SERVICE(15 downto 11) = x"0" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (10) = '1' and INT_SERVICE(15 downto 10) = x"0" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (9) = '1' and INT_SERVICE(15 downto 9) = x"0" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (8) = '1' and INT_SERVICE(15 downto 8) = x"00" then
INT_STATE <= REQUEST;
elsif INT_OUT (7) = '1' and INT_SERVICE(15 downto 7) = x"00" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (6) = '1' and INT_SERVICE(15 downto 6) = x"00" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (5) = '1' and INT_SERVICE(15 downto 5) = x"00" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (4) = '1' and INT_SERVICE(15 downto 4) = x"000" then
INT_STATE <= REQUEST;
elsif INT_OUT (3) = '1' and INT_SERVICE(15 downto 3) = x"000" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (2) = '1' and INT_SERVICE(15 downto 2) = x"000" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (1) = '1' and INT_SERVICE(15 downto 1) = x"000" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (0) = '1' and INT_SERVICE(15 downto 0) = x"0000" then
INT_STATE <= REQUEST;
else
INT_STATE <= SCAN; -- Wait for interrupt.
end if;
else
INT_STATE <= SCAN;
end if;
when REQUEST =>
if IACKn = '0' and DSn = '0' then -- Vectored interrupt mode.
INT_STATE <= VECTOR_OUT; -- Non masked interrupt is pending.
if INT_OUT(15) = '1' then
INT_PASS(15) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"F"; -- GPI 7.
elsif INT_OUT(14) = '1' then
INT_PASS(14) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"E"; -- GPI 6.
elsif INT_OUT(13) = '1' then
INT_PASS(13) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"D"; -- TIMER A.
elsif INT_OUT(12) = '1' then
INT_PASS(12) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"C"; -- Receive buffer full.
elsif INT_OUT(11) = '1' then
INT_PASS(11) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"B"; -- Receiver error.
elsif INT_OUT(10) = '1' then
INT_PASS(10) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"A"; -- Transmit buffer empty.
elsif INT_OUT(9) = '1' then
INT_PASS(9) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"9"; -- Transmit error.
elsif INT_OUT(8) = '1' then
INT_PASS(8) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"8"; -- Timer B.
elsif INT_OUT(7) = '1' then
INT_PASS(7) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"7"; -- GPI 5.
elsif INT_OUT(6) = '1' then
INT_PASS(6) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"6"; -- GPI 4.
elsif INT_OUT(5) = '1' then
INT_PASS(5) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"5"; -- Timer C.
elsif INT_OUT(4) = '1' then
INT_PASS(4) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"4"; -- Timer D.
elsif INT_OUT(3) = '1' then
INT_PASS(3) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"3"; -- GPI 3.
elsif INT_OUT(2) = '1' then
INT_PASS(2) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"2"; -- GPI 2.
elsif INT_OUT(1) = '1' then
INT_PASS(1) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"1"; -- GPI 1.
elsif INT_OUT(0) = '1' then
INT_PASS(0) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"0"; -- GPI 0.
end if;
-- Polled interrupt mode: End of interrupt by writing to the pending registers.
elsif CSn = '0' and DSn = '0' and RWn = '0' and (RS = "00101" or RS = "00110") then
INT_STATE <= SCAN;
else
INT_STATE <= REQUEST; -- Wait.
end if;
when VECTOR_OUT =>
INT_PASS <= x"0000";
if DSn = '1' or IACKn = '1' then
INT_STATE <= SCAN; -- Finished.
else
INT_STATE <= VECTOR_OUT; -- Wait for processor to read the vector.
end if;
end case;
end if;
end process P_INT_STATE;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,263 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the package file containing the component ----
---- declarations. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
package WF68901IP_PKG is
component WF68901IP_USART_TOP
port ( CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
RC : in bit;
TC : in bit;
SI : in bit;
SO : out bit;
SO_EN : out bit;
RX_ERR_INT : out bit;
RX_BUFF_INT : out bit;
TX_ERR_INT : out bit;
TX_BUFF_INT : out bit;
RRn : out bit;
TRn : out bit
);
end component;
component WF68901IP_USART_CTRL
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
RX_SAMPLE : in bit;
RX_DATA : in bit_vector(7 downto 0);
TX_DATA : out bit_vector(7 downto 0);
SCR_OUT : out bit_vector(7 downto 0);
BF : in bit;
BE : in bit;
FE : in bit;
OE : in bit;
UE : in bit;
PE : in bit;
M_CIP : in bit;
FS_B : in bit;
TX_END : in bit;
CL : out bit_vector(1 downto 0);
ST : out bit_vector(1 downto 0);
FS_CLR : out bit;
RSR_READ : out bit;
TSR_READ : out bit;
UDR_READ : out bit;
UDR_WRITE : out bit;
LOOPBACK : out bit;
SDOUT_EN : out bit;
SD_LEVEL : out bit;
CLK_MODE : out bit;
RE : out bit;
TE : out bit;
P_ENA : out bit;
P_EOn : out bit;
SS : out bit;
BR : out bit
);
end component;
component WF68901IP_USART_TX
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0);
TX_DATA : in bit_vector(7 downto 0);
SDATA_OUT : out bit;
TXCLK : in bit;
CL : in bit_vector(1 downto 0);
ST : in bit_vector(1 downto 0);
TE : in bit;
BR : in bit;
P_ENA : in bit;
P_EOn : in bit;
UDR_WRITE : in bit;
TSR_READ : in bit;
CLK_MODE : in bit;
TX_END : out bit;
UE : out bit;
BE : out bit
);
end component;
component WF68901IP_USART_RX
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0);
RX_SAMPLE : out bit;
RX_DATA : out bit_vector(7 downto 0);
RXCLK : in bit;
SDATA_IN : in bit;
CL : in bit_vector(1 downto 0);
ST : in bit_vector(1 downto 0);
P_ENA : in bit;
P_EOn : in bit;
CLK_MODE : in bit;
RE : in bit;
FS_CLR : in bit;
SS : in bit;
RSR_READ : in bit;
UDR_READ : in bit;
M_CIP : out bit;
FS_B : out bit;
BF : out bit;
OE : out bit;
PE : out bit;
FE : out bit
);
end component;
component WF68901IP_INTERRUPTS
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
GP_INT : in bit_vector(7 downto 0);
AER_4 : in bit;
AER_3 : in bit;
TAI : in bit;
TBI : in bit;
TA_PWM : in bit;
TB_PWM : in bit;
TIMER_A_INT : in bit;
TIMER_B_INT : in bit;
TIMER_C_INT : in bit;
TIMER_D_INT : in bit;
RCV_ERR : in bit;
TRM_ERR : in bit;
RCV_BUF_F : in bit;
TRM_BUF_E : in bit
);
end component;
component WF68901IP_GPIO
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
AER_4 : out bit;
AER_3 : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_OUT_EN : out bit_vector(7 downto 0);
GP_INT : out bit_vector(7 downto 0)
);
end component;
component WF68901IP_TIMERS
port (
CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
XTAL1 : in bit;
TAI : in bit;
TBI : in bit;
AER_4 : in bit;
AER_3 : in bit;
TA_PWM : out bit;
TB_PWM : out bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
TIMER_A_INT : out bit;
TIMER_B_INT : out bit;
TIMER_C_INT : out bit;
TIMER_D_INT : out bit
);
end component;
end WF68901IP_PKG;

View File

@@ -0,0 +1,533 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core timers logic file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K7A 2006/12/28 WF
-- The timer is modified to work on the CLK instead
-- of XTAL1. This modification is done to provide
-- a synchronous design.
-- Revision 2K8A 2008/02/29 WF
-- Fixed a serious prescaler bug.
-- Revision 2K9A 20090620 WF
-- Introduced timer readback registers.
-- TIMER_x_INT is now a strobe.
-- Minor improvements.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_TIMERS is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Timers and timer control:
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
TAI : in bit;
TBI : in bit;
AER_4 : in bit;
AER_3 : in bit;
TA_PWM : out bit; -- Indicates, that timer A is in PWM mode (used in Interrupt logic).
TB_PWM : out bit; -- Indicates, that timer B is in PWM mode (used in Interrupt logic).
TAO : buffer bit;
TBO : buffer bit;
TCO : buffer bit;
TDO : buffer bit;
TIMER_A_INT : out bit;
TIMER_B_INT : out bit;
TIMER_C_INT : out bit;
TIMER_D_INT : out bit
);
end entity WF68901IP_TIMERS;
architecture BEHAVIOR of WF68901IP_TIMERS is
signal XTAL1_S : bit;
signal XTAL_STRB : bit;
signal TACR : bit_vector(4 downto 0); -- Timer A control register.
signal TBCR : bit_vector(4 downto 0); -- Timer B control register.
signal TCDCR : bit_vector(5 downto 0); -- Timer C and D control register.
signal TADR : bit_vector(7 downto 0); -- Timer A data register.
signal TBDR : bit_vector(7 downto 0); -- Timer B data register.
signal TCDR : bit_vector(7 downto 0); -- Timer C data register.
signal TDDR : bit_vector(7 downto 0); -- Timer D data register.
signal TIMER_A : std_logic_vector(7 downto 0); -- Timer A count register.
signal TIMER_B : std_logic_vector(7 downto 0); -- Timer B count register.
signal TIMER_C : std_logic_vector(7 downto 0); -- Timer C count register.
signal TIMER_D : std_logic_vector(7 downto 0); -- Timer D count register.
signal TIMER_R_A : bit_vector(7 downto 0); -- Timer A readback register.
signal TIMER_R_B : bit_vector(7 downto 0); -- Timer B readback register.
signal TIMER_R_C : bit_vector(7 downto 0); -- Timer C readback register.
signal TIMER_R_D : bit_vector(7 downto 0); -- Timer D readback register.
signal A_CNTSTRB : bit;
signal B_CNTSTRB : bit;
signal C_CNTSTRB : bit;
signal D_CNTSTRB : bit;
signal TAI_I : bit;
signal TBI_I : bit;
signal TAI_STRB : bit; -- Strobe for the event counter mode.
signal TBI_STRB : bit; -- Strobe for the event counter mode.
signal TAO_I : bit; -- Timer A output signal.
signal TBO_I : bit; -- Timer A output signal.
begin
SYNC: process
-- This process provides a 'clean' XTAL1.
-- Without this sync, the edge detector for
-- XTAL_STRB does not work properly.
begin
wait until CLK = '1' and CLK' event;
XTAL1_S <= XTAL1;
-- Polarity control for the event counter and the PWM mode:
TAI_I <= TAI xnor AER_4;
TBI_I <= TBI xnor AER_3;
end process SYNC;
-- Output enables for timer A and timer B:
-- The outputs are held low for asserted reset flags in the control registers TACR
-- and TBCR but also during a write operation to these registers.
TAO <= '0' when TACR(4) = '1' else
'0' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "01100" else TAO_I;
TBO <= '0' when TBCR(4) = '1' else
'0' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "01101" else TBO_I;
-- Control outputs for the PWM modi of the timers A and B. These
-- controls are used in the interrupt logic to select the interrupt
-- sources GPIP4 or TAI repective GPIP3 or TBI.
TA_PWM <= '1' when TACR(3 downto 0) > x"8" else '0';
TB_PWM <= '1' when TBCR(3 downto 0) > x"8" else '0';
TIMER_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
TACR <= (others => '0');
TBCR <= (others => '0');
TCDCR <= (others => '0');
-- TADR <= Do not clear during reset!
-- TBDR <= Do not clear during reset!
-- TCDR <= Do not clear during reset!
-- TDDR <= Do not clear during reset!
elsif CLK = '1' and CLK' event then
if CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "01100" => TACR <= DATA_IN(4 downto 0);
when "01101" => TBCR <= DATA_IN(4 downto 0);
when "01110" => TCDCR <= DATA_IN(6 downto 4) & DATA_IN(2 downto 0);
when "01111" => TADR <= DATA_IN;
when "10000" => TBDR <= DATA_IN;
when "10001" => TCDR <= DATA_IN;
when "10010" => TDDR <= DATA_IN;
when others => null;
end case;
end if;
end if;
end process TIMER_REGISTERS;
TIMER_READBACK : process(RESETn, CLK)
-- This process provides the readback information for the
-- timers A to D. The information read is the information
-- last clocked into the timer read register when the DSn
-- pin had last gone high prior to the current read cycle.
variable READ_A : boolean;
variable READ_B : boolean;
variable READ_C : boolean;
variable READ_D : boolean;
begin
if RESETn = '0' then
TIMER_R_A <= x"00";
TIMER_R_B <= x"00";
TIMER_R_C <= x"00";
TIMER_R_D <= x"00";
elsif CLK = '1' and CLK' event then
if DSn = '0' and RS = "01111" then
READ_A := true;
elsif DSn = '0' and RS = "10000" then
READ_B := true;
elsif DSn = '0' and RS = "10001" then
READ_C := true;
elsif DSn = '0' and RS = "10010" then
READ_D := true;
elsif DSn = '1' and READ_A = true then
TIMER_R_A <= To_BitVector(TIMER_A);
READ_A := false;
elsif DSn = '1' and READ_B = true then
TIMER_R_B <= To_BitVector(TIMER_B);
READ_B := false;
elsif DSn = '1' and READ_C = true then
TIMER_R_C <= To_BitVector(TIMER_C);
READ_C := false;
elsif DSn = '1' and READ_D = true then
TIMER_R_D <= To_BitVector(TIMER_D);
READ_D := false;
end if;
end if;
end process TIMER_READBACK;
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "01011" and RS <= "10010" else '0';
DATA_OUT <= "000" & TACR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01100" else
"000" & TBCR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01101" else
'0' & TCDCR(5 downto 3) & '0' & TCDCR(2 downto 0) when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01110" else
TIMER_R_A when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01111" else
TIMER_R_B when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10000" else
TIMER_R_C when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10001" else
TIMER_R_D when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10010" else (others => '0');
XTAL_STROBE: process(RESETn, CLK)
-- This process provides a strobe with 1 clock cycle
-- (CLK) length after every rising edge of XTAL1.
variable LOCK : boolean;
begin
if RESETn = '0' then
XTAL_STRB <= '0';
elsif CLK = '1' and CLK' event then
if XTAL1_S = '1' and LOCK = false then
XTAL_STRB <= '1';
LOCK := true;
elsif XTAL1_S = '0' then
XTAL_STRB <= '0';
LOCK := false;
else
XTAL_STRB <= '0';
end if;
end if;
end process XTAL_STROBE;
TAI_STROBE: process(RESETn, CLK)
variable LOCK : boolean;
begin
if RESETn = '0' then
TAI_STRB <= '0';
elsif CLK = '1' and CLK' event then
if TAI_I = '1' and XTAL_STRB = '1' and LOCK = false then
LOCK := true;
TAI_STRB <= '1';
elsif TAI_I = '0' then
LOCK := false;
TAI_STRB <= '0';
else
TAI_STRB <= '0';
end if;
end if;
end process TAI_STROBE;
TBI_STROBE: process(RESETn, CLK)
variable LOCK : boolean;
begin
if RESETn = '0' then
TBI_STRB <= '0';
elsif CLK = '1' and CLK' event then
if TBI_I = '1' and XTAL_STRB = '1' and LOCK = false then
LOCK := true;
TBI_STRB <= '1';
elsif TBI_I = '0' then
LOCK := false;
TBI_STRB <= '0';
else
TBI_STRB <= '0';
end if;
end if;
end process TBI_STROBE;
PRESCALE_A: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
A_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TACR(2 downto 0) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
end case;
A_CNTSTRB <= '1';
end if;
end process PRESCALE_A;
PRESCALE_B: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
B_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TBCR(2 downto 0) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
end case;
B_CNTSTRB <= '1';
end if;
end process PRESCALE_B;
PRESCALE_C: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
C_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TCDCR(5 downto 3) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped.
end case;
C_CNTSTRB <= '1';
end if;
end process PRESCALE_C;
PRESCALE_D: process
-- The prescalers work even if the RESETn is asserted.
variable PRESCALE : std_logic_vector(7 downto 0);
begin
wait until CLK = '1' and CLK' event;
D_CNTSTRB <= '0';
if PRESCALE > x"00" and XTAL_STRB = '1' then
PRESCALE := PRESCALE - '1';
elsif XTAL_STRB = '1' then
case TCDCR(2 downto 0) is
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
when "000" => PRESCALE := x"00"; -- Timer stopped.
end case;
D_CNTSTRB <= '1';
end if;
end process PRESCALE_D;
TIMERA: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TAO_I <= '0';
TIMER_A_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_A_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "01111" and TACR(3 downto 0) = x"0" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_A <= To_StdLogicVector(DATA_IN);
else
case TACR(3 downto 0) is
when x"0" => -- Timer is off.
TAO_I <= '0';
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
if A_CNTSTRB = '1' and TIMER_A /= x"01" then -- Count.
TIMER_A <= TIMER_A - '1';
elsif A_CNTSTRB = '1' and TIMER_A = x"01" then -- Reload.
TIMER_A <= To_StdLogicVector(TADR);
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
TIMER_A_INT <= '1';
end if;
when x"8" => -- Event count operation.
if TAI_STRB = '1' and TIMER_A /= x"01" then -- Count.
TIMER_A <= TIMER_A - '1';
elsif TAI_STRB = '1' and TIMER_A = x"01" then -- Reload.
TIMER_A <= To_StdLogicVector(TADR);
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
TIMER_A_INT <= '1';
end if;
when x"9" | x"A" | x"B" | x"C" | x"D" | x"E" | x"F" => -- PWM mode.
if TAI_I = '1' and A_CNTSTRB = '1' and TIMER_A /= x"01" then -- Count.
TIMER_A <= TIMER_A - '1';
elsif TAI_I = '1' and A_CNTSTRB = '1' and TIMER_A = x"01" then -- Reload.
TIMER_A <= To_StdLogicVector(TADR);
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
TIMER_A_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERA;
TIMERB: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TBO_I <= '0';
TIMER_B_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_B_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10000" and TBCR(3 downto 0) = x"0" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_B <= To_StdLogicVector(DATA_IN);
else
case TBCR(3 downto 0) is
when x"0" => -- Timer is off.
TBO_I <= '0';
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
if B_CNTSTRB = '1' and TIMER_B /= x"01" then -- Count.
TIMER_B <= TIMER_B - '1';
elsif B_CNTSTRB = '1' and TIMER_B = x"01" then -- Reload.
TIMER_B <= To_StdLogicVector(TBDR);
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
TIMER_B_INT <= '1';
end if;
when x"8" => -- Event count operation.
if TBI_STRB = '1' and TIMER_B /= x"01" then -- Count.
TIMER_B <= TIMER_B - '1';
elsif TBI_STRB = '1' and TIMER_B = x"01" then -- Reload.
TIMER_B <= To_StdLogicVector(TBDR);
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
TIMER_B_INT <= '1';
end if;
when x"9" | x"A" | x"B" | x"C" | x"D" | x"E" | x"F" => -- PWM mode.
if TBI_I = '1' and B_CNTSTRB = '1' and TIMER_B /= x"01" then -- Count.
TIMER_B <= TIMER_B - '1';
elsif TBI_I = '1' and B_CNTSTRB = '1' and TIMER_B = x"01" then -- Reload.
TIMER_B <= To_StdLogicVector(TBDR);
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
TIMER_B_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERB;
TIMERC: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TCO <= '0';
TIMER_C_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_C_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10001" and TCDCR(5 downto 3) = "000" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_C <= To_StdLogicVector(DATA_IN);
else
case TCDCR(5 downto 3) is
when "000" => -- Timer is off.
TCO <= '0';
when others => -- Delay counter mode.
if C_CNTSTRB = '1' and TIMER_C /= x"01" then -- Count.
TIMER_C <= TIMER_C - '1';
elsif C_CNTSTRB = '1' and TIMER_C = x"01" then -- Reload.
TIMER_C <= To_StdLogicVector(TCDR);
TCO <= not TCO; -- Toggle the timer C output pin.
TIMER_C_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERC;
TIMERD: process(RESETn, CLK)
begin
if RESETn = '0' then
-- Do not clear the timer registers during system reset.
TDO <= '0';
TIMER_D_INT <= '0';
elsif CLK = '1' and CLK' event then
TIMER_D_INT <= '0';
--
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10010" and TCDCR(2 downto 0) = "000" then
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
-- The loading works asynchronous due to the possibly low XTAL1 clock.
TIMER_D <= To_StdLogicVector(DATA_IN);
else
case TCDCR(2 downto 0) is
when "000" => -- Timer is off.
TDO <= '0';
when others => -- Delay counter mode.
if D_CNTSTRB = '1' and TIMER_D /= x"01" then -- Count.
TIMER_D <= TIMER_D - '1';
elsif D_CNTSTRB = '1' and TIMER_D = x"01" then -- Reload.
TIMER_D <= To_StdLogicVector(TDDR);
TDO <= not TDO; -- Toggle the timer D output pin.
TIMER_D_INT <= '1';
end if;
end case;
end if;
end if;
end process TIMERD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,213 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core top level file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K7A 2006/12/28 WF
-- The timer is modified to work on the CLK instead
-- of XTAL1. This modification is done to provide
-- a synchronous design.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
--
use work.wf68901ip_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_TOP is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
DTACKn : out std_logic;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA : inout std_logic_vector(7 downto 0);
GPIP : inout std_logic_vector(7 downto 0);
-- Interrupt control:
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out std_logic;
-- Timers and timer control:
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
TAI : in bit;
TBI : in bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
-- Serial I/O control:
RC : in bit;
TC : in bit;
SI : in bit;
SO : out std_logic;
-- DMA control:
RRn : out bit;
TRn : out bit
);
end entity WF68901IP_TOP;
architecture STRUCTURE of WF68901IP_TOP is
component WF68901IP_TOP_SOC
port(CLK : in bit;
RESETn : in bit;
DSn : in bit;
CSn : in bit;
RWn : in bit;
DTACKn : out bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_EN : out bit_vector(7 downto 0);
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
XTAL1 : in bit;
TAI : in bit;
TBI : in bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
RC : in bit;
TC : in bit;
SI : in bit;
SO : out bit;
SO_EN : out bit;
RRn : out bit;
TRn : out bit
);
end component;
--
signal DTACK_In : bit;
signal IRQ_In : bit;
signal DATA_OUT : std_logic_vector(7 downto 0);
signal DATA_EN : bit;
signal GPIP_IN : bit_vector(7 downto 0);
signal GPIP_OUT : bit_vector(7 downto 0);
signal GPIP_EN : bit_vector(7 downto 0);
signal SO_I : bit;
signal SO_EN : bit;
begin
DTACKn <= '0' when DTACK_In = '0' else 'Z'; -- Open drain.
IRQn <= '0' when IRQ_In = '0' else 'Z'; -- Open drain.
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
GPIP_IN <= To_BitVector(GPIP);
P_GPIP_OUT: process(GPIP_OUT, GPIP_EN)
begin
for i in 7 downto 0 loop
if GPIP_EN(i) = '1' then
case GPIP_OUT(i) is
when '0' => GPIP(i) <= '0';
when others => GPIP(i) <= '1';
end case;
else
GPIP(i) <= 'Z';
end if;
end loop;
end process P_GPIP_OUT;
SO <= '0' when SO_I = '0' and SO_EN = '1' else
'1' when SO_I = '1' and SO_EN = '1' else 'Z';
I_MFP: WF68901IP_TOP_SOC
port map(CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
DTACKn => DTACK_In,
RS => RS,
DATA_IN => DATA,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
GPIP_IN => GPIP_IN,
GPIP_OUT => GPIP_OUT,
GPIP_EN => GPIP_EN,
IACKn => IACKn,
IEIn => IEIn,
IEOn => IEOn,
IRQn => IRQ_In,
XTAL1 => XTAL1,
TAI => TAI,
TBI => TBI,
TAO => TAO,
TBO => TBO,
TCO => TCO,
TDO => TDO,
RC => RC,
TC => TC,
SI => SI,
SO => SO_I,
SO_EN => SO_EN,
RRn => RRn,
TRn => TRn
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,309 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core top level file. ----
---- Top level file for use in systems on programmable chips. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Top level file provided for SOC (systems on programmable chips).
-- Revision 2K7A 2006/12/28 WF
-- The timer is modified to work on the CLK instead
-- of XTAL1. This modification is done to provide
-- a synchronous design.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- DTACK_OUTn has now synchronous reset to meet preset requirement.
--
--
use work.wf68901ip_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_TOP_SOC is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
DTACKn : out bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
GPIP_IN : in bit_vector(7 downto 0);
GPIP_OUT : out bit_vector(7 downto 0);
GPIP_EN : out bit_vector(7 downto 0);
-- Interrupt control:
IACKn : in bit;
IEIn : in bit;
IEOn : out bit;
IRQn : out bit;
-- Timers and timer control:
XTAL1 : in bit; -- Use an oszillator instead of a quartz.
TAI : in bit;
TBI : in bit;
TAO : out bit;
TBO : out bit;
TCO : out bit;
TDO : out bit;
-- Serial I/O control:
RC : in bit;
TC : in bit;
SI : in bit;
SO : out bit;
SO_EN : out bit;
-- DMA control:
RRn : out bit;
TRn : out bit
);
end entity WF68901IP_TOP_SOC;
architecture STRUCTURE of WF68901IP_TOP_SOC is
signal DATA_IN_I : bit_vector(7 downto 0);
signal DTACK_In : bit;
signal DTACK_LOCK : boolean;
signal DTACK_OUTn : bit;
signal RX_ERR_INT_I : bit;
signal TX_ERR_INT_I : bit;
signal RX_BUFF_INT_I : bit;
signal TX_BUFF_INT_I : bit;
signal DATA_OUT_USART_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_USART_I : bit;
signal DATA_OUT_INT_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_INT_I : bit;
signal DATA_OUT_GPIO_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_GPIO_I : bit;
signal DATA_OUT_TIMERS_I : bit_vector(7 downto 0);
signal DATA_OUT_EN_TIMERS_I : bit;
signal SO_I : bit;
signal SO_EN_I : bit;
signal GPIP_IN_I : bit_vector(7 downto 0);
signal GPIP_OUT_I : bit_vector(7 downto 0);
signal GPIP_EN_I : bit_vector(7 downto 0);
signal GP_INT_I : bit_vector(7 downto 0);
signal TIMER_A_INT_I : bit;
signal TIMER_B_INT_I : bit;
signal TIMER_C_INT_I : bit;
signal TIMER_D_INT_I : bit;
signal IRQ_In : bit;
signal AER_4_I : bit;
signal AER_3_I : bit;
signal TA_PWM_I : bit;
signal TB_PWM_I : bit;
begin
-- Interrupt request (open drain):
IRQn <= IRQ_In;
-- Serial data output:
SO <= SO_I;
SO_EN <= SO_EN_I and RESETn;
-- General purpose port:
GPIP_IN_I <= GPIP_IN;
GPIP_OUT <= GPIP_OUT_I;
GPIP_EN <= GPIP_EN_I;
DATA_IN_I <= To_BitVector(DATA_IN);
DATA_EN <= DATA_OUT_EN_USART_I or DATA_OUT_EN_INT_I or DATA_OUT_EN_GPIO_I or DATA_OUT_EN_TIMERS_I;
-- Output data multiplexer:
DATA_OUT <= To_StdLogicVector(DATA_OUT_USART_I) when DATA_OUT_EN_USART_I = '1' else
To_StdLogicVector(DATA_OUT_INT_I) when DATA_OUT_EN_INT_I = '1' else
To_StdLogicVector(DATA_OUT_GPIO_I) when DATA_OUT_EN_GPIO_I = '1' else
To_StdLogicVector(DATA_OUT_TIMERS_I) when DATA_OUT_EN_TIMERS_I = '1' else (others => '1');
-- Data acknowledge handshake is provided by the following statement and the consecutive two
-- processes. For more information refer to the M68000 family reference manual.
DTACK_In <= '0' when CSn = '0' and DSn = '0' and RS <= "10111" else -- Read and write operation.
'0' when IACKn = '0' and DSn = '0' and IEIn = '0' else '1'; -- Interrupt vector data acknowledge.
P_DTACK_LOCK: process
-- This process releases a data acknowledge detect, one rising clock
-- edge after the DTACK_In occured. This is necessary to ensure write
-- data to registers for there is one rising clock edge required.
begin
wait until CLK = '1' and CLK' event;
if DTACK_In = '0' then
DTACK_LOCK <= false;
else
DTACK_LOCK <= true;
end if;
end process P_DTACK_LOCK;
DTACK_OUT: process
-- The DTACKn port pin is released on the falling clock edge after the data
-- acknowledge detect (DTACK_LOCK) is asserted. The DTACKn is deasserted
-- immediately when there is no further register access DTACK_In = '1';
begin
wait until CLK = '0' and CLK' event;
if RESETn = '0' then
DTACK_OUTn <= '1';
elsif DTACK_In = '1' then
DTACK_OUTn <= '1';
elsif DTACK_LOCK = false then
DTACK_OUTn <= '0';
end if;
end process DTACK_OUT;
DTACKn <= '0' when DTACK_OUTn = '0' else '1';
I_USART: WF68901IP_USART_TOP
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_USART_I,
DATA_OUT_EN => DATA_OUT_EN_USART_I,
RC => RC,
TC => TC,
SI => SI,
SO => SO_I,
SO_EN => SO_EN_I,
RX_ERR_INT => RX_ERR_INT_I,
RX_BUFF_INT => RX_BUFF_INT_I,
TX_ERR_INT => TX_ERR_INT_I,
TX_BUFF_INT => TX_BUFF_INT_I,
RRn => RRn,
TRn => TRn
);
I_INTERRUPTS: WF68901IP_INTERRUPTS
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_INT_I,
DATA_OUT_EN => DATA_OUT_EN_INT_I,
IACKn => IACKn,
IEIn => IEIn,
IEOn => IEOn,
IRQn => IRQ_In,
GP_INT => GP_INT_I,
AER_4 => AER_4_I,
AER_3 => AER_3_I,
TAI => TAI,
TBI => TBI,
TA_PWM => TA_PWM_I,
TB_PWM => TB_PWM_I,
TIMER_A_INT => TIMER_A_INT_I,
TIMER_B_INT => TIMER_B_INT_I,
TIMER_C_INT => TIMER_C_INT_I,
TIMER_D_INT => TIMER_D_INT_I,
RCV_ERR => RX_ERR_INT_I,
TRM_ERR => TX_ERR_INT_I,
RCV_BUF_F => RX_BUFF_INT_I,
TRM_BUF_E => TX_BUFF_INT_I
);
I_GPIO: WF68901IP_GPIO
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_GPIO_I,
DATA_OUT_EN => DATA_OUT_EN_GPIO_I,
AER_4 => AER_4_I,
AER_3 => AER_3_I,
GPIP_IN => GPIP_IN_I,
GPIP_OUT => GPIP_OUT_I,
GPIP_OUT_EN => GPIP_EN_I,
GP_INT => GP_INT_I
);
I_TIMERS: WF68901IP_TIMERS
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN_I,
DATA_OUT => DATA_OUT_TIMERS_I,
DATA_OUT_EN => DATA_OUT_EN_TIMERS_I,
XTAL1 => XTAL1,
AER_4 => AER_4_I,
AER_3 => AER_3_I,
TAI => TAI,
TBI => TBI,
TAO => TAO,
TBO => TBO,
TCO => TCO,
TDO => TDO,
TA_PWM => TA_PWM_I,
TB_PWM => TB_PWM_I,
TIMER_A_INT => TIMER_A_INT_I,
TIMER_B_INT => TIMER_B_INT_I,
TIMER_C_INT => TIMER_C_INT_I,
TIMER_D_INT => TIMER_D_INT_I
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,191 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This is the SUSKA MFP IP core USART control file. ----
---- ----
---- Control unit and status logic. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_CTRL is
port (
-- System Control:
CLK : in bit;
RESETn : in bit;
-- Bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- USART data register
RX_SAMPLE : in bit;
RX_DATA : in bit_vector(7 downto 0);
TX_DATA : out bit_vector(7 downto 0);
SCR_OUT : out bit_vector(7 downto 0);
-- USART control inputs:
BF : in bit;
BE : in bit;
FE : in bit;
OE : in bit;
UE : in bit;
PE : in bit;
M_CIP : in bit;
FS_B : in bit;
TX_END : in bit;
-- USART control outputs:
CL : out bit_vector(1 downto 0);
ST : out bit_vector(1 downto 0);
FS_CLR : out bit;
UDR_WRITE : out bit;
UDR_READ : out bit;
RSR_READ : out bit;
TSR_READ : out bit;
LOOPBACK : out bit;
SDOUT_EN : out bit;
SD_LEVEL : out bit;
CLK_MODE : out bit;
RE : out bit;
TE : out bit;
P_ENA : out bit;
P_EOn : out bit;
SS : out bit;
BR : out bit
);
end entity WF68901IP_USART_CTRL;
architecture BEHAVIOR of WF68901IP_USART_CTRL is
signal SCR : bit_vector(7 downto 0); -- Synchronous data register.
signal UCR : bit_vector(7 downto 1); -- USART control register.
signal RSR : bit_vector(7 downto 0); -- Receiver status register.
signal TSR : bit_vector(7 downto 0); -- Transmitter status register.
signal UDR : bit_vector(7 downto 0); -- USART data register.
begin
USART_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
SCR <= (others => '0');
UCR <= (others => '0');
RSR <= (others => '0');
-- TSR and UDR are not cleared during an asserted RESETn
elsif CLK = '1' and CLK' event then
-- Loading via receiver shift register
-- has priority over data buss access:
if RX_SAMPLE = '1' then
UDR <= RX_DATA;
elsif CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "10011" => SCR <= DATA_IN;
when "10100" => UCR <= DATA_IN(7 downto 1);
when "10101" => RSR(1 downto 0) <= DATA_IN(1 downto 0); -- Only the two LSB are read/write.
when "10110" => TSR(5) <= DATA_IN(5); TSR(3 downto 0) <= DATA_IN(3 downto 0);
when "10111" => UDR <= DATA_IN;
when others => null;
end case;
end if;
RSR(7 downto 2) <= BF & OE & PE & FE & FS_B & M_CIP;
TSR(7 downto 6) <= BE & UE;
TSR(4) <= TX_END;
TX_DATA <= UDR;
end if;
end process USART_REGISTERS;
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS >= "10011" and RS <= "10111" else '0';
DATA_OUT <= SCR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10011" else
UCR & '0' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10100" else
RSR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10101" else
TSR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10110" else
UDR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10111" else x"00";
UDR_WRITE <= '1' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "10111" else '0';
UDR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10111" else '0';
RSR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10101" else '0';
TSR_READ <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10110" else '0';
FS_CLR <= '1' when CSn = '0' and DSn = '0' and RWn = '0' and RS = "10011" else '0';
RE <= '1' when RSR(0) = '1' else -- Receiver enable.
'1' when TSR(5) = '1' and TX_END = '1' else '0'; -- Auto Turnaround.
SS <= RSR(1); -- Synchronous strip enable.
BR <= TSR(3); -- Send break.
TE <= TSR(0); -- Transmitter enable.
SCR_OUT <= SCR;
CLK_MODE <= UCR(7); -- Clock mode.
CL <= UCR(6 downto 5); -- Character length.
ST <= UCR(4 downto 3); -- Start/Stop configuration.
P_ENA <= UCR(2); -- Parity enable.
P_EOn <= UCR(1); -- Even or odd parity.
SOUT_CONFIG: process
begin
wait until CLK = '1' and CLK' event;
-- Do not change the output configuration until the transmitter is disabled and
-- current character has been transmitted (TX_END = '1').
if TX_END = '1' then
case TSR(2 downto 1) is
when "00" => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '0';
when "01" => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '1';
when "10" => LOOPBACK <= '0'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
when "11" => LOOPBACK <= '1'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
end case;
end if;
end process SOUT_CONFIG;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,590 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This is the SUSKA MFP IP core USART receiver file. ----
---- ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- Process P_STARTBIT has now synchronous reset to meet preset requirement.
-- Process P_SAMPLE has now synchronous reset to meet preset requirement.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_RX is
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0); -- Synchronous character.
RX_SAMPLE : buffer bit; -- Flag indicating valid shift register data.
RX_DATA : out bit_vector(7 downto 0); -- Received data.
RXCLK : in bit; -- Receiver clock.
SDATA_IN : in bit; -- Serial data input.
CL : in bit_vector(1 downto 0); -- Character length.
ST : in bit_vector(1 downto 0); -- Start and stop bit configuration.
P_ENA : in bit; -- Parity enable.
P_EOn : in bit; -- Even or odd parity.
CLK_MODE : in bit; -- Clock mode configuration bit.
RE : in bit; -- Receiver enable.
FS_CLR : in bit; -- Clear the Found/Search flag for resynchronisation purpose.
SS : in bit; -- Synchronous strip enable.
UDR_READ : in bit; -- Flag indicating reading the data register.
RSR_READ : in bit; -- Flag indicating reading the receiver status register.
M_CIP : out bit; -- Match/Character in progress.
FS_B : buffer bit; -- Find/Search or Break detect flag.
BF : out bit; -- Buffer full.
OE : out bit; -- Overrun error.
PE : out bit; -- Parity error.
FE : out bit -- Framing error.
);
end entity WF68901IP_USART_RX;
architecture BEHAVIOR of WF68901IP_USART_RX is
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
signal SDATA_DIV16 : bit;
signal SDATA_IN_I : bit;
signal SDATA_EDGE : bit;
signal SHIFT_REG : bit_vector(7 downto 0);
signal CLK_STRB : bit;
signal CLK_2_STRB : bit;
signal BITCNT : std_logic_vector(2 downto 0);
signal BREAK : boolean;
signal RDRF : bit;
signal STARTBIT : boolean;
begin
BF <= RDRF; -- Buffer full = Receiver Data Register Full.
RX_SAMPLE <= '1' when RCV_STATE = SYNC and ST /= "00" else -- Asynchronous mode:
-- Synchronous modes:
'1' when RCV_STATE = SYNC and ST = "00" and SS = '0' else
'1' when RCV_STATE = SYNC and ST = "00" and SS = '1' and SHIFT_REG /= SCR else '0';
-- Data multiplexer for the received data:
RX_DATA <= "000" & SHIFT_REG(7 downto 3) when RX_SAMPLE = '1' and CL = "11" else -- 5 databits.
"00" & SHIFT_REG(7 downto 2) when RX_SAMPLE = '1' and CL = "10" else -- 6 databits.
'0' & SHIFT_REG(7 downto 1) when RX_SAMPLE = '1' and CL = "01" else -- 6 databits.
SHIFT_REG when RX_SAMPLE = '1' and CL = "00" else x"00"; -- 8 databits.
P_SAMPLE: process
-- This process provides the 'valid transition logic' of the originally MC68901. For further
-- details see the 'M68000 FAMILY REFERENCE MANUAL'.
variable LOW_FLT : std_logic_vector(1 downto 0);
variable HI_FLT : std_logic_vector(1 downto 0);
variable CLK_LOCK : boolean;
variable EDGE_LOCK : boolean;
variable TIMER : std_logic_vector(2 downto 0);
variable TIMER_LOCK : boolean;
variable NEW_SDATA : bit;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' or RE = '0' then
-- The reset condition assumes the SDATA_IN logic high. Otherwise
-- one not valid SDATA_EDGE pulse occurs during system startup.
CLK_LOCK := true;
EDGE_LOCK := true;
HI_FLT := "11";
LOW_FLT := "11";
SDATA_EDGE <= '0';
NEW_SDATA := '1';
-- Positive or negative edge detector for the incoming data.
-- Any transition must be valid for at least three receiver clock
-- cycles. The TIMER locking inhibits detecting four receiver
-- clock cycles after a valid transition.
elsif RXCLK = '1' and SDATA_IN = '0' and CLK_LOCK = false and LOW_FLT > "00" then
CLK_LOCK := true;
EDGE_LOCK := false;
HI_FLT := "00";
LOW_FLT := LOW_FLT - '1';
elsif RXCLK = '1' and SDATA_IN = '1' and CLK_LOCK = false and HI_FLT < "11" then
CLK_LOCK := true;
EDGE_LOCK := false;
LOW_FLT := "11";
HI_FLT := HI_FLT + '1';
elsif RXCLK = '1' and EDGE_LOCK = false and LOW_FLT = "00" then
EDGE_LOCK := true;
SDATA_EDGE <= '1'; -- Falling edge detected.
NEW_SDATA := '0';
elsif RXCLK = '1' and EDGE_LOCK = false and HI_FLT = "11" then
EDGE_LOCK := true;
SDATA_EDGE <= '1'; -- Rising edge detected.
NEW_SDATA := '1';
elsif RXCLK = '1' and CLK_LOCK = false then
CLK_LOCK := true;
SDATA_EDGE <= '0';
elsif RXCLK = '0' then
CLK_LOCK := false;
end if;
--
if RESETn = '0' or RE = '0' then
-- The reset condition assumes the SDATA_IN logic high. Otherwise
-- one not valid SDATA_EDGE pulse occurs during system startup.
TIMER := "111";
TIMER_LOCK := true;
SDATA_DIV16 <= '1';
-- The timer controls the SDATA in a way, that after a detected valid
-- Transistion, the serial data is sampled on the 8th receiver clock
-- edge after the initial valid transition occured.
elsif RXCLK = '1' and SDATA_EDGE = '1' and TIMER_LOCK = false then
TIMER_LOCK := true;
TIMER := "000"; -- Resynchronisation.
elsif RXCLK = '1' and TIMER = "011" and TIMER_LOCK = false then
TIMER_LOCK := true;
SDATA_DIV16 <= NEW_SDATA; -- Scan the new data.
TIMER := TIMER + '1'; -- Timing is active.
elsif RXCLK = '1' and TIMER < "111" and TIMER_LOCK = false then
TIMER_LOCK := true;
TIMER := TIMER + '1'; -- Timing is active.
elsif RXCLK = '0' then
TIMER_LOCK := false;
end if;
end process P_SAMPLE;
P_START_BIT: process(CLK)
-- This is the valid start bit logic of the original MC68901 multi function
-- port's USART receiver.
variable TMP : std_logic_vector(2 downto 0);
variable LOCK : boolean;
begin
if CLK = '1' and CLK' event then
if RESETn = '0' then
TMP := "000";
LOCK := true;
elsif RE = '0' or RCV_STATE /= IDLE then -- Start bit logic disabled.
TMP := "000";
LOCK := true;
elsif SDATA_EDGE = '1' then
TMP := "000"; -- (Re)-Initialize.
LOCK := false; -- Start counting.
elsif RXCLK = '1' and SDATA_IN = '0' and TMP < "111" and LOCK = false then
LOCK := true;
TMP := TMP + '1'; -- Count 8 low bits to declare start condition valid.
elsif RXCLK = '0' then
LOCK := false;
end if;
end if;
case TMP is
when "111" => STARTBIT <= true;
when others => STARTBIT <= false;
end case;
end process P_START_BIT;
SDATA_IN_I <= SDATA_IN when CLK_MODE = '0' else -- Clock div by 1 mode.
SDATA_IN when ST = "00" else SDATA_DIV16; -- Synchronous mode.
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(4 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CLK_MODE = '0' then -- Divider off.
if RXCLK = '1' and STRB_LOCK = false then
CLK_STRB <= '1';
STRB_LOCK := true;
elsif RXCLK = '0' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
CLK_2_STRB <= '0'; -- No 1 1/2 stop bits in no div by 16 mode.
elsif SDATA_EDGE = '1' then
CLK_DIVCNT := "01100"; -- Div by 16 mode.
CLK_STRB <= '0'; -- Default.
CLK_2_STRB <= '0'; -- Default.
else
CLK_STRB <= '0'; -- Default.
CLK_2_STRB <= '0'; -- Default.
if CLK_DIVCNT > "00000" and RXCLK = '1' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_LOCK := true;
if CLK_DIVCNT = "01000" then
-- This strobe is asserted at half of the clock cycle.
-- It is used for the stop bit timing.
CLK_2_STRB <= '1';
end if;
elsif CLK_DIVCNT = "00000" then
CLK_DIVCNT := "10000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
end if;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
end if;
end if;
end process CLKDIV;
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if RE = '0' then
SHIFT_REG <= x"00";
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' then
SHIFT_REG <= SDATA_IN_I & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_M_CIP: process(RESETn, CLK)
-- In Synchronous mode this flag indicates wether a synchronous character M_CIP = '1'
-- or another character (M_CIP = '0') is transferred to the receive buffer.
-- In asynchronous mode the flag indicates sampling condition.
begin
if RESETn = '0' then
M_CIP <= '0';
elsif CLK = '0' and CLK' event then
if RE = '0' then
M_CIP <= '0';
elsif ST = "00" then -- Synchronous mode.
if RCV_STATE = SYNC and SHIFT_REG = SCR and RDRF = '0' then
M_CIP <= '1'; -- SCR transferred.
elsif RCV_STATE = SYNC and RDRF = '0' then
M_CIP <= '0'; -- No SCR transferred.
end if;
else -- Asynchronous mode.
case RCV_STATE is
when SAMPLE | PARITY | STOP1 | STOP2 => M_CIP <= '1'; -- Sampling.
when others => M_CIP <= '0'; -- No Sampling.
end case;
end if;
end if;
end process P_M_CIP;
BREAK_DETECT: process(RESETn, CLK)
-- A break condition occurs, if there is no STOP1 bit and the
-- shift register contains zero data.
begin
if RESETn = '0' then
BREAK <= false;
elsif CLK = '1' and CLK' event then
if RE = '0' then
BREAK <= false;
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG = x"00" then
BREAK <= true; -- Break detected (empty shift register and no stop bit).
elsif RCV_STATE = STOP1 and SDATA_IN_I = '1' then
BREAK <= false; -- UPDATE.
elsif RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
BREAK <= false; -- UPDATE, but framing error.
end if;
end if;
end if;
end process BREAK_DETECT;
P_FS_B: process(RESETn, CLK)
-- In the synchronous mode, this process provides the flag detecting the synchronous
-- character. In the asynchronous mode, the flag indicates a break condition.
variable FS_B_I : bit;
variable FIRST_READ : boolean;
begin
if RESETn = '0' then
FS_B <= '0';
FIRST_READ := false;
FS_B_I := '0';
elsif CLK = '0' and CLK' event then
if RE = '0' then
FS_B <= '0';
FS_B_I := '0';
else
if ST = "00" then -- Synchronous operation.
if FS_CLR = '1' then
FS_B <= '0'; -- Clear during writing to the SCR.
elsif SHIFT_REG = SCR then
FS_B <= '1'; -- SCR detected.
end if;
else -- Asynchronous operation.
if RX_SAMPLE = '1' and BREAK = true then -- Break condition detected.
FS_B_I := '1'; -- Update.
elsif RX_SAMPLE = '1' then -- No break condition.
FS_B_I := '0'; -- Update.
elsif RSR_READ = '1' and FS_B_I = '1' then
-- If a break condition was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the break flag is reset
-- and the break condition disappears after a second read
-- (in time) of the receiver status register.
if FIRST_READ = false then
FS_B <= '1';
FIRST_READ := true;
else
FS_B <= '0';
FIRST_READ := false;
end if;
end if;
end if;
end if;
end if;
end process P_FS_B;
P_BITCNT: process
begin
wait until CLK = '1' and CLK' event;
if RCV_STATE = SAMPLE and CLK_STRB = '1' and ST /= "00" then -- Asynchronous mode.
BITCNT <= BITCNT + '1';
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' and ST = "00" and FS_B = '1' then -- Synchronous mode.
BITCNT <= BITCNT + '1'; -- Count, if matched data found (FS_B = '1').
elsif RCV_STATE /= SAMPLE then
BITCNT <= (others => '0');
end if;
end process P_BITCNT;
BUFFER_FULL: process(RESETn, CLK)
-- Receive data register full flag.
begin
if RESETn = '0' then
RDRF <= '0';
elsif CLK = '1' and CLK' event then
if RE = '0' then
RDRF <= '0';
elsif RX_SAMPLE = '1' then
RDRF <= '1'; -- Data register is full until now!
elsif UDR_READ = '1' then
RDRF <= '0'; -- After reading the data register ...
end if;
end if;
end process BUFFER_FULL;
OVERRUN: process(RESETn, CLK)
variable OE_I : bit;
variable FIRST_READ : boolean;
begin
if RESETn = '0' then
OE_I := '0';
OE <= '0';
FIRST_READ := false;
elsif CLK = '1' and CLK' event then
if RESETn = '0' then
OE_I := '0';
OE <= '0';
FIRST_READ := false;
elsif CLK_STRB = '1' and RCV_STATE = SYNC and BREAK = false then
-- Overrun appears if RDRF is '1' in this state and there
-- is no break condition.
OE_I := RDRF;
end if;
if RSR_READ = '1' and OE_I = '1' then
-- if an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OE_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OE <= '1';
FIRST_READ := true;
else
OE <= '0';
FIRST_READ := false;
end if;
end if;
end if;
end process OVERRUN;
PARITY_TEST: process(RESETn, CLK)
variable PAR_TMP : bit;
variable P_ERR : bit;
begin
if RESETn = '0' then
PE <= '0';
elsif CLK = '1' and CLK' event then
if RE = '0' then
PE <= '0';
elsif RX_SAMPLE = '1' then
PE <= P_ERR; -- Update on load shift register to data register.
elsif CLK_STRB = '1' then -- Sample parity on clock strobe.
P_ERR := '0'; -- Initialise.
if RCV_STATE = PARITY then
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if P_ENA = '1' and P_EOn = '1' then -- Even parity.
P_ERR := PAR_TMP xor SDATA_IN_I;
elsif P_ENA = '1' and P_EOn = '0' then -- Odd parity.
P_ERR := not PAR_TMP xor SDATA_IN_I;
elsif P_ENA = '0' then -- No parity.
P_ERR := '0';
end if;
end if;
end if;
end if;
end process PARITY_TEST;
FRAME_ERR: process(RESETn, CLK)
-- This module detects a framing error
-- during stop bit 1 and stop bit 2.
variable FE_I: bit;
begin
if RESETn = '0' then
FE_I := '0';
FE <= '0';
elsif CLK = '1' and CLK' event then
if RE = '0' then
FE_I := '0';
FE <= '0';
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
FE_I := '1';
elsif RCV_STATE = STOP2 and SDATA_IN_I = '0' and SHIFT_REG /= x"00" then
FE_I := '1';
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
FE_I := '0'; -- Error resets when correct data appears.
end if;
end if;
if RCV_STATE = SYNC then
FE <= FE_I; -- Update the FE every SYNC time.
end if;
end if;
end process FRAME_ERR;
RCV_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
RCV_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if RE = '0' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
end if;
end if;
end process RCV_STATEREG;
RCV_STATEDEC: process(RCV_STATE, SDATA_IN_I, BITCNT, CLK_STRB, STARTBIT,
CLK_2_STRB, ST, CLK_MODE, CL, P_ENA, SHIFT_REG)
begin
case RCV_STATE is
when IDLE =>
if ST = "00" then
RCV_NEXT_STATE <= SAMPLE; -- Synchronous mode.
elsif SDATA_IN_I = '0' and CLK_MODE = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
elsif STARTBIT = true and CLK_MODE = '1' then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
else
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
end if;
when WAIT_START =>
-- This state delays the sample process by one CLK_STRB pulse
-- to eliminate the start bit.
if CLK_STRB = '1' then
RCV_NEXT_STATE <= SAMPLE;
else
RCV_NEXT_STATE <= WAIT_START;
end if;
when SAMPLE =>
if CLK_STRB = '1' then
if CL = "11" and BITCNT < "100" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 5 data bits.
elsif CL = "10" and BITCNT < "101" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 6 data bits.
elsif CL = "01" and BITCNT < "110" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
elsif CL = "00" and BITCNT < "111" then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
elsif ST = "00" and P_ENA = '0' then -- Synchronous mode (no stop bits).
RCV_NEXT_STATE <= IDLE; -- No parity check enabled.
elsif P_ENA = '0' then
RCV_NEXT_STATE <= STOP1; -- No parity check enabled.
else
RCV_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
RCV_NEXT_STATE <= SAMPLE; -- Stay in sample mode.
end if;
when PARITY =>
if CLK_STRB = '1' then
if ST = "00" then -- Synchronous mode (no stop bits).
RCV_NEXT_STATE <= IDLE;
else
RCV_NEXT_STATE <= STOP1;
end if;
else
RCV_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' then
if SHIFT_REG > x"00" and SDATA_IN_I = '0' then -- No Stop bit after non zero data.
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
elsif ST = "11" or ST = "10" then
RCV_NEXT_STATE <= STOP2; -- More than one stop bits selected.
else
RCV_NEXT_STATE <= SYNC; -- One stop bit selected.
end if;
else
RCV_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_2_STRB = '1' and ST = "10" then
RCV_NEXT_STATE <= SYNC; -- One and a half stop bits selected.
elsif CLK_STRB = '1' then
RCV_NEXT_STATE <= SYNC; -- Two stop bits selected.
else
RCV_NEXT_STATE <= STOP2;
end if;
when SYNC =>
RCV_NEXT_STATE <= IDLE;
end case;
end process RCV_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,238 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- MC68901 compatible multi function port core. ----
---- ----
---- This is the SUSKA MFP IP core USART top level file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
use work.wf68901ip_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_TOP is
port ( -- System control:
CLK : in bit;
RESETn : in bit;
-- Asynchronous bus control:
DSn : in bit;
CSn : in bit;
RWn : in bit;
-- Data and Adresses:
RS : in bit_vector(5 downto 1);
DATA_IN : in bit_vector(7 downto 0);
DATA_OUT : out bit_vector(7 downto 0);
DATA_OUT_EN : out bit;
-- Serial I/O control:
RC : in bit; -- Receiver clock.
TC : in bit; -- Transmitter clock.
SI : in bit; -- Serial input.
SO : out bit; -- Serial output.
SO_EN : out bit; -- Serial output enable.
-- Interrupt channels:
RX_ERR_INT : out bit; -- Receiver errors.
RX_BUFF_INT : out bit; -- Receiver buffer full.
TX_ERR_INT : out bit; -- Transmitter errors.
TX_BUFF_INT : out bit; -- Transmitter buffer empty.
-- DMA control:
RRn : out bit;
TRn : out bit
);
end entity WF68901IP_USART_TOP;
architecture STRUCTURE of WF68901IP_USART_TOP is
signal BF_I : bit;
signal BE_I : bit;
signal FE_I : bit;
signal OE_I : bit;
signal UE_I : bit;
signal PE_I : bit;
signal LOOPBACK_I : bit;
signal SD_LEVEL_I : bit;
signal SDATA_IN_I : bit;
signal SDATA_OUT_I : bit;
signal RXCLK_I : bit;
signal CLK_MODE_I : bit;
signal SCR_I : bit_vector(7 downto 0);
signal RX_SAMPLE_I : bit;
signal RX_DATA_I : bit_vector(7 downto 0);
signal TX_DATA_I : bit_vector(7 downto 0);
signal CL_I : bit_vector(1 downto 0);
signal ST_I : bit_vector(1 downto 0);
signal P_ENA_I : bit;
signal P_EOn_I : bit;
signal RE_I : bit;
signal TE_I : bit;
signal FS_CLR_I : bit;
signal SS_I : bit;
signal M_CIP_I : bit;
signal FS_B_I : bit;
signal BR_I : bit;
signal UDR_READ_I : bit;
signal UDR_WRITE_I : bit;
signal RSR_READ_I : bit;
signal TSR_READ_I : bit;
signal TX_END_I : bit;
begin
SO <= SDATA_OUT_I when TE_I = '1' else SD_LEVEL_I;
-- Loopback mode:
SDATA_IN_I <= SDATA_OUT_I when LOOPBACK_I = '1' and TE_I = '1' else -- Loopback, transmitter enabled.
'1' when LOOPBACK_I = '1' and TE_I = '0' else SI; -- Loopback, transmitter disabled.
RXCLK_I <= TC when LOOPBACK_I = '1' else RC;
RRn <= '0' when BF_I = '1' and PE_I = '0' and FE_I = '0' else '1';
TRn <= not BE_I;
-- Interrupt sources:
RX_ERR_INT <= OE_I or PE_I or FE_I or FS_B_I;
RX_BUFF_INT <= BF_I;
TX_ERR_INT <= UE_I or TX_END_I;
TX_BUFF_INT <= BE_I;
I_USART_CTRL: WF68901IP_USART_CTRL
port map(
CLK => CLK,
RESETn => RESETn,
DSn => DSn,
CSn => CSn,
RWn => RWn,
RS => RS,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT,
DATA_OUT_EN => DATA_OUT_EN,
LOOPBACK => LOOPBACK_I,
SDOUT_EN => SO_EN,
SD_LEVEL => SD_LEVEL_I,
CLK_MODE => CLK_MODE_I,
RE => RE_I,
TE => TE_I,
P_ENA => P_ENA_I,
P_EOn => P_EOn_I,
BF => BF_I,
BE => BE_I,
FE => FE_I,
OE => OE_I,
UE => UE_I,
PE => PE_I,
M_CIP => M_CIP_I,
FS_B => FS_B_I,
SCR_OUT => SCR_I,
TX_DATA => TX_DATA_I,
RX_SAMPLE => RX_SAMPLE_I,
RX_DATA => RX_DATA_I,
SS => SS_I,
BR => BR_I,
CL => CL_I,
ST => ST_I,
FS_CLR => FS_CLR_I,
UDR_READ => UDR_READ_I,
UDR_WRITE => UDR_WRITE_I,
RSR_READ => RSR_READ_I,
TSR_READ => TSR_READ_I,
TX_END => TX_END_I
);
I_USART_RECEIVE: WF68901IP_USART_RX
port map (
CLK => CLK,
RESETn => RESETn,
SCR => SCR_I,
RX_SAMPLE => RX_SAMPLE_I,
RX_DATA => RX_DATA_I,
CL => CL_I,
ST => ST_I,
P_ENA => P_ENA_I,
P_EOn => P_EOn_I,
CLK_MODE => CLK_MODE_I,
RE => RE_I,
FS_CLR => FS_CLR_I,
SS => SS_I,
RXCLK => RXCLK_I,
SDATA_IN => SDATA_IN_I,
RSR_READ => RSR_READ_I,
UDR_READ => UDR_READ_I,
M_CIP => M_CIP_I,
FS_B => FS_B_I,
BF => BF_I,
OE => OE_I,
PE => PE_I,
FE => FE_I
);
I_USART_TRANSMIT: WF68901IP_USART_TX
port map (
CLK => CLK,
RESETn => RESETn,
SCR => SCR_I,
TX_DATA => TX_DATA_I,
SDATA_OUT => SDATA_OUT_I,
TXCLK => TC,
CL => CL_I,
ST => ST_I,
TE => TE_I,
BR => BR_I,
P_ENA => P_ENA_I,
P_EOn => P_EOn_I,
UDR_WRITE => UDR_WRITE_I,
TSR_READ => TSR_READ_I,
CLK_MODE => CLK_MODE_I,
TX_END => TX_END_I,
UE => UE_I,
BE => BE_I
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,387 @@
----------------------------------------------------------------------
---- ----
---- ATARI MFP compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This is the SUSKA MFP IP core USART transmitter file. ----
---- ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
-- Revision 2K9A 2009/06/20 WF
-- TDRE has now synchronous reset to meet preset requirement.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF68901IP_USART_TX is
port (
CLK : in bit;
RESETn : in bit;
SCR : in bit_vector(7 downto 0); -- Synchronous character.
TX_DATA : in bit_vector(7 downto 0); -- Normal data.
SDATA_OUT : out bit; -- Serial data output.
TXCLK : in bit; -- Transmitter clock.
CL : in bit_vector(1 downto 0); -- Character length.
ST : in bit_vector(1 downto 0); -- Start and stop bit configuration.
TE : in bit; -- Transmitter enable.
BR : in bit; -- BREAK character send enable (all '0' without stop bit).
P_ENA : in bit; -- Parity enable.
P_EOn : in bit; -- Even or odd parity.
UDR_WRITE : in bit; -- Flag indicating writing the data register.
TSR_READ : in bit; -- Flag indicating reading the transmitter status register.
CLK_MODE : in bit; -- Transmitter clock mode.
TX_END : out bit; -- End of transmission flag.
UE : out bit; -- Underrun Flag.
BE : out bit -- Buffer empty flag.
);
end entity WF68901IP_USART_TX;
architecture BEHAVIOR of WF68901IP_USART_TX is
type TR_STATES is (IDLE, CHECK_BREAK, LOAD_SHFT, START, SHIFTOUT, PARITY, STOP1, STOP2);
signal TR_STATE, TR_NEXT_STATE : TR_STATES;
signal CLK_STRB : bit;
signal CLK_2_STRB : bit;
signal SHIFT_REG : bit_vector(7 downto 0);
signal BITCNT : std_logic_vector(2 downto 0);
signal PARITY_I : bit;
signal TDRE : bit;
signal BREAK : bit;
begin
BE <= TDRE; -- Buffer empty flag.
-- The default condition in this statement is to ensure
-- to cover all possibilities for example if there is a
-- one hot decoding of the state machine with wrong states
-- (e.g. not one of the given here).
SDATA_OUT <= '0' when BREAK = '1' else
'1' when TR_STATE = IDLE else
'1' when TR_STATE = LOAD_SHFT else
'0' when TR_STATE = START else
SHIFT_REG(0) when TR_STATE = SHIFTOUT else
PARITY_I when TR_STATE = PARITY else
'1' when TR_STATE = STOP1 else
'1' when TR_STATE = STOP2 else '1';
P_BREAK : process(RESETn, CLK)
-- This process is responsible to control the BREAK signal. After the break request
-- is asserted via BR, the break character will be sent after the current transmission has
-- finished. The BREAK character is sent until the BR is disabled.
variable LOCK : boolean;
begin
if RESETn = '0' then
BREAK <= '0';
elsif CLK = '1' and CLK' event then
-- Break is only available in the asynchronous mode (ST /= "00").
-- The LOCK mechanism is reponsible for sending the BREAK character just once.
if TE = '1' and BR = '1' and ST /= "00" and TR_STATE = IDLE and LOCK = false then
BREAK <= '1'; -- Break for the case that there is no current transmission.
LOCK := true;
elsif BR = '1' and ST /= "00" and TR_STATE = STOP1 then
BREAK <= '0'; -- Break character sent.
elsif BR = '0' then
BREAK <= '0';
LOCK := false;
else
BREAK <= '0';
end if;
end if;
end process P_BREAK;
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(4 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CLK_MODE = '0' then -- Divider off.
if TXCLK = '0' and STRB_LOCK = false then -- Works on negative TXCLK edge.
CLK_STRB <= '1';
STRB_LOCK := true;
elsif TXCLK = '1' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
CLK_2_STRB <= '0'; -- No 1 1/2 stop bits in no div by 16 mode.
elsif TR_STATE = IDLE then
CLK_DIVCNT := "10000"; -- Div by 16 mode.
CLK_STRB <= '0';
else
CLK_STRB <= '0'; -- Default.
CLK_2_STRB <= '0'; -- Default.
-- Works on negative TXCLK edge:
if CLK_DIVCNT > "00000" and TXCLK = '0' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_LOCK := true;
if CLK_DIVCNT = "01000" then
-- This strobe is asserted at half of the clock cycle.
-- It is used for the stop bit timing.
CLK_2_STRB <= '1';
end if;
elsif CLK_DIVCNT = "00000" then
CLK_DIVCNT := "10000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
end if;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
end if;
end if;
end process CLKDIV;
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if TR_STATE = LOAD_SHFT and TDRE = '1' then -- Lost data ...
case ST is
when "00" => -- Synchronous mode.
SHIFT_REG <= SCR; -- Send the synchronous character.
when others => -- Asynchronous mode.
SHIFT_REG <= x"5A"; -- Load the shift register with a mark (underrun).
end case;
elsif TR_STATE = LOAD_SHFT then
-- Load 'normal' data if there is no break condition:
case CL is
when "11" => SHIFT_REG <= "000" & TX_DATA(4 downto 0); -- 5 databits.
when "10" => SHIFT_REG <= "00" & TX_DATA(5 downto 0); -- 6 databits.
when "01" => SHIFT_REG <= '0' & TX_DATA(6 downto 0); -- 7 databits.
when "00" => SHIFT_REG <= TX_DATA; -- 8 databits.
end case;
elsif TR_STATE = SHIFTOUT and CLK_STRB = '1' then
SHIFT_REG <= '0' & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
-- Counter for the data bits transmitted.
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end process P_BITCNT;
BUFFER_EMPTY: process
-- Transmit data register empty flag.
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
TDRE <= '1';
elsif TE = '0' then
TDRE <= '1';
elsif TR_STATE = START and BREAK = '0' then
-- Data has been loaded to the shift register,
-- thus data register is free again.
-- If the BREAK flag is enabled, the BE flag
-- respective TDRE flag cannot be set.
TDRE <= '1';
elsif UDR_WRITE = '1' then
TDRE <= '0';
end if;
end process BUFFER_EMPTY;
UNDERRUN: process(RESETn, CLK)
variable LOCK : boolean;
begin
if RESETn = '0' then
UE <= '0';
LOCK := false;
elsif CLK = '1' and CLK' event then
if TE = '0' then
UE <= '0';
LOCK := false;
elsif CLK_STRB = '1' and TR_STATE = START then
-- Underrun appears if TDRE is '0' at the end of this state.
UE <= TDRE; -- Never true for enabled BREAK flag. See alos process BUFFER_EMPTY.
LOCK := true;
elsif CLK_STRB = '1' then
LOCK := false; -- Disables clearing UE one transmit clock cycle.
elsif TSR_READ = '1' and LOCK = false then
UE <= '0';
end if;
end if;
end process UNDERRUN;
P_TX_END: process(RESETn, CLK)
begin
if RESETn = '0' then
TX_END <= '0';
elsif CLK = '1' and CLK' event then
if TE = '1' then -- Transmitter enabled.
TX_END <= '0';
elsif TE = '0' and TR_STATE = IDLE then
TX_END <= '1';
end if;
end if;
end process P_TX_END;
PARITY_GEN: process
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if P_ENA = '1' and P_EOn = '1' then -- Even parity.
PARITY_I <= PAR_TMP;
elsif P_ENA = '1' and P_EOn = '0' then -- Odd parity.
PARITY_I <= not PAR_TMP;
else -- No parity.
PARITY_I <= '0';
end if;
end if;
end process PARITY_GEN;
TR_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TR_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
TR_STATE <= TR_NEXT_STATE;
end if;
end process TR_STATEREG;
TR_STATEDEC: process(TR_STATE, CLK_STRB, CLK_2_STRB, BITCNT, TDRE, BREAK, TE, ST, P_ENA, CL, BR)
begin
case TR_STATE is
when IDLE =>
-- This IDLE state is just one clock cycle and is required to give the
-- break process time to set the BREAK flag.
TR_NEXT_STATE <= CHECK_BREAK;
when CHECK_BREAK =>
if BREAK = '1' then -- Send break character.
-- Do not load any data to the shift register, go directly
-- to the START state.
TR_NEXT_STATE <= START;
-- Start enabled transmitter, if the data register is not empty.
-- Do not send any further data for the case of an asserted BR flag.
elsif TE = '1' and TDRE = '0' and BR = '0' then
TR_NEXT_STATE <= LOAD_SHFT;
else
TR_NEXT_STATE <= IDLE; -- Go back, scan for BREAK.
end if;
when LOAD_SHFT =>
TR_NEXT_STATE <= START;
when START => -- Send the start bit.
if CLK_STRB = '1' then
TR_NEXT_STATE <= SHIFTOUT;
else
TR_NEXT_STATE <= START;
end if;
when SHIFTOUT =>
if CLK_STRB = '1' then
if BITCNT < "100" and CL = "11" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 5 data bits.
elsif BITCNT < "101" and CL = "10" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 6 data bits.
elsif BITCNT < "110" and CL = "01" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 7 data bits.
elsif BITCNT < "111" and CL = "00" then
TR_NEXT_STATE <= SHIFTOUT; -- Transmit 8 data bits.
elsif P_ENA = '0' and BREAK = '1' then
TR_NEXT_STATE <= IDLE; -- Break condition, no parity check enabled, no stop bits.
elsif P_ENA = '0' and ST = "00" then
TR_NEXT_STATE <= IDLE; -- Synchronous mode, no parity check enabled.
elsif P_ENA = '0' then
TR_NEXT_STATE <= STOP1; -- Asynchronous mode, no parity check enabled.
else
TR_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
TR_NEXT_STATE <= SHIFTOUT;
end if;
when PARITY =>
if CLK_STRB = '1' then
if ST = "00" then -- Synchronous mode (no stop bits).
TR_NEXT_STATE <= IDLE;
elsif BREAK = '1' then -- No stop bits during break condition.
TR_NEXT_STATE <= IDLE;
else
TR_NEXT_STATE <= STOP1;
end if;
else
TR_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' and (ST = "11" or ST = "10") then
TR_NEXT_STATE <= STOP2; -- More than one stop bits selected.
elsif CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE; -- One stop bits selected.
else
TR_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_2_STRB = '1' and ST = "10" then
TR_NEXT_STATE <= IDLE; -- One and a half stop bits selected.
elsif CLK_STRB = '1' then
TR_NEXT_STATE <= IDLE; -- Two stop bits detected.
else
TR_NEXT_STATE <= STOP2;
end if;
end case;
end process TR_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,228 @@
----------------------------------------------------------------------
---- ----
---- 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 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 1.0 2007/01/05 WF
-- Initial Release.
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 : inout std_logic_vector(7 downto 0);
-- Microcontroller interface:
MC_D : inout std_logic_vector(7 downto 0);
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
);
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 <= DATA_REG when MC_RWn = '0' and DONE_REG = '1' else (others => 'Z');
ACSI_D <= DATA_REG when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else (others => 'Z');
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; -- 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; -- 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; -- 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
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

@@ -0,0 +1,240 @@
----------------------------------------------------------------------
---- ----
---- 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'; -- Disabled.
--ACSI_INTn <= INT_REG;
ACSI_INTn <= '1'; -- Disabled.
--ACSI_DRQn <= DRQ_REG;
ACSI_DRQn <= '1'; -- Disabled.
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

@@ -0,0 +1,239 @@
----------------------------------------------------------------------
---- ----
---- 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

@@ -0,0 +1,84 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- ----
---- This is the package file containing the component ----
---- declarations. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
package WF2149IP_PKG is
type BUSCYCLES is (INACTIVE, R_READ, R_WRITE, ADDRESS);
component WF2149IP_WAVE
port(
RESETn : in bit;
SYS_CLK : in bit;
WAV_STRB : in bit;
ADR : in bit_vector(3 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
BUSCYCLE : in BUSCYCLES;
CTRL_REG : in bit_vector(5 downto 0);
OUT_A : out bit;
OUT_B : out bit;
OUT_C : out bit
);
end component;
end WF2149IP_PKG;

View File

@@ -0,0 +1,170 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- This IP core of the sound generator differs slightly from ----
---- the original. Firstly it is a synchronous design without any ----
---- latches (like assumed in the original chip). This required ----
---- the introduction of a system adequate clock. In detail this ----
---- SYS_CLK should on the one hand be fast enough to meet the ----
---- timing requirements of the system's bus cycle and should one ----
---- the other hand drive the PWM modules correctly. To meet both ----
---- a SYS_CLK of 16MHz or above is recommended. ----
---- Secondly, the original chip has an implemented DA converter. ----
---- This feature is not possible in today's FPGAs. Therefore the ----
---- converter is replaced by pulse width modulators. This solu- ----
---- tion is very simple in comparison to other approaches like ----
---- external DA converters with wave tables etc. The soltution ----
---- with the pulse width modulators is probably not as accurate ----
---- DAs with wavetables. For a detailed descrition of the hard- ----
---- ware PWM filter look at the end of the wave file, where the ----
---- pulse width modulators can be found. ----
---- For a proper operation it is required, that the wave clock ----
---- is lower than the system clock. A good choice is for example ----
---- 2MHz for the wave clock and 16MHz for the system clock. ----
---- ----
---- Main module file. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
--
library ieee;
use ieee.std_logic_1164.all;
use work.wf2149ip_pkg.all;
entity WF2149IP_TOP is
port(
SYS_CLK : in bit; -- Read the inforation in the header!
RESETn : in bit;
WAV_CLK : in bit; -- Read the inforation in the header!
SELn : in bit;
BDIR : in bit;
BC2, BC1 : in bit;
A9n, A8 : in bit;
DA : inout std_logic_vector(7 downto 0);
IO_A : inout std_logic_vector(7 downto 0);
IO_B : inout std_logic_vector(7 downto 0);
OUT_A : out bit; -- Analog (PWM) outputs.
OUT_B : out bit;
OUT_C : out bit
);
end WF2149IP_TOP;
architecture STRUCTURE of WF2149IP_TOP is
component WF2149IP_TOP_SOC
port(
SYS_CLK : in bit;
RESETn : in bit;
WAV_CLK : in bit;
SELn : in bit;
BDIR : in bit;
BC2, BC1 : in bit;
A9n, A8 : in bit;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out bit;
IO_A_IN : in bit_vector(7 downto 0);
IO_A_OUT : out bit_vector(7 downto 0);
IO_A_EN : out bit;
IO_B_IN : in bit_vector(7 downto 0);
IO_B_OUT : out bit_vector(7 downto 0);
IO_B_EN : out bit;
OUT_A : out bit;
OUT_B : out bit;
OUT_C : out bit
);
end component;
--
signal DA_OUT : std_logic_vector(7 downto 0);
signal DA_EN : bit;
signal IO_A_IN : bit_vector(7 downto 0);
signal IO_A_OUT : bit_vector(7 downto 0);
signal IO_A_EN : bit;
signal IO_B_IN : bit_vector(7 downto 0);
signal IO_B_OUT : bit_vector(7 downto 0);
signal IO_B_EN : bit;
begin
IO_A_IN <= To_BitVector(IO_A);
IO_B_IN <= To_BitVector(IO_B);
IO_A <= To_StdLogicVector(IO_A_OUT) when IO_A_EN = '1' else (others => 'Z');
IO_B <= To_StdLogicVector(IO_B_OUT) when IO_B_EN = '1' else (others => 'Z');
DA <= DA_OUT when DA_EN = '1' else (others => 'Z');
I_SOUND: WF2149IP_TOP_SOC
port map(SYS_CLK => SYS_CLK,
RESETn => RESETn,
WAV_CLK => WAV_CLK,
SELn => SELn,
BDIR => BDIR,
BC2 => BC2,
BC1 => BC1,
A9n => A9n,
A8 => A8,
DA_IN => DA,
DA_OUT => DA_OUT,
DA_EN => DA_EN,
IO_A_IN => IO_A_IN,
IO_A_OUT => IO_A_OUT,
IO_A_EN => IO_A_EN,
IO_B_IN => IO_B_IN,
IO_B_OUT => IO_B_OUT,
IO_B_EN => IO_B_EN,
OUT_A => OUT_A,
OUT_B => OUT_B,
OUT_C => OUT_C
);
end STRUCTURE;

View File

@@ -0,0 +1,229 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- This IP core of the sound generator differs slightly from ----
---- the original. Firstly it is a synchronous design without any ----
---- latches (like assumed in the original chip). This required ----
---- the introduction of a system adequate clock. In detail this ----
---- SYS_CLK should on the one hand be fast enough to meet the ----
---- timing requirements of the system's bus cycle and should one ----
---- the other hand drive the PWM modules correctly. To meet both ----
---- a SYS_CLK of 16MHz or above is recommended. ----
---- Secondly, the original chip has an implemented DA converter. ----
---- This feature is not possible in today's FPGAs. Therefore the ----
---- converter is replaced by pulse width modulators. This solu- ----
---- tion is very simple in comparison to other approaches like ----
---- external DA converters with wave tables etc. The soltution ----
---- with the pulse width modulators is probably not as accurate ----
---- DAs with wavetables. For a detailed descrition of the hard- ----
---- ware PWM filter look at the end of the wave file, where the ----
---- pulse width modulators can be found. ----
---- For a proper operation it is required, that the wave clock ----
---- is lower than the system clock. A good choice is for example ----
---- 2MHz for the wave clock and 16MHz for the system clock. ----
---- ----
---- Main module 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 work.wf2149ip_pkg.all;
entity WF2149IP_TOP_SOC is
port(
SYS_CLK : in bit; -- Read the inforation in the header!
RESETn : in bit;
WAV_CLK : in bit; -- Read the inforation in the header!
SELn : in bit;
BDIR : in bit;
BC2, BC1 : in bit;
A9n, A8 : in bit;
DA_IN : in std_logic_vector(7 downto 0);
DA_OUT : out std_logic_vector(7 downto 0);
DA_EN : out bit;
IO_A_IN : in bit_vector(7 downto 0);
IO_A_OUT : out bit_vector(7 downto 0);
IO_A_EN : out bit;
IO_B_IN : in bit_vector(7 downto 0);
IO_B_OUT : out bit_vector(7 downto 0);
IO_B_EN : out bit;
OUT_A : out bit; -- Analog (PWM) outputs.
OUT_B : out bit;
OUT_C : out bit
);
end WF2149IP_TOP_SOC;
architecture STRUCTURE of WF2149IP_TOP_SOC is
signal BUSCYCLE : BUSCYCLES;
signal DATA_OUT_I : std_logic_vector(7 downto 0);
signal DATA_EN_I : bit;
signal WAV_STRB : bit;
signal ADR_I : bit_vector(3 downto 0);
signal CTRL_REG : bit_vector(7 downto 0);
signal PORT_A : bit_vector(7 downto 0);
signal PORT_B : bit_vector(7 downto 0);
begin
P_WAVSTRB: process(RESETn, SYS_CLK)
variable LOCK : boolean;
variable TMP : bit;
begin
if RESETn = '0' then
LOCK := false;
TMP := '0';
elsif SYS_CLK = '1' and SYS_CLK' event then
if WAV_CLK = '1' and LOCK = false then
LOCK := true;
TMP := not TMP; -- Divider by 2.
case SELn is
when '1' => WAV_STRB <= '1';
when others => WAV_STRB <= TMP;
end case;
elsif WAV_CLK = '0' then
LOCK := false;
WAV_STRB <= '0';
else
WAV_STRB <= '0';
end if;
end if;
end process P_WAVSTRB;
with BDIR & BC2 & BC1 select
BUSCYCLE <= INACTIVE when "000" | "010" | "101",
ADDRESS when "001" | "100" | "111",
R_READ when "011",
R_WRITE when "110";
ADDRESSLATCH: process(RESETn, SYS_CLK)
-- This process is responsible to store the desired register
-- address. The default (after reset) is channel A fine tone
-- adjustment.
begin
if RESETn = '0' then
ADR_I <= (others => '0');
elsif SYS_CLK = '1' and SYS_CLK' event then
if BUSCYCLE = ADDRESS and A9n = '0' and A8 = '1' and DA_IN(7 downto 4) = x"0" then
ADR_I <= To_BitVector(DA_IN(3 downto 0));
end if;
end if;
end process ADDRESSLATCH;
P_CTRL_REG: process(RESETn, SYS_CLK)
-- THIS is the Control register for the mixer and for the I/O ports.
begin
if RESETn = '0' then
CTRL_REG <= x"00";
elsif SYS_CLK = '1' and SYS_CLK' event then
if BUSCYCLE = R_WRITE and ADR_I = x"7" then
CTRL_REG <= To_BitVector(DA_IN);
end if;
end if;
end process P_CTRL_REG;
DIG_PORTS: process(RESETn, SYS_CLK)
begin
if RESETn = '0' then
PORT_A <= x"00";
PORT_B <= x"00";
elsif SYS_CLK = '1' and SYS_CLK' event then
if BUSCYCLE = R_WRITE and ADR_I = x"E" then
PORT_A <= To_BitVector(DA_IN);
elsif BUSCYCLE = R_WRITE and ADR_I = x"F" then
PORT_B <= To_BitVector(DA_IN);
end if;
end if;
end process DIG_PORTS;
-- Set port direction to input or to output:
IO_A_EN <= '1' when CTRL_REG(6) = '1' else '0';
IO_B_EN <= '1' when CTRL_REG(7) = '1' else '0';
IO_A_OUT <= PORT_A;
IO_B_OUT <= PORT_B;
I_PSG_WAVE: WF2149IP_WAVE
port map(
RESETn => RESETn,
SYS_CLK => SYS_CLK,
WAV_STRB => WAV_STRB,
ADR => ADR_I,
DATA_IN => DA_IN,
DATA_OUT => DATA_OUT_I,
DATA_EN => DATA_EN_I,
BUSCYCLE => BUSCYCLE,
CTRL_REG => CTRL_REG(5 downto 0),
OUT_A => OUT_A,
OUT_B => OUT_B,
OUT_C => OUT_C
);
-- Read the ports and registers:
DA_EN <= '1' when DATA_EN_I = '1' else
'1' when BUSCYCLE = R_READ and ADR_I = x"7" else
'1' when BUSCYCLE = R_READ and ADR_I = x"E" else
'1' when BUSCYCLE = R_READ and ADR_I = x"F" else '0';
DA_OUT <= DATA_OUT_I when DATA_EN_I = '1' else -- WAV stuff.
To_StdLogicVector(IO_A_IN) when BUSCYCLE = R_READ and ADR_I = x"E" else
To_StdLogicVector(IO_B_IN) when BUSCYCLE = R_READ and ADR_I = x"F" else
To_StdLogicVector(CTRL_REG) when BUSCYCLE = R_READ and ADR_I = x"7" else (others => '0');
end STRUCTURE;

View File

@@ -0,0 +1,533 @@
----------------------------------------------------------------------
---- ----
---- YM2149 compatible sound generator. ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- Model of the ST or STE's YM2149 sound generator. ----
---- ----
---- Waveform generator. ----
---- ----
---- ----
---- 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
-- NOISE_OUT has now synchronous reset to meet preset requirement.
-- Fixed a bug in the envelope generator. Thanks to Lyndon Amsdon finding it.
-- Correction of the schematic given in the end of this file.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use work.wf2149ip_pkg.all;
entity WF2149IP_WAVE is
port(
RESETn : in bit;
SYS_CLK : in bit;
WAV_STRB : in bit;
ADR : in bit_vector(3 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_EN : out bit;
BUSCYCLE : in BUSCYCLES;
CTRL_REG : in bit_vector(5 downto 0);
OUT_A : out bit;
OUT_B : out bit;
OUT_C : out bit
);
end entity WF2149IP_WAVE;
architecture BEHAVIOR of WF2149IP_WAVE is
signal FREQUENCY_A : std_logic_vector(11 downto 0);
signal FREQUENCY_B : std_logic_vector(11 downto 0);
signal FREQUENCY_C : std_logic_vector(11 downto 0);
signal NOISE_FREQ : std_logic_vector(4 downto 0);
signal LEVEL_A : std_logic_vector(4 downto 0);
signal LEVEL_B : std_logic_vector(4 downto 0);
signal LEVEL_C : std_logic_vector(4 downto 0);
signal ENV_FREQ : std_logic_vector(15 downto 0);
signal ENV_SHAPE : std_logic_vector(3 downto 0);
signal ENV_RESET : boolean;
signal ENV_STRB : bit;
signal OSC_A_OUT : bit;
signal OSC_B_OUT : bit;
signal OSC_C_OUT : bit;
signal NOISE_OUT : bit;
signal AUDIO_A : bit;
signal AUDIO_B : bit;
signal AUDIO_C : bit;
signal VOL_ENV : std_logic_vector(4 downto 0);
signal AMPLITUDE_A : std_logic_vector(4 downto 0);
signal AMPLITUDE_B : std_logic_vector(4 downto 0);
signal AMPLITUDE_C : std_logic_vector(4 downto 0);
signal VOLUME_A : std_logic_vector(7 downto 0);
signal VOLUME_B : std_logic_vector(7 downto 0);
signal VOLUME_C : std_logic_vector(7 downto 0);
signal PWM_RAMP : std_logic_vector(7 downto 0);
begin
REGISTERS: process(RESETn, SYS_CLK)
-- This process is responsible for initialisation
-- and write access to the configuration registers.
begin
if RESETn = '0' then
FREQUENCY_A <= x"000";
FREQUENCY_B <= x"000";
FREQUENCY_C <= x"000";
NOISE_FREQ <= "00000";
LEVEL_A <= "00000";
LEVEL_B <= "00000";
LEVEL_C <= "00000";
ENV_FREQ <= (others => '0');
ENV_SHAPE <= "0000";
elsif SYS_CLK = '1' and SYS_CLK' event then
ENV_RESET <= false; -- Initialize signal.
if BUSCYCLE = R_WRITE then
case ADR is
when x"0" => FREQUENCY_A(7 downto 0) <= DATA_IN;
when x"1" => FREQUENCY_A(11 downto 8) <= DATA_IN(3 downto 0);
when x"2" => FREQUENCY_B(7 downto 0) <= DATA_IN;
when x"3" => FREQUENCY_B(11 downto 8) <= DATA_IN(3 downto 0);
when x"4" => FREQUENCY_C(7 downto 0) <= DATA_IN;
when x"5" => FREQUENCY_C(11 downto 8) <= DATA_IN(3 downto 0);
when x"6" => NOISE_FREQ <= DATA_IN(4 downto 0);
when x"8" => LEVEL_A <= DATA_IN(4 downto 0);
when x"9" => LEVEL_B <= DATA_IN(4 downto 0);
when x"A" => LEVEL_C <= DATA_IN(4 downto 0);
when x"B" => ENV_FREQ(7 downto 0) <= DATA_IN;
when x"C" => ENV_FREQ(15 downto 8) <= DATA_IN;
ENV_RESET <= true; -- Initialize the envelope generator.
when x"D" => ENV_SHAPE <= DATA_IN(3 downto 0);
when others => null;
end case;
end if;
end if;
end process REGISTERS;
-- Read back the configuration registers:
DATA_OUT <= FREQUENCY_A(7 downto 0) when BUSCYCLE = R_READ and ADR = x"0" else
"0000" & FREQUENCY_A(11 downto 8) when BUSCYCLE = R_READ and ADR = x"1" else
FREQUENCY_B(7 downto 0) when BUSCYCLE = R_READ and ADR = x"2" else
"0000" & FREQUENCY_B(11 downto 8) when BUSCYCLE = R_READ and ADR = x"3" else
FREQUENCY_C(7 downto 0) when BUSCYCLE = R_READ and ADR = x"4" else
"0000" & FREQUENCY_C(11 downto 8) when BUSCYCLE = R_READ and ADR = x"5" else
"000" & NOISE_FREQ when BUSCYCLE = R_READ and ADR = x"6" else
"000" & LEVEL_A when BUSCYCLE = R_READ and ADR = x"8" else
"000" & LEVEL_B when BUSCYCLE = R_READ and ADR = x"9" else
"000" & LEVEL_C when BUSCYCLE = R_READ and ADR = x"A" else
ENV_FREQ(7 downto 0) when BUSCYCLE = R_READ and ADR = x"B" else
ENV_FREQ(15 downto 8) when BUSCYCLE = R_READ and ADR = x"C" else
x"0" & ENV_SHAPE when BUSCYCLE = R_READ and ADR = x"D" else (others => '0');
DATA_EN <= '1' when BUSCYCLE = R_READ and ADR >= x"0" and ADR <= x"6" else
'1' when BUSCYCLE = R_READ and ADR >= x"8" and ADR <= x"D" else '0';
MUSICGENERATOR: process(RESETn, SYS_CLK)
variable CLK_DIV : std_logic_vector(2 downto 0);
variable CNT_CH_A : std_logic_vector(11 downto 0);
variable CNT_CH_B : std_logic_vector(11 downto 0);
variable CNT_CH_C : std_logic_vector(11 downto 0);
begin
if RESETn = '0' then
CLK_DIV := "000";
CNT_CH_A := (others => '0');
CNT_CH_B := (others => '0');
CNT_CH_C := (others => '0');
OSC_A_OUT <= '0';
OSC_B_OUT <= '0';
OSC_C_OUT <= '0';
elsif SYS_CLK = '1' and SYS_CLK' event then
if WAV_STRB = '1' then
-- Divider by 8 for the oscillators brings in connection
-- with the toggle flip flops CH_x_OUT the required divider
-- ratio of 16.
CLK_DIV := CLK_DIV + '1';
if CLK_DIV = "000" then
if FREQUENCY_A = x"000" then
CNT_CH_A := (others => '0');
OSC_A_OUT <= '0';
elsif CNT_CH_A = x"000" then
CNT_CH_A := FREQUENCY_A - '1' ;
OSC_A_OUT <= not OSC_A_OUT;
else
CNT_CH_A := CNT_CH_A - '1';
end if;
if FREQUENCY_B = x"000" then
CNT_CH_B := (others => '0');
OSC_B_OUT <= '0';
elsif CNT_CH_B = x"000" then
CNT_CH_B := FREQUENCY_B - '1' ;
OSC_B_OUT <= not OSC_B_OUT;
else
CNT_CH_B := CNT_CH_B - '1';
end if;
if FREQUENCY_C = x"000" then
CNT_CH_C := (others => '0');
OSC_C_OUT <= '0';
elsif CNT_CH_C = x"000" then
CNT_CH_C := FREQUENCY_C - '1' ;
OSC_C_OUT <= not OSC_C_OUT;
else
CNT_CH_C := CNT_CH_C - '1';
end if;
end if;
end if;
end if;
end process MUSICGENERATOR;
NOISEGENERATOR: process
-- The noise shift polynomial is taken from a template of Kazuhiro TSUJIKAWA's
-- (ESE Artists' factory) approach for a 2149 equivalent. But the implementation
-- is done in another way.
-- LFSR (linear feedback shift register polynomial: f(x) = x^17 + x^14 + 1.
variable CLK_DIV : std_logic_vector(3 downto 0);
variable CNT_NOISE : std_logic_vector(4 downto 0);
variable N_SHFT : std_logic_vector(16 downto 0);
begin
wait until SYS_CLK = '1' and SYS_CLK' event;
if RESETn = '0' then
CLK_DIV := x"0";
CNT_NOISE := (others => '1'); -- Preset the polynomial shift register.
NOISE_OUT <= '1';
elsif WAV_STRB = '1' then
-- Divider by 16 for the noise generator.
CLK_DIV := CLK_DIV + '1';
if CLK_DIV = x"0" then
-- Noise frequency counter.
if NOISE_FREQ = "00000" then
CNT_NOISE := (others => '0');
elsif CNT_NOISE = "00000" then
CNT_NOISE := NOISE_FREQ - '1' ;
N_SHFT := N_SHFT(15 downto 14) & not(N_SHFT(16) xor N_SHFT(13)) &
N_SHFT(12 downto 0) & not N_SHFT(16);
else
CNT_NOISE := CNT_NOISE - '1';
end if;
end if;
end if;
NOISE_OUT <= To_Bit(N_SHFT(16));
end process NOISEGENERATOR;
ENVELOPE_PERIOD: process(RESETn, SYS_CLK)
-- The envelope period is controlled by the Envelope Frequency and the divider ratio which is
-- 256/32 = 8. For further information see the original data sheet.
variable ENV_CLK : std_logic_vector(18 downto 0);
variable LOCK : boolean;
begin
if RESETn = '0' then
ENV_STRB <= '0';
ENV_CLK := (others => '0');
LOCK := false;
elsif SYS_CLK = '1' and SYS_CLK' event then
if WAV_STRB = '1' and LOCK = false then
LOCK := true;
if ENV_FREQ = x"0000" then
ENV_STRB <= '0';
elsif ENV_CLK = x"0000" & "000" then
ENV_CLK := (ENV_FREQ & "111") - '1' ;
ENV_STRB <= '1';
else
ENV_CLK := ENV_CLK - '1';
ENV_STRB <= '0';
end if;
elsif WAV_STRB = '0' then
LOCK := false;
ENV_STRB <= '0';
else
ENV_STRB <= '0';
end if;
end if;
end process ENVELOPE_PERIOD;
ENVELOPE: process(RESETn, SYS_CLK)
-- Envelope shapes:
-- case ENV_SHAPE:
--
-- 0 0 x x \___
--
-- 0 1 x x /|___
--
-- 1 0 0 0 _|\|\|\|\|
--
-- 1 0 0 1 \___
--
-- 1 0 1 0 \/\/
-- ___
-- 1 0 1 1 \|
--
-- 1 1 0 0 /|/|/|/|
-- ___
-- 1 1 0 1 /
--
-- 1 1 1 0 /\/\
--
-- 1 1 1 1 /|___
--
variable ENV_STOP : boolean;
variable ENV_UP_DNn : bit;
begin
if RESETn = '0' then
VOL_ENV <= (others => '0');
ENV_UP_DNn := '0';
ENV_STOP := false;
elsif SYS_CLK = '1' and SYS_CLK' event then
if ENV_RESET = true then
ENV_STOP := false;
case ENV_SHAPE is
when "1011" | "1010" | "1001" | "1000" | "0011" | "0010" | "0001" | "0000" =>
VOL_ENV <= "11111"; -- Start on top.
ENV_UP_DNn := '0';
when others =>
VOL_ENV <= "00000"; -- Start at bottom.
ENV_UP_DNn := '1';
end case;
elsif ENV_STRB = '1' then
case ENV_SHAPE is
when "1001" | "0011" | "0010" | "0001" | "0000" =>
if VOL_ENV > "00000" then
VOL_ENV <= VOL_ENV - '1';
end if;
when "1111" | "0111" | "0110" | "0101" | "0100" =>
if VOL_ENV < "11111" and ENV_STOP = false then
VOL_ENV <= VOL_ENV + '1';
else
VOL_ENV <= "00000";
ENV_STOP := true;
end if;
when "1000" =>
VOL_ENV <= VOL_ENV - '1';
when "1110" | "1010" =>
if ENV_UP_DNn = '0' then
VOL_ENV <= VOL_ENV - '1';
else
VOL_ENV <= VOL_ENV + '1';
end if;
--
if VOL_ENV = "00001" then
ENV_UP_DNn := '1';
elsif VOL_ENV = "11110" then
ENV_UP_DNn := '0';
end if;
when "1011" =>
if VOL_ENV > "00000" and ENV_STOP = false then
VOL_ENV <= VOL_ENV - '1';
else
VOL_ENV <= "11111";
ENV_STOP := true;
end if;
when "1100" =>
VOL_ENV <= VOL_ENV + '1';
when "1101" =>
if VOL_ENV < "11111" then
VOL_ENV <= VOL_ENV + '1';
end if;
when others => null; -- Covers U, X, Z, W, H, L, -.
end case;
end if;
end if;
end process ENVELOPE;
--MIXER:
-- The mixer controls are dependant on the mixer settings and the output of the
-- audio data for all three channels. The noise generator and the square wave
-- generators A, B and C are mixed together by a simple boolean OR.
AUDIO_A <= (OSC_A_OUT and not CTRL_REG(0)) or (NOISE_OUT and not CTRL_REG(3));
AUDIO_B <= (OSC_B_OUT and not CTRL_REG(1)) or (NOISE_OUT and not CTRL_REG(4));
AUDIO_C <= (OSC_C_OUT and not CTRL_REG(2)) or (NOISE_OUT and not CTRL_REG(5));
--LEVEL (e.g. volume control):
-- The linear amplitude for the DA converters of channel A, B or C are fixed
-- (LEVEL(3 downto 0)) or delivered by the envelope generator.
-- The following behavior is taken from the 2149 IP core of Mike J (www.fpgaarcade.com):
-- "make sure level 31 (env) = level 15 (tone)"
-- Thus there is a resulting & '1' modeling if LEVEL amplitudes are selected.
AMPLITUDE_A <= LEVEL_A(3 downto 0) & '1' when LEVEL_A(4) = '0' and AUDIO_A = '1' else
VOL_ENV when LEVEL_A(4) = '1' and AUDIO_A = '1' else "00000";
AMPLITUDE_B <= LEVEL_B(3 downto 0) & '1' when LEVEL_B(4) = '0' and AUDIO_B = '1' else
VOL_ENV when LEVEL_B(4) = '1' and AUDIO_B = '1' else "00000";
AMPLITUDE_C <= LEVEL_C(3 downto 0) & '1' when LEVEL_C(4) = '0' and AUDIO_C = '1' else
VOL_ENV when LEVEL_C(4) = '1' and AUDIO_C = '1' else "00000";
-- The values for the logarithmic DA converter volume controls are taken from the linear
-- mixer of Mike J's 2149 IP core (www.fpgaarcade.com).
with AMPLITUDE_A select
VOLUME_A <= x"FF" when "11111",
x"D9" when "11110",
x"BA" when "11101",
x"9F" when "11100",
x"88" when "11011",
x"74" when "11010",
x"63" when "11001",
x"54" when "11000",
x"48" when "10111",
x"3D" when "10110",
x"34" when "10101",
x"2C" when "10100",
x"25" when "10011",
x"1F" when "10010",
x"1A" when "10001",
x"16" when "10000",
x"13" when "01111",
x"10" when "01110",
x"0D" when "01101",
x"0B" when "01100",
x"09" when "01011",
x"08" when "01010",
x"07" when "01001",
x"06" when "01000",
x"05" when "00111",
x"04" when "00110",
x"03" when "00101",
x"03" when "00100",
x"02" when "00011",
x"02" when "00010",
x"01" when "00001",
x"00" when others; -- Also covers U, X, Z, W, H, L, -.
with AMPLITUDE_B select
VOLUME_B <= x"FF" when "11111",
x"D9" when "11110",
x"BA" when "11101",
x"9F" when "11100",
x"88" when "11011",
x"74" when "11010",
x"63" when "11001",
x"54" when "11000",
x"48" when "10111",
x"3D" when "10110",
x"34" when "10101",
x"2C" when "10100",
x"25" when "10011",
x"1F" when "10010",
x"1A" when "10001",
x"16" when "10000",
x"13" when "01111",
x"10" when "01110",
x"0D" when "01101",
x"0B" when "01100",
x"09" when "01011",
x"08" when "01010",
x"07" when "01001",
x"06" when "01000",
x"05" when "00111",
x"04" when "00110",
x"03" when "00101",
x"03" when "00100",
x"02" when "00011",
x"02" when "00010",
x"01" when "00001",
x"00" when others; -- Also covers U, X, Z, W, H, L, -.
with AMPLITUDE_C select
VOLUME_C <= x"FF" when "11111",
x"D9" when "11110",
x"BA" when "11101",
x"9F" when "11100",
x"88" when "11011",
x"74" when "11010",
x"63" when "11001",
x"54" when "11000",
x"48" when "10111",
x"3D" when "10110",
x"34" when "10101",
x"2C" when "10100",
x"25" when "10011",
x"1F" when "10010",
x"1A" when "10001",
x"16" when "10000",
x"13" when "01111",
x"10" when "01110",
x"0D" when "01101",
x"0B" when "01100",
x"09" when "01011",
x"08" when "01010",
x"07" when "01001",
x"06" when "01000",
x"05" when "00111",
x"04" when "00110",
x"03" when "00101",
x"03" when "00100",
x"02" when "00011",
x"02" when "00010",
x"01" when "00001",
x"00" when others; -- Also covers U, X, Z, W, H, L, -.
DA_CONVERSION: process
-- The DA conversion for the three analog outputs is originally performed by a built in DA converter.
-- For this is not possible in current FPGA designs, the converter is replaced by three PWM units
-- operating at a frequency which is 100 times higher than the highest noise or music frequency which
-- is 2MHz/16 = 125kHz. So the PWM frequency requires about 12.5MHz or more. The design is done for
-- a PWM frequency of 16MHz).
begin
wait until SYS_CLK = '1' and SYS_CLK' event;
PWM_RAMP <= PWM_RAMP + '1';
end process DA_CONVERSION;
OUT_A <= '0' when VOLUME_A = x"00" else '1' when PWM_RAMP < VOLUME_A else '0';
OUT_B <= '0' when VOLUME_B = x"00" else '1' when PWM_RAMP < VOLUME_B else '0';
OUT_C <= '0' when VOLUME_C = x"00" else '1' when PWM_RAMP < VOLUME_C else '0';
--
-- To obtain proper analog output it is necessary to install analog RC filters to the pulse width
-- outputs. An example is given for the direct wiring of the three analog outputs and for a system
-- clock frequency of 16MHz. The output circuitry looks in this case as follows:
--
-- OUT_A ---------|1kOhm|-----------| |\ e.g. LM741
-- |----------------------|+\ ||
-- OUT_B ---------|1kOhm|-----------| | OP------||--- Analog Signal
-- | |-----|-/ | ||
-- OUT_C ---------|1kOhm|-----------| | |/ | 4u7
-- | |__________|
-- |
-- --- 10nF.
-- ---
-- |
-- |
-- ---
-- WF.
end architecture BEHAVIOR;

View File

@@ -0,0 +1,244 @@
----------------------------------------------------------------------
---- ----
---- 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 bit;
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 : out 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 IRQ_I : bit;
signal CTS_In : bit;
signal DCD_In : bit;
signal DCD_FLAGn : bit;
begin
P_SAMPLE: process
begin
wait until CLK = '0' and CLK' event;
CTS_In <= CTSn; -- Sample CTSn on the negative clock edge.
DCD_In <= DCDn; -- Sample DCDn on the negative clock edge.
end process P_SAMPLE;
STATUS_REG(7) <= IRQ_I;
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' and E = '1' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' and E = '1' 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
variable DCD_OVR_LOCK : boolean;
variable DCD_LOCK : boolean;
variable DCD_TRANS : boolean;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
DCD_OVR_LOCK := false;
IRQn <= '1';
IRQ_I <= '0';
elsif CS = "011" and RWn = '1' and RS = '0' and E = '1' then
DCD_OVR_LOCK := false; -- Enable reset by reading the status.
end if;
-- Clear interrupts when disabled.
if CTRL_REG(7) = '0' then
IRQn <= '1';
IRQ_I <= '0';
elsif CTRL_REG(6 downto 5) /= "01" then
IRQn <= '1';
IRQ_I <= '0';
end if;
-- Transmitter interrupt:
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" and CTS_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by writing to the transmit data register.
end if;
-- Receiver interrupts:
if RDRF = '1' and RIE = '1' and DCD_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by reading the receive data register.
end if;
if OVR = '1' and RIE = '1' then
IRQn <= '0';
IRQ_I <= '1';
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
end if;
if DCD_In = '1' and RIE = '1' and DCD_TRANS = false then
IRQn <= '0';
IRQ_I <= '1';
-- DCD_TRANS is used to detect a low to high transition of DCDn.
DCD_TRANS := true;
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
elsif DCD_In = '0' then
DCD_TRANS := false;
end if;
-- The reset of the IRQ status flag:
-- Clear by writing to the transmit data register.
-- Clear by reading the receive data register.
if CS = "011" and RS = '1' and E = '1' then
IRQ_I <= '0';
end if;
end process P_IRQ;
CONTROL: process
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
CTRL_REG <= "01000000";
elsif CS = "011" and RWn = '0' and RS = '0' and E = '1' then
CTRL_REG <= DATA_IN;
end if;
end process CONTROL;
P_DCD: process
-- 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
wait until CLK = '1' and CLK' event;
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' and E = '1' then
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
elsif CS = "011" and RWn = '1' and RS = '1' and E = '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 process P_DCD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,244 @@
----------------------------------------------------------------------
---- ----
---- 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 bit;
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 : out 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 IRQ_I : bit;
signal CTS_In : bit;
signal DCD_In : bit;
signal DCD_FLAGn : bit;
begin
P_SAMPLE: process
begin
wait until CLK = '0' and CLK' event;
CTS_In <= CTSn; -- Sample CTSn on the negative clock edge.
DCD_In <= DCDn; -- Sample DCDn on the negative clock edge.
end process P_SAMPLE;
STATUS_REG(7) <= IRQ_I;
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' and E = '1' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' and E = '1' 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
variable DCD_OVR_LOCK : boolean;
variable DCD_LOCK : boolean;
variable DCD_TRANS : boolean;
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
DCD_OVR_LOCK := false;
IRQn <= '1';
IRQ_I <= '0';
elsif CS = "011" and RWn = '1' and RS = '0' and E = '1' then
DCD_OVR_LOCK := false; -- Enable reset by reading the status.
end if;
-- Clear interrupts when disabled.
if CTRL_REG(7) = '0' then
IRQn <= '1';
IRQ_I <= '0';
elsif CTRL_REG(6 downto 5) /= "01" then
IRQn <= '1';
IRQ_I <= '0';
end if;
-- Transmitter interrupt:
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" and CTS_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by writing to the transmit data register.
end if;
-- Receiver interrupts:
if RDRF = '1' and RIE = '1' and DCD_In = '0' then
IRQn <= '0';
IRQ_I <= '1';
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' then
IRQn <= '1'; -- Clear by reading the receive data register.
end if;
if OVR = '1' and RIE = '1' then
IRQn <= '0';
IRQ_I <= '1';
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
end if;
if DCD_In = '1' and RIE = '1' and DCD_TRANS = false then
IRQn <= '0';
IRQ_I <= '1';
-- DCD_TRANS is used to detect a low to high transition of DCDn.
DCD_TRANS := true;
DCD_OVR_LOCK := true;
elsif CS = "011" and RWn = '1' and RS = '1' and E = '1' and DCD_OVR_LOCK = false then
IRQn <= '1'; -- Clear by reading the receive data register after the status.
elsif DCD_In = '0' then
DCD_TRANS := false;
end if;
-- The reset of the IRQ status flag:
-- Clear by writing to the transmit data register.
-- Clear by reading the receive data register.
if CS = "011" and RS = '1' and E = '1' then
IRQ_I <= '0';
end if;
end process P_IRQ;
CONTROL: process
begin
wait until CLK = '1' and CLK' event;
if RESETn = '0' then
CTRL_REG <= "01000000";
elsif CS = "011" and RWn = '0' and RS = '0' and E = '1' then
CTRL_REG <= DATA_IN;
end if;
end process CONTROL;
P_DCD: process
-- 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
wait until CLK = '1' and CLK' event;
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' and E = '1' then
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
elsif CS = "011" and RWn = '1' and RS = '1' and E = '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 process P_DCD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,415 @@
----------------------------------------------------------------------
---- ----
---- 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' and E = '1' and OVR_I = '1' then
-- If an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OVR_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OVR <= '1';
FIRST_READ := true;
else
OVR <= '0';
FIRST_READ := false;
end if;
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' and E = '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' and E = '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

@@ -0,0 +1,415 @@
----------------------------------------------------------------------
---- ----
---- 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 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.
--
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';
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' 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' and E = '1' and OVR_I = '1' then
-- If an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OVR_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OVR <= '1';
FIRST_READ := true;
else
OVR <= '0';
FIRST_READ := false;
end if;
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' and E = '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' and E = '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

@@ -0,0 +1,135 @@
----------------------------------------------------------------------
---- ----
---- 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. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8B 2008/12/24 WF
-- Rewritten this top level file as a wrapper for the top_soc file.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_TOP is
port (
CLK : in bit;
RESETn : in bit;
CS2n, CS1, CS0 : in bit;
E : in bit;
RWn : in bit;
RS : in bit;
DATA : inout std_logic_vector(7 downto 0);
TXCLK : in bit;
RXCLK : in bit;
RXDATA : in bit;
CTSn : in bit;
DCDn : in bit;
IRQn : out std_logic;
TXDATA : out bit;
RTSn : out bit
);
end entity WF6850IP_TOP;
architecture STRUCTURE of WF6850IP_TOP is
component WF6850IP_TOP_SOC
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 component;
signal DATA_OUT : std_logic_vector(7 downto 0);
signal DATA_EN : bit;
signal IRQ_In : bit;
begin
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
IRQn <= '0' when IRQ_In = '0' else 'Z'; -- Open drain.
I_UART: WF6850IP_TOP_SOC
port map(CLK => CLK,
RESETn => RESETn,
CS2n => CS2n,
CS1 => CS1,
CS0 => CS0,
E => E,
RWn => RWn,
RS => RS,
DATA_IN => DATA,
DATA_OUT => DATA_OUT,
DATA_EN => DATA_EN,
TXCLK => TXCLK,
RXCLK => RXCLK,
RXDATA => RXDATA,
CTSn => CTSn,
DCDn => DCDn,
IRQn => IRQ_In,
TXDATA => TXDATA,
RTSn => RTSn
);
end architecture STRUCTURE;

View File

@@ -0,0 +1,255 @@
----------------------------------------------------------------------
---- ----
---- 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.
-- 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_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

@@ -0,0 +1,252 @@
----------------------------------------------------------------------
---- ----
---- 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

@@ -0,0 +1,339 @@
----------------------------------------------------------------------
---- ----
---- 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 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 : 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
wait until CLK = '1' and CLK' event;
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 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 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 CLK = '1' and CLK' event 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
-- Counter for the data bits transmitted.
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end process P_BITCNT;
P_TDRE: process(RESETn, CLK)
-- Transmit data register empty flag.
variable LOCK : boolean;
begin
if RESETn = '0' then
TDRE <= '1';
LOCK := false;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TDRE <= '1';
elsif 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';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' and LOCK = false then
LOCK := true;
elsif E = '0' and LOCK = true then
-- This construction clears TDRE after the falling edge of E
-- and after the transmit data register has been written to.
TDRE <= '0';
LOCK := false;
end if;
end if;
end process P_TDRE;
PARITY_GEN: process
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if 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 process PARITY_GEN;
TR_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TR_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TR_STATE <= IDLE;
else
TR_STATE <= TR_NEXT_STATE;
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,339 @@
----------------------------------------------------------------------
---- ----
---- 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 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 : 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
wait until CLK = '1' and CLK' event;
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 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 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 CLK = '1' and CLK' event 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
-- Counter for the data bits transmitted.
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end process P_BITCNT;
P_TDRE: process(RESETn, CLK)
-- Transmit data register empty flag.
variable LOCK : boolean;
begin
if RESETn = '0' then
TDRE <= '1';
LOCK := false;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TDRE <= '1';
elsif 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';
elsif CS = "011" and RWn = '0' and RS = '1' and E = '1' and LOCK = false then
LOCK := true;
elsif E = '0' and LOCK = true and CS /= "011" then
-- This construction clears TDRE after the falling edge of E
-- and after the transmit data register has been written to.
TDRE <= '0';
LOCK := false;
end if;
end if;
end process P_TDRE;
PARITY_GEN: process
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if 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 process PARITY_GEN;
TR_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
TR_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
TR_STATE <= IDLE;
else
TR_STATE <= TR_NEXT_STATE;
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,95 @@
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
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.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 160 168)
(text "dcfifo0" (rect 62 1 105 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 152 25 164)(font "Arial" ))
(port
(pt 0 32)
(input)
(text "data[7..0]" (rect 0 0 53 14)(font "Arial" (font_size 8)))
(text "data[7..0]" (rect 20 26 65 39)(font "Arial" (font_size 8)))
(line (pt 0 32)(pt 16 32)(line_width 3))
)
(port
(pt 0 56)
(input)
(text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))
(line (pt 0 56)(pt 16 56)(line_width 1))
)
(port
(pt 0 72)
(input)
(text "wrclk" (rect 0 0 31 14)(font "Arial" (font_size 8)))
(text "wrclk" (rect 26 66 48 79)(font "Arial" (font_size 8)))
(line (pt 0 72)(pt 16 72)(line_width 1))
)
(port
(pt 0 104)
(input)
(text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))
(text "rdreq" (rect 20 98 44 111)(font "Arial" (font_size 8)))
(line (pt 0 104)(pt 16 104)(line_width 1))
)
(port
(pt 0 120)
(input)
(text "rdclk" (rect 0 0 27 14)(font "Arial" (font_size 8)))
(text "rdclk" (rect 26 114 47 127)(font "Arial" (font_size 8)))
(line (pt 0 120)(pt 16 120)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))
(text "aclr" (rect 20 138 37 151)(font "Arial" (font_size 8)))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 160 72)
(output)
(text "wrusedw[9..0]" (rect 0 0 84 14)(font "Arial" (font_size 8)))
(text "wrusedw[9..0]" (rect 69 66 132 79)(font "Arial" (font_size 8)))
(line (pt 160 72)(pt 144 72)(line_width 3))
)
(port
(pt 160 96)
(output)
(text "q[31..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))
(text "q[31..0]" (rect 105 90 141 103)(font "Arial" (font_size 8)))
(line (pt 160 96)(pt 144 96)(line_width 3))
)
(drawing
(text "8 bits x 1024 words" (rect 63 140 144 152)(font "Arial" ))
(line (pt 16 16)(pt 144 16)(line_width 1))
(line (pt 144 16)(pt 144 152)(line_width 1))
(line (pt 144 152)(pt 16 152)(line_width 1))
(line (pt 16 152)(pt 16 16)(line_width 1))
(line (pt 16 84)(pt 144 84)(line_width 1))
(line (pt 16 132)(pt 144 132)(line_width 1))
(line (pt 16 66)(pt 22 72)(line_width 1))
(line (pt 22 72)(pt 16 78)(line_width 1))
(line (pt 16 114)(pt 22 120)(line_width 1))
(line (pt 22 120)(pt 16 126)(line_width 1))
)
)

View File

@@ -0,0 +1,28 @@
--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.
component dcfifo0
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component;

View File

@@ -0,0 +1,5 @@
set_global_assignment -name IP_TOOL_NAME "LPM_FIFO+"
set_global_assignment -name IP_TOOL_VERSION "9.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "dcfifo0.vhd"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo0.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo0.cmp"]

View File

@@ -0,0 +1,202 @@
-- megafunction wizard: %LPM_FIFO+%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: dcfifo_mixed_widths
-- ============================================================
-- File Name: dcfifo0.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 dcfifo0 IS
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
END dcfifo0;
ARCHITECTURE SYN OF dcfifo0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (9 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (31 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 (9 DOWNTO 0);
aclr : IN STD_LOGIC ;
rdclk : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
wrreq : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END COMPONENT;
BEGIN
wrusedw <= sub_wire0(9 DOWNTO 0);
q <= sub_wire1(31 DOWNTO 0);
dcfifo_mixed_widths_component : dcfifo_mixed_widths
GENERIC MAP (
intended_device_family => "Cyclone III",
lpm_numwords => 1024,
lpm_showahead => "OFF",
lpm_type => "dcfifo",
lpm_width => 8,
lpm_widthu => 10,
lpm_widthu_r => 8,
lpm_width_r => 32,
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 "1024"
-- 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 "8"
-- 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 "32"
-- 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 "1024"
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTH_R NUMERIC "32"
-- 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 8 0 INPUT NODEFVAL data[7..0]
-- Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..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 10 0 OUTPUT NODEFVAL wrusedw[9..0]
-- Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
-- Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 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 10 0 @wrusedw 0 0 10 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 dcfifo0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.bsf TRUE FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_waveforms.html FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,202 @@
-- megafunction wizard: %LPM_FIFO+%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: dcfifo_mixed_widths
-- ============================================================
-- File Name: dcfifo0.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 dcfifo0 IS
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdclk : IN STD_LOGIC ;
rdreq : IN STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
wrusedw : OUT STD_LOGIC_VECTOR (4 DOWNTO 0)
);
END dcfifo0;
ARCHITECTURE SYN OF dcfifo0 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (15 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 (4 DOWNTO 0);
aclr : IN STD_LOGIC ;
rdclk : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
wrreq : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END COMPONENT;
BEGIN
wrusedw <= sub_wire0(4 DOWNTO 0);
q <= sub_wire1(15 DOWNTO 0);
dcfifo_mixed_widths_component : dcfifo_mixed_widths
GENERIC MAP (
intended_device_family => "Cyclone III",
lpm_numwords => 32,
lpm_showahead => "OFF",
lpm_type => "dcfifo",
lpm_width => 8,
lpm_widthu => 5,
lpm_widthu_r => 4,
lpm_width_r => 16,
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 "32"
-- 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 "8"
-- 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 "16"
-- 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 "32"
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "5"
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "4"
-- Retrieval info: CONSTANT: LPM_WIDTH_R NUMERIC "16"
-- 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 8 0 INPUT NODEFVAL data[7..0]
-- Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..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 5 0 OUTPUT NODEFVAL wrusedw[4..0]
-- Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
-- Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 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 5 0 @wrusedw 0 0 5 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 dcfifo0.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0.bsf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_inst.vhd FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_waveforms.html FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL dcfifo0_wave*.jpg FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,95 @@
/*
WARNING: Do NOT edit the input and output ports in this file in a text
editor if you plan to continue editing the block that represents it in
the Block Editor! File corruption is VERY likely to occur.
*/
/*
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.
*/
(header "symbol" (version "1.1"))
(symbol
(rect 0 0 160 168)
(text "dcfifo1" (rect 62 1 105 17)(font "Arial" (font_size 10)))
(text "inst" (rect 8 152 25 164)(font "Arial" ))
(port
(pt 0 32)
(input)
(text "data[31..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))
(text "data[31..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))
(line (pt 0 32)(pt 16 32)(line_width 3))
)
(port
(pt 0 56)
(input)
(text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))
(line (pt 0 56)(pt 16 56)(line_width 1))
)
(port
(pt 0 72)
(input)
(text "wrclk" (rect 0 0 31 14)(font "Arial" (font_size 8)))
(text "wrclk" (rect 26 66 48 79)(font "Arial" (font_size 8)))
(line (pt 0 72)(pt 16 72)(line_width 1))
)
(port
(pt 0 104)
(input)
(text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))
(text "rdreq" (rect 20 98 44 111)(font "Arial" (font_size 8)))
(line (pt 0 104)(pt 16 104)(line_width 1))
)
(port
(pt 0 120)
(input)
(text "rdclk" (rect 0 0 27 14)(font "Arial" (font_size 8)))
(text "rdclk" (rect 26 114 47 127)(font "Arial" (font_size 8)))
(line (pt 0 120)(pt 16 120)(line_width 1))
)
(port
(pt 0 144)
(input)
(text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))
(text "aclr" (rect 20 138 37 151)(font "Arial" (font_size 8)))
(line (pt 0 144)(pt 16 144)(line_width 1))
)
(port
(pt 160 96)
(output)
(text "q[7..0]" (rect 0 0 35 14)(font "Arial" (font_size 8)))
(text "q[7..0]" (rect 111 90 141 103)(font "Arial" (font_size 8)))
(line (pt 160 96)(pt 144 96)(line_width 3))
)
(port
(pt 160 120)
(output)
(text "rdusedw[9..0]" (rect 0 0 80 14)(font "Arial" (font_size 8)))
(text "rdusedw[9..0]" (rect 73 114 135 127)(font "Arial" (font_size 8)))
(line (pt 160 120)(pt 144 120)(line_width 3))
)
(drawing
(text "32 bits x 256 words" (rect 63 140 144 152)(font "Arial" ))
(line (pt 16 16)(pt 144 16)(line_width 1))
(line (pt 144 16)(pt 144 152)(line_width 1))
(line (pt 144 152)(pt 16 152)(line_width 1))
(line (pt 16 152)(pt 16 16)(line_width 1))
(line (pt 16 84)(pt 144 84)(line_width 1))
(line (pt 16 132)(pt 144 132)(line_width 1))
(line (pt 16 66)(pt 22 72)(line_width 1))
(line (pt 22 72)(pt 16 78)(line_width 1))
(line (pt 16 114)(pt 22 120)(line_width 1))
(line (pt 22 120)(pt 16 126)(line_width 1))
)
)

View File

@@ -0,0 +1,28 @@
--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.
component dcfifo1
PORT
(
aclr : IN STD_LOGIC := '0';
data : IN STD_LOGIC_VECTOR (31 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);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
end component;

View File

@@ -0,0 +1,5 @@
set_global_assignment -name IP_TOOL_NAME "LPM_FIFO+"
set_global_assignment -name IP_TOOL_VERSION "9.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "dcfifo1.vhd"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo1.bsf"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "dcfifo1.cmp"]

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 (31 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);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
END dcfifo1;
ARCHITECTURE SYN OF dcfifo1 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (9 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 ;
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 (31 DOWNTO 0);
rdusedw : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(7 DOWNTO 0);
rdusedw <= sub_wire1(9 DOWNTO 0);
dcfifo_mixed_widths_component : dcfifo_mixed_widths
GENERIC MAP (
intended_device_family => "Cyclone III",
lpm_numwords => 256,
lpm_showahead => "OFF",
lpm_type => "dcfifo",
lpm_width => 32,
lpm_widthu => 8,
lpm_widthu_r => 10,
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,
q => sub_wire0,
rdusedw => 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 "256"
-- 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 "32"
-- 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 "1"
-- 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 "0"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "256"
-- Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"
-- Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "8"
-- Retrieval info: CONSTANT: LPM_WIDTHU_R NUMERIC "10"
-- 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 32 0 INPUT NODEFVAL data[31..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: rdusedw 0 0 10 0 OUTPUT NODEFVAL rdusedw[9..0]
-- 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: CONNECT: @data 0 0 32 0 data 0 0 32 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: rdusedw 0 0 10 0 @rdusedw 0 0 10 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 FALSE
-- 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

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