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

📄 atacntl.vhd

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -