⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atacntl.vhd

📁 这是一个基于FPGA的CF卡读写程序
💻 VHD
📖 第 1 页 / 共 3 页
字号:
			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 + -