Sync with Fredi's source tree 13/06/2015
Parallel port fix.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user