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

📄 atacntl.vhd

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