Sync with Fredi's source tree 13/06/2015

Parallel port fix.
This commit is contained in:
David Gálvez
2018-04-09 17:19:13 +02:00
parent 3fb6e3bd8a
commit 68129dbe57
107 changed files with 12435 additions and 27384 deletions

View File

@@ -115,7 +115,7 @@ ENTITY FalconIO_SDCard_IDE_CF IS
nCF_CS0 : OUT STD_LOGIC;
nIDE_RD : INOUT STD_LOGIC;
nIDE_WR : INOUT STD_LOGIC;
AMKB_TX : OUT STD_LOGIC;
AMKB_TX : buffer STD_LOGIC;
IDE_RES : OUT STD_LOGIC;
DTR : OUT STD_LOGIC;
RTS : OUT STD_LOGIC;
@@ -132,6 +132,7 @@ ENTITY FalconIO_SDCard_IDE_CF IS
DMA_DRQ : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
LP_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SND_A : 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;
@@ -156,12 +157,15 @@ 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
signal FB_ADI : STD_LOGIC_VECTOR(15 downto 0); -- gespeicherte writedaten
signal nResetatio : STD_LOGIC; -- reset atari bausteine
-- 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 AMKB_REG : STD_LOGIC_VECTOR(3 downto 0);
signal AMKB_TX_sync : std_logic;
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);
@@ -169,8 +173,8 @@ signal DATA_OUT_ACIA_II : STD_LOGIC_VECTOR(7 downto 0);
signal MFP_CS : STD_LOGIC;
signal MFP_INTACK : STD_LOGIC;
signal LDS : STD_LOGIC;
signal acia_irq : 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;
@@ -180,7 +184,22 @@ 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 SND_A_X : STD_LOGIC_VECTOR(7 downto 0);
signal LP_D_X : STD_LOGIC_VECTOR(7 downto 0);
signal nLP_STR : STD_LOGIC;
-- DMA SOUND
signal dma_snd_cs : STD_LOGIC;
signal sndmactl : STD_LOGIC_VECTOR(7 downto 0);
signal sndbashi : STD_LOGIC_VECTOR(7 downto 0);
signal sndbasmi : STD_LOGIC_VECTOR(7 downto 0);
signal sndbaslo : STD_LOGIC_VECTOR(7 downto 0);
signal sndadrhi : STD_LOGIC_VECTOR(7 downto 0);
signal sndadrmi : STD_LOGIC_VECTOR(7 downto 0);
signal sndadrlo : STD_LOGIC_VECTOR(7 downto 0);
signal sndendhi : STD_LOGIC_VECTOR(7 downto 0);
signal sndendmi : STD_LOGIC_VECTOR(7 downto 0);
signal sndendlo : STD_LOGIC_VECTOR(7 downto 0);
signal sndmode : 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;
@@ -265,22 +284,36 @@ 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;
-- Paddle
signal paddle_cs : STD_LOGIC;
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
FALCON_IO_TA <= '1' when ACIA_CS_I = '1' or DTACK_OUT_MFPn = '0' or DMA_MODUS_CS ='1' or dma_snd_cs = '1' or paddle_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';--SNDCS = '1' or
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';
nRP_UDS <= '0' when nFB_CS1 = '0' and SUB_BUS = '1' and FB_B0 = '1' else '1';
nRP_LDS <= '0' when nFB_CS1 = '0' and SUB_BUS = '1' and FB_B1 = '1' else '1';
nDREQ0 <= '0';
-- input daten halten
process(MAIN_CLK, nFB_WR, FB_AD(31 downto 16), FB_ADI(15 downto 0))
begin
if rising_edge(MAIN_CLK) then
IF nFB_WR = '0' THEN
FB_ADI <= FB_AD(31 downto 16);
ELSE
FB_ADI <= FB_ADI;
end if;
ELSE
FB_ADI <= FB_ADI;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- SD
----------------------------------------------------------------------------
@@ -386,7 +419,7 @@ RDF_DIN <= CD_OUT_FDC when DMA_MODUS(7) = '1' else SCSI_DOUT;
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
CD_IN_FDC <= WRF_DOUT when DMA_ACTIV = '1' and DMA_MODUS(8) = '1' else FB_ADI(7 downto 0); -- 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';
@@ -513,7 +546,7 @@ SCSI_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and FB_
I_FDC: WF1772IP_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
CSn => FDCS_In,
RWn => nFDC_WR,
A1 => CA2,
@@ -695,13 +728,13 @@ CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
I_SCSI: WF5380_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
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
CSn => SCSI_CSn,
RDn => (not nFDC_WR) or (not SCSI_CS),
WRn => nFDC_WR or (not SCSI_CS),
EOPn => '1',
@@ -745,18 +778,19 @@ CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
-- 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_D <= "ZZZZZZZZ";--DB_OUTn when DB_EN = '1' else "ZZZZZZZZ";
SCSI_DIR <= '1';-- when DB_EN = '1' else '1';
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';
nSCSI_RST <= 'Z';--RST_OUTn when RST_EN = '1' else 'Z';
nSCSI_BUSY <= 'Z';--BSY_OUTn when BSY_EN = '1' else 'Z';
nSCSI_SEL <= 'Z';--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';
nResetatio <= '0' when nRSTO = '0' or ACP_CONF(24) = '1' else '1';
----------------------------------------------------------------------------
-- ROM-PORT TA KOMMT FROM DEFAULT TA = 16 BUSCYCLEN = 500ns
----------------------------------------------------------------------------
@@ -769,16 +803,16 @@ nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
I_ACIA_KEYBOARD: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
CS2n => FB_ADR(2),
CS1 => '1',
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_IN => FB_ADI(15 downto 8),
DATA_OUT => DATA_OUT_ACIA_I,
-- DATA_EN => DATA_EN_ACIA_I,
@@ -790,40 +824,45 @@ nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
DCDn => '0',
IRQn => IRQ_KEYBDn,
TXDATA => AMKB_TX
TXDATA => AMKB_TX_sync
--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 ------------------------------------------
KEYB_RxD <= '0' when AMKB_REG(3) = '0' or PIC_AMKB_RX = '0' else '1'; -- 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
DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
-- AMKB_TX: SPIKES AUSFILTERN und sychronisieren ------------------------------------------
process(CLK2M, AMKB_RX, AMKB_REG)
begin
if rising_edge(CLK2M) then
if rising_edge(CLK500k) then
AMKB_TX <= AMKB_TX_sync;
IF AMKB_RX = '0' THEN
IF AMKB_REG < 16 THEN
AMKB_REG <= "00000";
IF AMKB_REG < 8 THEN
AMKB_REG <= "0000";
ELSE
AMKB_REG <= AMKB_REG - 1;
END IF;
ELSE
IF AMKB_REG > 15 THEN
AMKB_REG <= "11111";
IF AMKB_REG > 7 THEN
AMKB_REG <= "1111";
ELSE
AMKB_REG <= AMKB_REG + 1;
END IF;
END IF;
ELSE
AMKB_TX <= AMKB_TX;
AMKB_REG <= AMKB_REG;
end if;
END PROCESS;
-- acia interrupt ------------------------------------------
acia_irq <= '0' when IRQ_KEYBDn = '0' or IRQ_MIDIn = '0' else '1';
----------------------------------------------------------------------------
-- ACIA MIDI
----------------------------------------------------------------------------
I_ACIA_MIDI: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
CS2n => '0',
CS1 => FB_ADR(2),
@@ -832,7 +871,7 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0'
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_IN => FB_ADI(15 downto 8),
DATA_OUT => DATA_OUT_ACIA_II,
-- DATA_EN => DATA_EN_ACIA_II,
@@ -845,18 +884,17 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0'
IRQn => IRQ_MIDIn,
TXDATA => MIDI_OUT
--RTSn => -- Not used.
);
MIDI_TLR <= MIDI_OUT;
);
MIDI_TLR <= MIDI_IN;
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,
CLK => not MAIN_CLK,
RESETn => nResetatio,
-- Asynchronous bus control:
DSn => not LDS,
CSn => not MFP_CS,
@@ -867,14 +905,14 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '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(7) => not DMA_DRQ_Q,
GPIP_IN(6) => not RI,
GPIP_IN(5) => DINTn,
GPIP_IN(4) => IRQ_ACIAn,
GPIP_IN(4) => acia_irq,
GPIP_IN(3) => DSP_INT,
GPIP_IN(2) => not CTS,
GPIP_IN(1) => not DCD,
GPIP_IN(0) => LP_BUSY,
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:
@@ -885,7 +923,7 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1'
-- Timers and timer control:
XTAL1 => CLK2M4576,
TAI => '0',
TBI => nBLANK,
TBI => nBLANK,
-- TAO =>,
-- TBO =>,
-- TCO =>,
@@ -911,24 +949,13 @@ 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,
SYS_CLK => not MAIN_CLK,
RESETn => nResetatio,
WAV_CLK => CLK2M,
SELn => '1',
@@ -939,18 +966,11 @@ DINTn <= '0' when IDE_INT = '1' AND ACP_CONF(28) = '1' else
A9n => '0',
A8 => '1',
DA_IN => FB_AD(31 downto 24),
DA_IN => FB_ADI(15 downto 8),
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_IN => SND_A,
IO_A_OUT => SND_A_X,
-- IO_A_EN =>, -- Not required.
IO_B_IN => LP_D,
IO_B_OUT => LP_D_X,
@@ -965,7 +985,170 @@ SNDCS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 2) = x"3E200" else '0'; --
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";
nnIDE_RES <= SND_A_X(7);
LP_DIR_X <= SND_A_X(6);
LP_STR <= SND_A_X(5);
DTR <= SND_A_X(4);
RTS <= SND_A_X(3);
-- FDD_D1SEL <= SND_A_X(2)
DSA_D <= SND_A_X(1);
nSDSEL <= SND_A_X(0);
SND_A <= SND_A_X;
LP_D <= LP_D_X when LP_DIR_X = '0' else "ZZZZZZZZ";
LP_DIR <= LP_DIR_X;
----------------------------------------------------------------------------
-- DMA Sound register
----------------------------------------------------------------------------
dma_snd_cs <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3E24" else '0'; -- F8900-F893F
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndmactl <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"0" and nFB_WR = '0' and FB_B1 ='1' then
sndmactl <= FB_AD(23 downto 16);
else
sndmactl <= sndmactl;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndmactl when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"0" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndbashi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"1" and nFB_WR = '0' and FB_B1 ='1' then
sndbashi <= FB_AD(23 downto 16);
else
sndbashi <= sndbashi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndbashi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"1" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndbasmi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"2" and nFB_WR = '0' and FB_B1 ='1' then
sndbasmi <= FB_AD(23downto 16);
else
sndbasmi <= sndbasmi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndbasmi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"2" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndbaslo <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"3" and nFB_WR = '0' and FB_B1 ='1' then
sndbaslo <= FB_AD(23 downto 16);
else
sndbaslo <= sndbaslo;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndbaslo when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"3" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndadrhi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"4" and nFB_WR = '0' and FB_B1 ='1' then
sndadrhi <= FB_AD(23 downto 16);
else
sndadrhi <= sndadrhi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndadrhi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"4" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndadrmi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"5" and nFB_WR = '0' and FB_B1 ='1' then
sndadrmi <= FB_AD(23 downto 16);
else
sndadrmi <= sndadrmi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndadrmi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"5" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndadrlo <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"6" and nFB_WR = '0' and FB_B1 ='1' then
sndadrlo <= FB_AD(23 downto 16);
else
sndadrlo <= sndadrlo;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndadrlo when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"6" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndendhi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"7" and nFB_WR = '0' and FB_B1 ='1' then
sndendhi <= FB_AD(23 downto 16);
else
sndendhi <= sndendhi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndendhi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"7" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndendmi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"8" and nFB_WR = '0' and FB_B1 ='1' then
sndendmi <= FB_AD(23 downto 16);
else
sndendmi <= sndendmi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndendmi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"8" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndendlo <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"9" and nFB_WR = '0' and FB_B1 ='1' then
sndendlo <= FB_AD(23 downto 16);
else
sndendlo <= sndendlo;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndendlo when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"9" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndmode <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"10" and nFB_WR = '0' and FB_B1 ='1' then
sndmode <= FB_AD(23 downto 16);
else
sndmode <= sndmode;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndmode when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"10" and nFB_OE = '0' else "ZZZZZZZZ";
----------------------------------------------------------------------------
-- Paddle
----------------------------------------------------------------------------
paddle_cs <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3E48" else '0'; -- F9200-F923F
FB_AD(31 downto 16) <= x"bfff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"0" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"1" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"8" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"9" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"A" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"B" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"0000" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"10" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"0000" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"11" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
END FalconIO_SDCard_IDE_CF_architecture;

View File

@@ -115,7 +115,7 @@ ENTITY FalconIO_SDCard_IDE_CF IS
nCF_CS0 : OUT STD_LOGIC;
nIDE_RD : INOUT STD_LOGIC;
nIDE_WR : INOUT STD_LOGIC;
AMKB_TX : OUT STD_LOGIC;
AMKB_TX : buffer STD_LOGIC;
IDE_RES : OUT STD_LOGIC;
DTR : OUT STD_LOGIC;
RTS : OUT STD_LOGIC;
@@ -132,6 +132,7 @@ ENTITY FalconIO_SDCard_IDE_CF IS
DMA_DRQ : OUT STD_LOGIC;
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
LP_D : INOUT STD_LOGIC_VECTOR(7 downto 0);
SND_A : 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;
@@ -156,12 +157,15 @@ 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
signal FB_ADI : STD_LOGIC_VECTOR(15 downto 0); -- gespeicherte writedaten
signal nResetatio : STD_LOGIC; -- reset atari bausteine
-- 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 AMKB_REG : STD_LOGIC_VECTOR(3 downto 0);
signal AMKB_TX_sync : std_logic;
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);
@@ -169,8 +173,8 @@ signal DATA_OUT_ACIA_II : STD_LOGIC_VECTOR(7 downto 0);
signal MFP_CS : STD_LOGIC;
signal MFP_INTACK : STD_LOGIC;
signal LDS : STD_LOGIC;
signal acia_irq : 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;
@@ -180,7 +184,22 @@ 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 SND_A_X : STD_LOGIC_VECTOR(7 downto 0);
signal LP_D_X : STD_LOGIC_VECTOR(7 downto 0);
signal nLP_STR : STD_LOGIC;
-- DMA SOUND
signal dma_snd_cs : STD_LOGIC;
signal sndmactl : STD_LOGIC_VECTOR(7 downto 0);
signal sndbashi : STD_LOGIC_VECTOR(7 downto 0);
signal sndbasmi : STD_LOGIC_VECTOR(7 downto 0);
signal sndbaslo : STD_LOGIC_VECTOR(7 downto 0);
signal sndadrhi : STD_LOGIC_VECTOR(7 downto 0);
signal sndadrmi : STD_LOGIC_VECTOR(7 downto 0);
signal sndadrlo : STD_LOGIC_VECTOR(7 downto 0);
signal sndendhi : STD_LOGIC_VECTOR(7 downto 0);
signal sndendmi : STD_LOGIC_VECTOR(7 downto 0);
signal sndendlo : STD_LOGIC_VECTOR(7 downto 0);
signal sndmode : 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;
@@ -265,22 +284,36 @@ 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;
-- Paddle
signal paddle_cs : STD_LOGIC;
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
FALCON_IO_TA <= '1' when ACIA_CS_I = '1' or DTACK_OUT_MFPn = '0' or DMA_MODUS_CS ='1' or dma_snd_cs = '1' or paddle_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';--SNDCS = '1' or
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';
nRP_UDS <= '0' when nFB_CS1 = '0' and SUB_BUS = '1' and FB_B0 = '1' else '1';
nRP_LDS <= '0' when nFB_CS1 = '0' and SUB_BUS = '1' and FB_B1 = '1' else '1';
nDREQ0 <= '0';
-- input daten halten
process(MAIN_CLK, nFB_WR, FB_AD(31 downto 16), FB_ADI(15 downto 0))
begin
if rising_edge(MAIN_CLK) then
IF nFB_WR = '0' THEN
FB_ADI <= FB_AD(31 downto 16);
ELSE
FB_ADI <= FB_ADI;
end if;
ELSE
FB_ADI <= FB_ADI;
end if;
END PROCESS;
----------------------------------------------------------------------------
-- SD
----------------------------------------------------------------------------
@@ -386,7 +419,7 @@ RDF_DIN <= CD_OUT_FDC when DMA_MODUS(7) = '1' else SCSI_DOUT;
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
CD_IN_FDC <= WRF_DOUT when DMA_ACTIV = '1' and DMA_MODUS(8) = '1' else FB_ADI(7 downto 0); -- 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';
@@ -513,7 +546,7 @@ SCSI_CS <= '1' when DMA_DATEN_CS = '1' and DMA_MODUS(4 downto 3) = "01" and FB_
I_FDC: WF1772IP_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
CSn => FDCS_In,
RWn => nFDC_WR,
A1 => CA2,
@@ -695,13 +728,13 @@ CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
I_SCSI: WF5380_TOP_SOC
port map(
CLK => FDC_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
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
CSn => SCSI_CSn,
RDn => (not nFDC_WR) or (not SCSI_CS),
WRn => nFDC_WR or (not SCSI_CS),
EOPn => '1',
@@ -745,18 +778,19 @@ CLR_FIFO <= DMA_MODUS(8) xor DMA_DIR_OLD;
-- 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_D <= "ZZZZZZZZ";--DB_OUTn when DB_EN = '1' else "ZZZZZZZZ";
SCSI_DIR <= '1';-- when DB_EN = '1' else '1';
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';
nSCSI_RST <= 'Z';--RST_OUTn when RST_EN = '1' else 'Z';
nSCSI_BUSY <= 'Z';--BSY_OUTn when BSY_EN = '1' else 'Z';
nSCSI_SEL <= 'Z';--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';
nResetatio <= '0' when nRSTO = '0' or ACP_CONF(24) = '1' else '1';
----------------------------------------------------------------------------
-- ROM-PORT TA KOMMT FROM DEFAULT TA = 16 BUSCYCLEN = 500ns
----------------------------------------------------------------------------
@@ -769,16 +803,16 @@ nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
I_ACIA_KEYBOARD: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
CS2n => FB_ADR(2),
CS1 => '1',
CS0 => ACIA_CS_I,
E => ACIA_CS_I,
E => ACIA_CS_I,
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_IN => FB_ADI(15 downto 8),
DATA_OUT => DATA_OUT_ACIA_I,
-- DATA_EN => DATA_EN_ACIA_I,
@@ -790,40 +824,45 @@ nROM3 <= '0' when ROM_CS = '1' and FB_ADR(16) = '1' else '1';
DCDn => '0',
IRQn => IRQ_KEYBDn,
TXDATA => AMKB_TX
TXDATA => AMKB_TX_sync
--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 ------------------------------------------
KEYB_RxD <= '0' when AMKB_REG(3) = '0' or PIC_AMKB_RX = '0' else '1'; -- 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
DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1' and nFB_OE = '0' else "ZZZZZZZZ";
-- AMKB_TX: SPIKES AUSFILTERN und sychronisieren ------------------------------------------
process(CLK2M, AMKB_RX, AMKB_REG)
begin
if rising_edge(CLK2M) then
if rising_edge(CLK500k) then
AMKB_TX <= AMKB_TX_sync;
IF AMKB_RX = '0' THEN
IF AMKB_REG < 16 THEN
AMKB_REG <= "00000";
IF AMKB_REG < 8 THEN
AMKB_REG <= "0000";
ELSE
AMKB_REG <= AMKB_REG - 1;
END IF;
ELSE
IF AMKB_REG > 15 THEN
AMKB_REG <= "11111";
IF AMKB_REG > 7 THEN
AMKB_REG <= "1111";
ELSE
AMKB_REG <= AMKB_REG + 1;
END IF;
END IF;
ELSE
AMKB_TX <= AMKB_TX;
AMKB_REG <= AMKB_REG;
end if;
END PROCESS;
-- acia interrupt ------------------------------------------
acia_irq <= '0' when IRQ_KEYBDn = '0' or IRQ_MIDIn = '0' else '1';
----------------------------------------------------------------------------
-- ACIA MIDI
----------------------------------------------------------------------------
I_ACIA_MIDI: WF6850IP_TOP_SOC
port map(
CLK => MAIN_CLK,
RESETn => nRSTO,
RESETn => nResetatio,
CS2n => '0',
CS1 => FB_ADR(2),
@@ -832,7 +871,7 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0'
RWn => nFB_WR,
RS => FB_ADR(1),
DATA_IN => FB_AD(31 downto 24),
DATA_IN => FB_ADI(15 downto 8),
DATA_OUT => DATA_OUT_ACIA_II,
-- DATA_EN => DATA_EN_ACIA_II,
@@ -845,18 +884,17 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_I when ACIA_CS_I = '1' and FB_ADR(2) = '0'
IRQn => IRQ_MIDIn,
TXDATA => MIDI_OUT
--RTSn => -- Not used.
);
MIDI_TLR <= MIDI_OUT;
);
MIDI_TLR <= MIDI_IN;
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,
CLK => not MAIN_CLK,
RESETn => nResetatio,
-- Asynchronous bus control:
DSn => not LDS,
CSn => not MFP_CS,
@@ -867,14 +905,14 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '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(7) => not DMA_DRQ_Q,
GPIP_IN(6) => not RI,
GPIP_IN(5) => DINTn,
GPIP_IN(4) => IRQ_ACIAn,
GPIP_IN(4) => acia_irq,
GPIP_IN(3) => DSP_INT,
GPIP_IN(2) => not CTS,
GPIP_IN(1) => not DCD,
GPIP_IN(0) => LP_BUSY,
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:
@@ -885,7 +923,7 @@ FB_AD(31 downto 24) <= DATA_OUT_ACIA_II when ACIA_CS_I = '1' and FB_ADR(2) = '1'
-- Timers and timer control:
XTAL1 => CLK2M4576,
TAI => '0',
TBI => nBLANK,
TBI => nBLANK,
-- TAO =>,
-- TBO =>,
-- TCO =>,
@@ -908,27 +946,16 @@ FB_AD(23 downto 16) <= DATA_OUT_MFP when MFP_CS = '1' and nFB_OE = '0' else "ZZZ
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
DINTn <= '0' when IDE_INT = '1' AND ACP_CONF(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;
----------------------------------------------------------------------------
'0' when SCSI_INT = '1' AND ACP_CONF(28) = '1' else '1';
----------------------------------------------------------------------------
-- Sound
----------------------------------------------------------------------------
I_SOUND: WF2149IP_TOP_SOC
port map(
SYS_CLK => MAIN_CLK,
RESETn => nRSTO,
SYS_CLK => not MAIN_CLK,
RESETn => nResetatio,
WAV_CLK => CLK2M,
SELn => '1',
@@ -939,18 +966,11 @@ DINTn <= '0' when IDE_INT = '1' AND ACP_CONFIG[28] = '1' else
A9n => '0',
A8 => '1',
DA_IN => FB_AD(31 downto 24),
DA_IN => FB_ADI(15 downto 8),
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_IN => SND_A,
IO_A_OUT => SND_A_X,
-- IO_A_EN =>, -- Not required.
IO_B_IN => LP_D,
IO_B_OUT => LP_D_X,
@@ -965,7 +985,169 @@ SNDCS <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 2) = x"3E200" else '0'; --
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";
nnIDE_RES <= SND_A_X(7);
LP_DIR_X <= SND_A_X(6);
LP_STR <= SND_A_X(5);
DTR <= SND_A_X(4);
RTS <= SND_A_X(3);
-- FDD_D1SEL <= SND_A_X(2)
DSA_D <= SND_A_X(1);
nSDSEL <= SND_A_X(0);
LP_D <= LP_D_X when LP_DIR_X = '0' else "ZZZZZZZZ";
LP_DIR <= LP_DIR_X;
----------------------------------------------------------------------------
-- DMA Sound register
----------------------------------------------------------------------------
dma_snd_cs <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3E24" else '0'; -- F8900-F893F
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndmactl <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"0" and nFB_WR = '0' and FB_B1 ='1' then
sndmactl <= FB_AD(23 downto 16);
else
sndmactl <= sndmactl;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndmactl when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"0" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndbashi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"1" and nFB_WR = '0' and FB_B1 ='1' then
sndbashi <= FB_AD(23 downto 16);
else
sndbashi <= sndbashi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndbashi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"1" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndbasmi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"2" and nFB_WR = '0' and FB_B1 ='1' then
sndbasmi <= FB_AD(23downto 16);
else
sndbasmi <= sndbasmi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndbasmi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"2" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndbaslo <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"3" and nFB_WR = '0' and FB_B1 ='1' then
sndbaslo <= FB_AD(23 downto 16);
else
sndbaslo <= sndbaslo;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndbaslo when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"3" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndadrhi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"4" and nFB_WR = '0' and FB_B1 ='1' then
sndadrhi <= FB_AD(23 downto 16);
else
sndadrhi <= sndadrhi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndadrhi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"4" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndadrmi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"5" and nFB_WR = '0' and FB_B1 ='1' then
sndadrmi <= FB_AD(23 downto 16);
else
sndadrmi <= sndadrmi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndadrmi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"5" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndadrlo <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"6" and nFB_WR = '0' and FB_B1 ='1' then
sndadrlo <= FB_AD(23 downto 16);
else
sndadrlo <= sndadrlo;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndadrlo when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"6" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndendhi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"7" and nFB_WR = '0' and FB_B1 ='1' then
sndendhi <= FB_AD(23 downto 16);
else
sndendhi <= sndendhi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndendhi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"7" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndendmi <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"8" and nFB_WR = '0' and FB_B1 ='1' then
sndendmi <= FB_AD(23 downto 16);
else
sndendmi <= sndendmi;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndendmi when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"8" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndendlo <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"9" and nFB_WR = '0' and FB_B1 ='1' then
sndendlo <= FB_AD(23 downto 16);
else
sndendlo <= sndendlo;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndendlo when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"9" and nFB_OE = '0' else "ZZZZZZZZ";
process(nRSTO,MAIN_CLK,FB_ADR(5 downto 1), dma_snd_cs)
begin
if nRSTO = '0' THEN
sndmode <= x"00";
elsif rising_edge(MAIN_CLK) and dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"10" and nFB_WR = '0' and FB_B1 ='1' then
sndmode <= FB_AD(23 downto 16);
else
sndmode <= sndmode;
end if;
END PROCESS;
FB_AD(23 downto 16) <= sndmode when dma_snd_cs = '1' and FB_ADR(5 downto 1) = x"10" and nFB_OE = '0' else "ZZZZZZZZ";
----------------------------------------------------------------------------
-- Paddle
----------------------------------------------------------------------------
paddle_cs <= '1' when nFB_CS1 = '0' and FB_ADR(19 downto 6) = x"3E48" else '0'; -- F9200-F923F
FB_AD(31 downto 16) <= x"bfff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"0" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"1" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"8" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"9" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"A" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"ffff" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"B" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"0000" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"10" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
FB_AD(31 downto 16) <= x"0000" when paddle_cs = '1' and FB_ADR(5 downto 1) = x"11" and nFB_OE = '0' else "ZZZZZZZZZZZZZZZZ";
END FalconIO_SDCard_IDE_CF_architecture;

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 = '0' and CLK' event then
for i in 15 downto 0 loop
if INT_SRC(i) = '1' and INT_ENA(i) = '1' and LOCK(i) = '0' then
LOCK(i) := '1';
INT_SRC_EDGE(i) <= '1';
elsif INT_SRC(i) = '0' then
LOCK(i) := '0';
INT_SRC_EDGE(i) <= '0';
else
INT_SRC_EDGE(i) <= '0';
end if;
end loop;
end if;
end process EDGE_ENA;
INT_REGISTERS: process(RESETn, CLK)
begin
if RESETn = '0' then
IERA <= (others => '0');
IERB <= (others => '0');
IPRA <= (others => '0');
IPRB <= (others => '0');
ISRA <= (others => '0');
ISRB <= (others => '0');
IMRA <= (others => '0');
IMRB <= (others => '0');
elsif CLK = '1' and CLK' event then
if CSn = '0' and DSn = '0' and RWn = '0' then
case RS is
when "00011" => IERA <= DATA_IN; -- Enable A.
when "00100" => IERB <= DATA_IN; -- Enable B.
when "00101" =>
-- Only a '0' can be written to the pending register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
IPRA(i) <= '0'; -- Pending A.
end if;
end loop;
when "00110" =>
-- Only a '0' can be written to the pending register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
IPRB(i) <= '0'; -- Pending B.
end if;
end loop;
when "00111" =>
-- Only a '0' can be written to the in service register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
ISRA(i) <= '0'; -- In Service A.
end if;
end loop;
when "01000" =>
-- Only a '0' can be written to the in service register.
for i in 7 downto 0 loop
if DATA_IN(i) = '0' then
ISRB(i) <= '0'; -- In Service B.
end if;
end loop;
when "01001" => IMRA <= DATA_IN; -- Mask A.
when "01010" => IMRB <= DATA_IN; -- Mask B.
when "01011" => VR <= DATA_IN(7 downto 3); -- Vector register.
when others => null;
end case;
end if;
-- Pending register:
-- set and clear bit logic.
for i in 15 downto 8 loop
if INT_SRC_EDGE(i) = '1' then
IPRA(i-8) <= '1';
elsif INT_ENA(i) = '0' then
IPRA(i-8) <= '0'; -- Clear by disabling the channel.
elsif INT_PASS(i) = '1' then
IPRA(i-8) <= '0'; -- Clear by passing the interrupt.
end if;
end loop;
for i in 7 downto 0 loop
if INT_SRC_EDGE(i) = '1' then
IPRB(i) <= '1';
elsif INT_ENA(i) = '0' then
IPRB(i) <= '0'; -- Clear by disabling the channel.
elsif INT_PASS(i) = '1' then
IPRB(i) <= '0'; -- Clear by passing the interrupt.
end if;
end loop;
-- In-Service register:
-- Set bit logic, VR(3) is the service register enable.
for i in 15 downto 8 loop
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
ISRA(i-8) <= '1';
end if;
end loop;
for i in 7 downto 0 loop
if INT_OUT(i) = '1' and INT_PASS(i) = '1' and VR(3) = '1' then
ISRB(i) <= '1';
end if;
end loop;
end if;
end process INT_REGISTERS;
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "00010" and RS <= "01011" else '1' when INT_STATE = VECTOR_OUT else '0';
DATA_OUT <= IERA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00011" else
IERB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00100" else
IPRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00101" else
IPRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00110" else
ISRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "00111" else
ISRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01000" else
IMRA when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01001" else
IMRB when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01010" else
VR & "000" when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01011" else
VECT_NUMBER when INT_STATE = VECTOR_OUT else x"00";
P_INT_STATE : process(RESETn, CLK)
begin
if RESETn = '0' then
INT_STATE <= SCAN;
elsif CLK = '1' and CLK' event then
case INT_STATE is
when SCAN =>
INT_PASS <= x"0000";
-- Automatic End of Interrupt mode. Service register disabled.
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
-- vector number (VR(7 downto 4) = x"0").
if INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '0' and IEIn = '0' then
INT_STATE <= REQUEST; -- Non masked interrupt is pending.
-- The following 16 are the Software end of interrupt mode. Service register enabled.
-- The MFP does not respond for an interrupt acknowledge cycle for an uninitialized
-- vector number (VR(7 downto 4) = x"0"). The interrupts are prioritized.
elsif INT_OUT /= x"0000" and VR(7 downto 4) /= x"0" and VR(3) = '1' and IEIn = '0' then
if INT_OUT (15) = '1' and INT_SERVICE(15) = '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (14) = '1' and INT_SERVICE(15 downto 14) = "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (13) = '1' and INT_SERVICE(15 downto 13) = "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (12) = '1' and INT_SERVICE(15 downto 12) = x"0" then
INT_STATE <= REQUEST;
elsif INT_OUT (11) = '1' and INT_SERVICE(15 downto 11) = x"0" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (10) = '1' and INT_SERVICE(15 downto 10) = x"0" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (9) = '1' and INT_SERVICE(15 downto 9) = x"0" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (8) = '1' and INT_SERVICE(15 downto 8) = x"00" then
INT_STATE <= REQUEST;
elsif INT_OUT (7) = '1' and INT_SERVICE(15 downto 7) = x"00" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (6) = '1' and INT_SERVICE(15 downto 6) = x"00" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (5) = '1' and INT_SERVICE(15 downto 5) = x"00" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (4) = '1' and INT_SERVICE(15 downto 4) = x"000" then
INT_STATE <= REQUEST;
elsif INT_OUT (3) = '1' and INT_SERVICE(15 downto 3) = x"000" & '0' then
INT_STATE <= REQUEST;
elsif INT_OUT (2) = '1' and INT_SERVICE(15 downto 2) = x"000" & "00" then
INT_STATE <= REQUEST;
elsif INT_OUT (1) = '1' and INT_SERVICE(15 downto 1) = x"000" & "000" then
INT_STATE <= REQUEST;
elsif INT_OUT (0) = '1' and INT_SERVICE(15 downto 0) = x"0000" then
INT_STATE <= REQUEST;
else
INT_STATE <= SCAN; -- Wait for interrupt.
end if;
else
INT_STATE <= SCAN;
end if;
when REQUEST =>
if IACKn = '0' and DSn = '0' then -- Vectored interrupt mode.
INT_STATE <= VECTOR_OUT; -- Non masked interrupt is pending.
if INT_OUT(15) = '1' then
INT_PASS(15) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"F"; -- GPI 7.
elsif INT_OUT(14) = '1' then
INT_PASS(14) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"E"; -- GPI 6.
elsif INT_OUT(13) = '1' then
INT_PASS(13) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"D"; -- TIMER A.
elsif INT_OUT(12) = '1' then
INT_PASS(12) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"C"; -- Receive buffer full.
elsif INT_OUT(11) = '1' then
INT_PASS(11) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"B"; -- Receiver error.
elsif INT_OUT(10) = '1' then
INT_PASS(10) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"A"; -- Transmit buffer empty.
elsif INT_OUT(9) = '1' then
INT_PASS(9) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"9"; -- Transmit error.
elsif INT_OUT(8) = '1' then
INT_PASS(8) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"8"; -- Timer B.
elsif INT_OUT(7) = '1' then
INT_PASS(7) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"7"; -- GPI 5.
elsif INT_OUT(6) = '1' then
INT_PASS(6) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"6"; -- GPI 4.
elsif INT_OUT(5) = '1' then
INT_PASS(5) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"5"; -- Timer C.
elsif INT_OUT(4) = '1' then
INT_PASS(4) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"4"; -- Timer D.
elsif INT_OUT(3) = '1' then
INT_PASS(3) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"3"; -- GPI 3.
elsif INT_OUT(2) = '1' then
INT_PASS(2) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"2"; -- GPI 2.
elsif INT_OUT(1) = '1' then
INT_PASS(1) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"1"; -- GPI 1.
elsif INT_OUT(0) = '1' then
INT_PASS(0) <= '1'; VECT_NUMBER <= VR(7 downto 4) & x"0"; -- GPI 0.
end if;
-- Polled interrupt mode: End of interrupt by writing to the pending registers.
elsif CSn = '0' and DSn = '0' and RWn = '0' and (RS = "00101" or RS = "00110") then
INT_STATE <= SCAN;
else
INT_STATE <= REQUEST; -- Wait.
end if;
when VECTOR_OUT =>
INT_PASS <= x"0000";
if DSn = '1' or IACKn = '1' then
INT_STATE <= SCAN; -- Finished.
else
INT_STATE <= VECTOR_OUT; -- Wait for processor to read the vector.
end if;
end case;
end if;
end process P_INT_STATE;
end architecture BEHAVIOR;

View File

@@ -190,8 +190,8 @@ begin
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_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;

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 '1'; --0
IO_B_EN <= '1' when CTRL_REG(7) = '1' else '1'; --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

@@ -67,7 +67,7 @@ use ieee.std_logic_unsigned.all;
entity WF6850IP_CTRL_STATUS is
port (
CLK : in bit;
CLK : in std_logic;
RESETn : in bit;
CS : in bit_vector(2 downto 0); -- Active if "011".
@@ -94,7 +94,7 @@ entity WF6850IP_CTRL_STATUS is
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.
IRQn : buffer bit -- Interrupt request.
);
end entity WF6850IP_CTRL_STATUS;
@@ -102,19 +102,14 @@ 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;
CTS_In <= CTSn;
DCD_In <= DCDn; -- immer 0
STATUS_REG(7) <= IRQ_I;
STATUS_REG(7) <= not IRQn;
STATUS_REG(6) <= PE;
STATUS_REG(5) <= OVR;
STATUS_REG(4) <= FE;
@@ -123,8 +118,8 @@ begin
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';
DATA_OUT <= STATUS_REG when CS = "011" and RWn = '1' and RS = '0' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' else '0';
MCLR <= '1' when CTRL_REG(1 downto 0) = "11" else '0';
RTSn <= '0' when CTRL_REG(6 downto 5) /= "10" else '1';
@@ -134,110 +129,73 @@ begin
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.
P_IRQ: process(CLK)
begin
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
IRQn <= '1';
else
-- Transmitter interrupt:
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" then
IRQn <= '0';
end if;
-- Receiver interrupts:
if RDRF = '1' and RIE = '1' then
IRQn <= '0';
end if;
-- Overrun
if OVR = '1' and RIE = '1' then
IRQn <= '0';
end if;
-- The reset of the IRQ status flag:
-- Clear by writing to the transmit data register.
-- Clear by reading the receive data register.
if CS = "011" and RS = '1' then
IRQn <= '1';
end if;
end if;
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
CONTROL: process(CLK)
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;
if rising_edge(CLK) then
if RESETn = '0' then
CTRL_REG <= "01000000";
elsif CS = "011" and RWn = '0' and RS = '0' then
CTRL_REG <= DATA_IN;
end if;
end if;
end process CONTROL;
P_DCD: process
P_DCD: process(CLK)
-- This process is some kind of tricky. Refer to the MC6850 data
-- sheet for more information.
variable READ_LOCK : boolean;
variable DCD_RELEASE : boolean;
begin
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;
if rising_edge(CLK) then
if RESETn = '0' then
DCD_FLAGn <= '0'; -- This interrupt source must initialise low.
READ_LOCK := true;
DCD_RELEASE := false;
elsif MCLR = '1' then
DCD_FLAGn <= DCD_In;
READ_LOCK := true;
elsif DCD_In = '1' then
DCD_FLAGn <= '1';
elsif CS = "011" and RWn = '1' and RS = '0' then
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
elsif CS = "011" and RWn = '1' and RS = '1' and READ_LOCK = false then
-- Clear if receiver status register read access.
-- After data register has ben read and READ_LOCK again.
DCD_RELEASE := true;
READ_LOCK := true;
DCD_FLAGn <= DCD_In;
elsif DCD_In = '0' and DCD_RELEASE = true then
DCD_FLAGn <= '0';
DCD_RELEASE := false;
end if;
end if;
end process P_DCD;
end architecture BEHAVIOR;

View File

@@ -67,7 +67,7 @@ use ieee.std_logic_unsigned.all;
entity WF6850IP_CTRL_STATUS is
port (
CLK : in bit;
CLK : in std_logic;
RESETn : in bit;
CS : in bit_vector(2 downto 0); -- Active if "011".
@@ -94,7 +94,7 @@ entity WF6850IP_CTRL_STATUS is
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.
IRQn : buffer bit -- Interrupt request.
);
end entity WF6850IP_CTRL_STATUS;
@@ -102,19 +102,14 @@ 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;
CTS_In <= CTSn;
DCD_In <= DCDn; -- immer 0
STATUS_REG(7) <= IRQ_I;
STATUS_REG(7) <= not IRQn;
STATUS_REG(6) <= PE;
STATUS_REG(5) <= OVR;
STATUS_REG(4) <= FE;
@@ -123,8 +118,8 @@ begin
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';
DATA_OUT <= STATUS_REG when CS = "011" and RWn = '1' and RS = '0' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '0' else '0';
MCLR <= '1' when CTRL_REG(1 downto 0) = "11" else '0';
RTSn <= '0' when CTRL_REG(6 downto 5) /= "10" else '1';
@@ -134,110 +129,85 @@ begin
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.
P_IRQ: process(CLK)
variable irq_v : std_logic_vector(3 downto 0);
begin
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
irq_v := x"0";
IRQn <= '1';
else
-- Transmitter interrupt:
if TDRE = '1' and CTRL_REG(6 downto 5) = "01" then
if irq_v = x"F" then
irq_v := irq_v + 1;
end if;
-- Receiver interrupts:
elsif RDRF = '1' and RIE = '1' then
if irq_v < 15 then
irq_v := irq_v + 1;
end if;
-- Overrun
elsif OVR = '1' and RIE = '1' then
if irq_v < 15 then
irq_v := irq_v + 1;
end if;
else
if irq_v > 0 then
irq_v := irq_v - 1;
end if;
end if;
if irq_v < 8 then
IRQn <= '1';
else
IRQn <= '0';
end if;
-- The reset of the IRQ status flag:
-- Clear by writing to the transmit data register.
-- Clear by reading the receive data register.
end if;
end if;
-- 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
CONTROL: process(CLK)
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;
if rising_edge(CLK) then
if RESETn = '0' then
CTRL_REG <= "01000000";
elsif CS = "011" and RWn = '0' and RS = '0' then
CTRL_REG <= DATA_IN;
end if;
end if;
end process CONTROL;
P_DCD: process
P_DCD: process(CLK)
-- This process is some kind of tricky. Refer to the MC6850 data
-- sheet for more information.
variable READ_LOCK : boolean;
variable DCD_RELEASE : boolean;
begin
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;
if rising_edge(CLK) then
if RESETn = '0' then
DCD_FLAGn <= '0'; -- This interrupt source must initialise low.
READ_LOCK := true;
DCD_RELEASE := false;
elsif MCLR = '1' then
DCD_FLAGn <= DCD_In;
READ_LOCK := true;
elsif DCD_In = '1' then
DCD_FLAGn <= '1';
elsif CS = "011" and RWn = '1' and RS = '0' then
READ_LOCK := false; -- Un-READ_LOCK if receiver data register is read.
elsif CS = "011" and RWn = '1' and RS = '1' and READ_LOCK = false then
-- Clear if receiver status register read access.
-- After data register has ben read and READ_LOCK again.
DCD_RELEASE := true;
READ_LOCK := true;
DCD_FLAGn <= DCD_In;
elsif DCD_In = '0' and DCD_RELEASE = true then
DCD_FLAGn <= '0';
DCD_RELEASE := false;
end if;
end if;
end process P_DCD;
end architecture BEHAVIOR;

View File

@@ -0,0 +1,419 @@
----------------------------------------------------------------------
---- ----
---- 6850 compatible IP Core ----
---- ----
---- This file is part of the SUSKA ATARI clone project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- UART 6850 compatible IP core ----
---- ----
---- 6850's receiver unit. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF6850IP_RECEIVE is
port (
CLK : in bit;
RESETn : in bit;
MCLR : in bit;
CS : in bit_vector(2 downto 0);
E : in bit;
RWn : in bit;
RS : in bit;
DATA_OUT : out bit_vector(7 downto 0);
DATA_EN : out bit;
WS : in bit_vector(2 downto 0);
CDS : in bit_vector(1 downto 0);
RXCLK : in bit;
RXDATA : in bit;
RDRF : buffer bit;
OVR : out bit;
PE : out bit;
FE : out bit
);
end entity WF6850IP_RECEIVE;
architecture BEHAVIOR of WF6850IP_RECEIVE is
type RCV_STATES is (IDLE, WAIT_START, SAMPLE, PARITY, STOP1, STOP2, SYNC);
signal RCV_STATE, RCV_NEXT_STATE : RCV_STATES;
signal RXDATA_I : bit;
signal RXDATA_S : bit;
signal DATA_REG : bit_vector(7 downto 0);
signal SHIFT_REG : bit_vector(7 downto 0);
signal CLK_STRB : bit;
signal BITCNT : std_logic_vector(2 downto 0);
begin
P_SAMPLE: process
-- This filter provides a synchronisation to the system
-- clock, even for random baud rates of the received data
-- stream.
variable FLT_TMP : integer range 0 to 2;
begin
wait until CLK = '1' and CLK' event;
--
RXDATA_I <= RXDATA;
--
if RXDATA_I = '1' and FLT_TMP < 2 then
FLT_TMP := FLT_TMP + 1;
elsif RXDATA_I = '1' then
RXDATA_S <= '1';
elsif RXDATA_I = '0' and FLT_TMP > 0 then
FLT_TMP := FLT_TMP - 1;
elsif RXDATA_I = '0' then
RXDATA_S <= '0';
end if;
end process P_SAMPLE;
CLKDIV: process
variable CLK_LOCK : boolean;
variable STRB_LOCK : boolean;
variable CLK_DIVCNT : std_logic_vector(6 downto 0);
begin
wait until CLK = '1' and CLK' event;
if CDS = "00" then -- Divider off.
if RXCLK = '1' and STRB_LOCK = false then
CLK_STRB <= '1';
STRB_LOCK := true;
elsif RXCLK = '0' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif RCV_STATE = IDLE then
-- Preset the CLKDIV with the start delays.
if CDS = "01" then
CLK_DIVCNT := "0001000"; -- Half of div by 16 mode.
elsif CDS = "10" then
CLK_DIVCNT := "0100000"; -- Half of div by 64 mode.
end if;
CLK_STRB <= '0';
else
if CLK_DIVCNT > "0000000" and RXCLK = '1' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
--
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
DATA_REG <= x"00";
elsif RCV_STATE = SYNC and WS(2) = '0' and RDRF = '0' then -- 7 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= '0' & SHIFT_REG(7 downto 1);
elsif RCV_STATE = SYNC and WS(2) = '1' and RDRF = '0' then -- 8 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= SHIFT_REG;
end if;
end if;
end process DATAREG;
DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' and E = '1' else (others => '0');
DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' and E = '1' else '0';
SHIFTREG: process(RESETn, CLK)
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
SHIFT_REG <= x"00";
elsif RCV_STATE = SAMPLE and CLK_STRB = '1' then
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
begin
wait until CLK = '1' and CLK' event;
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif RCV_STATE /= SAMPLE then
BITCNT <= (others => '0');
end if;
end process P_BITCNT;
FRAME_ERR: process(RESETn, CLK)
-- This module detects a framing error
-- during stop bit 1 and stop bit 2.
variable FE_I: bit;
begin
if RESETn = '0' then
FE_I := '0';
FE <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
FE_I := '0';
FE <= '0';
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP2 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
FE_I := '0'; -- Error resets when correct data appears.
end if;
end if;
if RCV_STATE = SYNC then
FE <= FE_I; -- Update the FE every SYNC time.
end if;
end if;
end process FRAME_ERR;
OVERRUN: process(RESETn, CLK)
variable OVR_I : bit;
variable FIRST_READ : boolean;
begin
if RESETn = '0' then
OVR_I := '0';
OVR <= '0';
FIRST_READ := false;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
OVR_I := '0';
OVR <= '0';
FIRST_READ := false;
elsif CLK_STRB = '1' and RCV_STATE = STOP1 then
-- Overrun appears if RDRF is '1' in this state.
OVR_I := RDRF;
end if;
if CS = "011" and RWn = '1' and RS = '1' then
-- If an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OVR_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
if OVR_I = '1' then
OVR <= '1';
OVR_I := '0';
FIRST_READ := true;
else
OVR <= '0';
end if;
end if;
else
FIRST_READ := false;
end if;
end if;
end process OVERRUN;
PARITY_TEST: process(RESETn, CLK)
variable PAR_TMP : bit;
variable PE_I : bit;
begin
if RESETn = '0' then
PE <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
PE <= '0';
elsif CLK_STRB = '1' then -- Sample parity on clock strobe.
PE_I := '0'; -- Initialise.
if RCV_STATE = PARITY then
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if WS = "000" or WS = "010" or WS = "110" then -- Even parity.
PE_I := PAR_TMP xor RXDATA_S;
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
PE_I := not PAR_TMP xor RXDATA_S;
else -- No parity for WS = "100" and WS = "101".
PE_I := '0';
end if;
end if;
end if;
-- Transmit the parity flag together with the data
-- In other words: no parity to the status register
-- when RDRF inhibits the data transfer to the
-- receiver data register.
if RCV_STATE = SYNC and RDRF = '0' then
PE <= PE_I;
elsif CS = "011" and RWn = '1' and RS = '1' then
PE <= '0'; -- Clear when reading the data register.
end if;
end if;
end process PARITY_TEST;
P_RDRF: process(RESETn, CLK)
-- Receive data register full flag.
begin
if RESETn = '0' then
RDRF <= '0';
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RDRF <= '0';
elsif RCV_STATE = SYNC then
RDRF <= '1'; -- Data register is full until now!
elsif CS = "011" and RWn = '1' and RS = '1' then
RDRF <= '0'; -- After reading the data register ...
end if;
end if;
end process P_RDRF;
RCV_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
RCV_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
end if;
end if;
end process RCV_STATEREG;
RCV_STATEDEC: process(RCV_STATE, RXDATA_S, CDS, WS, BITCNT, CLK_STRB)
begin
case RCV_STATE is
when IDLE =>
if RXDATA_S = '0' and CDS = "00" then
RCV_NEXT_STATE <= SAMPLE; -- Startbit detected in div by 1 mode.
elsif RXDATA_S = '0' and CDS = "01" then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 16 mode.
elsif RXDATA_S = '0' and CDS = "10" then
RCV_NEXT_STATE <= WAIT_START; -- Startbit detected in div by 64 mode.
else
RCV_NEXT_STATE <= IDLE; -- No startbit; sleep well :-)
end if;
when WAIT_START =>
if CLK_STRB = '1' then
if RXDATA_S = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Start condition in no div by 1 modes.
else
RCV_NEXT_STATE <= IDLE; -- No valid start condition, go back.
end if;
else
RCV_NEXT_STATE <= WAIT_START; -- Stay.
end if;
when SAMPLE =>
if CLK_STRB = '1' then
if BITCNT < "110" and WS(2) = '0' then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 7 data bits.
elsif BITCNT < "111" and WS(2) = '1' then
RCV_NEXT_STATE <= SAMPLE; -- Go on sampling 8 data bits.
elsif WS = "100" or WS = "101" then
RCV_NEXT_STATE <= STOP1; -- No parity check enabled.
else
RCV_NEXT_STATE <= PARITY; -- Parity enabled.
end if;
else
RCV_NEXT_STATE <= SAMPLE; -- Stay in sample mode.
end if;
when PARITY =>
if CLK_STRB = '1' then
RCV_NEXT_STATE <= STOP1;
else
RCV_NEXT_STATE <= PARITY;
end if;
when STOP1 =>
if CLK_STRB = '1' then
if RXDATA_S = '0' then
RCV_NEXT_STATE <= SYNC; -- Framing error detected.
elsif WS = "000" or WS = "001" or WS = "100" then
RCV_NEXT_STATE <= STOP2; -- Two stop bits selected.
else
RCV_NEXT_STATE <= SYNC; -- One stop bit selected.
end if;
else
RCV_NEXT_STATE <= STOP1;
end if;
when STOP2 =>
if CLK_STRB = '1' then
RCV_NEXT_STATE <= SYNC;
else
RCV_NEXT_STATE <= STOP2;
end if;
when SYNC =>
RCV_NEXT_STATE <= IDLE;
end case;
end process RCV_STATEDEC;
end architecture BEHAVIOR;

View File

@@ -60,7 +60,7 @@ use ieee.std_logic_unsigned.all;
entity WF6850IP_RECEIVE is
port (
CLK : in bit;
CLK : in std_logic;
RESETn : in bit;
MCLR : in bit;
@@ -95,124 +95,127 @@ signal SHIFT_REG : bit_vector(7 downto 0);
signal CLK_STRB : bit;
signal BITCNT : std_logic_vector(2 downto 0);
begin
P_SAMPLE: process
P_SAMPLE: process(CLK)
-- This filter provides a synchronisation to the system
-- clock, even for random baud rates of the received data
-- stream.
variable FLT_TMP : integer range 0 to 2;
begin
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';
if rising_edge(CLK) then
--
RXDATA_I <= RXDATA;
--
if RXDATA_I = '1' and FLT_TMP < 2 then
FLT_TMP := FLT_TMP + 1;
elsif RXDATA_I = '1' then
RXDATA_S <= '1';
elsif RXDATA_I = '0' and FLT_TMP > 0 then
FLT_TMP := FLT_TMP - 1;
elsif RXDATA_I = '0' then
RXDATA_S <= '0';
end if;
end if;
end process P_SAMPLE;
CLKDIV: process
CLKDIV: process(CLK)
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;
if rising_edge(CLK) then
if CDS = "00" then -- Divider off.
if RXCLK = '1' and STRB_LOCK = false then
CLK_STRB <= '1';
STRB_LOCK := true;
elsif RXCLK = '0' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif 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';
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;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
if CLK_DIVCNT > "0000000" and RXCLK = '1' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
--
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
if RESETn = '0' or MCLR = '1' 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;
else
if rising_edge(CLK) then
if RCV_STATE = SYNC and WS(2) = '0' and RDRF = '0' then -- 7 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= '0' & SHIFT_REG(7 downto 1);
elsif RCV_STATE = SYNC and WS(2) = '1' and RDRF = '0' then -- 8 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= SHIFT_REG;
end if;
end if;
end if;
end process DATAREG;
DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' 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.
if RESETn = '0' or MCLR = '1' then
SHIFT_REG <= x"00";
else
if rising_edge(CLK) then
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
P_BITCNT: process(CLK)
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');
if rising_edge(CLK) then
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif RCV_STATE /= SAMPLE then
BITCNT <= (others => '0');
end if;
end if;
end process P_BITCNT;
@@ -224,84 +227,88 @@ 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.
else
if rising_edge(CLK) then
if MCLR = '1' then
FE_I := '0';
FE <= '0';
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP2 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
FE_I := '0'; -- Error resets when correct data appears.
end if;
end if;
if RCV_STATE = SYNC then
FE <= FE_I; -- Update the FE every SYNC time.
end if;
end if;
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 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
if rising_edge(CLK) then
if RESETn = '0' or 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
else
if CLK_STRB = '1' and RCV_STATE = STOP1 then
-- Overrun appears if RDRF is '1' in this state.
OVR_I := RDRF;
end if;
if CS = "011" and RWn = '1' and RS = '1' then
-- If an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OVR_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OVR <= '1';
FIRST_READ := true;
else
OVR <= '0';
FIRST_READ := false;
end if;
if FIRST_READ = false then
if OVR_I = '1' then
OVR <= '1';
OVR_I := '0';
FIRST_READ := true;
else
OVR <= '0';
end if;
end if;
else
FIRST_READ := false;
end if;
end if;
end if;
end process OVERRUN;
PARITY_TEST: process(RESETn, CLK)
PARITY_TEST: process(RESETn,MCLR,CLK)
variable PAR_TMP : bit;
variable PE_I : bit;
begin
if RESETn = '0' then
if RESETn = '0' or MCLR = '1' 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';
else
if rising_edge(CLK) then
if CLK_STRB = '1' then -- Sample parity on clock strobe.
PE_I := '0'; -- Initialise.
if RCV_STATE = PARITY then
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if WS = "000" or WS = "010" or WS = "110" then -- Even parity.
PE_I := PAR_TMP xor RXDATA_S;
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
PE_I := not PAR_TMP xor RXDATA_S;
else -- No parity for WS = "100" and WS = "101".
PE_I := '0';
end if;
end if;
end if;
end if;
@@ -311,7 +318,7 @@ begin
-- 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
elsif CS = "011" and RWn = '1' and RS = '1' then
PE <= '0'; -- Clear when reading the data register.
end if;
end if;
@@ -320,28 +327,31 @@ begin
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;
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
RDRF <= '0';
else
if RCV_STATE = SYNC then
RDRF <= '1'; -- Data register is full until now!
end if;
if CS = "011" and RWn = '1' and RS = '1' then
RDRF <= '0'; -- when reading the data register ...
end if;
end if;
end if;
end process P_RDRF;
RCV_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
RCV_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
else
if rising_edge(CLK) then
if MCLR = '1' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
end if;
end if;
end if;
end process RCV_STATEREG;

View File

@@ -19,7 +19,7 @@
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2006 Wolfgang Foerster ----
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
@@ -48,8 +48,10 @@
--
-- Revision 2K6A 2006/06/03 WF
-- Initial Release.
-- Revision 2K6B 2006/11/07 WF
-- Revision 2K6B 2006/11/07 WF
-- Modified Source to compile with the Xilinx ISE.
-- Revision 2K8A 2008/07/14 WF
-- Minor changes.
--
library ieee;
@@ -58,7 +60,7 @@ use ieee.std_logic_unsigned.all;
entity WF6850IP_RECEIVE is
port (
CLK : in bit;
CLK : in std_logic;
RESETn : in bit;
MCLR : in bit;
@@ -93,126 +95,127 @@ signal SHIFT_REG : bit_vector(7 downto 0);
signal CLK_STRB : bit;
signal BITCNT : std_logic_vector(2 downto 0);
begin
P_SAMPLE: process
P_SAMPLE: process(CLK)
-- This filter provides a synchronisation to the system
-- clock, even for random baud rates of the received data
-- stream.
variable FLT_TMP : integer range 0 to 2;
begin
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';
if rising_edge(CLK) then
--
RXDATA_I <= RXDATA;
--
if RXDATA_I = '1' and FLT_TMP < 2 then
FLT_TMP := FLT_TMP + 1;
elsif RXDATA_I = '1' then
RXDATA_S <= '1';
elsif RXDATA_I = '0' and FLT_TMP > 0 then
FLT_TMP := FLT_TMP - 1;
elsif RXDATA_I = '0' then
RXDATA_S <= '0';
end if;
end if;
end process P_SAMPLE;
CLKDIV: process
CLKDIV: process(CLK)
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;
if rising_edge(CLK) then
if CDS = "00" then -- Divider off.
if RXCLK = '1' and STRB_LOCK = false then
CLK_STRB <= '1';
STRB_LOCK := true;
elsif RXCLK = '0' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif 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';
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;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
if CLK_DIVCNT > "0000000" and RXCLK = '1' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
--
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif RXCLK = '0' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end if;
end process CLKDIV;
DATAREG: process(RESETn, CLK)
begin
if RESETn = '0' then
if RESETn = '0' or MCLR = '1' 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;
else
if rising_edge(CLK) then
if RCV_STATE = SYNC and WS(2) = '0' and RDRF = '0' then -- 7 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= '0' & SHIFT_REG(7 downto 1);
elsif RCV_STATE = SYNC and WS(2) = '1' and RDRF = '0' then -- 8 bit data.
-- Transfer from shift- to data register only if
-- data register is empty (RDRF = '0').
DATA_REG <= SHIFT_REG;
end if;
end if;
end if;
end process DATAREG;
--DATA_OUT <= DATA_REG when CS = "011" and RWn = '1' and RS = '1' 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';
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.
if RESETn = '0' or MCLR = '1' then
SHIFT_REG <= x"00";
else
if rising_edge(CLK) then
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
SHIFT_REG <= RXDATA_S & SHIFT_REG(7 downto 1); -- Shift right.
end if;
end if;
end if;
end process SHIFTREG;
P_BITCNT: process
P_BITCNT: process(CLK)
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');
if rising_edge(CLK) then
if RCV_STATE = SAMPLE and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif RCV_STATE /= SAMPLE then
BITCNT <= (others => '0');
end if;
end if;
end process P_BITCNT;
@@ -224,84 +227,88 @@ DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' else '0';
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.
else
if rising_edge(CLK) then
if MCLR = '1' then
FE_I := '0';
FE <= '0';
elsif CLK_STRB = '1' then
if RCV_STATE = STOP1 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP2 and RXDATA_S = '0' then
FE_I := '1';
elsif RCV_STATE = STOP1 or RCV_STATE = STOP2 then
FE_I := '0'; -- Error resets when correct data appears.
end if;
end if;
if RCV_STATE = SYNC then
FE <= FE_I; -- Update the FE every SYNC time.
end if;
end if;
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 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
if rising_edge(CLK) then
if RESETn = '0' or 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
else
if CLK_STRB = '1' and RCV_STATE = STOP1 then
-- Overrun appears if RDRF is '1' in this state.
OVR_I := RDRF;
end if;
if CS = "011" and RWn = '1' and RS = '1' then
-- If an overrun was detected, the concerning flag is
-- set when the valid data word in the receiver data
-- register is read. Thereafter the RDRF flag is reset
-- and the overrun disappears (OVR_I goes low) after
-- a second read (in time) of the receiver data register.
if FIRST_READ = false then
OVR <= '1';
FIRST_READ := true;
else
OVR <= '0';
FIRST_READ := false;
end if;
if FIRST_READ = false then
if OVR_I = '1' then
OVR <= '1';
OVR_I := '0';
FIRST_READ := true;
else
OVR <= '0';
end if;
end if;
else
FIRST_READ := false;
end if;
end if;
end if;
end process OVERRUN;
PARITY_TEST: process(RESETn, CLK)
PARITY_TEST: process(RESETn,MCLR,CLK)
variable PAR_TMP : bit;
variable PE_I : bit;
begin
if RESETn = '0' then
if RESETn = '0' or MCRL = '1' 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';
else
if rising_edge(CLK) then
if CLK_STRB = '1' then -- Sample parity on clock strobe.
PE_I := '0'; -- Initialise.
if RCV_STATE = PARITY then
for i in 1 to 7 loop
if i = 1 then
PAR_TMP := SHIFT_REG(i-1) xor SHIFT_REG(i);
else
PAR_TMP := PAR_TMP xor SHIFT_REG(i);
end if;
end loop;
if WS = "000" or WS = "010" or WS = "110" then -- Even parity.
PE_I := PAR_TMP xor RXDATA_S;
elsif WS = "001" or WS = "011" or WS = "111" then -- Odd parity.
PE_I := not PAR_TMP xor RXDATA_S;
else -- No parity for WS = "100" and WS = "101".
PE_I := '0';
end if;
end if;
end if;
end if;
@@ -311,7 +318,7 @@ DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' else '0';
-- 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
elsif CS = "011" and RWn = '1' and RS = '1' then
PE <= '0'; -- Clear when reading the data register.
end if;
end if;
@@ -320,28 +327,31 @@ DATA_EN <= '1' when CS = "011" and RWn = '1' and RS = '1' else '0';
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;
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
RDRF <= '0';
else
if RCV_STATE = SYNC then
RDRF <= '1'; -- Data register is full until now!
end if;
if CS = "011" and RWn = '1' and RS = '1' then
RDRF <= '0'; -- when reading the data register ...
end if;
end if;
end if;
end process P_RDRF;
RCV_STATEREG: process(RESETn, CLK)
begin
if RESETn = '0' then
RCV_STATE <= IDLE;
elsif CLK = '1' and CLK' event then
if MCLR = '1' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
else
if rising_edge(CLK) then
if MCLR = '1' then
RCV_STATE <= IDLE;
else
RCV_STATE <= RCV_NEXT_STATE;
end if;
end if;
end if;
end process RCV_STATEREG;

View File

@@ -63,7 +63,7 @@ use ieee.std_logic_unsigned.all;
entity WF6850IP_TRANSMIT is
port (
CLK : in bit;
CLK : in std_logic;
RESETn : in bit;
MCLR : in bit;
@@ -108,58 +108,59 @@ begin
'1' when TR_STATE = STOP1 else
'1' when TR_STATE = STOP2 else '1';
CLKDIV: process
CLKDIV: process(CLK)
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;
if rising_edge(CLK) then
if CDS = "00" then -- divider off
if TXCLK = '0' and STRB_LOCK = false then -- Works on negative TXCLK edge.
CLK_STRB <= '1';
STRB_LOCK := true;
elsif TXCLK = '1' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif 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';
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;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
-- Works on negative TXCLK edge:
if CLK_DIVCNT > "0000000" and TXCLK = '0' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end if;
end process CLKDIV;
@@ -168,7 +169,7 @@ begin
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
elsif rising_edge(CLK) then
if MCLR = '1' then
DATA_REG <= x"00";
elsif WS(2) = '0' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
@@ -183,7 +184,7 @@ begin
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
elsif rising_edge(CLK) then
if MCLR = '1' then
SHIFT_REG <= x"00";
elsif TR_STATE = LOAD_SHFT and TDRE = '0' then
@@ -198,47 +199,42 @@ begin
end if;
end process SHIFTREG;
P_BITCNT: process
P_BITCNT: process(CLK)
-- 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";
if rising_edge(CLK) then
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end if;
end process P_BITCNT;
P_TDRE: process(RESETn, CLK)
-- Transmit data register empty flag.
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
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
TDRE <= '1';
else
if TR_NEXT_STATE = START and TR_STATE /= START then
-- Data has been loaded to shift register, thus data register is free again.
-- Thanks to Lyndon Amsdon for finding a bug here. The TDRE is set to one once
-- entering the state now.
TDRE <= '1';
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;
-- entering the state now.
TDRE <= '1';
end if;
if CS = "011" and RWn = '0' and RS = '1' then
TDRE <= '0';
end if;
end if;
end if;
end process P_TDRE;
PARITY_GEN: process
PARITY_GEN: process(CLK)
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if rising_edge(CLK) then
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
@@ -254,6 +250,7 @@ begin
else -- No parity for WS = "100" and WS = "101".
PARITY_I <= '0';
end if;
end if;
end if;
end process PARITY_GEN;
@@ -261,11 +258,13 @@ begin
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;
else
if rising_edge(CLK) then
if MCLR = '1' then
TR_STATE <= IDLE;
else
TR_STATE <= TR_NEXT_STATE;
end if;
end if;
end if;
end process TR_STATEREG;

View File

@@ -63,7 +63,7 @@ use ieee.std_logic_unsigned.all;
entity WF6850IP_TRANSMIT is
port (
CLK : in bit;
CLK : in std_logic;
RESETn : in bit;
MCLR : in bit;
@@ -113,53 +113,54 @@ begin
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;
if rising_edge(CLK) then
if CDS = "00" then -- divider off
if TXCLK = '0' and STRB_LOCK = false then -- Works on negative TXCLK edge.
CLK_STRB <= '1';
STRB_LOCK := true;
elsif TXCLK = '1' then
CLK_STRB <= '0';
STRB_LOCK := false;
else
CLK_STRB <= '0';
end if;
elsif 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';
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;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
-- Works on negative TXCLK edge:
if CLK_DIVCNT > "0000000" and TXCLK = '0' and CLK_LOCK = false then
CLK_DIVCNT := CLK_DIVCNT - '1';
CLK_STRB <= '0';
CLK_LOCK := true;
elsif CDS = "01" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "0010000"; -- Div by 16 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif CDS = "10" and CLK_DIVCNT = "0000000" then
CLK_DIVCNT := "1000000"; -- Div by 64 mode.
if STRB_LOCK = false then
STRB_LOCK := true;
CLK_STRB <= '1';
else
CLK_STRB <= '0';
end if;
elsif TXCLK = '1' then
CLK_LOCK := false;
STRB_LOCK := false;
CLK_STRB <= '0';
else
CLK_STRB <= '0';
end if;
end if;
end if;
end process CLKDIV;
@@ -168,7 +169,7 @@ begin
begin
if RESETn = '0' then
DATA_REG <= x"00";
elsif CLK = '1' and CLK' event then
elsif rising_edge(CLK) then
if MCLR = '1' then
DATA_REG <= x"00";
elsif WS(2) = '0' and CS = "011" and RWn = '0' and RS = '1' and E = '1' then
@@ -183,7 +184,7 @@ begin
begin
if RESETn = '0' then
SHIFT_REG <= x"00";
elsif CLK = '1' and CLK' event then
elsif rising_edge(CLK) then
if MCLR = '1' then
SHIFT_REG <= x"00";
elsif TR_STATE = LOAD_SHFT and TDRE = '0' then
@@ -198,47 +199,42 @@ begin
end if;
end process SHIFTREG;
P_BITCNT: process
P_BITCNT: process(CLK)
-- 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";
if rising_edge(CLK) then
if TR_STATE = SHIFTOUT and CLK_STRB = '1' then
BITCNT <= BITCNT + '1';
elsif TR_STATE /= SHIFTOUT then
BITCNT <= "000";
end if;
end if;
end process P_BITCNT;
P_TDRE: process(RESETn, CLK)
-- Transmit data register empty flag.
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
if rising_edge(CLK) then
if RESETn = '0' or MCLR = '1' then
TDRE <= '1';
else
if TR_NEXT_STATE = START and TR_STATE /= START then
-- Data has been loaded to shift register, thus data register is free again.
-- Thanks to Lyndon Amsdon for finding a bug here. The TDRE is set to one once
-- entering the state now.
TDRE <= '1';
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;
-- entering the state now.
TDRE <= '1';
end if;
if CS = "011" and RWn = '0' and RS = '1' then
TDRE <= '0';
end if;
end if;
end if;
end process P_TDRE;
PARITY_GEN: process
PARITY_GEN: process(CLK)
variable PAR_TMP : bit;
begin
wait until CLK = '1' and CLK' event;
if rising_edge(CLK) then
if TR_STATE = START then -- Calculate the parity during the start phase.
for i in 1 to 7 loop
if i = 1 then
@@ -254,6 +250,7 @@ begin
else -- No parity for WS = "100" and WS = "101".
PARITY_I <= '0';
end if;
end if;
end if;
end process PARITY_GEN;
@@ -261,11 +258,13 @@ begin
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;
else
if rising_edge(CLK) then
if MCLR = '1' then
TR_STATE <= IDLE;
else
TR_STATE <= TR_NEXT_STATE;
end if;
end if;
end if;
end process TR_STATEREG;