?? atacntl.vhd
字號:
library IEEE, UNISIM;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use WORK.common.all;
package ata is
component pioIntfc
generic(
FREQ: natural := 50_000 -- operating frequency in KHz
);
port(
-- host side
clk: in std_logic; -- master clock
pioRst: in std_logic; -- async. reset
pioRd: in std_logic; -- initiate read operation
pioWr: in std_logic; -- initiate write operation
pioAddr: in unsigned(4 downto 0); -- disk register address from host
pioDIn: in unsigned(15 downto 0); -- data from host to disk
pioDOut: out unsigned(15 downto 0); -- data from disk to host
pioBusy: out std_logic; -- read or write operation is in progress
pioIntrq: out std_logic; -- debounced interrupt from disk
status: out std_logic_vector(3 downto 0); -- diagnostic status for the R/W
-- disk side
dior_n: out std_logic; -- disk register read-enable
diow_n: out std_logic; -- disk register write-enable
cs0_n: out std_logic; -- disk command block register select
cs1_n: out std_logic; -- disk control block register select
da: out unsigned(2 downto 0); -- disk register address
ddIn: in unsigned(15 downto 0); -- data from disk
ddOut: out unsigned(15 downto 0); -- data to disk
ddOutEnbl: out std_logic; -- enable data outputs to disk
intrq: in std_logic; -- interrupt from disk
dmack_n: out std_logic -- DMA acknowledge
);
end component;
component ataCntl
generic(
FREQ: natural := 50_000 -- operating frequency in KHz
);
port(
-- host side
clk: in std_logic; -- master clock
rst: in std_logic; -- reset
rd: in std_logic; -- initiate read operation
wr: in std_logic; -- initiate write operation
abort: in std_logic; -- aborts read/write sector operation
head: in unsigned(3 downto 0); -- disk head for data access
cylinder: in unsigned(15 downto 0); -- cylinder for data access
sector: in unsigned(7 downto 0); -- sector for data access
hDIn: in unsigned(15 downto 0); -- data from host to disk
hDOut: out unsigned(15 downto 0); -- data from disk to host
done: out std_logic; -- read or write operation is done
status: out std_logic_vector(3 downto 0); -- diagnostic status
-- disk side
dior_n: out std_logic; -- disk register read-enable
diow_n: out std_logic; -- disk register write-enable
cs0_n: out std_logic; -- disk command block register select
cs1_n: out std_logic; -- disk control block register select
da: out unsigned(2 downto 0); -- register address
ddIn: in unsigned(15 downto 0); -- data from disk
ddOut: out unsigned(15 downto 0); -- data to disk
ddOutEnbl: out std_logic; -- enable data outputs to disk
intrq: in std_logic; -- interrupt from disk
dmack_n: out std_logic -- DMA acknowledge
);
end component;
end package ata;
library IEEE, UNISIM;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
--use WORK.common.all;
----------------------------------------------------------------------------------
-- This module executes a timed read/write operation to one of the disk registers.
--
-- For a read operation, the host supplies a register address and pulls the read
-- control line high. The read operation begins on the next rising clock edge
-- and the busy signal goes high. The host gets the data from the disk register
-- once the busy signal goes low again.
--
-- For a write operation, the host supplies a register address and the data to
-- be stored there and pulls the write control line high. The write operation
-- begins on the nxt rising clock edge an the busy signal goes high. The register
-- contains the new data once the busy signal goes low again.
--
-- The 5-bit register address from the host contains the 3-bit disk register address
-- along with the control and command block register select bits in the most
-- significant bit positions.
----------------------------------------------------------------------------------
entity pioIntfc is
generic(
FREQ: natural := 50_000 -- operating frequency in KHz
);
port(
-- host side
clk: in std_logic; -- master clock
pioRst: in std_logic; -- async. reset
pioRd: in std_logic; -- initiate read operation
pioWr: in std_logic; -- initiate write operation
pioAddr: in unsigned(4 downto 0); -- disk register address from host
pioDIn: in unsigned(15 downto 0); -- data from host to disk
pioDOut: out unsigned(15 downto 0); -- data from disk to host
pioBusy: out std_logic; -- read or write operation is in progress
pioIntrq: out std_logic; -- debounced interrupt from disk
status: out std_logic_vector(3 downto 0); -- diagnostic status for the R/W
-- disk side
dior_n: out std_logic; -- disk register read-enable
diow_n: out std_logic; -- disk register write-enable
cs0_n: out std_logic; -- disk command block register select
cs1_n: out std_logic; -- disk control block register select
da: out unsigned(2 downto 0); -- disk register address
ddIn: in unsigned(15 downto 0); -- data from disk
ddOut: out unsigned(15 downto 0); -- data to disk
ddOutEnbl: out std_logic; -- enable data outputs to disk
intrq: in std_logic; -- interrupt from disk
dmack_n: out std_logic -- DMA acknowledge
);
end pioIntfc;
architecture arch of pioIntfc is
-- PIO mode 0 timing parameters in ns
constant Top: natural := 600; -- minimum cycle time between R/W operations
constant Tsetup: natural := 70; -- address/data setup before R/W pulse
constant Tpulse: natural := 290; -- R/W pulse width
constant Thold: natural := Top-Tsetup-Tpulse; -- address/data hold after R/W pulse
-- PIO mode timing parameters converted into clock cycles (based on FREQ)
constant NORM: natural := 1_000_000; -- normalize ns * KHz
constant OP_CYCLES_N: natural := 1+((Top*FREQ)/NORM);
constant SETUP_CYCLES_N: natural := 1+((Tsetup*FREQ)/NORM);
constant PULSE_CYCLES_N: natural := 1+((Tpulse*FREQ)/NORM);
constant HOLD_CYCLES_N: natural := 1+((Thold*FREQ)/NORM);
-- timer register that counts down times for the phases of the disk R/W operation
signal timer_r, timer_x: unsigned(log2(OP_CYCLES_N+1)-1 downto 0);
-- PIO mode timing parameters converted into unsigned clock cycles for clarity
constant OP_CYCLES: unsigned := TO_UNSIGNED(OP_CYCLES_N, timer_r'length);
constant SETUP_CYCLES: unsigned := TO_UNSIGNED(SETUP_CYCLES_N, timer_r'length);
constant PULSE_CYCLES: unsigned := TO_UNSIGNED(PULSE_CYCLES_N, timer_r'length);
constant HOLD_CYCLES: unsigned := TO_UNSIGNED(HOLD_CYCLES_N, timer_r'length);
-- states of the PIO interface state machine
type cntlState is (
RW_SETUP, -- setup address/data before read pulse
RD_PULSE, -- read pulse active
RD_HOLD, -- hold address/data after read pulse
WR_PULSE, -- write pulse active
WR_HOLD -- hold address/data after write pulse
);
signal state_r, state_x: cntlState; -- state register and next state
-- PIO interface registers
signal pioBusy_r, pioBusy_x: std_logic; -- R/W in-progress register
signal dior_r, dior_x: std_logic; -- disk read signal register
signal diow_r, diow_x: std_logic; -- disk write signal register
signal da_r, da_x: unsigned(pioAddr'range); -- disk register address register
signal ddOut_r, ddOut_x: unsigned(ddOut'range); -- data output to disk register
signal ddOutEnbl_r, ddOutEnbl_x: std_logic; -- enable data output to disk register
signal ddIn_r, ddIn_x: unsigned(ddIn'range); -- data input from disk register
-- reports the status of the PIO interface
signal status_r, status_x: std_logic_vector(3 downto 0);
-- debounce counter for the interrupt request input
signal intrqCnt_r,intrqCnt_x: unsigned(3 downto 0);
constant DEBOUNCE_CNT: natural := 10;
signal pioIntrq_r, pioIntrq_x: std_logic;
signal intrq_r, intrq_x: std_logic;
begin
-----------------------------------------------------------
-- attach some internal signals to the host and disk ports
-----------------------------------------------------------
dior_n <= dior_r;
diow_n <= diow_r;
da <= da_r(da'range);
cs0_n <= da_r(3);
cs1_n <= da_r(4);
ddOut <= ddOut_r;
ddOutEnbl <= ddOutEnbl_r;
pioDOut <= ddIn_r; -- output data to host is the input data from the disk
pioBusy <= pioBusy_r;
pioIntrq <= pioIntrq_r;
status <= status_r;
dmack_n <= HI; -- never acknowledge DMA requests from disk
-----------------------------------------------------------
-- debounce the interrupt signal from the disk
-----------------------------------------------------------
debounce: process(intrq,intrqCnt_r,intrq_r,pioIntrq_r)
begin
intrq_x <= intrq;
pioIntrq_x <= pioIntrq_r;
if(intrq = intrq_r) then
if(intrqCnt_r = DEBOUNCE_CNT) then
intrqCnt_x <= (others=>'0');
pioIntrq_x <= intrq_r;
else
intrqCnt_x <= intrqCnt_r + 1;
end if;
else
intrqCnt_x <= (others=>'0');
end if;
end process debounce;
-----------------------------------------------------------
-- compute the next state and outputs
-----------------------------------------------------------
combinatorial: process(pioRd,pioWr,pioAddr,pioDIn,state_r,timer_r,dior_r,pioBusy_r,
diow_r,da_r,ddOut_r,ddOutEnbl_r,ddIn_r,ddIn,status_r)
begin
-----------------------------------------------------------
-- setup default values for signals
-----------------------------------------------------------
state_x <= state_r;
dior_x <= dior_r;
diow_x <= diow_r;
da_x <= da_r;
ddOut_x <= ddOut_r;
ddOutEnbl_x <= ddOutEnbl_r;
ddIn_x <= ddIn_r;
pioBusy_x <= pioBusy_r;
status_x <= status_r;
-----------------------------------------------------------
-- update the timers
-----------------------------------------------------------
-- main timer for sequencing the phases of the R/W waveforms
if timer_r /= 0 then
-- decrement the timer and do nothing else since the previous
-- phase has not completed yet.
timer_x <= timer_r - 1;
else
-- the previous phase has completed once the timer hits zero.
-- By default, leave the timer at zero. A R/W op will set it
-- to non-zero below.
timer_x <= timer_r;
-----------------------------------------------------------
-- compute the next state and outputs
-----------------------------------------------------------
case state_r is
-----------------------------------------------------------
-- wait for a disk read or write operation
-----------------------------------------------------------
when RW_SETUP =>
dior_x <= HI; -- don't read or write the disk until requested
diow_x <= HI;
ddOutEnbl_x <= NO; -- don't drive disk data bus until requested
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -