if_main.vhd

来自「基于4个mips核的noc设计」· VHDL 代码 · 共 565 行 · 第 1/2 页

VHD
565
字号
------------------------------------------------------------------
--								--
--	If_main.vhd - Main Interface Control			--
--	Paul Dunn - Nallatech Ltd Copyright 1999		--
--	Description - 						--
--	This process contains the main state machine for	--
--	controlling the interface between the Virtex and the	--
--	Spartan on the Ballynuey.				--
--	This process also contains the main CSR.  This CSR	--
--	controls the DMA engine (enables and determines 	--
--	direction).						--
--								--
------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

entity if_main is
    	generic (-- Number of memory blocks in memory map in bit size.
    		NUM_BLOCKSg : integer range 1 to 29;-- := 4;
    		-- Block size.
    		BLOCK_SIZEg : integer range 1 to 29;--:= 8;
    		-- Number of registers.
    		NUM_REGSg : integer range 1 to 29-- := 4
    		);
    	port (	-- Spartan - Virtex clock.
        	CLK: in STD_LOGIC;
        	-- Global reset
        	RST: in STD_LOGIC;
        	-- Synchronous reset.
        	SYNC_RST: in STD_LOGIC;
        	-- Indicates if Spartan can receive data.
        	BUSY: in STD_LOGIC;
        	-- Indicates if Spartan has data to send.
        	EMPTY: in STD_LOGIC;
        	-- Address Strobe / Data Strobe.
        	AS_DSl: in STD_LOGIC;
        	-- DMA engine is writing to Spartan.
        	DMA_IN_FULL: in STD_LOGIC;
        	DMA_IN_EMPTY: in STD_LOGIC;
        	DMA_OUT_FULL: in STD_LOGIC;
        	-- DMA engine is reading from Spartan.
        	DMA_OUT_EMPTY: in STD_LOGIC;
        	-- Terminal count of DMA counter.
        	TERM_CNT: in STD_LOGIC;
        	-- DMA count output.
        	COUNT_OUT: in STD_LOGIC_VECTOR (31 downto 0);
        	-- DMA output.
        	DMA_OUT: in STD_LOGIC_VECTOR (31 downto 0);
        	-- Read Enable / Write Enable.
       	 	RENl_WENl: out STD_LOGIC;
        	-- Read / Write.
        	RDl_WR: out STD_LOGIC;
        	-- Load DMA count.
        	WR_COUNT: out STD_LOGIC;
        	-- Enable DMA engine.
        	DMA_ENABLE: out STD_LOGIC;
        	-- DMA direction.
        	DMA_DIRECTION: out STD_LOGIC;
        	-- DMA select.
        	DMA_SEL: out STD_LOGIC_VECTOR (3 downto 0);	
			-- DMA reset.
			DMA_RST: out STD_LOGIC;
        	-- Active address.
        	ADDRESS: out STD_LOGIC_VECTOR (30 downto 0);
       	 	-- Write to active register.
        	WR_STROBE: out STD_LOGIC;
        	-- Read from active register.
        	RD_STROBE: out STD_LOGIC;
        	-- Write DMA.
        	WR_DMA: out STD_LOGIC;
        	-- Read DMA.
        	RD_DMA: out STD_LOGIC;
        	-- DMA count input.
        	COUNT_IN: out STD_LOGIC_VECTOR (31 downto 0);
        	-- DMA input.
        	DMA_IN: out STD_LOGIC_VECTOR (31 downto 0);
        	-- Data to and from Spartan.
        	ADIO: inout STD_LOGIC_VECTOR (31 downto 0);
        	-- Data to and from user's design.
        	DATA: inout STD_LOGIC_VECTOR (31 downto 0)
    		);
end if_main;

architecture if_main_arch of if_main is

-- Main control states of interface.
type IFACE_STATES is (RST_STATE, IDLE, WAIT_DATA, DATA_READ, ADDR_DEC, RD_REG, WR_REG, WAIT_TO_DMARD, WAIT_DATACHK, WAIT_ENDTRANS, 
			DMA_READ, WAIT_ADDRDEC, DMA_WRITE, WAIT_DMA_RD, WAIT_ADDRCHK, WAIT_TO_DMAWR, WAIT_END_DMARD);
signal SM_STATE : IFACE_STATES;

-- Delayed versions of busy and empty.
signal EMPTYd1 : std_logic;
signal BUSYd1 : std_logic;

-- Data input register.
signal DATAIN : std_logic_vector (31 downto 0);
-- Address strobe / Data strobe.
signal AS_DSl_IN : std_logic;
-- Address in.
signal ADDRESSi : std_logic_vector (31 downto 0);

-- Data valid required to determine valid data when in DMA read mode.
signal DVALID : std_logic;
signal DVALIDd1 : std_logic;
signal DVALIDd2 : std_logic;
-- Write data into input register.
signal DATAIN_WR : std_logic;
-- Write in address.
signal ADDRESS_WR : std_logic;
-- Memory block 0 is being addressed.
signal MEM_BLOCK0_EN : std_logic;

-- Internal read and write strobe signals.
signal READ_STROBEi : std_logic;
signal WRITE_STROBEi : std_logic;
signal WRITE_STROBEid1 : std_logic;

-- Read DMA count.
signal RD_COUNTi : std_logic;
-- Read DMA.
signal RD_DMAi : std_logic;
signal RD_DMAii : std_logic;

signal WR_DMAi, WR_DMAid1 : std_logic;

-- Write to Control/Status register.
signal WR_CSR : std_logic;
-- Read from control/status register.
signal RD_CSR : std_logic;
-- Control/status register.
signal CSR : std_logic_vector (31 downto 0);

-- Enable DMA read.
signal DMA_RD_EN : std_logic;
-- Enable DMA write.
signal DMA_WR_EN : std_logic;

-- Data is in buffer waiting to be processed.
signal DATA_READY : std_logic;

-- Internal use of signals RDl_WR and RENl_WENl.
signal RDl_WRi : std_logic;
signal RENl_WENli : std_logic;

-- Data out to be driven onto ADIO.
signal DATAOUTi : std_logic_vector (31 downto 0);
signal DATAOUT : std_logic_vector (31 downto 0);

signal WR_REG_WR : std_logic;
signal WR_REG_WRd1 : std_logic;

-- Constant values for zero and one. 32 bits wide.
constant ZEROS : std_logic_vector (31 downto 0) := (others => '0');
constant ONE : std_logic_vector (31 downto 0) := ( 0 => '1', others => '0');

begin

-- This state machine controls the all data to and from the Spartan.
-- Priority is given to reading data from the Spartan in case any CSRs need updating.
process (RST, CLK)
begin
	if RST='1' then
		SM_STATE <= RST_STATE;
		RDl_WRi <= '1';
		RENl_WENli <= '1';
		DATA_READY <= '0';
		WR_DMAi <= '0';
		RD_DMAi <= '0';
	elsif CLK'event and CLK='1' then
		case SM_STATE is
			-- Reset state ensures that the state machine remains reset until the whole design is definitely reset.
			when RST_STATE =>
				if SYNC_RST='1' then
					SM_STATE <= RST_STATE;
					RDl_WRi <= '1';
					RENl_WENli <= '1';
					DATA_READY <= '0';
					WR_DMAi <= '0';
					RD_DMAi <= '0';
				else
					SM_STATE <= IDLE;
				end if;
			-- When idle, check to see if there's data to be sent.  
			-- If there isn't, check to see if the DMA engine is set up to output data.	
			when IDLE =>
				if EMPTYd1='0' then
					SM_STATE <= WAIT_DATA;
					RDl_WRi <= '0';
					RENl_WENli <= '0';
				elsif EMPTYd1='1' and DMA_WR_EN='1' and TERM_CNT='0' then
					SM_STATE <= WAIT_TO_DMAWR;
				end if;
			-- Wait for data to be valid.	
			when WAIT_DATA =>
				RDl_WRi <= '1';
				RENl_WENli <= '1';
				SM_STATE <= DATA_READ;
			-- Firstly check to see if data is address or not.
			-- If it is an address, go to address decode.
			-- If it's not an address see if the data is for the DMA engine or not.	
			when DATA_READ =>
				RDl_WRi <= '1';
				RENl_WENli <= '1';
				if AS_DSl_IN='1' then
					SM_STATE <= ADDR_DEC;
				elsif DMA_RD_EN='1' and TERM_CNT='0' then
					if DMA_IN_FULL='1' then
						SM_STATE <= WAIT_DMA_RD;
						WR_DMAi <= '0';
					elsif EMPTY='0' and DMA_IN_FULL='0' then
						SM_STATE <= WAIT_TO_DMARD;
						RDl_WRi <= '0';
						RENl_WENli <= '0';
						WR_DMAi <= '1';
					elsif EMPTY='1' and DMA_IN_FULL='0' then 
						SM_STATE <= WAIT_ENDTRANS;
						WR_DMAi <= '1';
					end if;	
				else	
					DATA_READY <= '1';
					SM_STATE <= WR_REG;
				end if;
			-- Determine if the address is being written to or read from.	
			when ADDR_DEC =>
				if ADDRESSi(31)='0' then
					SM_STATE <= WR_REG;
				else
					SM_STATE <= RD_REG;
				end if;
			-- Check to see if data has already been read.
			-- If it hasn't, read from Spartan.	
			when WR_REG =>
				if DATA_READY='0' then
					if EMPTYd1='0' then
						RDl_WRi <= '0';
						RENl_WENli <= '0';
						SM_STATE <= WAIT_DATACHK;
					end if;	
				else
					DATA_READY <= '0';
					SM_STATE <= WAIT_DATACHK;	
				end if;
			-- Read from register.		
			when RD_REG =>
				RDl_WRi <= '1';
				RENl_WENli <= '0';
				SM_STATE <= WAIT_DATACHK;
			-- Wait before going into DMA read.	
			when WAIT_TO_DMARD =>
				RDl_WRi <= '0';
				RENl_WENli <= '0';
				WR_DMAi <= '1';
				SM_STATE <= DMA_READ;
			-- Check to see if there's still data to be processed.
			-- If there is, determine the nature of the data.	
			when WAIT_DATACHK =>
				RDl_WRi <= '1';
				RENl_WENli <= '1';
				if DATA_READY='1' then
					if AS_DSl_IN='1' then
						SM_STATE <= ADDR_DEC;
						DATA_READY <= '0';
					elsif DMA_RD_EN='1' and TERM_CNT='0' then
						SM_STATE <= WAIT_TO_DMARD;
						DATA_READY <= '0';
					else
						SM_STATE <= WR_REG;
					end if;
				else				
					SM_STATE <= WAIT_ENDTRANS;
				end if;	
			-- Wait before going idle.	
			when WAIT_ENDTRANS =>
				SM_STATE <= IDLE;
				WR_DMAi <= '0';
				RDl_WRi <= '1';
				RENl_WENli <= '1';
			-- Check that data in isn't an address.
			-- Also check for terminal count.
			-- If neither of these are true, check that it's okay to read data.	
			when DMA_READ =>
				if EMPTY='1' then--or TERM_CNT='1' then

⌨️ 快捷键说明

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