This commit is contained in:
253
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_am_detector.vhd
Normal file
253
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_am_detector.vhd
Normal file
@@ -0,0 +1,253 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- Address mark detector file. This part detects the address ----
|
||||
---- mark in the incoming data stream in FM and also in MFM mode ----
|
||||
---- and provides therewith synchronisation information for the ----
|
||||
---- control state machine and for the data separator in the ----
|
||||
---- transceiver unit. ----
|
||||
---- ----
|
||||
------------------------------- Some theory -------------------------------------
|
||||
---- Frequency modulation FM: ----
|
||||
---- The frequency modulation works as follows: ----
|
||||
---- 1. every first pulse of the clock and data line is a clock. ----
|
||||
---- 2. every second pulse is a data. ----
|
||||
---- 3. a logic 1 is represented by two consecutive pulses (clock and data). ----
|
||||
---- 4. a logic 0 is represented by one clock pulse and no data pulse. ----
|
||||
---- 5. Hence there are a maximum of two pulses per data bit. ----
|
||||
---- 6. one clock and one data pulse come together in one bit cell. ----
|
||||
---- 7. the duration of a bit cell in FM is 4 microseconds. ----
|
||||
---- 8. an ID address mark is represented as data FE with clock C7. ----
|
||||
---- 9. a DATA address mark is represented as data FB with clock C7. ----
|
||||
---- Examples: ----
|
||||
---- Binary data 1 1 0 0 1 0 1 1 is represented in FM as follows: ----
|
||||
---- 1111101011101111 ----
|
||||
---- the FE data 1 1 1 1 1 1 1 0 is represented as follows: ----
|
||||
---- 1111111111111110 ----
|
||||
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
|
||||
---- results: 1111010101111110 this is the ID address mark. ----
|
||||
---- the FB data 1 1 1 1 1 0 1 1 is represented as follows: ----
|
||||
---- 1111111111101111 ----
|
||||
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
|
||||
---- results: 1111010101101111 this is the DATA address mark. ----
|
||||
---- the F8 data 1 1 1 1 1 0 0 0 is represented as follows: ----
|
||||
---- 1111111111101010 ----
|
||||
---- with C7 clock mask 1 1 0 0 0 1 1 1 which masks the clock pulses there ----
|
||||
---- results: 1111010101101010 this is the deleted DATA mark. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- Modified frequency modulation MFM: ----
|
||||
---- The modified frequency modulation works as follows: ----
|
||||
---- 1. every first pulse of the clock and data line is a clock. ----
|
||||
---- 2. every second pulse is a data. ----
|
||||
---- 3. a logic 1 is represented by no clock but a data pulse. ----
|
||||
---- 4. a logic 0 is represented by a clock pulse and no data pulse if ----
|
||||
---- following a 0. ----
|
||||
---- 5. a logic 0 is represented by no pulse if following a 1. ----
|
||||
---- 6. Hence there are a maximum of one pulse per data bit. ----
|
||||
---- 7. one clock and one data pulse form together one bit cell. ----
|
||||
---- 8. the duration of a bit cell in MFM is 2 microseconds. ----
|
||||
---- 9. an address mark sync is represented as data A1 with missing clock ----
|
||||
---- pulse between bit 4 and 5. ----
|
||||
---- Examples: ----
|
||||
---- Binary data FE 1 1 1 1 1 1 1 0 is represented in MFM as follows: ----
|
||||
---- 0101010101010100 this is the ID address mark. ----
|
||||
---- Binary data FB 1 1 1 1 1 0 1 1 is represented in MFM as follows: ----
|
||||
---- 0101010101000101 this is the DATA address mark. ----
|
||||
---- Binary data F8 1 1 1 1 1 0 0 0 is represented in MFM as follows: ----
|
||||
---- 0101010101001010 this is the deleted DATA address mark. ----
|
||||
---- the A1 data 1 0 1 0 0 0 0 1 is represented as follows: ----
|
||||
---- 0100010010101001 ----
|
||||
---- with the missing clock pulse between bits 4 and 5 there results: ----
|
||||
---- results: 0100010010001001 this is the address mark sync. ----
|
||||
---- ----
|
||||
---- Both MFM and FM are during read and write shifted with most significant ----
|
||||
---- bit (MSB) first. During the FM address marks are written without a ----
|
||||
---- SYNC pulse the MFM coded data requires a synchronisation (A1 with ----
|
||||
---- missing clock pulse because at the beginning of the data stream it is ----
|
||||
---- not defined wether a clock pulse or a data pulse appears first. In FM ----
|
||||
---- coding the first pulse is in any case a clock pulse. ----
|
||||
---------------------------------------------------------------------------------
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF1772IP_AM_DETECTOR is
|
||||
port(
|
||||
-- System control
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Controls:
|
||||
DDEn : in bit;
|
||||
|
||||
-- Serial data and clock:
|
||||
DATA : in bit;
|
||||
DATA_STRB : in bit;
|
||||
|
||||
-- Address mark detector:
|
||||
ID_AM : out bit; -- ID address mark strobe.
|
||||
DATA_AM : out bit; -- Data address mark strobe.
|
||||
DDATA_AM : out bit -- Deleted data address mark strobe.
|
||||
);
|
||||
end WF1772IP_AM_DETECTOR;
|
||||
|
||||
architecture BEHAVIOR of WF1772IP_AM_DETECTOR is
|
||||
signal SHIFT : bit_vector(15 downto 0);
|
||||
signal SYNC : boolean;
|
||||
signal ID_AM_I : bit;
|
||||
signal DATA_AM_I : bit;
|
||||
signal DDATA_AM_I : bit;
|
||||
begin
|
||||
SHIFTREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SHIFT <= (others => '0');
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DATA_STRB = '1' then
|
||||
-- MSB first leads to a shift left operation.
|
||||
SHIFT <= SHIFT(14 downto 0) & DATA;
|
||||
elsif DDEn = '0' and SHIFT = "0100010010001001" then -- This is the synchronisation in MFM.
|
||||
SHIFT <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process SHIFTREG;
|
||||
|
||||
MFM_SYNCLOCK: process(RESETn, CLK)
|
||||
-- The SYNC pulse is generated in MFM mode only when the sync character
|
||||
-- appears in the shift register (A1 sync mark, see file header).
|
||||
-- After the sync character is detected, the sync time counter is loaded
|
||||
-- with a value of 17. During counting the following 17 read clock pulses
|
||||
-- down, the SYNC is true. After exactly 16 pulses the address mark is
|
||||
-- detected if the pattern in the shift register fits one of the address
|
||||
-- marks. The address mark pulses are valid for one read clock cycle until
|
||||
-- SYNC goes low again. This mechanism is used to detect the correct address
|
||||
-- marks in the MFM data stream during the type III read track command.
|
||||
-- This is an improvement over the original WD1772 chip.
|
||||
variable TMP : std_logic_vector(4 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TMP := "00000";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if SHIFT = "0100010010001001" and DDEn = '0' then
|
||||
TMP := "10001"; -- Load sync time counter.
|
||||
elsif DATA_STRB = '1' and TMP > "00000" then
|
||||
TMP := TMP - '1';
|
||||
end if;
|
||||
end if;
|
||||
case TMP is
|
||||
when "00000" => SYNC <= false;
|
||||
when others => SYNC <= true;
|
||||
end case;
|
||||
end process MFM_SYNCLOCK;
|
||||
|
||||
-- The addressmark is nominally valid for one data pulse cycle (1us, 2us, 4us).
|
||||
-- The pulse is shorter due to the fact that the detected address marks change the
|
||||
-- state of the control state machine and so clear the address mark shift register...
|
||||
ID_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101111110" else
|
||||
'1' when DDEn = '0' and SHIFT = "0101010101010100" and SYNC = true else '0';
|
||||
DATA_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101101111" else
|
||||
-- Normal data address mark...
|
||||
'1' when DDEn = '0' and SHIFT = "0101010101000101" and SYNC = true else '0';
|
||||
DDATA_AM_I <= '1' when DDEn = '1' and SHIFT = "1111010101101010" else
|
||||
-- ... and deleted address mark in MFM mode:
|
||||
'1' when DDEn = '0' and SHIFT = "0101010101001010" and SYNC = true else '0';
|
||||
|
||||
ADRMARK_STROBES: process(RESETn, CLK)
|
||||
-- ... nevertheless The controller and the transceiver require ID address mark strobes
|
||||
-- and DATA address mark strobes. Therefore this process provides these strobe
|
||||
-- signals independant of any 'feedbacks' like pulse shortening by the controller
|
||||
-- state machine itself.
|
||||
variable ID_AM_LOCK, DATA_AM_LOCK, DDATA_AM_LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
ID_AM_LOCK := false;
|
||||
DATA_AM_LOCK := false;
|
||||
ID_AM <= '0';
|
||||
DATA_AM <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
-- ID address mark:
|
||||
if ID_AM_I = '1' and ID_AM_LOCK = false then
|
||||
ID_AM <= '1';
|
||||
ID_AM_LOCK := true;
|
||||
elsif ID_AM_I = '0' then
|
||||
ID_AM <= '0';
|
||||
ID_AM_LOCK := false;
|
||||
else
|
||||
ID_AM <= '0';
|
||||
end if;
|
||||
-- Data address mark:
|
||||
if DATA_AM_I = '1' and DATA_AM_LOCK = false then
|
||||
DATA_AM <= '1';
|
||||
DATA_AM_LOCK := true;
|
||||
elsif DATA_AM_I = '0' then
|
||||
DATA_AM <= '0';
|
||||
DATA_AM_LOCK := false;
|
||||
else
|
||||
DATA_AM <= '0';
|
||||
end if;
|
||||
-- Deleted data address mark:
|
||||
if DDATA_AM_I = '1' and DDATA_AM_LOCK = false then
|
||||
DDATA_AM <= '1';
|
||||
DDATA_AM_LOCK := true;
|
||||
elsif DDATA_AM_I = '0' then
|
||||
DDATA_AM <= '0';
|
||||
DDATA_AM_LOCK := false;
|
||||
else
|
||||
DDATA_AM <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process ADRMARK_STROBES;
|
||||
end architecture BEHAVIOR;
|
||||
1463
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_control.vhd
Normal file
1463
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_control.vhd
Normal file
File diff suppressed because it is too large
Load Diff
162
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_crc_logic.vhd
Normal file
162
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_crc_logic.vhd
Normal file
@@ -0,0 +1,162 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- The CRC cyclic redundancy checker unit. Further description ----
|
||||
---- see below. ----
|
||||
---- ----
|
||||
---- Working principle of the CRC generator and verify unit: ----
|
||||
---- During read operation: ----
|
||||
---- The CRC generator is switched on via after the detection of ----
|
||||
---- the address ID of the data ID mark. The CRC generation last ----
|
||||
---- in case of the address ID until the lenght byte is read. ----
|
||||
---- In case of generation after the data address mark the CRC ----
|
||||
---- generator is activated until the last data byte is read. ----
|
||||
---- The number of data bytes to be read depends on the LENGHT ----
|
||||
---- information in the header file. After generation of the CRC ----
|
||||
---- the CRC_GEN is switched off and the VERIFY procedure begins ----
|
||||
---- by activating CRC_VERIFY. The previously generated CRC is ----
|
||||
---- then compared (serially) with the two consecutive read CRC ----
|
||||
---- bytes. The CRC error appeas, when the comparision fails. ----
|
||||
---- During write operation: ----
|
||||
---- The CRC generator is switched on via after the detection of ----
|
||||
---- the address ID of the data ID mark. The CRC generation last ----
|
||||
---- in case of the address ID until the lenght byte is read. ----
|
||||
---- In case of generation after the data address mark the CRC ----
|
||||
---- generator is activated until the last data byte is read. ----
|
||||
---- The number of data bytes to be read depends on the LENGHT ----
|
||||
---- information in the header file. After the generation of the ----
|
||||
---- two CRC bytes, the write out process begins by activating ----
|
||||
---- CRC_SHFTOUT. The CRC data appears in this case serially on ----
|
||||
---- the CRC_SDOUT. ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- CRC_SHIFT has now synchronous reset to meeet preset behaviour.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF1772IP_CRC_LOGIC is
|
||||
port(
|
||||
-- System control
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DISK_RWn : in bit;
|
||||
|
||||
-- Preset controls:
|
||||
DDEn : in bit;
|
||||
ID_AM : in bit;
|
||||
DATA_AM : in Bit;
|
||||
DDATA_AM : in Bit;
|
||||
|
||||
-- CRC unit:
|
||||
SD : in bit; -- Serial data input.
|
||||
CRC_STRB : in bit; -- Data strobe.
|
||||
CRC_2_DISK : in bit; -- Forces the unit to flush the CRC remainder.
|
||||
CRC_PRES : in bit; -- Presets the CRC unit during write to disk.
|
||||
CRC_SDOUT : out bit; -- Serial data output.
|
||||
CRC_ERR : out bit -- Indicates CRC error.
|
||||
);
|
||||
end WF1772IP_CRC_LOGIC;
|
||||
|
||||
architecture BEHAVIOR of WF1772IP_CRC_LOGIC is
|
||||
signal CRC_SHIFT : bit_vector(15 downto 0);
|
||||
begin
|
||||
P_CRC: process
|
||||
-- The shift register is initialised with appropriate values in HD or DD mode.
|
||||
-- In theory the shift register should be preset to ones. Due to a latency of one byte
|
||||
-- in FM mode or 4 bytes in MFM mode it is necessary to preset the shift register with
|
||||
-- the CRC values of this ID address mark, data address mark and the A1 sync bytes. The
|
||||
-- latency is caused by the addressmark detector which needs one or 4 byte time(s) for
|
||||
-- detection. The CRC unit therefore starts with every detection of an address mark and
|
||||
-- ends if the CRC unit is flushed.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RESETn = '0' then
|
||||
CRC_SHIFT <= (others => '1');
|
||||
elsif CRC_2_DISK = '1' then
|
||||
if CRC_STRB = '1' then
|
||||
CRC_SHIFT <= CRC_SHIFT(14 downto 0) & '0';
|
||||
end if;
|
||||
elsif CRC_PRES = '1' then -- Preset during write sector or write track command.
|
||||
CRC_SHIFT <= x"FFFF";
|
||||
elsif DDEn = '1' and ID_AM = '1' then -- DD mode and ID address mark detected.
|
||||
CRC_SHIFT <= x"EF21"; -- The CRC-CCITT for data x"FE" is x"EF21"
|
||||
elsif DDEn = '1' and DATA_AM = '1' then -- DD mode and data address mark detected.
|
||||
CRC_SHIFT <= x"BF84"; -- The CRC-CCITT for data x"FB" is x"BF84"
|
||||
elsif DDEn = '1' and DDATA_AM = '1' then -- DD mode and deleted data address mark detected.
|
||||
CRC_SHIFT <= x"8FE7"; -- The CRC-CCITT for data x"F8" is x"8FE7"
|
||||
elsif DDEn = '0' and ID_AM = '1' then -- HD mode and ID address mark detected.
|
||||
CRC_SHIFT <= x"B230"; -- The CRC-CCITT for data x"A1A1A1FE" is x"B230"
|
||||
elsif DDEn = '0' and DATA_AM = '1' then -- HD mode and data address mark detected.
|
||||
CRC_SHIFT <= x"E295"; -- The CRC-CCITT for data x"A1A1A1FB" is x"E295"
|
||||
elsif DDEn = '0' and DDATA_AM = '1' then -- HD mode and deleted data address mark detected.
|
||||
CRC_SHIFT <= x"D2F6"; -- The CRC-CCITT for data x"A1A1A1F8" is x"D2F6"
|
||||
elsif CRC_STRB = '1' then
|
||||
-- CRC-CCITT (xFFFF):
|
||||
-- the polynomial is G(x) = x^16 + x^12 + x^5 + 1
|
||||
-- In this mode the CRC is encoded. In read from disk mode, the encoding works as CRC
|
||||
-- verification. In this operating condition the ID or the data field is compared
|
||||
-- against the CRC checksum. if there are no errors, the shift register's value is
|
||||
-- x"0000" after the last bit of the checksum is shifted in. In write to disk mode the
|
||||
-- CRC linear feedback shift register (lfsr) works to generate the CRC remainder of the
|
||||
-- ID or data field.
|
||||
CRC_SHIFT <= CRC_SHIFT(14 downto 12) & (CRC_SHIFT(15) xor CRC_SHIFT(11) xor SD) &
|
||||
CRC_SHIFT(10 downto 5) & (CRC_SHIFT(15) xor CRC_SHIFT(4) xor SD) &
|
||||
CRC_SHIFT(3 downto 0) & (CRC_SHIFT(15) xor SD);
|
||||
end if;
|
||||
end process P_CRC;
|
||||
|
||||
CRC_SDOUT <= CRC_SHIFT(15);
|
||||
CRC_ERR <= '0' when CRC_SHIFT = x"0000" else '1';
|
||||
end architecture BEHAVIOR;
|
||||
426
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_digital_pll.vhd
Normal file
426
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_digital_pll.vhd
Normal file
@@ -0,0 +1,426 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- The digital PLL is responsible to detect the incoming serial ----
|
||||
---- data stream and provide a system clock synchronous signal ----
|
||||
---- containing the data and clock information. ----
|
||||
---- To understand how the code works in detail refer to the free ----
|
||||
---- US patent no. 4,780,844. ----
|
||||
---- ----
|
||||
---- Attention: The settings for TOP and BOTTOM, which control ----
|
||||
---- the PLL frequency and for PHASE_CORR which control the PLL ----
|
||||
---- phase are rather critical for a good read condition! To test ----
|
||||
---- the PLL in the WD1772 compatible core do the following: ----
|
||||
---- Sample on an oscilloscope on one channel the falling edge of ----
|
||||
---- the RDn pulse and on the other channel the PLL_DSTRB. The ----
|
||||
---- RDn must be located exactly between the PLL_DSTRB pulses. ----
|
||||
---- Otherwise, the parameters TOP, BOTTOM and PHASE_CORR have to ----
|
||||
---- be optimized. ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release: the MFM portion for HD and DD floppies is tested.
|
||||
-- The FM mode (DDEn = '1') is not completely tested due to lack of FM
|
||||
-- drives.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K7B 2006/12/29 WF
|
||||
-- Introduced several improvements based on a very good examination
|
||||
-- of the pll code by Jean Louis-Guerin.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K8B 2008/12/24 WF
|
||||
-- Improvement of the INPORT process.
|
||||
-- Bugfix of the FREQ_AMOUNT counter: now stops if its value is zero.
|
||||
-- Several changes concerning the PLL parameters to improve the
|
||||
-- stability of the PLL.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF1772IP_DIGITAL_PLL is
|
||||
generic(
|
||||
-- The valid range of the period counter of the PLL is given by the TOP and BOTTOM
|
||||
-- limits. The counter range is therefore BOTTOM <= counter value <= TOP.
|
||||
-- The generic PHASE_CORR is responsible fo the center setting of PLL_DSTRB concerning
|
||||
-- the RDn period.
|
||||
-- The nominal frequency setting is 128. So it is recommended to use TOP and BOTTOM
|
||||
-- settings symmetrically around 128. If TOP = BOTTOM = 128, the frequency control
|
||||
-- is disabled. TOP + PHASE_CORR may not exceed a value of 255. BOTTOM - PHASE_CORR
|
||||
-- may not drop below zero.
|
||||
TOP : integer range 0 to 255 := 152; -- +18.0%
|
||||
BOTTOM : integer range 0 to 255 := 104; -- -18.0%
|
||||
PHASE_CORR : integer range 0 to 128 := 75
|
||||
);
|
||||
port(
|
||||
-- System control
|
||||
CLK : in bit; -- 16MHz clock.
|
||||
RESETn : in bit;
|
||||
|
||||
-- Controls
|
||||
DDEn : in bit; -- Double density enable.
|
||||
HDTYPE : in bit; -- This control is '1' when HD disks are inserted.
|
||||
DISK_RWn : in bit; -- Read write control.
|
||||
|
||||
-- Data and clock lines
|
||||
RDn : in bit; -- Read signal from the disk.
|
||||
PLL_D : out bit; -- Synchronous read signal.
|
||||
PLL_DSTRB : out bit -- Read strobe.
|
||||
);
|
||||
end WF1772IP_DIGITAL_PLL;
|
||||
|
||||
architecture BEHAVIOR of WF1772IP_DIGITAL_PLL is
|
||||
signal RD_In : bit;
|
||||
signal UP, DOWN : bit;
|
||||
signal PHASE_DECREASE : bit;
|
||||
signal PHASE_INCREASE : bit;
|
||||
signal HI_STOP, LOW_STOP : bit;
|
||||
signal PER_CNT : std_logic_vector(7 downto 0);
|
||||
signal ADDER_IN : std_logic_vector(7 downto 0);
|
||||
signal ADDER_MSBs : bit_vector(2 downto 0);
|
||||
signal RD_PULSE : bit;
|
||||
signal ROLL_OVER : bit;
|
||||
signal HISTORY_REG : bit_vector(1 downto 0);
|
||||
signal ERROR_HISTORY : integer range 0 to 2;
|
||||
begin
|
||||
INPORT: process
|
||||
-- This process is necessary due to the poor quality of the rising
|
||||
-- edge of RDn. Let it work on the negative clock edge.
|
||||
begin
|
||||
wait until CLK = '0' and CLK' event;
|
||||
RD_In <= RDn;
|
||||
end process INPORT;
|
||||
|
||||
EDGEDETECT: process(RESETn, CLK)
|
||||
-- This process forms a falling edge detector for the incoming
|
||||
-- data read port. The output (RD_PULSE) goes high for exactly
|
||||
-- one clock period after the RDn is low and the positive
|
||||
-- clock edge is detected.
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
RD_PULSE <= '0';
|
||||
LOCK := false;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DISK_RWn = '0' then -- Disable detector in write mode.
|
||||
RD_PULSE <= '0';
|
||||
elsif RD_In = '0' and LOCK = false then
|
||||
RD_PULSE <= '1'; -- READ_PULSE is inverted against RDn
|
||||
LOCK := true;
|
||||
elsif RD_In = '1' then
|
||||
LOCK := false;
|
||||
RD_PULSE <= '0';
|
||||
else
|
||||
RD_PULSE <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process EDGEDETECT;
|
||||
|
||||
PERIOD_CNT: process(RESETn, CLK)
|
||||
-- This process provides the nominal variable added to the adder. To achieve a good
|
||||
-- settling time of the PLL in all cases, the period counter is controlled via the DDEn
|
||||
-- and HDTYPE flags respective to its added value. Be aware, that in case of adding "10"
|
||||
-- or "11", the TOP value may be exceeded or the period counter may drop below the BOTTOM
|
||||
-- value. The higher the value added, the faster will be the settling time of phase locked
|
||||
-- loop .
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
PER_CNT <= "10000000"; -- Initial value is 128.
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if UP = '1' then
|
||||
PER_CNT <= PER_CNT + '1';
|
||||
elsif DOWN = '1' then
|
||||
PER_CNT <= PER_CNT - '1';
|
||||
end if;
|
||||
end if;
|
||||
end process PERIOD_CNT;
|
||||
|
||||
HI_STOP <= '1' when PER_CNT >= TOP else '0';
|
||||
LOW_STOP <= '1' when PER_CNT <= BOTTOM else '0';
|
||||
|
||||
ADDER_IN <= -- This DISK_RWn = '0' implementation keeps the last phase information
|
||||
-- of the PLL in read from disk mode. It should be a good solution concer-
|
||||
-- ning alternative read write cycles.
|
||||
"10000000" when DISK_RWn = '0' else -- Nominal value for write to disk.
|
||||
PER_CNT + PHASE_CORR when PHASE_INCREASE = '1' else -- Phase lags.
|
||||
PER_CNT - PHASE_CORR when PHASE_DECREASE = '1' else -- Phase leeds.
|
||||
PER_CNT; -- No phase correction;
|
||||
|
||||
ADDER: process(RESETn, CLK, DDEn, HDTYPE)
|
||||
-- Clock adjustment: The clock cycle is 62.5ns for the 16MHz system clock.
|
||||
-- The offset (LSBs) of the adder input is chosen to be conform with the required
|
||||
-- rollover period in the different DDEn and HDTYPE modi as follows:
|
||||
-- With a nominal adder input term of 128:
|
||||
-- The adder rolls over every 4us for DDEn = 1 and HDTYPE = 0.
|
||||
-- The adder rolls over every 2us for DDEn = 1 and HDTYPE = 1.
|
||||
-- The adder rolls over every 2us for DDEn = 0 and HDTYPE = 0.
|
||||
-- The adder rolls over every 1us for DDEn = 0 and HDTYPE = 1.
|
||||
-- The given times are the half of a data period time in MFM or FM.
|
||||
variable ADDER_DATA : std_logic_vector(12 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
ADDER_DATA := (others => '0');
|
||||
elsif CLK = '1' and CLK' event then
|
||||
ADDER_DATA := ADDER_DATA + ADDER_IN;
|
||||
end if;
|
||||
--
|
||||
case DDEn & HDTYPE is
|
||||
when "01" => -- MFM mode using HD disks, results in 1us inspection period:
|
||||
ADDER_MSBs <= To_BitVector(ADDER_DATA(10 downto 8));
|
||||
when "00" => -- MFM mode using DD disks, results in 2us inspection period:
|
||||
ADDER_MSBs <= To_BitVector(ADDER_DATA(11 downto 9));
|
||||
when "11" => -- FM mode using HD disks, results in 2us inspection period:
|
||||
ADDER_MSBs <= To_BitVector(ADDER_DATA(11 downto 9));
|
||||
when "10" => -- FM mode using DD disks, results in 4us inspection period:
|
||||
ADDER_MSBs <= To_BitVector(ADDER_DATA(12 downto 10));
|
||||
end case;
|
||||
end process ADDER;
|
||||
|
||||
ROLLOVER: process(RESETn, CLK)
|
||||
-- This process forms a falling edge detector for the detection
|
||||
-- of the adder's rollover time. The output goes low for exactly
|
||||
-- one clock period after the rollover is detected and the positive
|
||||
-- clock edge appears.
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
ROLL_OVER <= '0';
|
||||
LOCK := false;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if ADDER_MSBs /= "111" and LOCK = false then
|
||||
ROLL_OVER <= '1';
|
||||
LOCK := true;
|
||||
elsif ADDER_MSBs = "111" then
|
||||
LOCK := false;
|
||||
ROLL_OVER <= '0';
|
||||
else
|
||||
ROLL_OVER <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process ROLLOVER;
|
||||
PLL_DSTRB <= ROLL_OVER;
|
||||
|
||||
DATA_FLIP_FLOP: process(RESETn, CLK, RD_PULSE)
|
||||
-- This flip-flop is responsible for 'catching' the read pulses of the
|
||||
-- serial data input.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
PLL_D <= '0'; -- Asynchronous reset.
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RD_PULSE = '1' then
|
||||
PLL_D <= '1'; -- Read pulse detected.
|
||||
elsif ROLL_OVER = '1' then
|
||||
PLL_D <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process DATA_FLIP_FLOP;
|
||||
|
||||
WIN_HISTORY: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
HISTORY_REG <= "00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RD_PULSE = '1' then
|
||||
HISTORY_REG <= ADDER_MSBs(2) & HISTORY_REG(1);
|
||||
end if;
|
||||
end if;
|
||||
end process WIN_HISTORY;
|
||||
|
||||
-- Error history:
|
||||
-- This signal indicates the number of consequtive levels of the adder's
|
||||
-- MSB and the history register as shown in the following table. The default
|
||||
-- setting of 0 was added to compile with the Xilinx ISE.
|
||||
ERROR_HISTORY <= 2 when ADDER_MSBs(2) = '0' and HISTORY_REG = "00" else -- Speed strongly up.
|
||||
1 when ADDER_MSBs(2) = '0' and HISTORY_REG = "01" else -- Speed up.
|
||||
0 when ADDER_MSBs(2) = '0' and HISTORY_REG = "10" else -- o.k.
|
||||
0 when ADDER_MSBs(2) = '0' and HISTORY_REG = "11" else -- Now adjusted.
|
||||
0 when ADDER_MSBs(2) = '1' and HISTORY_REG = "00" else -- Now adjusted.
|
||||
0 when ADDER_MSBs(2) = '1' and HISTORY_REG = "01" else -- o.k.
|
||||
1 when ADDER_MSBs(2) = '1' and HISTORY_REG = "10" else -- Slow down.
|
||||
2 when ADDER_MSBs(2) = '1' and HISTORY_REG = "11" else 0; -- Slow strongly down.
|
||||
|
||||
FREQUENCY_DECODER: process(RESETn, CLK, HI_STOP, LOW_STOP)
|
||||
-- The frequency decoder controls the period of the data inspection window respective to the
|
||||
-- ERROR_HISTORY for the 11 bit adder is as follows:
|
||||
-- ERROR_HISTORY = 0:
|
||||
-- -> no correction necessary <-
|
||||
-- ERROR_HISTORY = 1:
|
||||
-- MSBs input: 7 6 5 4 3 2 1 0
|
||||
-- Correction output: -3 -2 -1 0 0 +1 +2 +3
|
||||
-- ERROR_HISTORY = 2:
|
||||
-- MSBs input: 7 6 5 4 3 2 1 0
|
||||
-- Correction output: -4 -3 -2 -1 +1 +2 +3 +4
|
||||
-- The most significant bit of the FREQ_AMOUNT controls incrementation or decrementation
|
||||
-- of the adder (0 is up).
|
||||
variable FREQ_AMOUNT: std_logic_vector(3 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
FREQ_AMOUNT := "0000";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RD_PULSE = '1' then -- Load the frequency amount register.
|
||||
case ERROR_HISTORY is
|
||||
when 2 =>
|
||||
case ADDER_MSBs is
|
||||
when "000" => FREQ_AMOUNT := "0100";
|
||||
when "001" => FREQ_AMOUNT := "0011";
|
||||
when "010" => FREQ_AMOUNT := "0010";
|
||||
when "011" => FREQ_AMOUNT := "0001";
|
||||
when "100" => FREQ_AMOUNT := "1001";
|
||||
when "101" => FREQ_AMOUNT := "1010";
|
||||
when "110" => FREQ_AMOUNT := "1011";
|
||||
when "111" => FREQ_AMOUNT := "1100";
|
||||
end case;
|
||||
when 1 =>
|
||||
case ADDER_MSBs is
|
||||
when "000" => FREQ_AMOUNT := "0011";
|
||||
when "001" => FREQ_AMOUNT := "0010";
|
||||
when "010" => FREQ_AMOUNT := "0001";
|
||||
when "011" => FREQ_AMOUNT := "0000";
|
||||
when "100" => FREQ_AMOUNT := "1000";
|
||||
when "101" => FREQ_AMOUNT := "1001";
|
||||
when "110" => FREQ_AMOUNT := "1010";
|
||||
when "111" => FREQ_AMOUNT := "1011";
|
||||
end case;
|
||||
when others =>
|
||||
FREQ_AMOUNT := "0000";
|
||||
end case;
|
||||
elsif FREQ_AMOUNT(2 downto 0) > "000" then
|
||||
FREQ_AMOUNT := FREQ_AMOUNT - '1'; -- Modify the frequency amount register.
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
if FREQ_AMOUNT(3) = '0' and FREQ_AMOUNT(2 downto 0) /= "000" and HI_STOP = '0' then
|
||||
-- FREQ_AMOUNT(3) = '0' means Frequency is too low. Count up when counter is not at HI_STOP.
|
||||
UP <= '1';
|
||||
DOWN <= '0';
|
||||
elsif FREQ_AMOUNT(3) = '1' and FREQ_AMOUNT (2 downto 0) /= "000" and LOW_STOP = '0' then
|
||||
-- FREQ_AMOUNT(3) = '1' means Frequency is too high. Count down when counter is not at LOW_STOP.
|
||||
UP <= '0';
|
||||
DOWN <= '1';
|
||||
else
|
||||
UP <= '0';
|
||||
DOWN <= '0';
|
||||
end if;
|
||||
end process FREQUENCY_DECODER;
|
||||
|
||||
PHASE_DECODER: process(RESETn, CLK)
|
||||
-- The phase decoder depends on the value of ADDER_MSBs. If the phase leeds, the most significant bit
|
||||
-- of PHASE_AMOUNT indicates with a '0', that the next rollover should appear earlier. In case of a
|
||||
-- phase lag, the next rollover should come later (indicated by a '1' of the most significant bit of
|
||||
-- PHASE_AMOUNT).
|
||||
-- This implementation gives the freedom to adjust the phase amount individually for every mode
|
||||
-- depending on DDEn and HDTYPE.
|
||||
variable PHASE_AMOUNT: std_logic_vector(5 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
PHASE_AMOUNT := "000000";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if RD_PULSE = '1' and DDEn = '1' and HDTYPE = '0' then -- FM mode, single density.
|
||||
case ADDER_MSBs is -- Multiplier: 4.
|
||||
when "000" => PHASE_AMOUNT := "010000";
|
||||
when "001" => PHASE_AMOUNT := "001101";
|
||||
when "010" => PHASE_AMOUNT := "001000";
|
||||
when "011" => PHASE_AMOUNT := "000100";
|
||||
when "100" => PHASE_AMOUNT := "100100";
|
||||
when "101" => PHASE_AMOUNT := "101000";
|
||||
when "110" => PHASE_AMOUNT := "101100";
|
||||
when "111" => PHASE_AMOUNT := "110000";
|
||||
end case;
|
||||
elsif RD_PULSE = '1' and DDEn = '1' and HDTYPE = '1' then -- FM mode, double density
|
||||
case ADDER_MSBs is -- Multiplier: 2.
|
||||
when "000" => PHASE_AMOUNT := "001000";
|
||||
when "001" => PHASE_AMOUNT := "000110";
|
||||
when "010" => PHASE_AMOUNT := "000100";
|
||||
when "011" => PHASE_AMOUNT := "000010";
|
||||
when "100" => PHASE_AMOUNT := "100010";
|
||||
when "101" => PHASE_AMOUNT := "100100";
|
||||
when "110" => PHASE_AMOUNT := "100110";
|
||||
when "111" => PHASE_AMOUNT := "101000";
|
||||
end case;
|
||||
elsif RD_PULSE = '1' and DDEn = '0' and HDTYPE = '0' then -- MFM mode, single density
|
||||
case ADDER_MSBs is -- Multiplier: 2.
|
||||
when "000" => PHASE_AMOUNT := "000110";
|
||||
when "001" => PHASE_AMOUNT := "000100";
|
||||
when "010" => PHASE_AMOUNT := "000011";
|
||||
when "011" => PHASE_AMOUNT := "000010";
|
||||
when "100" => PHASE_AMOUNT := "100010";
|
||||
when "101" => PHASE_AMOUNT := "100011";
|
||||
when "110" => PHASE_AMOUNT := "100100";
|
||||
when "111" => PHASE_AMOUNT := "100110";
|
||||
end case;
|
||||
elsif RD_PULSE = '1' and DDEn = '0' and HDTYPE = '1' then -- MFM mode, double density.
|
||||
case ADDER_MSBs is -- Multiplier: 1.
|
||||
when "000" => PHASE_AMOUNT := "000100";
|
||||
when "001" => PHASE_AMOUNT := "000011";
|
||||
when "010" => PHASE_AMOUNT := "000010";
|
||||
when "011" => PHASE_AMOUNT := "000001";
|
||||
when "100" => PHASE_AMOUNT := "100001";
|
||||
when "101" => PHASE_AMOUNT := "100010";
|
||||
when "110" => PHASE_AMOUNT := "100011";
|
||||
when "111" => PHASE_AMOUNT := "100100";
|
||||
end case;
|
||||
else -- Modify phase amount register:
|
||||
if PHASE_AMOUNT(4 downto 0) > x"0" then
|
||||
PHASE_AMOUNT := PHASE_AMOUNT - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
if PHASE_AMOUNT(5) = '0' and PHASE_AMOUNT(4 downto 0) > x"0" then
|
||||
-- PHASE_AMOUNT(5) = '0' means, that the phase leeds.
|
||||
PHASE_INCREASE <= '1'; -- Speed phase up, accelerate next rollover.
|
||||
PHASE_DECREASE <= '0';
|
||||
elsif PHASE_AMOUNT(5) = '1' and PHASE_AMOUNT(4 downto 0) > x"0" then
|
||||
-- PHASE_AMOUNT(5) = '1' means, that the phase lags.
|
||||
PHASE_INCREASE <= '0';
|
||||
PHASE_DECREASE <= '1'; -- Speed phase down, delay of next rollover.
|
||||
else
|
||||
PHASE_INCREASE <= '0';
|
||||
PHASE_DECREASE <= '0';
|
||||
end if;
|
||||
end process PHASE_DECODER;
|
||||
end architecture BEHAVIOR;
|
||||
232
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_pkg.vhd
Normal file
232
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_pkg.vhd
Normal file
@@ -0,0 +1,232 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- This is the package file containing the component ----
|
||||
---- declarations. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Removed CRC_BUSY.
|
||||
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
package WF1772IP_PKG is
|
||||
-- component declarations:
|
||||
component WF1772IP_AM_DETECTOR
|
||||
port(
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DDEn : in bit;
|
||||
DATA : in bit;
|
||||
DATA_STRB : in bit;
|
||||
ID_AM : out bit;
|
||||
DATA_AM : out bit;
|
||||
DDATA_AM : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF1772IP_CONTROL
|
||||
port(
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
A1, A0 : in bit;
|
||||
RWn : in bit;
|
||||
CSn : in bit;
|
||||
DDEn : in bit;
|
||||
DR : in bit_vector(7 downto 0);
|
||||
CMD : in std_logic_vector(7 downto 0);
|
||||
DSR : in std_logic_vector(7 downto 0);
|
||||
TR : in std_logic_vector(7 downto 0);
|
||||
SR : in std_logic_vector(7 downto 0);
|
||||
MO : out bit;
|
||||
WR_PR : out bit;
|
||||
SPINUP_RECTYPE : out bit;
|
||||
SEEK_RNF : out bit;
|
||||
CRC_ERRFLAG : out bit;
|
||||
LOST_DATA_TR00 : out bit;
|
||||
DRQ : out bit;
|
||||
DRQ_IPn : out bit;
|
||||
BUSY : out bit;
|
||||
AM_2_DISK : out bit;
|
||||
ID_AM : in bit;
|
||||
DATA_AM : in bit;
|
||||
DDATA_AM : in bit;
|
||||
CRC_ERR : in bit;
|
||||
CRC_PRES : out bit;
|
||||
TR_PRES : out bit;
|
||||
TR_CLR : out bit;
|
||||
TR_INC : out bit;
|
||||
TR_DEC : out bit;
|
||||
SR_LOAD : out bit;
|
||||
SR_INC : out bit;
|
||||
TRACK_NR : out std_logic_vector(7 downto 0);
|
||||
DR_CLR : out bit;
|
||||
DR_LOAD : out bit;
|
||||
SHFT_LOAD_SD : out bit;
|
||||
SHFT_LOAD_ND : out bit;
|
||||
CRC_2_DISK : out bit;
|
||||
DSR_2_DISK : out bit;
|
||||
FF_2_DISK : out bit;
|
||||
PRECOMP_EN : out bit;
|
||||
DATA_STRB : in bit;
|
||||
DISK_RWn : out bit;
|
||||
WPRTn : in bit;
|
||||
TRACK00n : in bit;
|
||||
IPn : in bit;
|
||||
DIRC : out bit;
|
||||
STEP : out bit;
|
||||
WG : out bit;
|
||||
INTRQ : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF1772IP_CRC_LOGIC
|
||||
port(
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DDEn : in bit;
|
||||
DISK_RWn : in bit;
|
||||
ID_AM : in bit;
|
||||
DATA_AM : in bit;
|
||||
DDATA_AM : in bit;
|
||||
SD : in bit;
|
||||
CRC_STRB : in bit;
|
||||
CRC_2_DISK : in bit;
|
||||
CRC_PRES : in bit;
|
||||
CRC_SDOUT : out bit;
|
||||
CRC_ERR : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF1772IP_DIGITAL_PLL
|
||||
port(
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DDEn : in bit;
|
||||
HDTYPE : in bit;
|
||||
DISK_RWn : in bit;
|
||||
RDn : in bit;
|
||||
PLL_D : out bit;
|
||||
PLL_DSTRB : out bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF1772IP_REGISTERS
|
||||
port(
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
CSn : in bit;
|
||||
ADR : in bit_vector(1 downto 0);
|
||||
RWn : in bit;
|
||||
DATA_IN : in std_logic_vector (7 downto 0);
|
||||
DATA_OUT : out std_logic_vector (7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
CMD : out std_logic_vector(7 downto 0);
|
||||
SR : out std_logic_vector(7 downto 0);
|
||||
TR : out std_logic_vector(7 downto 0);
|
||||
DSR : out std_logic_vector(7 downto 0);
|
||||
DR : out bit_vector(7 downto 0);
|
||||
SD_R : in bit;
|
||||
DATA_STRB : in bit;
|
||||
DR_CLR : in bit;
|
||||
DR_LOAD : in bit;
|
||||
TR_PRES : in bit;
|
||||
TR_CLR : in bit;
|
||||
TR_INC : in bit;
|
||||
TR_DEC : in bit;
|
||||
TRACK_NR : in std_logic_vector(7 downto 0);
|
||||
SR_LOAD : in bit;
|
||||
SR_INC : in bit;
|
||||
SHFT_LOAD_SD : in bit;
|
||||
SHFT_LOAD_ND : in bit;
|
||||
MOTOR_ON : in bit;
|
||||
WRITE_PROTECT : in bit;
|
||||
SPINUP_RECTYPE : in bit;
|
||||
SEEK_RNF : in bit;
|
||||
CRC_ERRFLAG : in bit;
|
||||
LOST_DATA_TR00 : in bit;
|
||||
DRQ : in bit;
|
||||
DRQ_IPn : in bit;
|
||||
BUSY : in bit;
|
||||
DDEn : in bit
|
||||
);
|
||||
end component;
|
||||
|
||||
component WF1772IP_TRANSCEIVER
|
||||
port(
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
DDEn : in bit;
|
||||
HDTYPE : in bit;
|
||||
ID_AM : in bit;
|
||||
DATA_AM : in bit;
|
||||
DDATA_AM : in bit;
|
||||
SHFT_LOAD_SD : in bit;
|
||||
DR : in bit_vector(7 downto 0);
|
||||
PRECOMP_EN : in bit;
|
||||
AM_TYPE : in bit;
|
||||
AM_2_DISK : in bit;
|
||||
CRC_2_DISK : in bit;
|
||||
DSR_2_DISK : in bit;
|
||||
FF_2_DISK : in bit;
|
||||
SR_SDOUT : in std_logic;
|
||||
CRC_SDOUT : in bit;
|
||||
WRn : out bit;
|
||||
PLL_DSTRB : in bit;
|
||||
PLL_D : in bit;
|
||||
WDATA : out bit;
|
||||
DATA_STRB : out bit;
|
||||
SD_R : out bit
|
||||
);
|
||||
end component;
|
||||
end WF1772IP_PKG;
|
||||
264
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_registers.vhd
Normal file
264
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_registers.vhd
Normal file
@@ -0,0 +1,264 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- This file models all the five WD1772 registers: DATA-, ----
|
||||
---- COMMAND-, SECTOR-, TRACK- and STATUS register as also the ----
|
||||
---- shift register. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF1772IP_REGISTERS is
|
||||
port(
|
||||
-- System control:
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
|
||||
-- Bus interface:
|
||||
CSn : in bit;
|
||||
ADR : in bit_vector(1 downto 0);
|
||||
RWn : in bit;
|
||||
DATA_IN : in std_logic_vector (7 downto 0);
|
||||
DATA_OUT : out std_logic_vector (7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
|
||||
-- FDC data:
|
||||
CMD : out std_logic_vector(7 downto 0); -- Command register.
|
||||
SR : out std_logic_vector(7 downto 0); -- Sector register.
|
||||
TR : out std_logic_vector(7 downto 0); -- Track register.
|
||||
DSR : out std_logic_vector(7 downto 0); -- Data shift register.
|
||||
DR : out bit_vector(7 downto 0); -- Data register.
|
||||
|
||||
-- Serial data and clock strobes (in and out):
|
||||
DATA_STRB : in bit; -- Strobe for the incoming data.
|
||||
SD_R : in bit; -- Serial data input.
|
||||
|
||||
-- DATA register control:
|
||||
DR_CLR : in bit; -- Clear.
|
||||
DR_LOAD : in bit; -- LOAD.
|
||||
|
||||
-- Track register controls:
|
||||
TR_PRES : in bit; -- Set x"FF".
|
||||
TR_CLR : in bit; -- Clear.
|
||||
TR_INC : in bit; -- Increment.
|
||||
TR_DEC : in bit; -- Decrement.
|
||||
|
||||
-- Sector register control:
|
||||
TRACK_NR : in std_logic_vector(7 downto 0);
|
||||
SR_LOAD : in bit; -- Load.
|
||||
SR_INC : in bit; -- Increment.
|
||||
|
||||
-- Shift register control:
|
||||
SHFT_LOAD_SD : in bit;
|
||||
SHFT_LOAD_ND : in bit;
|
||||
|
||||
-- Status register stuff
|
||||
MOTOR_ON : in bit;
|
||||
WRITE_PROTECT : in bit;
|
||||
SPINUP_RECTYPE : in bit; -- Disk is on speed / data mark status.
|
||||
SEEK_RNF : in bit; -- Seek error / record not found status flag.
|
||||
CRC_ERRFLAG : in bit; -- CRC status flag.
|
||||
LOST_DATA_TR00 : in bit;
|
||||
DRQ : in bit;
|
||||
DRQ_IPn : in bit;
|
||||
BUSY : in bit;
|
||||
|
||||
-- Others:
|
||||
DDEn : in bit
|
||||
);
|
||||
end WF1772IP_REGISTERS;
|
||||
|
||||
architecture BEHAVIOR of WF1772IP_REGISTERS is
|
||||
-- Remark: In the original data sheet 'WD17X-00' there is the following statement:
|
||||
-- "After any register is written to, the same register cannot be read from until
|
||||
-- 16us in MFM or 32us in FMMM have elapsed." If this is a hint for a hardware read
|
||||
-- lock ... this lock is not implemented in this code.
|
||||
signal SHIFT_REG : std_logic_vector(7 downto 0);
|
||||
signal DATA_REG : std_logic_vector(7 downto 0);
|
||||
signal COMMAND_REG : std_logic_vector(7 downto 0);
|
||||
signal SECTOR_REG : std_logic_vector(7 downto 0);
|
||||
signal TRACK_REG : std_logic_vector(7 downto 0);
|
||||
signal STATUS_REG : bit_vector(7 downto 0);
|
||||
signal SD_R_I : std_logic;
|
||||
begin
|
||||
-- Type conversion To_Std_Logic:
|
||||
SD_R_I <= '1' when SD_R = '1' else '0';
|
||||
|
||||
P_SHIFTREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SHIFT_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if SHFT_LOAD_ND = '1' then
|
||||
SHIFT_REG <= DATA_REG; -- Load data register stuff.
|
||||
elsif SHFT_LOAD_SD = '1' and DDEn = '1' then
|
||||
SHIFT_REG <= DATA_REG; -- Normal data in FM mode.
|
||||
elsif SHFT_LOAD_SD = '1' and DDEn = '0' then -- MFM mode:
|
||||
case DATA_REG is
|
||||
when x"F5" => SHIFT_REG <= x"A1"; -- Special character.
|
||||
when x"F6" => SHIFT_REG <= x"C2"; -- Special character.
|
||||
when others => SHIFT_REG <= DATA_REG; -- Normal MFM data.
|
||||
end case;
|
||||
elsif DATA_STRB = '1' then -- Shift left during read from disk or write to disk.
|
||||
SHIFT_REG <= SHIFT_REG(6 downto 0) & SD_R_I; -- for write operation SD_R_I is a dummy.
|
||||
end if;
|
||||
end if;
|
||||
end process P_SHIFTREG;
|
||||
DSR <= SHIFT_REG;
|
||||
|
||||
DATAREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
DATA_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if CSn = '0' and ADR = "11" and RWn = '0' then
|
||||
DATA_REG <= DATA_IN; -- Write bus data to register
|
||||
elsif DR_LOAD = '1' and DRQ = '0' then
|
||||
DATA_REG <= SHIFT_REG; -- Correct data loaded to shift register.
|
||||
elsif DR_LOAD = '1' and DRQ = '1' then
|
||||
DATA_REG <= x"00"; -- Dummy byte due to lost data loaded to shift register.
|
||||
elsif DR_CLR = '1' then
|
||||
DATA_REG <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process DATAREG;
|
||||
-- Data register buffered for further data processing.
|
||||
DR <= To_BitVector(DATA_REG);
|
||||
|
||||
SECTORREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
SECTOR_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if CSn = '0' and ADR = "10" and RWn = '0' and BUSY = '0' then
|
||||
SECTOR_REG <= DATA_IN; -- Write to register when device is not busy.
|
||||
elsif SR_LOAD = '1' then
|
||||
-- Load the track number to the sector register in the type III command
|
||||
-- 'Read Address'.
|
||||
SECTOR_REG <= TRACK_NR;
|
||||
elsif SR_INC = '1' then
|
||||
SECTOR_REG <= SECTOR_REG + '1';
|
||||
end if;
|
||||
end if;
|
||||
end process SECTORREG;
|
||||
SR <= SECTOR_REG;
|
||||
|
||||
TRACKREG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TRACK_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if CSn = '0' and ADR = "01" and RWn = '0' and BUSY = '0' then
|
||||
TRACK_REG <= DATA_IN; -- Write to register when device is busy.
|
||||
elsif TR_PRES = '1' then
|
||||
TRACK_REG <= (others => '1'); -- Preset the track register.
|
||||
elsif TR_CLR = '1' then
|
||||
TRACK_REG <= (others => '0'); -- Reset the track register.
|
||||
elsif TR_INC = '1' then
|
||||
TRACK_REG <= TRACK_REG + '1'; -- Increment register contents.
|
||||
elsif TR_DEC = '1' then
|
||||
TRACK_REG <= TRACK_REG - '1'; -- Decrement register contents.
|
||||
end if;
|
||||
end if;
|
||||
end process TRACKREG;
|
||||
TR <= TRACK_REG;
|
||||
|
||||
COMMANDREG: process(RESETn, CLK)
|
||||
-- The command register is write only.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
COMMAND_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if CSn = '0' and ADR = "00" and RWn = '0' and BUSY = '0' then
|
||||
COMMAND_REG <= DATA_IN; -- Write to register when device is not busy.
|
||||
-- Write 'force interrupt' to register even when device is busy:
|
||||
elsif CSn = '0' and ADR = "00" and RWn = '0' and DATA_IN(7 downto 4) = x"D" then
|
||||
COMMAND_REG <= DATA_IN;
|
||||
end if;
|
||||
end if;
|
||||
end process COMMANDREG;
|
||||
CMD <= COMMAND_REG;
|
||||
|
||||
STATUSREG: process(RESETn, CLK)
|
||||
-- The status register is read only to the data bus.
|
||||
begin
|
||||
-- Status register wiring:
|
||||
if RESETn = '0' then
|
||||
STATUS_REG <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
STATUS_REG(7) <= MOTOR_ON;
|
||||
STATUS_REG(6) <= WRITE_PROTECT;
|
||||
STATUS_REG(5) <= SPINUP_RECTYPE;
|
||||
STATUS_REG(4) <= SEEK_RNF;
|
||||
STATUS_REG(3) <= CRC_ERRFLAG;
|
||||
STATUS_REG(2) <= LOST_DATA_TR00;
|
||||
STATUS_REG(1) <= DRQ_IPn;
|
||||
STATUS_REG(0) <= BUSY;
|
||||
end if;
|
||||
end process STATUSREG;
|
||||
-- Read from track, sector or data register:
|
||||
-- The register data after writing to the track register is valid at least
|
||||
-- after 32us in FM mode and after 16us in MFM mode.
|
||||
-- Read from status register. This register is read only:
|
||||
-- Be aware, that the status register data bits 7 to 1 after writing
|
||||
-- the command regsiter are valid at least after 64us in FM mode or 32us in MFM mode and
|
||||
-- the bit 0 (BUSY) is valid after 48us in FM mode or 24us in MFM mode.
|
||||
DATA_OUT <= TRACK_REG when CSn = '0' and ADR = "01" and RWn = '1' else
|
||||
SECTOR_REG when CSn = '0' and ADR = "10" and RWn = '1' else
|
||||
DATA_REG when CSn = '0' and ADR = "11" and RWn = '1' else
|
||||
To_StdLogicVector(STATUS_REG) when CSn = '0' and ADR = "00" and RWn = '1' else (others => '0');
|
||||
DATA_EN <= '1' when CSn = '0' and RWn = '1' else '0';
|
||||
end architecture BEHAVIOR;
|
||||
154
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_top.vhd
Normal file
154
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_top.vhd
Normal file
@@ -0,0 +1,154 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- This is the top level file. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - Test of the FM portion of the code (if there is any need). ----
|
||||
---- - Test of the read track command. ----
|
||||
---- - Test of the read address command. ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release: the MFM portion for HD and DD floppies is tested.
|
||||
-- The FM mode (DDEn = '1') is not completely tested due to the lack
|
||||
-- of FM drives.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Fixed the polarity of the precompensation flag.
|
||||
-- The flag is no active '0'. Thanks to Jorma
|
||||
-- Oksanen for the information.
|
||||
-- Revision 2K7B 2006/12/29 WF
|
||||
-- Introduced several improvements based on a very good examination
|
||||
-- of the pll code by Jean Louis-Guerin.
|
||||
-- Revision 2K8B 2008/12/24 WF
|
||||
-- Rewritten this top level file as a wrapper for the top_soc file.
|
||||
|
||||
library work;
|
||||
use work.WF1772IP_PKG.all;
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF1772IP_TOP is
|
||||
port (
|
||||
CLK : in bit; -- 16MHz clock!
|
||||
MRn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
A1, A0 : in bit;
|
||||
DATA : inout std_logic_vector(7 downto 0);
|
||||
RDn : in bit;
|
||||
TR00n : in bit;
|
||||
IPn : in bit;
|
||||
WPRTn : in bit;
|
||||
DDEn : in bit;
|
||||
HDTYPE : in bit; -- '0' = DD disks, '1' = HD disks.
|
||||
MO : out bit;
|
||||
WG : out bit;
|
||||
WD : out bit;
|
||||
STEP : out bit;
|
||||
DIRC : out bit;
|
||||
DRQ : out bit;
|
||||
INTRQ : out bit
|
||||
);
|
||||
end entity WF1772IP_TOP;
|
||||
|
||||
architecture STRUCTURE of WF1772IP_TOP is
|
||||
component WF1772IP_TOP_SOC
|
||||
port (
|
||||
CLK : in bit;
|
||||
RESETn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
A1, A0 : in bit;
|
||||
DATA_IN : in std_logic_vector(7 downto 0);
|
||||
DATA_OUT : out std_logic_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
RDn : in bit;
|
||||
TR00n : in bit;
|
||||
IPn : in bit;
|
||||
WPRTn : in bit;
|
||||
DDEn : in bit;
|
||||
HDTYPE : in bit;
|
||||
MO : out bit;
|
||||
WG : out bit;
|
||||
WD : out bit;
|
||||
STEP : out bit;
|
||||
DIRC : out bit;
|
||||
DRQ : out bit;
|
||||
INTRQ : out bit
|
||||
);
|
||||
end component;
|
||||
signal DATA_OUT : std_logic_vector(7 downto 0);
|
||||
signal DATA_EN : bit;
|
||||
begin
|
||||
DATA <= DATA_OUT when DATA_EN = '1' else (others => 'Z');
|
||||
|
||||
I_1772: WF1772IP_TOP_SOC
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => MRn,
|
||||
CSn => CSn,
|
||||
RWn => RWn,
|
||||
A1 => A1,
|
||||
A0 => A0,
|
||||
DATA_IN => DATA,
|
||||
DATA_OUT => DATA_OUT,
|
||||
DATA_EN => DATA_EN,
|
||||
RDn => RDn,
|
||||
TR00n => TR00n,
|
||||
IPn => IPn,
|
||||
WPRTn => WPRTn,
|
||||
DDEn => DDEn,
|
||||
HDTYPE => HDTYPE,
|
||||
MO => MO,
|
||||
WG => WG,
|
||||
WD => WD,
|
||||
STEP => STEP,
|
||||
DIRC => DIRC,
|
||||
DRQ => DRQ,
|
||||
INTRQ => INTRQ
|
||||
);
|
||||
end architecture STRUCTURE;
|
||||
333
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_top_soc.vhd
Normal file
333
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_top_soc.vhd
Normal file
@@ -0,0 +1,333 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- Top level file for use in systems on programmable chips. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - Test of the FM portion of the code (if there is any need). ----
|
||||
---- - Test of the read track command. ----
|
||||
---- - Test of the read address command. ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release: the MFM portion for HD and DD floppies is tested.
|
||||
-- The FM mode (DDEn = '1') is not completely tested due to the lack
|
||||
-- of FM drives.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Fixed the polarity of the precompensation flag.
|
||||
-- The flag is no active '0'. Thanks to Jorma Oksanen for the information.
|
||||
-- Top level file provided for SOC (systems on programmable chips).
|
||||
-- Revision 2K7B 2006/12/29 WF
|
||||
-- Introduced several improvements based on a very good examination
|
||||
-- of the pll code by Jean Louis-Guerin.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K8B 2008/12/24 WF
|
||||
-- Bugfixes in the controller due to hanging state machine.
|
||||
-- Removed CRC_BUSY.
|
||||
--
|
||||
|
||||
library work;
|
||||
use work.WF1772IP_PKG.all;
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF1772IP_TOP_SOC is
|
||||
port (
|
||||
CLK : in bit; -- 16MHz clock!
|
||||
RESETn : in bit;
|
||||
CSn : in bit;
|
||||
RWn : in bit;
|
||||
A1, A0 : in bit;
|
||||
DATA_IN : in std_logic_vector(7 downto 0);
|
||||
DATA_OUT : out std_logic_vector(7 downto 0);
|
||||
DATA_EN : out bit;
|
||||
RDn : in bit;
|
||||
TR00n : in bit;
|
||||
IPn : in bit;
|
||||
WPRTn : in bit;
|
||||
DDEn : in bit;
|
||||
HDTYPE : in bit; -- '0' = DD disks, '1' = HD disks.
|
||||
MO : out bit;
|
||||
WG : out bit;
|
||||
WD : out bit;
|
||||
STEP : out bit;
|
||||
DIRC : out bit;
|
||||
DRQ : out bit;
|
||||
INTRQ : out bit
|
||||
);
|
||||
end entity WF1772IP_TOP_SOC;
|
||||
|
||||
architecture STRUCTURE of WF1772IP_TOP_SOC is
|
||||
signal DATA_OUT_REG : std_logic_vector(7 downto 0);
|
||||
signal DATA_EN_REG : bit;
|
||||
signal CMD_I : std_logic_vector(7 downto 0);
|
||||
signal DR_I : bit_vector(7 downto 0);
|
||||
signal DSR_I : std_logic_vector(7 downto 0);
|
||||
signal TR_I : std_logic_vector(7 downto 0);
|
||||
signal SR_I : std_logic_vector(7 downto 0);
|
||||
signal ID_AM_I : bit;
|
||||
signal DATA_AM_I : bit;
|
||||
signal DDATA_AM_I : bit;
|
||||
signal AM_TYPE_I : bit;
|
||||
signal AM_2_DISK_I : bit;
|
||||
signal DATA_STRB_I : bit;
|
||||
signal BUSY_I : bit;
|
||||
signal DRQ_I : bit;
|
||||
signal DRQ_IPn_I : bit;
|
||||
signal LD_TR00_I : bit;
|
||||
signal SP_RT_I : bit;
|
||||
signal SEEK_RNF_I : bit;
|
||||
signal WR_PR_I : bit;
|
||||
signal MO_I : bit;
|
||||
signal PLL_DSTRB_I : bit;
|
||||
signal PLL_D_I : bit;
|
||||
signal CRC_SD_I : bit;
|
||||
signal CRC_ERR_I : bit;
|
||||
signal CRC_PRES_I : bit;
|
||||
signal CRC_ERRFLAG_I : bit;
|
||||
signal SD_R_I : bit;
|
||||
signal CRC_SDOUT_I : bit;
|
||||
signal SHFT_LOAD_SD_I : bit;
|
||||
signal SHFT_LOAD_ND_I : bit;
|
||||
signal WR_In : bit;
|
||||
signal TR_PRES_I : bit;
|
||||
signal TR_CLR_I : bit;
|
||||
signal TR_INC_I : bit;
|
||||
signal TR_DEC_I : bit;
|
||||
signal SR_LOAD_I : bit;
|
||||
signal SR_INC_I : bit;
|
||||
signal DR_CLR_I : bit;
|
||||
signal DR_LOAD_I : bit;
|
||||
signal TRACK_NR_I : std_logic_vector(7 downto 0);
|
||||
signal CRC_2_DISK_I : bit;
|
||||
signal DSR_2_DISK_I : bit;
|
||||
signal FF_2_DISK_I : bit;
|
||||
signal PRECOMP_EN_I : bit;
|
||||
signal DISK_RWn_I : bit;
|
||||
signal WDATA_I : bit;
|
||||
begin
|
||||
-- Three state data bus:
|
||||
DATA_OUT <= DATA_OUT_REG when DATA_EN_REG = '1' else (others => '0');
|
||||
DATA_EN <= DATA_EN_REG;
|
||||
|
||||
-- Some signals copied to the outputs:
|
||||
WD <= not WR_In;
|
||||
MO <= MO_I;
|
||||
DRQ <= DRQ_I;
|
||||
|
||||
-- Write deleted data address mark in MFM mode in 'Write Sector' command in
|
||||
-- case of asserted command bit 0.
|
||||
AM_TYPE_I <= '0' when CMD_I(7 downto 5) = "101" and CMD_I(0) = '1' else '1';
|
||||
|
||||
-- The CRC unit is used during read from disk and write to disk.
|
||||
-- This is the data multiplexer for the data stream to encode.
|
||||
CRC_SD_I <= SD_R_I when DISK_RWn_I = '1' else WDATA_I;
|
||||
|
||||
I_CONTROL: WF1772IP_CONTROL
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
A1 => A0,
|
||||
A0 => A1,
|
||||
RWn => RWn,
|
||||
CSn => CSn,
|
||||
DDEn => DDEn,
|
||||
DR => DR_I,
|
||||
CMD => CMD_I,
|
||||
DSR => DSR_I,
|
||||
TR => TR_I,
|
||||
SR => SR_I,
|
||||
MO => MO_I,
|
||||
WR_PR => WR_PR_I,
|
||||
SPINUP_RECTYPE => SP_RT_I,
|
||||
SEEK_RNF => SEEK_RNF_I,
|
||||
CRC_ERRFLAG => CRC_ERRFLAG_I,
|
||||
LOST_DATA_TR00 => LD_TR00_I,
|
||||
DRQ => DRQ_I,
|
||||
DRQ_IPn => DRQ_IPn_I,
|
||||
BUSY => BUSY_I,
|
||||
AM_2_DISK => AM_2_DISK_I,
|
||||
ID_AM => ID_AM_I,
|
||||
DATA_AM => DATA_AM_I,
|
||||
DDATA_AM => DDATA_AM_I,
|
||||
CRC_ERR => CRC_ERR_I,
|
||||
CRC_PRES => CRC_PRES_I,
|
||||
TR_PRES => TR_PRES_I,
|
||||
TR_CLR => TR_CLR_I,
|
||||
TR_INC => TR_INC_I,
|
||||
TR_DEC => TR_DEC_I,
|
||||
SR_LOAD => SR_LOAD_I,
|
||||
SR_INC => SR_INC_I,
|
||||
TRACK_NR => TRACK_NR_I,
|
||||
DR_CLR => DR_CLR_I,
|
||||
DR_LOAD => DR_LOAD_I,
|
||||
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
|
||||
SHFT_LOAD_ND => SHFT_LOAD_ND_I,
|
||||
CRC_2_DISK => CRC_2_DISK_I,
|
||||
DSR_2_DISK => DSR_2_DISK_I,
|
||||
FF_2_DISK => FF_2_DISK_I,
|
||||
PRECOMP_EN => PRECOMP_EN_I,
|
||||
DATA_STRB => DATA_STRB_I,
|
||||
DISK_RWn => DISK_RWn_I,
|
||||
WPRTn => WPRTn,
|
||||
TRACK00n => TR00n,
|
||||
IPn => IPn,
|
||||
DIRC => DIRC,
|
||||
STEP => STEP,
|
||||
WG => WG,
|
||||
INTRQ => INTRQ
|
||||
);
|
||||
|
||||
I_REGISTERS: WF1772IP_REGISTERS
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
CSn => CSn,
|
||||
ADR(1) => A1,
|
||||
ADR(0) => A0,
|
||||
RWn => RWn,
|
||||
DATA_IN => DATA_IN,
|
||||
DATA_OUT => DATA_OUT_REG,
|
||||
DATA_EN => DATA_EN_REG,
|
||||
CMD => CMD_I,
|
||||
TR => TR_I,
|
||||
SR => SR_I,
|
||||
DSR => DSR_I,
|
||||
DR => DR_I,
|
||||
SD_R => SD_R_I,
|
||||
DATA_STRB => DATA_STRB_I,
|
||||
DR_CLR => DR_CLR_I,
|
||||
DR_LOAD => DR_LOAD_I,
|
||||
TR_PRES => TR_PRES_I,
|
||||
TR_CLR => TR_CLR_I,
|
||||
TR_INC => TR_INC_I,
|
||||
TR_DEC => TR_DEC_I,
|
||||
TRACK_NR => TRACK_NR_I,
|
||||
SR_LOAD => SR_LOAD_I,
|
||||
SR_INC => SR_INC_I,
|
||||
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
|
||||
SHFT_LOAD_ND => SHFT_LOAD_ND_I,
|
||||
MOTOR_ON => MO_I,
|
||||
WRITE_PROTECT => WR_PR_I,
|
||||
SPINUP_RECTYPE => SP_RT_I,
|
||||
SEEK_RNF => SEEK_RNF_I,
|
||||
CRC_ERRFLAG => CRC_ERRFLAG_I,
|
||||
LOST_DATA_TR00 => LD_TR00_I,
|
||||
DRQ => DRQ_I,
|
||||
DRQ_IPn => DRQ_IPn_I,
|
||||
BUSY => BUSY_I,
|
||||
DDEn => DDEn
|
||||
);
|
||||
|
||||
I_DIGITAL_PLL: WF1772IP_DIGITAL_PLL
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DDEn => DDEn,
|
||||
HDTYPE => HDTYPE,
|
||||
DISK_RWn => DISK_RWn_I,
|
||||
RDn => RDn,
|
||||
PLL_D => PLL_D_I,
|
||||
PLL_DSTRB => PLL_DSTRB_I
|
||||
);
|
||||
|
||||
I_AM_DETECTOR: WF1772IP_AM_DETECTOR
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DDEn => DDEn,
|
||||
DATA => PLL_D_I,
|
||||
DATA_STRB => PLL_DSTRB_I,
|
||||
ID_AM => ID_AM_I,
|
||||
DATA_AM => DATA_AM_I,
|
||||
DDATA_AM => DDATA_AM_I
|
||||
);
|
||||
|
||||
I_CRC_LOGIC: WF1772IP_CRC_LOGIC
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DDEn => DDEn,
|
||||
DISK_RWn => DISK_RWn_I,
|
||||
ID_AM => ID_AM_I,
|
||||
DATA_AM => DATA_AM_I,
|
||||
DDATA_AM => DDATA_AM_I,
|
||||
SD => CRC_SD_I,
|
||||
CRC_STRB => DATA_STRB_I,
|
||||
CRC_2_DISK => CRC_2_DISK_I,
|
||||
CRC_PRES => CRC_PRES_I,
|
||||
CRC_SDOUT => CRC_SDOUT_I,
|
||||
CRC_ERR => CRC_ERR_I
|
||||
);
|
||||
|
||||
I_TRANSCEIVER: WF1772IP_TRANSCEIVER
|
||||
port map(
|
||||
CLK => CLK,
|
||||
RESETn => RESETn,
|
||||
DDEn => DDEn,
|
||||
HDTYPE => HDTYPE,
|
||||
ID_AM => ID_AM_I,
|
||||
DATA_AM => DATA_AM_I,
|
||||
DDATA_AM => DDATA_AM_I,
|
||||
SHFT_LOAD_SD => SHFT_LOAD_SD_I,
|
||||
DR => DR_I,
|
||||
PRECOMP_EN => PRECOMP_EN_I,
|
||||
AM_TYPE => AM_TYPE_I,
|
||||
AM_2_DISK => AM_2_DISK_I,
|
||||
CRC_2_DISK => CRC_2_DISK_I,
|
||||
DSR_2_DISK => DSR_2_DISK_I,
|
||||
FF_2_DISK => FF_2_DISK_I,
|
||||
SR_SDOUT => DSR_I(7),
|
||||
CRC_SDOUT => CRC_SDOUT_I,
|
||||
WRn => WR_In,
|
||||
WDATA => WDATA_I,
|
||||
PLL_DSTRB => PLL_DSTRB_I,
|
||||
PLL_D => PLL_D_I,
|
||||
DATA_STRB => DATA_STRB_I,
|
||||
SD_R => SD_R_I
|
||||
);
|
||||
end architecture STRUCTURE;
|
||||
517
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_transceiver.vhd
Normal file
517
FalconIO_SDCard_IDE_CF/WF_FDC1772_IP/wf1772ip_transceiver.vhd
Normal file
@@ -0,0 +1,517 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- WD1772 compatible floppy disk controller IP Core. ----
|
||||
---- ----
|
||||
---- This file is part of the SUSKA ATARI clone project. ----
|
||||
---- http://www.experiment-s.de ----
|
||||
---- ----
|
||||
---- Description: ----
|
||||
---- Floppy disk controller with all features of the Western ----
|
||||
---- Digital WD1772-02 controller. ----
|
||||
---- ----
|
||||
---- The transceiver unit contains on the one hand the receiver ----
|
||||
---- part which strips off the clock signal from the data stream ----
|
||||
---- and on the other hand the transmitter unit which provides in ----
|
||||
---- the different modes (FM and MFM) all functions which are ----
|
||||
---- necessary to send data, CRC bytes, 'FF', '00' or the address ----
|
||||
---- marks. ----
|
||||
---- ----
|
||||
---- ----
|
||||
---- To Do: ----
|
||||
---- - ----
|
||||
---- ----
|
||||
---- Author(s): ----
|
||||
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- MFM_In and MASK_SHFT have now synchronous reset to meet preset requirement.
|
||||
--
|
||||
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity WF1772IP_TRANSCEIVER is
|
||||
port(
|
||||
-- System control
|
||||
CLK : in bit; -- must be 16MHz
|
||||
RESETn : in bit;
|
||||
|
||||
-- Data and Control:
|
||||
HDTYPE : in bit; -- Floppy type HD or DD.
|
||||
DDEn : in bit; -- Double density select (FM or MFM).
|
||||
ID_AM : in bit; -- ID addressmark strobe.
|
||||
DATA_AM : in Bit; -- Data addressmark strobe.
|
||||
DDATA_AM : in Bit; -- Deleted data addressmark strobe.
|
||||
SHFT_LOAD_SD : in bit; -- Indication for shift register load time.
|
||||
DR : in bit_vector(7 downto 0); -- Content of the data register.
|
||||
|
||||
-- Data strobes:
|
||||
PLL_DSTRB : in bit; -- Clock strobe for RD serial data input.
|
||||
DATA_STRB : buffer bit;
|
||||
|
||||
-- Data strobe and data for the CRC during write operation:
|
||||
WDATA : buffer bit;
|
||||
|
||||
-- Encoder (logic to disk):
|
||||
PRECOMP_EN : in bit; -- control signal for MFM write precompensation.
|
||||
AM_TYPE : in bit; -- Write deleted address mark in MFM mode when 0.
|
||||
AM_2_DISK : in bit;
|
||||
DSR_2_DISK : in bit;
|
||||
FF_2_DISK : in bit;
|
||||
CRC_2_DISK : in bit;
|
||||
SR_SDOUT : in std_logic; -- encoder's data input from the shift register (serial).
|
||||
CRC_SDOUT : in bit; -- encoder's data input from the CRC unit (serial).
|
||||
WRn : out bit; -- write output for the MFM drive containing clock and data.
|
||||
|
||||
-- Decoder (disk to logic):
|
||||
PLL_D : in bit; -- Serial data input.
|
||||
SD_R : out bit -- Serial (decoded) data output.
|
||||
);
|
||||
end WF1772IP_TRANSCEIVER;
|
||||
|
||||
architecture BEHAVIOR of WF1772IP_TRANSCEIVER is
|
||||
type MFM_STATES is (A_00, B_01, C_10);
|
||||
type PRECOMP_VALUES is (EARLY, NOMINAL, LATE);
|
||||
type DEC_STATES is (CLK_PHASE, DATA_PHASE);
|
||||
|
||||
signal MFM_STATE : MFM_STATES;
|
||||
signal NEXT_MFM_STATE : MFM_STATES;
|
||||
signal PRECOMP : PRECOMP_VALUES;
|
||||
signal DEC_STATE : DEC_STATES;
|
||||
signal NEXT_DEC_STATE : DEC_STATES;
|
||||
|
||||
signal FM_In : bit;
|
||||
|
||||
signal CLKMASK : bit; -- Control for suppression of FM clock transitions.
|
||||
|
||||
signal MFM_10_STRB : bit;
|
||||
signal MFM_01_STRB : bit;
|
||||
|
||||
signal WR_CNT : std_logic_vector(3 downto 0);
|
||||
signal MFM_In : bit;
|
||||
|
||||
signal AM_SHFT : bit_vector(31 downto 0);
|
||||
|
||||
begin
|
||||
-- ####################### encoder stuff ###########################
|
||||
ADRMARK: process(RESETn, CLK)
|
||||
-- This process provides the address mark data for both FM and MFM in
|
||||
-- write to disk mode. In FM only one byte is written where in MFM
|
||||
-- 3 sync bytes x"A1" and one data address mark is written.
|
||||
-- In this process only the data address mark is provided. The only way
|
||||
-- writing the ID address mark is the write track command.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
AM_SHFT <= (others => '0');
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if AM_2_DISK = '1' and DATA_STRB = '1' then
|
||||
AM_SHFT <= AM_SHFT (30 downto 0) & '0'; -- Shift out.
|
||||
elsif AM_2_DISK = '0' and DDEn = '1' and AM_TYPE = '0' then -- FM mode.
|
||||
AM_SHFT <= x"F8000000"; -- Load deleted FM address mark.
|
||||
elsif AM_2_DISK = '0' and DDEn = '1' and AM_TYPE = '1' then -- FM mode.
|
||||
AM_SHFT <= x"FB000000"; -- Load normal FM address mark.
|
||||
elsif AM_2_DISK = '0' and DDEn = '0' and AM_TYPE = '0' then -- MFM mode deleted data mark.
|
||||
AM_SHFT <= x"A1A1A1F8"; -- Load MFM syncs and address mark.
|
||||
elsif AM_2_DISK = '0' and DDEn = '0' and AM_TYPE = '1' then -- Default: MFM mode normal data mark.
|
||||
AM_SHFT <= x"A1A1A1FB"; -- Load MFM syncs and address mark.
|
||||
end if;
|
||||
end if;
|
||||
end process ADRMARK;
|
||||
|
||||
-- Input multiplexer:
|
||||
WDATA <= AM_SHFT(31) when AM_2_DISK = '1' else -- Address mark data data.
|
||||
To_Bit(SR_SDOUT) when DSR_2_DISK = '1' else -- Shift register data.
|
||||
CRC_SDOUT when CRC_2_DISK = '1' else -- CRC data.
|
||||
'1' when FF_2_DISK = '1' else '0'; -- Write zeros is default.
|
||||
|
||||
-- Output multiplexer:
|
||||
WRn <= '0' when FM_In = '0' and DDEn = '1' else -- FM portion.
|
||||
'0' when MFM_In = '0' and DDEn = '0' else '1'; -- MFM portion and default.
|
||||
|
||||
CLK_MASK: process(CLK)
|
||||
-- This part of software controls the suppression of the clock pulses
|
||||
-- during transmission of several FM special characters. During writing
|
||||
-- 'normal' data to the disk, only 8 mask bits of the shift register are
|
||||
-- used. During writing MFM sync and address mark bits, the register is
|
||||
-- used with 32 mask bits.
|
||||
variable MASK_SHFT : bit_vector(23 downto 0);
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if CLK = '1' and CLK' event then
|
||||
if RESETn = '0' then
|
||||
MASK_SHFT := (others => '1');
|
||||
LOCK := false;
|
||||
-- Load the mask shift register just in time when the shift register is
|
||||
-- loaded with valid data from the data register.
|
||||
elsif SHFT_LOAD_SD = '1' and DDEn = '1' then -- FM mode.
|
||||
case DR is
|
||||
when x"F8" | x"F9" | x"FA" | x"FB" | x"FE" => MASK_SHFT := x"C7FFFF";
|
||||
when x"FC" => MASK_SHFT := x"D7FFFF";
|
||||
when x"F5" | x"F6" => MASK_SHFT := (others => '0'); -- Not allowed.
|
||||
when others => MASK_SHFT := x"FFFFFF"; -- Normal data.
|
||||
end case;
|
||||
elsif SHFT_LOAD_SD = '1' and DDEn = '0' then -- MFM mode.
|
||||
case DR is
|
||||
when x"F5" => MASK_SHFT := x"FBFFFF"; -- Suppress clock pulse between bits 4 and 5.
|
||||
when x"F6" => MASK_SHFT := x"F7FFFF"; -- Suppress clock pulse between bits 3 and 4.
|
||||
when others => MASK_SHFT := x"FFFFFF"; -- Normal data.
|
||||
end case;
|
||||
elsif AM_2_DISK = '1' and DDEn = '1' and LOCK = false then -- FM mode.
|
||||
MASK_SHFT := x"C7FFFF"; -- Load just once per AM_2_DISK rising edge.
|
||||
LOCK := true;
|
||||
elsif AM_2_DISK = '1' and DDEn = '0' and LOCK = false then -- MFM mode.
|
||||
MASK_SHFT := x"FBFBFB"; -- Three syncs with suppressed clock pulse then transparent mask.
|
||||
LOCK := true;
|
||||
elsif DATA_STRB = '1' then -- shift as long as transmission is active
|
||||
-- The Shift register is shifted left. After shifting the clockmasks out it is
|
||||
-- transparent due to the '1's filled up from the left.
|
||||
MASK_SHFT := MASK_SHFT(22 downto 0) & '1'; -- Shift left.
|
||||
elsif AM_2_DISK = '0' then
|
||||
LOCK := false; -- Release the lock after address mark has been written.
|
||||
end if;
|
||||
end if;
|
||||
CLKMASK <= MASK_SHFT(23);
|
||||
end process CLK_MASK;
|
||||
|
||||
FM_ENCODER: process (RESETn, DATA_STRB, CLK)
|
||||
-- For DD type floppies the data rate is 125kBps. Therefore there are 128 16-MHz clocks cycles
|
||||
-- per FM bit.
|
||||
-- For HD type floppies the data rate is 250kBps. Therefore there are 64 16-MHz clocks cycles
|
||||
-- per FM bit.
|
||||
-- The FM write pulse width is 1.375us for DD and 0.750us HD type floppies.
|
||||
-- This process provides the FM encoded signal. The first pulse is in any case the clock
|
||||
-- pulse and the second pulse is due to data. The FM encoding is very simple and therefore
|
||||
-- self explaining.
|
||||
variable CNT : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
FM_In <= '1';
|
||||
CNT := x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
-- In case of HD type floppies the counter reaches a value of b"0100000"
|
||||
-- In case of DD type floppies the counter reaches a value of b"1000000"
|
||||
if DATA_STRB = '1' then
|
||||
CNT := x"00";
|
||||
else
|
||||
CNT := CNT + '1';
|
||||
end if;
|
||||
-- The flux reversal pulses are centered between the DATA_STRB pulses.
|
||||
-- In detail: the clock pulse appears in the middle of the first half
|
||||
-- of the DATA_STRB period and the data pulse appears in the middle of
|
||||
-- the second half.
|
||||
case HDTYPE is
|
||||
when '0' => -- DD type floppies:
|
||||
if CNT > "00010101" and CNT <= "00101011" then
|
||||
FM_In <= not CLKMASK; -- FM clock.
|
||||
elsif CNT > "01010101" and CNT <= "01101011" then
|
||||
FM_In <= not WDATA; -- FM data.
|
||||
else
|
||||
FM_In <= '1';
|
||||
end if;
|
||||
when '1' => -- HD type floppies:
|
||||
if CNT > "00001010" and CNT <= "00010110" then
|
||||
FM_In <= not CLKMASK; -- FM clock.
|
||||
elsif CNT > "00101010" and CNT <= "00110110" then
|
||||
FM_In <= not WDATA; -- FM data.
|
||||
else
|
||||
FM_In <= '1';
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end process FM_ENCODER;
|
||||
|
||||
MFM_ENCODE_REG: process(RESETn, CLK)
|
||||
-- This process is the first portion of the more complicated MFM encoder. It can be interpreted
|
||||
-- as a Moore machine. This part is the current state register.
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
MFM_STATE <= A_00;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
MFM_STATE <= NEXT_MFM_STATE;
|
||||
end if;
|
||||
end process MFM_ENCODE_REG;
|
||||
|
||||
MFM_ENCODE_LOGIC: process(MFM_STATE, WDATA, DATA_STRB)
|
||||
-- Rules for Encoding:
|
||||
-- transitions are never located at the mid point of a 'zero'.
|
||||
-- transistions are always located at the mid point of a '1'.
|
||||
-- no transitions at the borders of a '1'.
|
||||
-- transitions appear between two adjacent 'zeros'.
|
||||
-- states are as follows:
|
||||
-- A_00: idle state, no transition.
|
||||
-- B_01: transistion between the MFM clock edges.
|
||||
-- C_10: transition on the leading MFM clock edges.
|
||||
-- The timing of the MFM output is done in the process MFM_WR_OUT.
|
||||
begin
|
||||
case MFM_STATE is
|
||||
when A_00 =>
|
||||
if WDATA = '0' and DATA_STRB = '1' then
|
||||
NEXT_MFM_STATE <= C_10;
|
||||
elsif WDATA = '1' and DATA_STRB = '1' then
|
||||
NEXT_MFM_STATE <= B_01;
|
||||
else
|
||||
NEXT_MFM_STATE <= A_00; -- Stay, if there is no strobe.
|
||||
end if;
|
||||
when C_10 =>
|
||||
if WDATA = '0' and DATA_STRB = '1' then
|
||||
NEXT_MFM_STATE <= C_10;
|
||||
elsif WDATA = '1' and DATA_STRB = '1' then
|
||||
NEXT_MFM_STATE <= B_01;
|
||||
else
|
||||
NEXT_MFM_STATE <= C_10; -- Stay, if there is no strobe.
|
||||
end if;
|
||||
when B_01 =>
|
||||
if WDATA = '0' and DATA_STRB = '1' then
|
||||
NEXT_MFM_STATE <= A_00;
|
||||
elsif WDATA = '1' and DATA_STRB = '1' then
|
||||
NEXT_MFM_STATE <= B_01;
|
||||
else
|
||||
NEXT_MFM_STATE <= B_01; -- Stay, if there is no strobe.
|
||||
end if;
|
||||
end case;
|
||||
end process MFM_ENCODE_LOGIC;
|
||||
|
||||
MFM_PRECOMPENSATION: process(RESETn, CLK)
|
||||
-- The write pattern is adjusted in the MFM write timing process as follows:
|
||||
-- after DATA_STRB (the duty cycle of this strobe is exactly one CLK) the
|
||||
-- incoming data is bufferd in WRITEPATTERN. After the following DATA_STRB
|
||||
-- the WDATA is shifted through WRITEPATTERN. After further DATA_STRBs the
|
||||
-- WRITEPATTERN consists of previous, current and next WDATA like this:
|
||||
-- WRITEPATTERN(3) is the second previous WDATA.
|
||||
-- WRITEPATTERN(2) is the previous WDATA.
|
||||
-- WRITEPATTERN(1) is the current WDATA to be sent.
|
||||
-- WRITEPATTERN(0) is the next WDATA to be sent.
|
||||
variable WRITEPATTERN : bit_vector(3 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
PRECOMP <= NOMINAL;
|
||||
WRITEPATTERN := "0000";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DATA_STRB = '1' then
|
||||
WRITEPATTERN := WRITEPATTERN(2 downto 0) & WDATA; -- shift left
|
||||
end if;
|
||||
if PRECOMP_EN = '0' then
|
||||
PRECOMP <= NOMINAL; -- no precompensation
|
||||
else
|
||||
case WRITEPATTERN is
|
||||
when "1110" | "0110" => PRECOMP <= EARLY;
|
||||
when "1011" | "0011" => PRECOMP <= LATE;
|
||||
when "0001" => PRECOMP <= EARLY;
|
||||
when "1000" => PRECOMP <= LATE;
|
||||
when others => PRECOMP <= NOMINAL;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process MFM_PRECOMPENSATION;
|
||||
|
||||
MFM_STROBES: process (RESETn, DATA_STRB, CLK)
|
||||
-- For the MFM frequency is 250 kBps for DD type floppies, there are 64
|
||||
-- 16 MHz clock cycles per MFM bit and for HD type floppies, which have
|
||||
-- 500 kBps there are 32 16MHz clock pulses for one MFM bit.
|
||||
-- The MFM state machine (Moore) switches on the DATA_STRB.
|
||||
-- During one cycle there are the two further strobes MFM_10_STRB and
|
||||
-- MFM_01_STRB which control the MFM output in the process MFM_WR_OUT.
|
||||
-- The strobes are centered in the middle of the first half and in the
|
||||
-- middle of the second half of the DATA_STRB cycle.
|
||||
variable CNT : std_logic_vector(5 downto 0);
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
CNT := "000000";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DATA_STRB = '1' then
|
||||
CNT := (others => '0');
|
||||
else
|
||||
CNT := CNT + '1';
|
||||
end if;
|
||||
if HDTYPE = '1' then
|
||||
case CNT is
|
||||
-- encoder timing for MFM and HD type floppies.
|
||||
when "000100" => MFM_10_STRB <= '1'; MFM_01_STRB <= '0'; -- Pulse centered in the first half.
|
||||
when "010100" => MFM_10_STRB <= '0'; MFM_01_STRB <= '1'; -- Pulse centered in the second half.
|
||||
when others => MFM_10_STRB <= '0'; MFM_01_STRB <= '0';
|
||||
end case;
|
||||
else
|
||||
case CNT is
|
||||
-- encoder timing for MFM and DD type floppies.
|
||||
when "001010" => MFM_10_STRB <= '1'; MFM_01_STRB <= '0'; -- Pulse centered in the first half.
|
||||
when "101000" => MFM_10_STRB <= '0'; MFM_01_STRB <= '1'; -- Pulse centered in the second half.
|
||||
when others => MFM_10_STRB <= '0'; MFM_01_STRB <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process MFM_STROBES;
|
||||
|
||||
-- MFM_WR_TIMING generates the timing for the write pulses which are
|
||||
-- required by a MFM device like floppy disk drive. The pulse timing
|
||||
-- meets the timing of the MFM data with pulse width of 700ns +/- 100ns
|
||||
-- depending on write precompensation.
|
||||
-- The original WD1772 (CLK = 8MHz) data timing was as follows:
|
||||
-- The output is asserted as long as CNT is active; in detail
|
||||
-- this are 4,5; 5,5 or 6,5 CLK cycles depending on the write
|
||||
-- precompensation.
|
||||
-- The new design which works with a 16MHz clock requires the following
|
||||
-- timing: 9; 11 or 13 CLK cycles depending on the writeprecompensation
|
||||
-- for DD floppies and 5; 6 or 7 CLK cycles depending on the write
|
||||
-- precompensation for HD floppies.
|
||||
-- To meet the timing requirements of half clocks
|
||||
-- the WRn is controlled by the following three processes where the one
|
||||
-- syncs on the positive clock edge and the other on the negative.
|
||||
-- For more information on the WTn timing see the datasheet of the
|
||||
-- WD177x floppy disc controller.
|
||||
|
||||
MFM_WR_TIMING: process(RESETn, CLK)
|
||||
variable CLKMASK_MFM : bit;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
WR_CNT <= x"F";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DATA_STRB = '1' then
|
||||
-- The CLKMASK_MFM is synchronised to DATA_STRB. This brings one strobe latency.
|
||||
-- The timing in connection with the data is correct because the MFM encoder state machine
|
||||
-- causes the data to be 1 DATA_STRB late too.
|
||||
CLKMASK_MFM := CLKMASK;
|
||||
end if;
|
||||
if MFM_STATE = C_10 and MFM_10_STRB = '1' and CLKMASK_MFM = '1' then
|
||||
WR_CNT <= x"0";
|
||||
elsif MFM_STATE = B_01 and MFM_01_STRB = '1' then
|
||||
WR_CNT <= x"0";
|
||||
elsif WR_CNT < x"F" then
|
||||
WR_CNT <= WR_CNT + '1';
|
||||
end if;
|
||||
end if;
|
||||
end process MFM_WR_TIMING;
|
||||
|
||||
MFM_WR_OUT: process
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RESETn = '0' then
|
||||
MFM_In <= '1';
|
||||
else
|
||||
case HDTYPE is
|
||||
when '1' => -- HD type.
|
||||
if PRECOMP = EARLY and WR_CNT > x"0" and WR_CNT <= x"9" then
|
||||
MFM_In <= '0'; -- 9,0 clock cycles for WRn --> early timing
|
||||
elsif PRECOMP = NOMINAL and WR_CNT > x"0" and WR_CNT <= x"8" then
|
||||
MFM_In <= '0'; -- 8,0 clock cycles for WRn --> nominal timing
|
||||
elsif PRECOMP = LATE and WR_CNT > x"0" and WR_CNT <= x"7" then
|
||||
MFM_In <= '0'; -- 7,0 clock cycles for WRn --> late timing
|
||||
else
|
||||
MFM_In <= '1';
|
||||
end if;
|
||||
when '0' => -- DD type.
|
||||
if PRECOMP = EARLY and WR_CNT > x"0" and WR_CNT <= x"D" then
|
||||
MFM_In <= '0'; -- 13,0 clock cycles for WRn --> early timing
|
||||
elsif PRECOMP = NOMINAL and WR_CNT > x"0" and WR_CNT <= x"B" then
|
||||
MFM_In <= '0'; -- 11,0 clock cycles for WRn --> nominal timing
|
||||
elsif PRECOMP = LATE and WR_CNT > x"0" and WR_CNT <= x"9" then
|
||||
MFM_In <= '0'; -- 9,0 clock cycles for WRn --> late timing
|
||||
else
|
||||
MFM_In <= '1';
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end process MFM_WR_OUT;
|
||||
|
||||
-- ####################### Decoder stuff ###########################
|
||||
-- The decoding of the serial FM or MFM encoded data stream
|
||||
-- is done in the following two processes (Moore machine).
|
||||
-- The decoder works in principle like a simple toggle Flip-Flop.
|
||||
-- It is important to synchronise it in a way, that the clock
|
||||
-- pulses are separated from the data pulses. The principle
|
||||
-- works for both FM and MFM data due to the digital phase
|
||||
-- locked loop, which delivers the serial data and the clock
|
||||
-- strobe. In general this decoder can be understood as the
|
||||
-- data separator where the digital phase locked loop provides
|
||||
-- the FM or the MFM decoding. The data separation lives from
|
||||
-- the fact, that FM and also MFM encoded signals consist of a
|
||||
-- mixture of alternating data and clock pulses.
|
||||
-- FM works as follows:
|
||||
-- every first pulse of the FM signal is a clock pulse and every
|
||||
-- second pulse is a logic '1' of the data. A missing second
|
||||
-- pulse represents a logic '0' of the data.
|
||||
-- MFM works as follows:
|
||||
-- every first pulse of the MFM signal is a clock pulse. The coding
|
||||
-- principle causes clock pulses to be absent in some conditions.
|
||||
-- Every second pulse is a logic '1' of the data. A missing second
|
||||
-- pulse represents a logic '0' of the data.
|
||||
-- So FM and MFM compared, the data is represented directly by the
|
||||
-- second pulses and the data separator has to look only for these.
|
||||
-- The missing MFM clock pulses do not cause a problem because the
|
||||
-- digital PLL used in conjunction with this data separator fills
|
||||
-- up the clock pulses and delivers a PLL_DSTRB containing aequidistant
|
||||
-- clock strobes and data strobes.
|
||||
|
||||
DEC_REG: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
DEC_STATE <= CLK_PHASE;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
DEC_STATE <= NEXT_DEC_STATE;
|
||||
end if;
|
||||
end process DEC_REG;
|
||||
|
||||
DEC_LOGIC: process(DEC_STATE, ID_AM, DATA_AM, DDATA_AM, PLL_DSTRB, PLL_D)
|
||||
begin
|
||||
case DEC_STATE is
|
||||
when CLK_PHASE =>
|
||||
if PLL_DSTRB = '1' then
|
||||
NEXT_DEC_STATE <= DATA_PHASE;
|
||||
else
|
||||
NEXT_DEC_STATE <= CLK_PHASE;
|
||||
end if;
|
||||
DATA_STRB <= '0'; -- Inactive during clock pulse time.
|
||||
SD_R <= '0'; -- Inactive during clock pulse time.
|
||||
when DATA_PHASE =>
|
||||
if ID_AM = '1' or DATA_AM = '1' or DDATA_AM = '1' then
|
||||
-- Here the state machine is synchronised
|
||||
-- to separate data and clock pulses correctly.
|
||||
NEXT_DEC_STATE <= CLK_PHASE;
|
||||
elsif PLL_DSTRB = '1' then
|
||||
NEXT_DEC_STATE <= CLK_PHASE;
|
||||
else
|
||||
NEXT_DEC_STATE <= DATA_PHASE;
|
||||
end if;
|
||||
-- During the data phase valid data appears at SD.
|
||||
-- The data is valid during DATA_STRB.
|
||||
DATA_STRB <= PLL_DSTRB;
|
||||
SD_R <= PLL_D;
|
||||
end case;
|
||||
end process DEC_LOGIC;
|
||||
end architecture BEHAVIOR;
|
||||
Reference in New Issue
Block a user