?? atacntl.vhd
字號:
ddIn => ddIn,
ddOut => ddOut,
ddOutEnbl => ddOutEnbl,
intrq => intrq,
dmack_n => dmack_n
);
-----------------------------------------------------------
-- attach some internal signals to the host and disk ports
-----------------------------------------------------------
hdOut <= pioDOut;
status <= status_r;
-----------------------------------------------------------
-- compute the next state and outputs
-----------------------------------------------------------
combinatorial: process(state_r,rd,wr,head,cylinder,sector,hDIn,cmd_r,pioDOut,
status_r,pioBusy,wordCnt_r,rtnState_r)
begin
-----------------------------------------------------------
-- setup default values for signals
-----------------------------------------------------------
done <= NO;
pioRd <= NO;
pioWr <= NO;
pioDIn <= (others=>'0');
pioAddr <= (others=>'0');
state_x <= state_r;
rtnState_x <= rtnState_r;
cmd_x <= cmd_r;
wordCnt_x <= wordCnt_r;
status_x <= status_r;
if(pioBusy = NO) then
-----------------------------------------------------------
-- compute the next state and outputs
-----------------------------------------------------------
case state_r is
-----------------------------------------------------------------
-- set and then clear the reset bit in the disk control register
-----------------------------------------------------------------
when RESET_DRIVE =>
pioWr <= YES;
pioAddr <= CONTROL_REG;
pioDIn(7 downto 0) <= DRIVE_RESET_CMD;
state_x <= RESET_DRIVE_1;
when RESET_DRIVE_1 =>
pioWr <= YES;
pioAddr <= CONTROL_REG;
pioDIn(7 downto 0) <= DRIVE_RELEASE_CMD;
state_x <= WAIT_FOR_NOT_BUSY; -- wait for the drive to go non-busy after reset
-----------------------------------------------------------------
-- abort the current command by issuing a NOP command
-----------------------------------------------------------------
when ABORT_1 =>
pioWr <= YES;
pioAddr <= CMD_REG;
pioDIn(7 downto 0) <= NOP_CMD;
state_x <= WAIT_FOR_NOT_BUSY;
rtnState_x <= WAIT_FOR_CMD;
-----------------------------------------------------------------
-- wait for the busy bit in the disk status register to clear
-----------------------------------------------------------------
when WAIT_FOR_NOT_BUSY =>
pioRd <= YES;
pioAddr <= STATUS_REG;
state_x <= WAIT_FOR_NOT_BUSY_1;
when WAIT_FOR_NOT_BUSY_1 =>
if(pioDOut(STATUS_REG_BSY) = YES) then
state_x <= WAIT_FOR_NOT_BUSY; -- busy bit not clear so check it again
else
state_x <= rtnState_r; -- pop the state registers
end if;
-----------------------------------------------------------------
-- wait for a read or write sector command
-----------------------------------------------------------------
when WAIT_FOR_CMD =>
if(rd = YES) then
-- read a sector of the disk
wordCnt_x <= SECTOR_SIZE-1; -- set number of words to read from sector
cmd_x <= READ_SECTOR_CMD; -- command for rading a sector
state_x <= SETUP_DRIVE; -- setup the disk registers for reading the sector
rtnState_x <= READ_WORDS;
elsif(wr = YES) then
-- write a sector of the disk
wordCnt_x <= SECTOR_SIZE-1; -- set number of words to write to sector
cmd_x <= WRITE_SECTOR_CMD; -- command for writing a sector
state_x <= SETUP_DRIVE; -- setup the disk registers for writing the sector
rtnState_x <= WRITE_WORDS;
else
-- no operation requested
state_x <= WAIT_FOR_CMD; -- keep waiting for a R/W command
end if;
-----------------------------------------------------------------
-- setup the disk to read or write a sector
-----------------------------------------------------------------
when SETUP_DRIVE =>
-- load the sector count register with 1 since only a single sector will be read/written
pioWr <= YES;
pioAddr <= SECTOR_CNT_REG;
pioDIn <= TO_UNSIGNED(1,pioDIn'length);
state_x <= SETUP_DRIVE_1;
when SETUP_DRIVE_1 =>
-- load the number of the sector that will be read/written
pioWr <= YES;
pioAddr <= SECTOR_REG;
pioDIn(7 downto 0) <= sector;
state_x <= SETUP_DRIVE_2;
when SETUP_DRIVE_2 =>
-- load the number of the cylinder that contains the desired sector
pioWr <= YES;
pioAddr <= CYL_LOW_REG;
pioDIn(7 downto 0) <= cylinder(7 downto 0);
state_x <= SETUP_DRIVE_3;
when SETUP_DRIVE_3 =>
pioWr <= YES;
pioAddr <= CYL_HIGH_REG;
pioDIn(7 downto 0) <= cylinder(15 downto 8);
state_x <= SETUP_DRIVE_4;
when SETUP_DRIVE_4 =>
-- load the number of the head that accesses the desired cylinder
pioWr <= YES;
pioAddr <= DRIVE_HEAD_REG;
pioDIn(7 downto 0) <= "1010" & head;
state_x <= SETUP_DRIVE_5;
when SETUP_DRIVE_5 =>
-- load the command (read sector or write sector)
pioWr <= YES;
pioAddr <= CMD_REG;
pioDIn(cmd_r'range) <= cmd_r;
state_x <= rtnState_r;
-----------------------------------------------------------------
-- write data to the disk sector
-----------------------------------------------------------------
when WRITE_WORDS =>
state_x <= WAIT_FOR_NOT_BUSY;
rtnState_x <= WRITE_WORDS_1;
when WRITE_WORDS_1 =>
-- check the data request bit to see if the sector is ready for read/write ops
if(pioDOut(STATUS_REG_DRQ) = YES) then
state_x <= WRITE_WORDS_2; -- if ready, then write sector state
elsif(pioDOut(STATUS_REG_ERR) = YES) then
status_x(ERROR_FLAG) <= YES; -- tell the host there was an error
state_x <= ERROR;
else
-- data not ready, so read status again
pioRd <= YES;
pioAddr <= STATUS_REG;
state_x <= WRITE_WORDS_1;
end if;
when WRITE_WORDS_2 =>
-- write another word to the disk each time the write control is high
if(wr = YES) then
pioWr <= YES;
pioAddr <= DATA_REG;
pioDIn <= hDIn;
state_x <= WRITE_WORDS_3;
else
state_x <= WRITE_WORDS_2; -- halt writes to disk when wr is inactive
end if;
when WRITE_WORDS_3 =>
done <= YES; -- tell the host this word has been written to disk
if(wordCnt_r = 0) then
-- return and wait for another command if the entire sector has been written
state_x <= WRITE_WORDS_4;
else
-- otherwise, write the next word to the disk
wordCnt_x <= wordCnt_r - 1;
state_x <= WRITE_WORDS_2;
end if;
when WRITE_WORDS_4 =>
if(pioIntrq = YES) then
pioRd <= YES;
pioAddr <= STATUS_REG;
state_x <= WAIT_FOR_CMD;
else
state_x <= WRITE_WORDS_4;
end if;
-----------------------------------------------------------------
-- read data from the disk sector
-----------------------------------------------------------------
when READ_WORDS =>
if(pioIntrq = YES) then
pioRd <= YES;
pioAddr <= STATUS_REG;
state_x <= READ_WORDS_1;
else
state_x <= READ_WORDS;
end if;
when READ_WORDS_1 =>
-- read another word from the disk each time the read control is high
if(rd = YES) then
pioRd <= YES;
pioAddr <= DATA_REG;
state_x <= READ_WORDS_2;
else
state_x <= READ_WORDS_1; -- halt reads from disk when rd is inactive
end if;
when READ_WORDS_2 =>
done <= YES; -- tell the host a word has been read and is available
if(wordCnt_r = 0) then
-- return and wait for another command if the entire sector has been read
state_x <= WAIT_FOR_CMD;
else
-- otherwise, read the next word from the disk
wordCnt_x <= wordCnt_r - 1;
state_x <= READ_WORDS_1;
end if;
-----------------------------------------------------------------
-- error state. Requires a reset to leave this state
-----------------------------------------------------------------
when ERROR =>
status_x(ERROR_FLAG) <= YES;
state_x <= ERROR;
-----------------------------------------------------------------
-- unknown state. Go to the error state
-----------------------------------------------------------------
when others =>
status_x(ERROR_FLAG) <= YES;
state_x <= ERROR;
end case;
end if;
end process combinatorial;
-----------------------------------------------------------
-- update registers on the appropriate clock edge
-----------------------------------------------------------
update: process(rst,clk)
begin
if rst = YES then
-- asynchronous reset
state_r <= RESET_DRIVE; -- upon reset, reset the drive
rtnState_r <= WAIT_FOR_CMD; -- and then wait for read/write commands
cmd_r <= (others=>'0');
wordCnt_r <= (others=>'0');
status_r <= (others=>'0'); -- clear the status register
elsif clk'event and clk='1' then
if(abort = YES) then
-- abort a read or write sector command and go back to wait for another command
state_r <= ABORT_1;
else
state_r <= state_x;
end if;
rtnState_r <= rtnState_x;
cmd_r <= cmd_x;
wordCnt_r <= wordCnt_x;
status_r <= status_x;
end if;
end process update;
end arch;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -