atahost_controller.vhd

来自「ATA接口的IP核,经过量产的验证,已经在quartus5.1下编译通过了.」· VHDL 代码 · 共 588 行 · 第 1/2 页

VHD
588
字号
	--
	-- signals
	--
	signal SelDev : std_logic;                       -- selected device
	signal DMARxFull : std_logic;                    -- DMA receive buffer full

	-- PIO / DMA signals
	signal PIOgo, DMAgo : std_logic;                 -- start PIO / DMA timing controller
	signal PIOdone, DMAdone : std_logic;             -- PIO / DMA timing controller done

	-- PIO signals
	signal PIOdior, PIOdiow : std_logic;
	signal PIOoe : std_logic;

	-- PIO pingpong signals
	signal PIOd : std_logic_vector(15 downto 0);
	signal PIOa : unsigned(3 downto 0);
	signal PIOreq : std_logic;

	-- DMA signals
	signal DMAd : std_logic_vector(15 downto 0);
	signal DMAdior, DMAdiow : std_logic;

	-- synchronized ATA inputs
	signal sDMARQ, sIORDY : std_logic;

begin

	--
	-- synchronize incoming signals
	--
	synch_incoming: block
		signal cDMARQ : std_logic;                   -- capture DMARQ
		signal cIORDY : std_logic;                   -- capture IORDY
		signal cINTRQ : std_logic;                   -- capture INTRQ
	begin
		process(clk)
		begin
			if (clk'event and clk = '1') then
				cDMARQ <= DMARQ;
				cIORDY <= IORDY;
				cINTRQ <= INTRQ;

				sDMARQ <= cDMARQ;
				sIORDY <= cIORDY;
				irq    <= cINTRQ;
			end if;
		end process;

		DMA_dmarq <= sDMARQ;
	end block synch_incoming;

	--
	-- generate ATA signals
	--
	gen_ata_sigs: block
		signal iDDo : std_logic_vector(15 downto 0);
	begin
		-- generate registers for ATA signals
		gen_regs: process(clk, nReset)
		begin
			if (nReset = '0') then
				RESETn <= '0';
				DIORn  <= '1';
				DIOWn  <= '1';
				DA     <= (others => '0');
				CS0n	  <= '1';
				CS1n	  <= '1';
				DDo    <= (others => '0');
				DDoe   <= '0';
				DMACKn <= '1';
			elsif (clk'event and clk = '1') then
				if (rst = '1') then
					RESETn <= '0';
					DIORn  <= '1';
					DIOWn  <= '1';
					DA     <= (others => '0');
					CS0n   <= '1';
					CS1n  	<= '1';
					DDo    <= (others => '0');
					DDoe   <= '0';
					DMACKn <= '1';
				else
					RESETn <= not IDEctrl_rst;
					DA     <= PIOa(2 downto 0);
					CS0n	  <= not (not PIOa(3) and PIOtip); -- CS0 asserted when A(3) = '0', negate during DMA transfers
					CS1n	  <= not (    PIOa(3) and PIOtip); -- CS1 asserted when A(3) = '1', negate during DMA transfers

					if (PIOtip = '1') then
						DDo   <= PIOd;
						DDoe  <= PIOoe;
						DIORn <= not PIOdior;
						DIOWn <= not PIOdiow;
					else
						DDo   <= DMAd;
						DDoe  <= DMActrl_dir and DMAtip;
						DIORn <= not DMAdior;
						DIOWn <= not DMAdiow;
					end if;

					DMACKn <= not DMAtip;
				end if;
			end if;
		end process gen_regs;
	end block gen_ata_sigs;
	
	--
	-- generate bus controller statemachine
	--
	statemachine: block
		type states is (idle, PIO_state, DMA_state);
		signal nxt_state, c_state : states; -- next_state, current_state

		signal iPIOgo, iDMAgo : std_logic;
	begin
		-- generate next state decoder + output decoder
		gen_nxt_state: process(c_state, DMActrl_DMAen, DMActrl_dir, PIOreq, sDMARQ, DMATxFull, DMARxFull, PIOdone, DMAdone)
		begin
			nxt_state <= c_state; -- initialy stay in current state

			iPIOgo <= '0';
			iDMAgo <= '0';

			case c_state is
				-- idle
				when idle =>
					-- DMA transfer pending ?
					if ( (sDMARQ = '1') and (DMActrl_DMAen = '1') ) then
						if (( (DMActrl_dir = '1') and (DMATxFull = '1') ) or ( (DMActrl_dir = '0') and (DMARxFull = '0') )) then
							nxt_state <= DMA_state;                        -- DMA transfer
							iDMAgo    <= '1'; -- start DMA timing controller
						end if;
					-- PIO transfer pending ?
					elsif (PIOreq = '1') then
						nxt_state <= PIO_state;                            -- PIO transfer
						iPIOgo    <= '1';
					end if;
				
				-- PIO transfer
				when PIO_state =>
					if (PIOdone = '1') then
							nxt_state <= idle;
					end if;

				-- DMA transfer
				when DMA_state =>
					if (DMAdone = '1') then
	 					nxt_state <= idle;
					end if;

				when others =>
					nxt_state <= idle;                                   -- go to idle state

			end case;
		end process gen_nxt_state;

		-- generate registers
		gen_regs: process(clk, nReset)
		begin
			if (nReset = '0') then
				c_state <= idle;
				PIOgo <= '0';
				DMAgo <= '0';
			elsif (clk'event and clk = '1') then
				if (rst = '1') then
					c_state <= idle;
					PIOgo <= '0';
					DMAgo <= '0';
				else
					c_state <= nxt_state;
					PIOgo <= iPIOgo;
					DMAgo <= iDMAgo;
				end if;
			end if;
		end process gen_regs;

		-- generate PIOtip / DMAtip
		gen_tip: process(clk, nReset)
		begin
			if (nReset = '0') then
				PIOtip <= '0';
				DMAtip <= '0';
			elsif (clk'event and clk = '1') then
				if (rst = '1') then
					PIOtip <= '0';
					DMAtip <= '0';
				else
					PIOtip <= iPIOgo or (PIOtip and not PIOdone);
					DMAtip <= iDMAgo or (DMAtip and not ((DMAdone and DMActrl_dir) or (DMAdone and not sDMARQ and not DMActrl_dir)) );
				end if;
			end if;
		end process gen_tip;
	end block statemachine;

	--
	-- Hookup PIO controller
	--
	PIO_control: atahost_pio_controller
		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_IDEen => IDEctrl_IDEen,
			IDEctrl_ppen  => IDEctrl_ppen,
			IDEctrl_FATR0 => IDEctrl_FATR0,
			IDEctrl_FATR1 => IDEctrl_FATR1,
			cmdport_T1    => PIO_cmdport_T1,
			cmdport_T2    => PIO_cmdport_T2,
			cmdport_T4    => PIO_cmdport_T4,
			cmdport_Teoc  => PIO_cmdport_Teoc,
			cmdport_IORDYen => PIO_cmdport_IORDYen,
			dport0_T1     => PIO_dport0_T1,
			dport0_T2     => PIO_dport0_T2,
			dport0_T4     => PIO_dport0_T4,
			dport0_Teoc   => PIO_dport0_Teoc,
			dport0_IORDYen => PIO_dport0_IORDYen,
			dport1_T1     => PIO_dport1_T1,
			dport1_T2     => PIO_dport1_T2,
			dport1_T4     => PIO_dport1_T4,
			dport1_Teoc   => PIO_dport1_Teoc,
			dport1_IORDYen => PIO_dport1_IORDYen,
			sel    => PIOsel,
			ack    => PIOack,
			a      => a,
			we     => we,
			d      => d(15 downto 0),
			q      => PIOq, 
			PIOreq => PIOreq,
			PPFull => PIOpp_full,
			go     => PIOgo,
			done   => PIOdone,
			PIOa   => PIOa,
			PIOd   => PIOd,
			SelDev => SelDev,
			DDi    => DDi,
			DDoe   => PIOoe,
			DIOR   => PIOdior,
			DIOW   => PIOdiow,
			IORDY  => sIORDY
		);

	--
	-- Hookup DMA access controller
	--
	DMA_control: atahost_dma_actrl
		generic map(
			TWIDTH => TWIDTH,
			DMA_mode0_Tm => DMA_mode0_Tm,
			DMA_mode0_Td => DMA_mode0_Td,
			DMA_mode0_Teoc => DMA_mode0_Teoc
		)
		port map(
			clk    => clk,
			nReset => nReset,
			rst    => rst,
			IDEctrl_rst    => IDEctrl_rst,
			DMActrl_DMAen  => DMActrl_DMAen, 
			DMActrl_dir    => DMActrl_dir,
			DMActrl_BeLeC0 => DMActrl_BeLeC0,
			DMActrl_BeLeC1 => DMActrl_BeLeC1, 
			dev0_Td   => DMA_dev0_Td,
			dev0_Tm   => DMA_dev0_Tm,
			dev0_Teoc => DMA_dev0_Teoc, 
			dev1_Td   => DMA_dev1_Td,
			dev1_Tm   => DMA_dev1_Tm,
			dev1_Teoc => DMA_dev1_Teoc,
			sel     => DMAsel,
			ack     => DMAack,
			we      => we,
			TxD     => d,
			TxFull  => DMATxFull,
			RxQ     => DMAq,
			RxFull  => DMARxFull,
			RxEmpty => DMARxEmpty,
			DMA_req => DMA_req,
			DMA_ack => DMA_ack,
			SelDev  => SelDev,
			Go      => DMAgo,
			Done    => DMAdone,
			DDi     => DDi,
			DDo     => DMAd,
			DIOR    => DMAdior,
			DIOW    => DMAdiow,
			DMARQ   => sDMARQ
		);
end architecture structural;

⌨️ 快捷键说明

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