?? atacntl.vhd
字號:
if(pioRd = YES) then
-- a read operation is requested
pioBusy_x <= YES; -- set busy bit
da_x <= pioAddr; -- output disk register address
timer_x <= SETUP_CYCLES; -- set timer for address setup
state_x <= RD_PULSE; -- next state after address setup completes
status_x <= "0010";
elsif(pioWr = YES) then
-- a write operation is requested
pioBusy_x <= YES; -- set busy bit
da_x <= pioAddr; -- output disk register address
ddOut_x <= pioDIn; -- output data to disk
ddOutEnbl_x <= YES; -- enable output bus
timer_x <= SETUP_CYCLES; -- set timer for address/data setup
state_x <= WR_PULSE; -- next state after address/data setup completes
status_x <= "0100";
else
-- no operation is requested
pioBusy_x <= NO; -- clear busy bit
state_x <= RW_SETUP; -- return to this state and wait for R/W request
status_x <= "0001";
end if;
-----------------------------------------------------------
-- pulse disk read control signal
-----------------------------------------------------------
when RD_PULSE =>
dior_x <= LO; -- lower disk read control line
timer_x <= PULSE_CYCLES; -- load duration of read pulse
state_x <= RD_HOLD; -- next state after pulse completes
-----------------------------------------------------------
-- get data and hold address after read pulse ends
-----------------------------------------------------------
when RD_HOLD =>
ddIn_x <= ddIn; -- load the data from the disk
dior_x <= HI; -- terminate the read pulse
timer_x <= HOLD_CYCLES; -- insert hold period after read operation
state_x <= RW_SETUP; -- look for another operation after the hold period
-----------------------------------------------------------
-- pulse disk write control signal
-----------------------------------------------------------
when WR_PULSE =>
diow_x <= LO; -- lower disk write control line
timer_x <= PULSE_CYCLES; -- load duration of write pulse
state_x <= WR_HOLD; -- next state after pulse completes
-----------------------------------------------------------
-- hold address and data after write pulse ends
-----------------------------------------------------------
when WR_HOLD =>
diow_x <= HI; -- terminate the write pulse
timer_x <= HOLD_CYCLES; -- insert hold period after write operation
state_x <= RW_SETUP; -- look for another operation after the hold period
-----------------------------------------------------------
-- unknown state
-----------------------------------------------------------
when others =>
state_x <= RW_SETUP; -- reset state if in erroneous state
status_x <= "1000";
end case;
end if;
end process combinatorial;
-----------------------------------------------------------
-- update registers on the appropriate clock edge
-----------------------------------------------------------
update: process(pioRst,clk)
begin
if pioRst = YES then
-- asynchronous reset
state_r <= RW_SETUP;
timer_r <= (others=>'0');
pioBusy_r <= NO;
pioIntrq_r <= NO;
intrq_r <= NO;
intrqCnt_r <= (others=>'0');
dior_r <= HI;
diow_r <= HI;
da_r <= (others=>'0');
ddOut_r <= (others=>'0');
ddOutEnbl_r <= NO;
ddIn_r <= (others=>'0');
status_r <= (others=>'0');
elsif clk'event and clk='1' then
state_r <= state_x;
timer_r <= timer_x;
pioBusy_r <= pioBusy_x;
pioIntrq_r <= pioIntrq_x;
intrq_r <= intrq_x;
intrqCnt_r <= intrqCnt_x;
dior_r <= dior_x;
diow_r <= diow_x;
da_r <= da_x;
ddOut_r <= ddOut_x;
ddOutEnbl_r <= ddOutEnbl_x;
ddIn_r <= ddIn_x;
status_r <= status_x;
end if;
end process update;
end arch;
library IEEE, UNISIM;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use WORK.common.all;
use WORK.ata.all;
----------------------------------------------------------------------------------
-- This module reads or write a complete 256-word sector of the disk.
--
-- 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 ataCntl is
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 ataCntl;
architecture arch of ataCntl is
-- disk register addresses: (cs1,cs0,da2,da1,da0)
constant CONTROL_REG: unsigned(4 downto 0) := "01110";
constant DATA_REG: unsigned(4 downto 0) := "10000";
constant SECTOR_CNT_REG: unsigned(4 downto 0) := "10010";
constant SECTOR_REG: unsigned(4 downto 0) := "10011";
constant CYL_LOW_REG: unsigned(4 downto 0) := "10100";
constant CYL_HIGH_REG: unsigned(4 downto 0) := "10101";
constant DRIVE_HEAD_REG: unsigned(4 downto 0) := "10110";
constant CMD_REG: unsigned(4 downto 0) := "10111";
constant STATUS_REG: unsigned(4 downto 0) := "10111";
-- commands for disk
constant DRIVE_RESET_CMD: unsigned(7 downto 0) := x"0C";
constant DRIVE_RELEASE_CMD: unsigned(7 downto 0) := x"08";
constant NOP_CMD: unsigned(7 downto 0) := x"00";
constant READ_SECTOR_CMD: unsigned(7 downto 0) := x"20";
constant WRITE_SECTOR_CMD: unsigned(7 downto 0) := x"30";
-- disk status register bits
constant STATUS_REG_BSY: natural := 7;
constant STATUS_REG_DRQ: natural := 3;
constant STATUS_REG_ERR: natural := 0;
-- number of 16-bit words per disk sector
constant SECTOR_SIZE_N: natural := 256;
-- states of the ATA drive interface state machine
type cntlState is (
WAIT_FOR_NOT_BUSY,
WAIT_FOR_NOT_BUSY_1,
RESET_DRIVE,
RESET_DRIVE_1,
ABORT_1,
WAIT_FOR_CMD,
SETUP_DRIVE,
SETUP_DRIVE_1,
SETUP_DRIVE_2,
SETUP_DRIVE_3,
SETUP_DRIVE_4,
SETUP_DRIVE_5,
WRITE_WORDS,
WRITE_WORDS_1,
WRITE_WORDS_2,
WRITE_WORDS_3,
WRITE_WORDS_4,
READ_WORDS,
READ_WORDS_1,
READ_WORDS_2,
ERROR
);
signal state_r, state_x: cntlState; -- state register and next state
signal rtnState_r, rtnState_x: cntlState; -- state register and next state
-- ATA drive interface registers
signal cmd_r, cmd_x: unsigned(7 downto 0); -- ATA drive command (e.g. READ_SECTOR)
signal wordCnt_r, wordCnt_x: unsigned(log2(SECTOR_SIZE_N)-1 downto 0); -- counts words read from sector
signal status_r, status_x: std_logic_vector(status'range);
constant ERROR_FLAG: natural := 0; -- position of error flag bit in status register
constant SECTOR_SIZE: unsigned(wordCnt_r'range) := TO_UNSIGNED(SECTOR_SIZE_N,wordCnt_r'length);
-- PIO interface signals
signal pioRd: std_logic; -- initiate read operation
signal pioWr: std_logic; -- initiate write operation
signal pioBusy: std_logic; -- read or write operation in-progress
signal pioIntrq: std_logic; -- debounced interrupt from disk
signal pioAddr: unsigned(4 downto 0); -- register address from host
signal pioDIn: unsigned(15 downto 0); -- data from host to disk
signal pioDOut: unsigned(15 downto 0); -- data from disk to host
begin
-------------------------------------------------------------------
-- instantiate the low-level interface to the disk registers
-------------------------------------------------------------------
u0: pioIntfc
generic map(
FREQ => FREQ
)
port map(
clk => clk,
pioRst => rst,
pioRd => pioRd,
pioWr => pioWr,
pioAddr => pioAddr,
pioDIn => pioDIn,
pioDOut => pioDOut,
pioBusy => pioBusy,
pioIntrq => pioIntrq,
status => open,
dior_n => dior_n,
diow_n => diow_n,
cs0_n => cs0_n,
cs1_n => cs1_n,
da => da,
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -