head	1.2;
access;
symbols;
locks; strict;
comment	@# @;


1.2
date	2001.08.03.10.18.38;	author rherveille;	state dead;
branches;
next	1.1;

1.1
date	2001.06.29.14.06.50;	author rherveille;	state Exp;
branches;
next	;


desc
@@


1.2
log
@no message
@
text
@--
-- file: controller.vhd
--	description: single ATA-controller
-- author : Richard Herveille
-- rev.: 1.0 march 8th, 2001
--
--

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity PIOcontroller is
	generic(
		TWIDTH : natural := 8;                        -- counter width

		-- PIO mode 0 settings (@@100MHz clock)
		PIO_mode0_T1 : natural := 6;                  -- 70ns
		PIO_mode0_T2 : natural := 28;                 -- 290ns
		PIO_mode0_T4 : natural := 2;                  -- 30ns
		PIO_mode0_Teoc : natural := 23                -- 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
	);
	port(
		clk : in std_logic;  		                    	  -- master clock in
		nReset	: in std_logic := '1';                 -- asynchronous active low reset
		rst : in std_logic := '0';                    -- synchronous active high reset
		
		-- control / registers
		IDEctrl_IDEen,
		IDEctrl_ppen,
		IDEctrl_FATR0,
		IDEctrl_FATR1 : in std_logic;

		-- PIO registers
		cmdport_T1,
		cmdport_T2,
		cmdport_T4,
		cmdport_Teoc : in unsigned(7 downto 0);
		cmdport_IORDYen : in std_logic;               -- PIO command port / non-fast timing

		dport0_T1,
		dport0_T2,
		dport0_T4,
		dport0_Teoc : in unsigned(7 downto 0);
		dport0_IORDYen : in std_logic;                -- PIO mode data-port / fast timing device 0

		dport1_T1,
		dport1_T2,
		dport1_T4,
		dport1_Teoc : in unsigned(7 downto 0);
		dport1_IORDYen : in std_logic;                -- PIO mode data-port / fast timing device 1

		sel : in std_logic;                           -- PIO controller selected
		ack : out std_logic;                          -- PIO controller acknowledge
		a : in unsigned(3 downto 0);                  -- lower address bits
		we : in std_logic;                            -- write enable input
		d : in std_logic_vector(15 downto 0);
		q : out std_logic_vector(15 downto 0);

		PIOreq : out std_logic;                       -- PIO transfer request
		PPFull : out std_logic;                       -- PIO Write PingPong Full
		go : in std_logic;                            -- start PIO transfer
		done : buffer std_logic;                      -- done with PIO transfer

		PIOa : out unsigned(3 downto 0);              -- PIO address, address lines towards ATA devices
		PIOd : out std_logic_vector(15 downto 0);     -- PIO data, data towards ATA devices

		SelDev : buffer std_logic;                    -- Selected Device, Dev-bit in ATA Device/Head register

		DDi	: in std_logic_vector(15 downto 0);
		DDoe : buffer std_logic;

		DIOR	: buffer std_logic;
		DIOW	: buffer std_logic;
		IORDY	: in std_logic
	);
end entity PIOcontroller;

architecture structural of PIOcontroller is
	--
	-- component declarations
	--
	component PIO_actrl is
	generic(
		TWIDTH : natural := 8;                     -- counter width

		-- PIO mode 0 settings (@@100MHz clock)
		PIO_mode0_T1 : natural := 6;               -- 70ns
		PIO_mode0_T2 : natural := 28;              -- 290ns
		PIO_mode0_T4 : natural := 2;               -- 30ns
		PIO_mode0_Teoc : natural := 23             -- 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
	);
	port(
		clk : in std_logic;                        -- master clock
		nReset : in std_logic;                     -- asynchronous active low reset
		rst : in std_logic;                        -- synchronous active high reset

		IDEctrl_FATR0,
		IDEctrl_FATR1 : in std_logic;

		cmdport_T1,
		cmdport_T2,
		cmdport_T4,
		cmdport_Teoc : in unsigned(7 downto 0);
		cmdport_IORDYen : in std_logic;            -- PIO command port / non-fast timing

		dport0_T1,
		dport0_T2,
		dport0_T4,
		dport0_Teoc : in unsigned(7 downto 0);
		dport0_IORDYen : in std_logic;             -- PIO mode data-port / fast timing device 0

		dport1_T1,
		dport1_T2,
		dport1_T4,
		dport1_Teoc : in unsigned(7 downto 0);
		dport1_IORDYen : in std_logic;             -- PIO mode data-port / fast timing device 1

		SelDev : in std_logic;                     -- Selected device	

		Go : in std_logic;                         -- Start transfer sequence
		Done : out std_logic;                      -- Transfer sequence done
		Dir : in std_logic;                        -- Transfer direction '1'=write, '0'=read
		A : in unsigned(3 downto 0);               -- PIO transfer address
		Q : out std_logic_vector(15 downto 0);     -- Data read from ATA devices

		DDi : in std_logic_vector(15 downto 0);    -- Data from ATA DD bus
		oe : buffer std_logic;                     -- DDbus output-enable signal

		DIOR,
		DIOW : buffer std_logic;
		IORDY : in std_logic 
	);
	end component PIO_actrl;

	--
	-- signals
	--

	-- PIO pingpong signals
	signal pp_d : std_logic_vector(15 downto 0);
	signal pp_a : unsigned(3 downto 0);
	signal pp_we : std_logic;
	signal idone : std_logic;

begin
	--
	-- generate selected device
	--
	gen_seldev: process(clk)
		variable Asel : std_logic; -- address selected
	begin
		Asel := not pp_a(3) and pp_a(2) and pp_a(1) and not pp_a(0); -- header/device register

		if (clk'event and clk = '1') then
			if ( (idone = '1') and (Asel = '1') and (pp_we = '1') ) then
				SelDev <= pp_d(4);
			end if;
		end if;
	end process gen_seldev;

	--
	-- generate PIO write pingpong system
	--
	gen_pingpong: block
		signal ping_d, pong_d : std_logic_vector(15 downto 0);
		signal ping_a, pong_a : unsigned(3 downto 0);
		signal ping_we, pong_we : std_logic;
		signal ping_valid, pong_valid : std_logic;
		signal dping_valid, dpong_valid : std_logic;
		signal wpp, rpp : std_logic;

		signal dsel, sel_strb : std_logic;

		signal iack : std_logic;
	begin
		-- generate PIO acknowledge
		gen_ack: process(clk)
			variable ping_re, ping_fe, pong_re, pong_fe : std_logic;
		begin
			-- detect rising edge of ping_valid and pong_valid
			ping_re := ping_valid and not dping_valid and we;
			pong_re := pong_valid and not dpong_valid and we;

			-- detect falling edge of ping_valid and pong_valid
			ping_fe := not ping_valid and dping_valid;
			pong_fe := not pong_valid and dpong_valid;

			if (clk'event and clk = '1') then
				if ((pp_we = '1') and (IDEctrl_ppen = '1')) then -- write sequence
					if (wpp = '1') then
						iack <= ping_re;
					else
						iack <= pong_re;
					end if;
				else                                           -- read sequence
					if (rpp = '1') then
						iack <= ping_fe;
					else
						iack <= pong_fe;
					end if;
				end if;
			end if;
		end process gen_ack;
		ack <= (iack or not IDEctrl_IDEen) and sel; -- acknowledge access when not enabled (discard access)

		-- generate select-strobe, hold sel_strb until pingpong system ready for new data
		gen_sel_strb: process(clk, nReset)
		begin
			if (nReset = '0') then
				dsel <= '0';
			elsif (clk'event and clk = '1') then
				if (rst = '1') then
					dsel <= '0';
				else
					dsel <= sel_strb or (dsel and sel);
				end if;
			end if;
		end process gen_sel_strb;
		sel_strb <= sel and not dsel and IDEctrl_IDEen and ((wpp and not ping_valid) or (not wpp and not pong_valid));

		-- generate pingpong control
		gen_pp : process(clk, nReset)
		begin
			if (nReset = '0') then
				wpp <= '0';
				rpp <= '0';
				ping_valid <= '0';
				pong_valid <= '0';
				dping_valid <= '0';
				dpong_valid <= '0';
			elsif (clk'event and clk = '1') then
				if (rst = '1') then
					wpp <= '0';
					rpp <= '0';
					ping_valid <= '0';
					pong_valid <= '0';
					dping_valid <= '0';
					dpong_valid <= '0';
				else
					wpp <= (wpp xor (iack and we)) and IDEctrl_ppen;
					rpp <= (rpp xor (idone and pp_we)) and IDEctrl_ppen;
					ping_valid <= ((    wpp and sel_strb) or ping_valid) and not (    rpp and idone);
					pong_valid <= ((not wpp and sel_strb) or pong_valid) and not (not rpp and idone);
					dping_valid <= ping_valid;
					dpong_valid <= pong_valid;
				end if;
			end if;
		end process gen_pp;
		
		-- generate pingpong full signal
		PPFull <= (ping_valid and pong_valid) when (IDEctrl_ppen = '1') else pong_valid;

		-- fill ping/pong registers
		fill_pp: process(clk)
		begin
			if (clk'event and clk = '1') then
				if (sel = '1') then
					if (wpp = '1') then
						if (ping_valid = '0') then
							ping_d <= d;
							ping_a <= a;
							ping_we <= we;
						end if;
					else
						if (pong_valid = '0') then
							pong_d <= d;
							pong_a <= a;
							pong_we <= we;
						end if;
					end if;
				end if;
			end if;
		end process fill_pp;

		-- multiplex pingpong data to pp_d, pp_a, pp_we
		pp_d <= ping_d when (rpp = '1') else pong_d;
		pp_a <= ping_a when (rpp = '1') else pong_a;
		pp_we <= ping_we when (rpp = '1') else pong_we;

		-- generate PIOreq
		PIOreq <= (ping_valid and not idone) when (rpp = '1') else (pong_valid and not idone);
	end block gen_pingpong;

	--
	-- Hookup PIO access controller
	--
	PIO_access_control: PIO_actrl
		generic map(TWIDTH => TWIDTH, PIO_mode0_T1 => PIO_mode0_T1, PIO_mode0_T2 => PIO_mode0_T2, PIO_mode0_T4 => PIO_mode0_T4, PIO_mode0_Teoc => PIO_mode0_Teoc)
		port map(clk => clk,nReset => nReset, rst => rst, IDEctrl_FATR0 => IDEctrl_FATR0, IDEctrl_FATR1 => IDEctrl_FATR1, 
			cmdport_T1 => cmdport_T1, cmdport_T2 => cmdport_T2, cmdport_T4 => cmdport_T4, cmdport_Teoc => cmdport_Teoc, cmdport_IORDYen => cmdport_IORDYen,
			dport0_T1 => dport0_T1, dport0_T2 => dport0_T2, dport0_T4 => dport0_T4, dport0_Teoc => dport0_Teoc, dport0_IORDYen => dport0_IORDYen,
			dport1_T1 => dport1_T1, dport1_T2 => dport1_T2, dport1_T4 => dport1_T4, dport1_Teoc => dport1_Teoc, dport1_IORDYen => dport1_IORDYen,
			SelDev => SelDev, Go => go, Done => idone, Dir => pp_we, A => pp_a, Q => Q, DDi => DDi, oe => DDoe, DIOR => dior, DIOW => diow, IORDY => IORDY);

	--
	-- assign outputs
	--
	PIOa <= pp_a;
	PIOd <= pp_d;
	Done <= idone;
end architecture structural;





@


1.1
log
@Created VHDL & Verilog subdirectories. Moved files accordingly.
@
text
@@

