now gets accepted by Modelsim
This commit is contained in:
@@ -51,22 +51,22 @@
|
||||
--
|
||||
-- Revision 2006A 2006/06/03 WF
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/05 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- 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 2K8A 2008/02/26 WF
|
||||
-- Fixed a bug in the 6ms delay. Thanks to Lyndon Amsdon.
|
||||
-- Revision 2K8B 2008/12/24 WF
|
||||
-- Bugfixes to avoid hanging state machine.
|
||||
-- Changed DELAY_30MS to DELAY_15MS, which is the correct value. Thanks to L. Amsdon for the information.
|
||||
-- Removed CRC_BUSY.
|
||||
-- Fixed a bug in the Delay for the state T2_VERIFY_AM.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- Fix to provide correct LOST_DATA_TR00 flag during seek command.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- Fixed the timing for DR_LOAD.
|
||||
-- Revision 2K8A 2008/02/26 WF
|
||||
-- Fixed a bug in the 6ms delay. Thanks to Lyndon Amsdon.
|
||||
-- Revision 2K8B 2008/12/24 WF
|
||||
-- Bugfixes to avoid hanging state machine.
|
||||
-- Changed DELAY_30MS to DELAY_15MS, which is the correct value. Thanks to L. Amsdon for the information.
|
||||
-- Removed CRC_BUSY.
|
||||
-- Fixed a bug in the Delay for the state T2_VERIFY_AM.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- Fix to provide correct LOST_DATA_TR00 flag during seek command.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- Fixed the timing for DR_LOAD.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
@@ -74,7 +74,7 @@ use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity WF1772IP_CONTROL is
|
||||
port(
|
||||
port(
|
||||
-- System control:
|
||||
CLK : in std_logic;
|
||||
RESETn : in std_logic;
|
||||
@@ -83,7 +83,7 @@ entity WF1772IP_CONTROL is
|
||||
A1, A0 : in std_logic;
|
||||
RWn : in std_logic;
|
||||
CSn : in std_logic;
|
||||
DDEn : in std_logic;
|
||||
DDEn : in std_logic;
|
||||
|
||||
-- Registers:
|
||||
DR : in std_logic_vector(7 downto 0); -- Data register.
|
||||
@@ -129,7 +129,7 @@ entity WF1772IP_CONTROL is
|
||||
-- DATA register control:
|
||||
DR_CLR : out std_logic; -- Clear.
|
||||
DR_LOAD : out std_logic; -- LOAD.
|
||||
|
||||
|
||||
-- Shift register control:
|
||||
SHFT_LOAD_ND : out std_logic; -- Load normal data.
|
||||
SHFT_LOAD_SD : out std_logic; -- Load special data.
|
||||
@@ -175,7 +175,7 @@ architecture BEHAVIOR of WF1772IP_CONTROL is
|
||||
signal DATA_RD : boolean;
|
||||
signal CMD_WR : boolean;
|
||||
signal STAT_RD : boolean;
|
||||
signal DELAY : boolean;
|
||||
signal DELAY : boolean;
|
||||
signal DRQ_I : std_logic;
|
||||
signal INDEX_CNT : boolean;
|
||||
signal DIR : std_logic;
|
||||
@@ -186,12 +186,12 @@ architecture BEHAVIOR of WF1772IP_CONTROL is
|
||||
signal SECT_LEN : unsigned (10 downto 0);
|
||||
signal TRACKMEM : std_logic_vector(7 downto 0);
|
||||
signal T3_TRADR : boolean;
|
||||
signal T3_DATATYPE : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
signal T3_DATATYPE : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
-- The Forced interrupt stops any command at the end of an internal micro instruction.
|
||||
-- Forced interrupt waits until ALU operations in progress are complete (CRC calculations,
|
||||
-- compares etc.). the TYPE_IV_BREAK controls this behavior.
|
||||
TYPE_IV_BREAK <= true when CMD(7 downto 4) = x"D" and DELAY = true else false;
|
||||
TYPE_IV_BREAK <= true when CMD(7 downto 4) = x"D" and DELAY = true else false;
|
||||
|
||||
CMD_REG: process(RESETn, CLK)
|
||||
begin
|
||||
@@ -255,7 +255,7 @@ begin
|
||||
when DECODE =>
|
||||
case CMD(7 downto 5) is
|
||||
when "000" => -- 'restore', 'seek'.
|
||||
NEXT_CMD_STATE <= T1_SEEK_RESTORE;
|
||||
NEXT_CMD_STATE <= T1_SEEK_RESTORE;
|
||||
when "001" |"010" | "011" => -- 'step', 'step in', 'step out'.
|
||||
NEXT_CMD_STATE <= T1_STEPPING;
|
||||
when "100" | "101" => -- 'read sector', 'write sector'
|
||||
@@ -271,9 +271,9 @@ begin
|
||||
when '1' => NEXT_CMD_STATE <= T3_WR;
|
||||
when others => NEXT_CMD_STATE <= T3_WR; -- Dummy for U, X, Z, W, H, L, -.
|
||||
end case;
|
||||
when others =>
|
||||
-- The following NEXT_CMD_STATE is chosen to compile fine with
|
||||
-- the Xilinx ISE not to produce a latch.
|
||||
when others =>
|
||||
-- The following NEXT_CMD_STATE is chosen to compile fine with
|
||||
-- the Xilinx ISE not to produce a latch.
|
||||
NEXT_CMD_STATE <= IDLE; -- Never true due to IDLE preselection.
|
||||
end case;
|
||||
--------------------------------------------------------------------
|
||||
@@ -283,7 +283,7 @@ begin
|
||||
-- In this state, the data register and the track register are updated, if the
|
||||
-- command is a RESTORE. The update is done further down with the track register
|
||||
-- and the data register controls.
|
||||
NEXT_CMD_STATE <= T1_LOAD_SHFT;
|
||||
NEXT_CMD_STATE <= T1_LOAD_SHFT;
|
||||
when T1_STEPPING =>
|
||||
if CMD(4) = '1' then -- '1' means update track register.
|
||||
NEXT_CMD_STATE <= T1_CHECK_DIR;
|
||||
@@ -315,7 +315,7 @@ begin
|
||||
else
|
||||
NEXT_CMD_STATE <= T1_STEP;
|
||||
end if;
|
||||
when T1_STEP =>
|
||||
when T1_STEP =>
|
||||
NEXT_CMD_STATE <= T1_TRAP;
|
||||
when T1_TRAP =>
|
||||
if STEP_TRAP = true then
|
||||
@@ -373,16 +373,16 @@ begin
|
||||
else
|
||||
NEXT_CMD_STATE <= T1_SCAN_CRC;
|
||||
end if;
|
||||
when T1_VERIFY_CRC =>
|
||||
-- The CRC logic starts during T1_SPINDOWN (missing clock transitions).
|
||||
when T1_VERIFY_CRC =>
|
||||
-- The CRC logic starts during T1_SPINDOWN (missing clock transitions).
|
||||
if DELAY = true then
|
||||
if CRC_ERR = '1' then
|
||||
NEXT_CMD_STATE <= T1_SPINDOWN; -- CRC error.
|
||||
else
|
||||
NEXT_CMD_STATE <= IDLE; -- Operation finished.
|
||||
end if;
|
||||
else
|
||||
NEXT_CMD_STATE <= T1_VERIFY_CRC; -- Wait until CRC logic is ready.
|
||||
end if;
|
||||
else
|
||||
NEXT_CMD_STATE <= T1_VERIFY_CRC; -- Wait until CRC logic is ready.
|
||||
end if;
|
||||
--------------------------------------------------------------------
|
||||
------------------ special type2 command stuff ---------------------
|
||||
@@ -737,7 +737,7 @@ begin
|
||||
DELCNT := DELCNT + 1;
|
||||
-- Bit count delays work on data strobes.
|
||||
-- Read from disk operation:
|
||||
when T1_SCAN_TRACK | T1_SCAN_CRC | T1_VERIFY_CRC | T2_SCAN_TRACK | T2_SCAN_SECT |
|
||||
when T1_SCAN_TRACK | T1_SCAN_CRC | T1_VERIFY_CRC | T2_SCAN_TRACK | T2_SCAN_SECT |
|
||||
T2_SCAN_LEN | T2_VERIFY_CRC_1 | T2_VERIFY_AM | T2_FIRSTBYTE |
|
||||
T2_NEXTBYTE | T2_VERIFY_CRC_2 | T3_SHIFT | T3_SHIFT_ADR | T3_VERIFY_CRC =>
|
||||
if DATA_STRB = '1' then
|
||||
@@ -760,7 +760,7 @@ begin
|
||||
when DELAY_15MS | T1_VERIFY_DELAY =>
|
||||
case DELCNT is
|
||||
--when x"75300" => DELAY <= true; -- 30ms
|
||||
when x"3A980" => DELAY <= true; -- 15ms, thanks to L. Amsdon.
|
||||
when x"3A980" => DELAY <= true; -- 15ms, thanks to L. Amsdon.
|
||||
when others => DELAY <= false;
|
||||
end case;
|
||||
when T1_CHECK_DIR =>
|
||||
@@ -782,7 +782,7 @@ begin
|
||||
DELAY <= true;
|
||||
else
|
||||
DELAY <= false;
|
||||
end if;
|
||||
end if;
|
||||
when T1_SCAN_TRACK | T2_SCAN_TRACK | T2_SCAN_LEN | T2_FIRSTBYTE | T2_NEXTBYTE |
|
||||
T2_WR_BYTE | T2_DATALOST | T2_WR_FF | T3_DATALOST | T3_SHIFT_ADR =>
|
||||
case DELCNT is
|
||||
@@ -791,7 +791,7 @@ begin
|
||||
end case;
|
||||
when T1_SCAN_CRC =>
|
||||
case DELCNT is
|
||||
when x"00018" => DELAY <= true; -- Scan for 3 bytes.
|
||||
when x"00018" => DELAY <= true; -- Scan for 3 bytes.
|
||||
when others => DELAY <= false;
|
||||
end case;
|
||||
when T2_WR_AM =>
|
||||
@@ -803,9 +803,9 @@ begin
|
||||
DELAY <= false;
|
||||
end if;
|
||||
when T2_VERIFY_AM =>
|
||||
if DDEn = '1' and DELCNT >= x"00148" then -- FM mode.
|
||||
if DDEn = '1' and DELCNT >= x"00148" then -- FM mode.
|
||||
DELAY <= true; -- (11+6+1)+1 = 19 Byte Times, plus 10 Byte times uncertainty.
|
||||
elsif DDEn = '0' and DELCNT >= x"00188" then -- MFM mode.
|
||||
elsif DDEn = '0' and DELCNT >= x"00188" then -- MFM mode.
|
||||
DELAY <= true; -- (22+12+3+1)+1 = 39 Byte Times, plus 10 Byte times uncertainty.
|
||||
else
|
||||
DELAY <= false;
|
||||
@@ -846,7 +846,7 @@ begin
|
||||
case DELCNT is
|
||||
when x"00008" => DELAY <= true; -- Scan for 2 bytes but wait only 1 byte.
|
||||
when others => DELAY <= false;
|
||||
end case;
|
||||
end case;
|
||||
when T1_VERIFY_CRC | T2_SCAN_SECT | T2_VERIFY_CRC_1 | T2_DELAY_B2 | T2_WR_CRC | T3_VERIFY_CRC =>
|
||||
case DELCNT is
|
||||
when x"00010" => DELAY <= true; -- Scan for 2 bytes (e. g. side and sector in T2_SCAN_SECT).
|
||||
@@ -887,23 +887,23 @@ begin
|
||||
elsif CLK = '1' and CLK' event then
|
||||
case CMD_STATE is
|
||||
-- Be aware that there must sometimes checked several states for the presence of IPn!
|
||||
when SPINUP | T1_SPINDOWN | T1_SCAN_TRACK | T1_SCAN_CRC | T1_VERIFY_CRC |
|
||||
when SPINUP | T1_SPINDOWN | T1_SCAN_TRACK | T1_SCAN_CRC | T1_VERIFY_CRC |
|
||||
T2_INIT | T2_SCAN_TRACK | T2_SCAN_SECT |T2_SCAN_LEN | T2_VERIFY_CRC_1 | T3_RD_ADR | T3_VERIFY_AM =>
|
||||
if IPn = '0' and LOCK = false then -- Count the index pulses.
|
||||
if IPn = '0' and LOCK = false then -- Count the index pulses.
|
||||
CNT := CNT + 1;
|
||||
LOCK := true;
|
||||
elsif IPn = '1' then
|
||||
LOCK := false;
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
if TIMEOUT < x"17FFFFF" then -- Timeout of about 1.5s.
|
||||
TIMEOUT := TIMEOUT + 1;
|
||||
TIMEOUT := TIMEOUT + 1;
|
||||
end if;
|
||||
when others =>
|
||||
CNT := x"0";
|
||||
TIMEOUT := (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
if CMD_STATE = SPINUP and (CNT = "110" or TIMEOUT = x"17FFFFF") then -- 6 pulses or timeout.
|
||||
INDEX_CNT <= true;
|
||||
@@ -1042,9 +1042,9 @@ begin
|
||||
if (DATA_RD = true or DATA_WR = true) then
|
||||
DRQ_I <= '0';
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
DRQ <= DRQ_I; -- Copy to entity.
|
||||
end if;
|
||||
--
|
||||
DRQ <= DRQ_I; -- Copy to entity.
|
||||
--
|
||||
end process P_DRQ;
|
||||
|
||||
@@ -1066,7 +1066,7 @@ begin
|
||||
elsif CMD_STATE = IDLE then
|
||||
BUSY <= '0'; -- Reset BUSY after entering IDLE in any case.
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process P_BUSY;
|
||||
|
||||
P_SEEK_RNF: process(RESETn, CLK)
|
||||
@@ -1094,7 +1094,7 @@ begin
|
||||
if RESETn = '0' then
|
||||
INTRQ <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
-- Interrupt reset conditions:
|
||||
-- Interrupt reset conditions:
|
||||
if STAT_RD = true and CMD /= x"D8" then
|
||||
-- No clear during immediately forced interrupt.
|
||||
INTRQ <= '0'; -- Clear the flag when status register is read.
|
||||
@@ -1191,7 +1191,7 @@ begin
|
||||
elsif IPn = '1' then
|
||||
LOCK := false;
|
||||
end if;
|
||||
--
|
||||
--
|
||||
if CMD_STATE = INIT and CMD_WR = false then
|
||||
MO <= '1'; -- Start the motor for all command types I ... III in this state.
|
||||
elsif INDEXCNT = x"0" then
|
||||
@@ -1248,7 +1248,7 @@ begin
|
||||
null;
|
||||
end case;
|
||||
end if;
|
||||
end process WRITEGATE;
|
||||
end process WRITEGATE;
|
||||
|
||||
RESTORE_TRAP: process(RESETn, CLK)
|
||||
-- This process is responsible to supervise the RESTORE command.
|
||||
@@ -1267,7 +1267,7 @@ begin
|
||||
elsif CMD_STATE = T1_STEP and STEP_CNT < x"FF" then
|
||||
STEP_CNT := STEP_CNT + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
case STEP_CNT is
|
||||
when x"FF" => STEP_TRAP <= true;
|
||||
@@ -1286,7 +1286,8 @@ begin
|
||||
if CMD_STATE = T1_STEP then
|
||||
case DDEn is
|
||||
when '1' => CNT := x"80"; --Start counter for FM step pulse.
|
||||
when '0' => CNT := x"40"; --Start counter for MFM step pulse.
|
||||
when '0' => CNT := x"40"; --Start counter for MFM step pulse.
|
||||
when others => CNT := x"80";
|
||||
end case;
|
||||
elsif CNT > x"00" then
|
||||
CNT := CNT - 1; -- Count 63 or 127 CLK cycles ...
|
||||
@@ -1380,10 +1381,10 @@ begin
|
||||
STAT_RD <= true when CSn = '0' and A1 = '0' and A0 = '0' and RWn = '1' else false; -- Status register read.
|
||||
DATA_WR <= true when CSn = '0' and A1 = '1' and A0 = '1' and RWn = '0' else false; -- Data register write.
|
||||
DATA_RD <= true when CSn = '0' and A1 = '1' and A0 = '1' and RWn = '1' else false; -- Data register read.
|
||||
|
||||
|
||||
-- Track register arithmetics controls:
|
||||
TR_PRES <= '1' when CMD_STATE = T1_SEEK_RESTORE and CMD(7 downto 4) = "0000" else '0'; -- Restore command.
|
||||
TR_CLR <= '1' when CMD_STATE = T1_HEAD_CTRL and TRACK00n = '0' and DIR = '0' else '0';
|
||||
TR_CLR <= '1' when CMD_STATE = T1_HEAD_CTRL and TRACK00n = '0' and DIR = '0' else '0';
|
||||
TR_INC <= '1' when CMD_STATE = T1_CHECK_DIR and DELAY = true and DIR = '1' else '0';
|
||||
TR_DEC <= '1' when CMD_STATE = T1_CHECK_DIR and DELAY = true and DIR = '0' else '0';
|
||||
|
||||
@@ -1445,7 +1446,7 @@ begin
|
||||
PRECOMP_EN <= '1' when CMD(7 downto 4) = x"A" and CMD(1) = '0' else -- Write single sector.
|
||||
'1' when CMD(7 downto 4) = x"B" and CMD(1) = '0' else -- Write multiple sector.
|
||||
'1' when CMD(7 downto 4) = x"F" and CMD(1) = '0' else '0'; -- Write track.
|
||||
|
||||
|
||||
-- Disk data flow direction:
|
||||
DISK_RWn <= -- Write sector command:
|
||||
'0' when CMD_STATE = T2_WR_LEADIN else
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
---- 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. ----
|
||||
---- 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: ----
|
||||
---- - ----
|
||||
@@ -69,13 +69,13 @@
|
||||
-- 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.
|
||||
-- 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;
|
||||
@@ -86,21 +86,21 @@ 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 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
|
||||
-- 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 : unsigned (7 downto 0) := to_unsigned(75, 8)
|
||||
TOP : integer range 0 to 255 := 152; -- +18.0%
|
||||
BOTTOM : integer range 0 to 255 := 104; -- -18.0%
|
||||
PHASE_CORR : unsigned (7 downto 0) := to_unsigned(75, 8)
|
||||
);
|
||||
port(
|
||||
-- System control
|
||||
CLK : in std_logic; -- 16MHz clock.
|
||||
RESETn : in std_logic;
|
||||
|
||||
|
||||
-- Controls
|
||||
DDEn : in std_logic; -- Double density enable.
|
||||
HDTYPE : in std_logic; -- This control is '1' when HD disks are inserted.
|
||||
@@ -117,7 +117,7 @@ architecture BEHAVIOR of WF1772IP_DIGITAL_PLL is
|
||||
signal RD_In : std_logic;
|
||||
signal UP, DOWN : std_logic;
|
||||
signal PHASE_DECREASE : std_logic;
|
||||
signal PHASE_INCREASE : std_logic;
|
||||
signal PHASE_INCREASE : std_logic;
|
||||
signal HI_STOP, LOW_STOP : std_logic;
|
||||
signal PER_CNT : unsigned (7 downto 0);
|
||||
signal ADDER_IN : unsigned (7 downto 0);
|
||||
@@ -126,17 +126,17 @@ signal RD_PULSE : std_logic;
|
||||
signal ROLL_OVER : std_logic;
|
||||
signal HISTORY_REG : std_logic_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;
|
||||
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
|
||||
-- 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.
|
||||
@@ -145,13 +145,13 @@ begin
|
||||
if RESETn = '0' then
|
||||
RD_PULSE <= '0';
|
||||
LOCK := false;
|
||||
elsif CLK = '1' and CLK' event then
|
||||
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
|
||||
elsif RD_In = '0' and LOCK = false then
|
||||
RD_PULSE <= '1'; -- READ_PULSE is inverted against RDn
|
||||
LOCK := true;
|
||||
elsif RD_In = '1' then
|
||||
elsif RD_In = '1' then
|
||||
LOCK := false;
|
||||
RD_PULSE <= '0';
|
||||
else
|
||||
@@ -161,19 +161,19 @@ begin
|
||||
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
|
||||
-- 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
|
||||
if UP = '1' then
|
||||
PER_CNT <= PER_CNT + 1;
|
||||
elsif DOWN = '1' then
|
||||
elsif DOWN = '1' then
|
||||
PER_CNT <= PER_CNT - 1;
|
||||
end if;
|
||||
end if;
|
||||
@@ -185,9 +185,9 @@ begin
|
||||
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.
|
||||
"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)
|
||||
@@ -207,7 +207,7 @@ begin
|
||||
ADDER_DATA := (others => '0');
|
||||
elsif CLK = '1' and CLK' event then
|
||||
ADDER_DATA := ADDER_DATA + ADDER_IN;
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
cat := DDEn & HDTYPE;
|
||||
case cat is
|
||||
@@ -219,6 +219,7 @@ begin
|
||||
ADDER_MSBs <= std_logic_vector(ADDER_DATA(11 downto 9));
|
||||
when "10" => -- FM mode using DD disks, results in 4us inspection period:
|
||||
ADDER_MSBs <= std_logic_vector(ADDER_DATA(12 downto 10));
|
||||
when others => ADDER_MSBs <= std_logic_vector(ADDER_DATA(11 downto 9));
|
||||
end case;
|
||||
end process ADDER;
|
||||
|
||||
@@ -303,7 +304,7 @@ 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.
|
||||
if RD_PULSE = '1' then -- Load the frequency amount register.
|
||||
case ERROR_HISTORY is
|
||||
when 2 =>
|
||||
case ADDER_MSBs is
|
||||
@@ -315,6 +316,7 @@ begin
|
||||
when "101" => FREQ_AMOUNT := "1010";
|
||||
when "110" => FREQ_AMOUNT := "1011";
|
||||
when "111" => FREQ_AMOUNT := "1100";
|
||||
when others => FREQ_AMOUNT := "0100";
|
||||
end case;
|
||||
when 1 =>
|
||||
case ADDER_MSBs is
|
||||
@@ -326,14 +328,15 @@ begin
|
||||
when "101" => FREQ_AMOUNT := "1001";
|
||||
when "110" => FREQ_AMOUNT := "1010";
|
||||
when "111" => FREQ_AMOUNT := "1011";
|
||||
end case;
|
||||
when others => FREQ_AMOUNT := "0011";
|
||||
end case;
|
||||
when others =>
|
||||
FREQ_AMOUNT := "0000";
|
||||
end case;
|
||||
elsif FREQ_AMOUNT(2 downto 0) > "000" then
|
||||
elsif FREQ_AMOUNT(2 downto 0) > "000" then
|
||||
FREQ_AMOUNT := FREQ_AMOUNT - 1; -- Modify the frequency amount register.
|
||||
end if;
|
||||
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.
|
||||
@@ -353,15 +356,15 @@ begin
|
||||
-- The phase decoder depends on the value of ADDER_MSBs. If the phase leeds, the most significant std_logic
|
||||
-- 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 std_logic of
|
||||
-- PHASE_AMOUNT).
|
||||
-- This implementation gives the freedom to adjust the phase amount individually for every mode
|
||||
-- PHASE_AMOUNT).
|
||||
-- This implementation gives the freedom to adjust the phase amount individually for every mode
|
||||
-- depending on DDEn and HDTYPE.
|
||||
variable PHASE_AMOUNT: unsigned (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.
|
||||
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";
|
||||
@@ -371,6 +374,7 @@ begin
|
||||
when "101" => PHASE_AMOUNT := "101000";
|
||||
when "110" => PHASE_AMOUNT := "101100";
|
||||
when "111" => PHASE_AMOUNT := "110000";
|
||||
when others => PHASE_AMOUNT := "010000";
|
||||
end case;
|
||||
elsif RD_PULSE = '1' and DDEn = '1' and HDTYPE = '1' then -- FM mode, double density
|
||||
case ADDER_MSBs is -- Multiplier: 2.
|
||||
@@ -382,43 +386,46 @@ begin
|
||||
when "101" => PHASE_AMOUNT := "100100";
|
||||
when "110" => PHASE_AMOUNT := "100110";
|
||||
when "111" => PHASE_AMOUNT := "101000";
|
||||
when others => PHASE_AMOUNT := "001000";
|
||||
end case;
|
||||
elsif RD_PULSE = '1' and DDEn = '0' and HDTYPE = '0' then -- MFM mode, single density
|
||||
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";
|
||||
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";
|
||||
when others => PHASE_AMOUNT := "000110";
|
||||
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";
|
||||
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";
|
||||
when others => PHASE_AMOUNT := "000100";
|
||||
end case;
|
||||
else -- Modify phase amount register:
|
||||
if PHASE_AMOUNT(4 downto 0) > x"0" then
|
||||
PHASE_AMOUNT := PHASE_AMOUNT - 1;
|
||||
PHASE_AMOUNT := PHASE_AMOUNT - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
--
|
||||
if PHASE_AMOUNT(5) = '0' and PHASE_AMOUNT(4 downto 0) > x"0" then
|
||||
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_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_INCREASE <= '0';
|
||||
PHASE_DECREASE <= '1'; -- Speed phase down, delay of next rollover.
|
||||
else
|
||||
PHASE_INCREASE <= '0';
|
||||
|
||||
@@ -56,10 +56,10 @@
|
||||
-- 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.
|
||||
-- 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.
|
||||
--
|
||||
|
||||
|
||||
@@ -175,11 +175,11 @@ begin
|
||||
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.
|
||||
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";
|
||||
@@ -253,6 +253,7 @@ begin
|
||||
else
|
||||
FM_In <= '1';
|
||||
end if;
|
||||
when OTHERS => FM_In <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end process FM_ENCODER;
|
||||
@@ -421,9 +422,9 @@ begin
|
||||
MFM_WR_OUT: process
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RESETn = '0' then
|
||||
MFM_In <= '1';
|
||||
else
|
||||
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
|
||||
@@ -445,6 +446,7 @@ begin
|
||||
else
|
||||
MFM_In <= '1';
|
||||
end if;
|
||||
when others => MFM_In <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end process MFM_WR_OUT;
|
||||
|
||||
@@ -54,14 +54,14 @@
|
||||
-- The timer is modified to work on the CLK instead
|
||||
-- of XTAL1. This modification is done to provide
|
||||
-- a synchronous design.
|
||||
-- Revision 2K8A 2008/02/29 WF
|
||||
-- Fixed a serious prescaler bug.
|
||||
-- Revision 2K9A 20090620 WF
|
||||
-- Introduced timer readback registers.
|
||||
-- TIMER_x_INT is now a strobe.
|
||||
-- Minor improvements.
|
||||
-- Revision 2K11A 20110620 WF
|
||||
-- A minor change in the data readback logic (RWn is now taken into consideration).
|
||||
-- Revision 2K8A 2008/02/29 WF
|
||||
-- Fixed a serious prescaler bug.
|
||||
-- Revision 2K9A 20090620 WF
|
||||
-- Introduced timer readback registers.
|
||||
-- TIMER_x_INT is now a strobe.
|
||||
-- Minor improvements.
|
||||
-- Revision 2K11A 20110620 WF
|
||||
-- A minor change in the data readback logic (RWn is now taken into consideration).
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
@@ -102,7 +102,7 @@ entity WF68901IP_TIMERS is
|
||||
);
|
||||
end entity WF68901IP_TIMERS;
|
||||
|
||||
architecture BEHAVIOR of WF68901IP_TIMERS is
|
||||
architecture BEHAVIOR of WF68901IP_TIMERS is
|
||||
signal XTAL1_S : std_logic;
|
||||
signal XTAL_STRB : std_logic;
|
||||
signal TACR : std_logic_vector(4 downto 0); -- Timer A control register.
|
||||
@@ -115,11 +115,11 @@ signal TDDR : std_logic_vector(7 downto 0); -- Timer D data register.
|
||||
signal TIMER_A : unsigned (7 downto 0); -- Timer A count register.
|
||||
signal TIMER_B : unsigned (7 downto 0); -- Timer B count register.
|
||||
signal TIMER_C : unsigned (7 downto 0); -- Timer C count register.
|
||||
signal TIMER_D : unsigned (7 downto 0); -- Timer D count register.
|
||||
signal TIMER_D : unsigned (7 downto 0); -- Timer D count register.
|
||||
signal TIMER_R_A : std_logic_vector (7 downto 0); -- Timer A readback register.
|
||||
signal TIMER_R_B : std_logic_vector (7 downto 0); -- Timer B readback register.
|
||||
signal TIMER_R_C : std_logic_vector (7 downto 0); -- Timer C readback register.
|
||||
signal TIMER_R_D : std_logic_vector (7 downto 0); -- Timer D readback register.
|
||||
signal TIMER_R_B : std_logic_vector (7 downto 0); -- Timer B readback register.
|
||||
signal TIMER_R_C : std_logic_vector (7 downto 0); -- Timer C readback register.
|
||||
signal TIMER_R_D : std_logic_vector (7 downto 0); -- Timer D readback register.
|
||||
signal A_CNTSTRB : std_logic;
|
||||
signal B_CNTSTRB : std_logic;
|
||||
signal C_CNTSTRB : std_logic;
|
||||
@@ -129,19 +129,19 @@ signal TBI_I : std_logic;
|
||||
signal TAI_STRB : std_logic; -- Strobe for the event counter mode.
|
||||
signal TBI_STRB : std_logic; -- Strobe for the event counter mode.
|
||||
signal TAO_I : std_logic; -- Timer A output signal.
|
||||
signal TBO_I : std_logic; -- Timer A output signal.
|
||||
begin
|
||||
SYNC: process
|
||||
-- This process provides a 'clean' XTAL1.
|
||||
-- Without this sync, the edge detector for
|
||||
-- XTAL_STRB does not work properly.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
XTAL1_S <= XTAL1;
|
||||
-- Polarity control for the event counter and the PWM mode:
|
||||
TAI_I <= TAI xnor AER_4;
|
||||
TBI_I <= TBI xnor AER_3;
|
||||
end process SYNC;
|
||||
signal TBO_I : std_logic; -- Timer A output signal.
|
||||
begin
|
||||
SYNC: process
|
||||
-- This process provides a 'clean' XTAL1.
|
||||
-- Without this sync, the edge detector for
|
||||
-- XTAL_STRB does not work properly.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
XTAL1_S <= XTAL1;
|
||||
-- Polarity control for the event counter and the PWM mode:
|
||||
TAI_I <= TAI xnor AER_4;
|
||||
TBI_I <= TBI xnor AER_3;
|
||||
end process SYNC;
|
||||
|
||||
-- Output enables for timer A and timer B:
|
||||
-- The outputs are held low for asserted reset flags in the control registers TACR
|
||||
@@ -181,47 +181,47 @@ begin
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMER_REGISTERS;
|
||||
|
||||
TIMER_READBACK : process(RESETn, CLK)
|
||||
-- This process provides the readback information for the
|
||||
-- timers A to D. The information read is the information
|
||||
-- last clocked into the timer read register when the DSn
|
||||
-- pin had last gone high prior to the current read cycle.
|
||||
variable READ_A : boolean;
|
||||
variable READ_B : boolean;
|
||||
variable READ_C : boolean;
|
||||
variable READ_D : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TIMER_R_A <= x"00";
|
||||
TIMER_R_B <= x"00";
|
||||
TIMER_R_C <= x"00";
|
||||
TIMER_R_D <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DSn = '0' and RWn = '1' and RS = "01111" then
|
||||
READ_A := true;
|
||||
elsif DSn = '0' and RWn = '1' and RS = "10000" then
|
||||
READ_B := true;
|
||||
elsif DSn = '0' and RWn = '1' and RS = "10001" then
|
||||
READ_C := true;
|
||||
elsif DSn = '0' and RWn = '1' and RS = "10010" then
|
||||
READ_D := true;
|
||||
elsif DSn = '1' and READ_A = true then
|
||||
TIMER_R_A <= std_logic_vector(TIMER_A);
|
||||
READ_A := false;
|
||||
elsif DSn = '1' and READ_B = true then
|
||||
TIMER_R_B <= std_logic_vector(TIMER_B);
|
||||
READ_B := false;
|
||||
elsif DSn = '1' and READ_C = true then
|
||||
TIMER_R_C <= std_logic_vector(TIMER_C);
|
||||
READ_C := false;
|
||||
elsif DSn = '1' and READ_D = true then
|
||||
TIMER_R_D <= std_logic_vector(TIMER_D);
|
||||
READ_D := false;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMER_READBACK;
|
||||
end process TIMER_REGISTERS;
|
||||
|
||||
TIMER_READBACK : process(RESETn, CLK)
|
||||
-- This process provides the readback information for the
|
||||
-- timers A to D. The information read is the information
|
||||
-- last clocked into the timer read register when the DSn
|
||||
-- pin had last gone high prior to the current read cycle.
|
||||
variable READ_A : boolean;
|
||||
variable READ_B : boolean;
|
||||
variable READ_C : boolean;
|
||||
variable READ_D : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
TIMER_R_A <= x"00";
|
||||
TIMER_R_B <= x"00";
|
||||
TIMER_R_C <= x"00";
|
||||
TIMER_R_D <= x"00";
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if DSn = '0' and RWn = '1' and RS = "01111" then
|
||||
READ_A := true;
|
||||
elsif DSn = '0' and RWn = '1' and RS = "10000" then
|
||||
READ_B := true;
|
||||
elsif DSn = '0' and RWn = '1' and RS = "10001" then
|
||||
READ_C := true;
|
||||
elsif DSn = '0' and RWn = '1' and RS = "10010" then
|
||||
READ_D := true;
|
||||
elsif DSn = '1' and READ_A = true then
|
||||
TIMER_R_A <= std_logic_vector(TIMER_A);
|
||||
READ_A := false;
|
||||
elsif DSn = '1' and READ_B = true then
|
||||
TIMER_R_B <= std_logic_vector(TIMER_B);
|
||||
READ_B := false;
|
||||
elsif DSn = '1' and READ_C = true then
|
||||
TIMER_R_C <= std_logic_vector(TIMER_C);
|
||||
READ_C := false;
|
||||
elsif DSn = '1' and READ_D = true then
|
||||
TIMER_R_D <= std_logic_vector(TIMER_D);
|
||||
READ_D := false;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMER_READBACK;
|
||||
|
||||
DATA_OUT_EN <= '1' when CSn = '0' and DSn = '0' and RWn = '1' and RS > "01011" and RS <= "10010" else '0';
|
||||
DATA_OUT <= "000" & TACR when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01100" else
|
||||
@@ -230,17 +230,17 @@ begin
|
||||
TIMER_R_A when CSn = '0' and DSn = '0' and RWn = '1' and RS = "01111" else
|
||||
TIMER_R_B when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10000" else
|
||||
TIMER_R_C when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10001" else
|
||||
TIMER_R_D when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10010" else (others => '0');
|
||||
TIMER_R_D when CSn = '0' and DSn = '0' and RWn = '1' and RS = "10010" else (others => '0');
|
||||
|
||||
XTAL_STROBE: process(RESETn, CLK)
|
||||
-- This process provides a strobe with 1 clock cycle
|
||||
-- (CLK) length after every rising edge of XTAL1.
|
||||
variable LOCK : boolean;
|
||||
variable LOCK : boolean;
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
XTAL_STRB <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if XTAL1_S = '1' and LOCK = false then
|
||||
XTAL_STRB <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
if XTAL1_S = '1' and LOCK = false then
|
||||
XTAL_STRB <= '1';
|
||||
LOCK := true;
|
||||
elsif XTAL1_S = '0' then
|
||||
@@ -293,7 +293,7 @@ begin
|
||||
variable PRESCALE : unsigned (7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
A_CNTSTRB <= '0';
|
||||
A_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - 1;
|
||||
elsif XTAL_STRB = '1' then
|
||||
@@ -306,8 +306,9 @@ begin
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
|
||||
when others => PRESCALE := x"00";
|
||||
end case;
|
||||
A_CNTSTRB <= '1';
|
||||
A_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_A;
|
||||
|
||||
@@ -316,7 +317,7 @@ begin
|
||||
variable PRESCALE : unsigned (7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
B_CNTSTRB <= '0';
|
||||
B_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - 1;
|
||||
elsif XTAL_STRB = '1' then
|
||||
@@ -329,40 +330,42 @@ begin
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped or event count mode.
|
||||
when others => PRESCALE := x"00";
|
||||
end case;
|
||||
B_CNTSTRB <= '1';
|
||||
B_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_B;
|
||||
|
||||
PRESCALE_C: process
|
||||
-- The prescalers work even if the RESETn is asserted.
|
||||
variable PRESCALE : unsigned (7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
C_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - 1;
|
||||
elsif XTAL_STRB = '1' then
|
||||
case TCDCR(5 downto 3) is
|
||||
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
|
||||
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
|
||||
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
|
||||
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
|
||||
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped.
|
||||
end case;
|
||||
C_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_C;
|
||||
PRESCALE_C: process
|
||||
-- The prescalers work even if the RESETn is asserted.
|
||||
variable PRESCALE : unsigned (7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
C_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - 1;
|
||||
elsif XTAL_STRB = '1' then
|
||||
case TCDCR(5 downto 3) is
|
||||
when "111" => PRESCALE := x"C7"; -- Prescaler = 200.
|
||||
when "110" => PRESCALE := x"63"; -- Prescaler = 100.
|
||||
when "101" => PRESCALE := x"3F"; -- Prescaler = 64.
|
||||
when "100" => PRESCALE := x"31"; -- Prescaler = 50.
|
||||
when "011" => PRESCALE := x"0F"; -- Prescaler = 16.
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped.
|
||||
when others => PRESCALE := x"00";
|
||||
end case;
|
||||
C_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_C;
|
||||
|
||||
PRESCALE_D: process
|
||||
-- The prescalers work even if the RESETn is asserted.
|
||||
variable PRESCALE : unsigned (7 downto 0);
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
D_CNTSTRB <= '0';
|
||||
D_CNTSTRB <= '0';
|
||||
if PRESCALE > x"00" and XTAL_STRB = '1' then
|
||||
PRESCALE := PRESCALE - 1;
|
||||
elsif XTAL_STRB = '1' then
|
||||
@@ -375,8 +378,9 @@ begin
|
||||
when "010" => PRESCALE := x"09"; -- Prescaler = 10.
|
||||
when "001" => PRESCALE := x"03"; -- Prescaler = 4.
|
||||
when "000" => PRESCALE := x"00"; -- Timer stopped.
|
||||
when others => PRESCALE := x"00";
|
||||
end case;
|
||||
D_CNTSTRB <= '1';
|
||||
D_CNTSTRB <= '1';
|
||||
end if;
|
||||
end process PRESCALE_D;
|
||||
|
||||
@@ -386,16 +390,16 @@ begin
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TAO_I <= '0';
|
||||
TIMER_A_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_A_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_A_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "01111" and TACR(3 downto 0) = x"0" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
TIMER_A <= unsigned(DATA_IN);
|
||||
else
|
||||
case TACR(3 downto 0) is
|
||||
when x"0" => -- Timer is off.
|
||||
TAO_I <= '0';
|
||||
when x"0" => -- Timer is off.
|
||||
TAO_I <= '0';
|
||||
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
|
||||
if A_CNTSTRB = '1' and TIMER_A /= x"01" then -- Count.
|
||||
TIMER_A <= TIMER_A - 1;
|
||||
@@ -420,6 +424,7 @@ begin
|
||||
TAO_I <= not TAO_I; -- Toggle the timer A output pin.
|
||||
TIMER_A_INT <= '1';
|
||||
end if;
|
||||
when others => TAO_I <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
@@ -431,16 +436,16 @@ begin
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TBO_I <= '0';
|
||||
TIMER_B_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_B_INT <= '0';
|
||||
--
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_B_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10000" and TBCR(3 downto 0) = x"0" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
TIMER_B <= unsigned(DATA_IN);
|
||||
else
|
||||
case TBCR(3 downto 0) is
|
||||
when x"0" => -- Timer is off.
|
||||
TBO_I <= '0';
|
||||
when x"0" => -- Timer is off.
|
||||
TBO_I <= '0';
|
||||
when x"1" | x"2" | x"3" | x"4" | x"5" | x"6" | x"7" => -- Delay counter mode.
|
||||
if B_CNTSTRB = '1' and TIMER_B /= x"01" then -- Count.
|
||||
TIMER_B <= TIMER_B - 1;
|
||||
@@ -465,27 +470,28 @@ begin
|
||||
TBO_I <= not TBO_I; -- Toggle the timer B output pin.
|
||||
TIMER_B_INT <= '1';
|
||||
end if;
|
||||
when others => TBO_I <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process TIMERB;
|
||||
|
||||
|
||||
TIMERC: process(RESETn, CLK)
|
||||
begin
|
||||
if RESETn = '0' then
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TCO <= '0';
|
||||
TIMER_C_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_C_INT <= '0';
|
||||
--
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_C_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10001" and TCDCR(5 downto 3) = "000" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
TIMER_C <= unsigned(DATA_IN);
|
||||
else
|
||||
else
|
||||
case TCDCR(5 downto 3) is
|
||||
when "000" => -- Timer is off.
|
||||
TCO <= '0';
|
||||
TCO <= '0';
|
||||
when others => -- Delay counter mode.
|
||||
if C_CNTSTRB = '1' and TIMER_C /= x"01" then -- Count.
|
||||
TIMER_C <= TIMER_C - 1;
|
||||
@@ -505,16 +511,16 @@ begin
|
||||
-- Do not clear the timer registers during system reset.
|
||||
TDO <= '0';
|
||||
TIMER_D_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_D_INT <= '0';
|
||||
elsif CLK = '1' and CLK' event then
|
||||
TIMER_D_INT <= '0';
|
||||
--
|
||||
if CSn = '0' and DSn = '0' and RWn = '0' and RS = "10010" and TCDCR(2 downto 0) = "000" then
|
||||
-- The timer is reloaded simultaneously to it's timer data register, if it is off.
|
||||
TIMER_D <= unsigned(DATA_IN);
|
||||
else
|
||||
case TCDCR(2 downto 0) is
|
||||
when "000" => -- Timer is off.
|
||||
TDO <= '0';
|
||||
when "000" => -- Timer is off.
|
||||
TDO <= '0';
|
||||
when others => -- Delay counter mode.
|
||||
if D_CNTSTRB = '1' and TIMER_D /= x"01" then -- Count.
|
||||
TIMER_D <= TIMER_D - 1;
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
@@ -184,6 +184,7 @@ begin
|
||||
when "01" => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '1';
|
||||
when "10" => LOOPBACK <= '0'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
|
||||
when "11" => LOOPBACK <= '1'; SD_LEVEL <= '1'; SDOUT_EN <= '1';
|
||||
when others => LOOPBACK <= '0'; SD_LEVEL <= '0'; SDOUT_EN <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end process SOUT_CONFIG;
|
||||
|
||||
@@ -49,10 +49,10 @@
|
||||
-- Initial Release.
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- TDRE has now synchronous reset to meet preset requirement.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K9A 2009/06/20 WF
|
||||
-- TDRE has now synchronous reset to meet preset requirement.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
@@ -197,10 +197,11 @@ begin
|
||||
elsif TR_STATE = LOAD_SHFT then
|
||||
-- Load 'normal' data if there is no break condition:
|
||||
case CL is
|
||||
when "11" => SHIFT_REG <= "000" & TX_DATA(4 downto 0); -- 5 datastd_logics.
|
||||
when "10" => SHIFT_REG <= "00" & TX_DATA(5 downto 0); -- 6 datastd_logics.
|
||||
when "01" => SHIFT_REG <= '0' & TX_DATA(6 downto 0); -- 7 datastd_logics.
|
||||
when "00" => SHIFT_REG <= TX_DATA; -- 8 datastd_logics.
|
||||
when "11" => SHIFT_REG <= "000" & TX_DATA(4 downto 0); -- 5 databits.
|
||||
when "10" => SHIFT_REG <= "00" & TX_DATA(5 downto 0); -- 6 databits
|
||||
when "01" => SHIFT_REG <= '0' & TX_DATA(6 downto 0); -- 7 databits
|
||||
when "00" => SHIFT_REG <= TX_DATA; -- 8 databits
|
||||
when others => SHIFT_REG <= x"00";
|
||||
end case;
|
||||
elsif TR_STATE = SHIFTOUT and CLK_STRB = '1' then
|
||||
SHIFT_REG <= '0' & SHIFT_REG(7 downto 1); -- Shift right.
|
||||
@@ -223,8 +224,8 @@ begin
|
||||
-- Transmit data register empty flag.
|
||||
begin
|
||||
wait until CLK = '1' and CLK' event;
|
||||
if RESETn = '0' then
|
||||
TDRE <= '1';
|
||||
if RESETn = '0' then
|
||||
TDRE <= '1';
|
||||
elsif TE = '0' then
|
||||
TDRE <= '1';
|
||||
elsif TR_STATE = START and BREAK = '0' then
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
-- Revision 2K6B 2006/11/07 WF
|
||||
-- Modified Source to compile with the Xilinx ISE.
|
||||
-- Top level file provided for SOC (systems on programmable chips).
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
-- Revision 2K8A 2008/07/14 WF
|
||||
-- Minor changes.
|
||||
--
|
||||
|
||||
library ieee;
|
||||
@@ -149,7 +149,8 @@ begin
|
||||
BUSCYCLE <= INACTIVE when "000" | "010" | "101",
|
||||
ADDRESS when "001" | "100" | "111",
|
||||
R_READ when "011",
|
||||
R_WRITE when "110";
|
||||
R_WRITE when "110",
|
||||
INACTIVE when others;
|
||||
|
||||
ADDRESSLATCH: process(RESETn, SYS_CLK)
|
||||
-- This process is responsible to store the desired register
|
||||
|
||||
Reference in New Issue
Block a user