uc_interface.vhd

来自「可编程器件厂商Xilinx的用于设计SMBus 控制器的源程序」· VHDL 代码 · 共 457 行

VHD
457
字号
-- File:     uC_interface.vhd
-- 
-- Author:   Jennifer Jenkins
--	     Xilinx
-- Purpose:  Description of an interface with a Hitachi SH7750 uC 
--	     	 bus to internal module registers
--           to be used for control of an SMBUS bus as master/slave with
--           transmit and receive modes.
--
--
-- Created:  6-23-00 ALS 
--	This file created from the Motorola uC interface file used in the I2C design
--	Note that the use of the CS_N signal eliminates the need for a base address
--	therefore, only 8 bits of address bus are needed.
--
-- Modified: 8-10-00 JRH
--	Changed to reflect unknown number of uC wait states and Tsu/Thold wait states.
--
-- Modified: 8-14-00 JRH
--	Changed addresses for MADR, MBCR, MBSR, MBDR to even numbers.

	


library IEEE;
use IEEE.std_logic_1164.all;


entity uC_interface is
	port(
		-- SH7750 parallel bus interface
		clk		: in STD_LOGIC;
		reset 	: in STD_LOGIC;	 
		
		addr_bus	: in STD_LOGIC_VECTOR (7 downto 0);
		data_bus	: inout STD_LOGIC_VECTOR (7 downto 0);
		cs_n		: in STD_LOGIC; 	-- chip select, active low	
		bs_n 		: in STD_LOGIC; 	-- bus cycle, active low
		
		-- Directional pins
		rd_n		: in STD_LOGIC;	-- Active low write 
		we_n		: in STD_LOGIC;	-- Active low read
		rd_wrn		: in STD_LOGIC; -- active high read, active low write
		rdy_n 		: out STD_LOGIC;	-- Active low ready signal, if high a wait state is inserted 
		irq		: out STD_LOGIC;	-- Interrupt request, active low
	
		-- Internal SMBUS Bus Registers
		-- Address Register (Contains slave address)
		madr	      : inout STD_LOGIC_VECTOR(7 downto 0);
   
                -- Control Register		
		men             : inout STD_LOGIC;  -- SMBUS Enable bit
		mien            : inout STD_LOGIC;	-- interrupt enable
		msta            : inout STD_LOGIC;	-- Master/Slave bit
		mtx             : inout STD_LOGIC;	-- Master read/write
		txak            : inout STD_LOGIC;	-- acknowledge bit
		rsta            : inout STD_LOGIC;	-- repeated start
	
		mbcr_wr         : out STD_LOGIC;	-- indicates that the control reg has been written
		rsta_rst	    : in STD_LOGIC;	-- input to modify rsta bit in contol register

                -- Status Register
		mcf             : in STD_LOGIC;	-- end of data transfer
		maas            : in STD_LOGIC;	-- addressed as slave
		mbb             : in STD_LOGIC;	-- bus busy
		mal             : in STD_LOGIC;	-- arbitration lost
		srw             : in STD_LOGIC;	-- slave read/write
		mif             : in STD_LOGIC;	-- interrupt pending
		rxak            : in STD_LOGIC;	-- received acknowledge

		mal_bit_reset   : out STD_LOGIC;	-- indicates that the MAL bit should be reset
		mif_bit_reset   : out STD_LOGIC;	-- indicates that the MIF bit should be reset
		men_bit_reset   : in STD_LOGIC;		-- indicates that the MEN bit should be reset
		msta_rst	    : in STD_LOGIC;	-- resets the MSTA bit if arbitration is lost
		

                -- Data Register 
		mbdr_micro      : inout STD_LOGIC_VECTOR (7 downto 0);
		mbdr_smbus        : in STD_LOGIC_VECTOR (7 downto 0);

		mbdr_read       : out STD_LOGIC
		
		);
		

end uC_interface;




architecture BEHAVIOUR of uC_interface is

-- Constant Declarations
constant RESET_ACTIVE : STD_LOGIC := '0';

-- Register Addresses (5 Total):
-- Address Register (8Ch)
constant MADR_ADDR 	: STD_LOGIC_VECTOR(7 downto 0) := "10001100";


-- Control Register (90h)
constant MBCR_ADDR 	: STD_LOGIC_VECTOR(7 downto 0) := "10010000";

-- Status Register (92h)
constant MBSR_ADDR 	: STD_LOGIC_VECTOR(7 downto 0) := "10010010";

-- Data I/O Register (94h)
constant MBDR_ADDR 	: STD_LOGIC_VECTOR(7 downto 0) := "10010100";

-- State Machine Signals
type STATE_TYPE is (IDLE, ADDR_VALID, READ_WRITE);

-- Signal Declarations

-- Internal handshaking lines for microprocessor
signal wen_int 	  : STD_LOGIC;
signal data_out	: std_logic_vector(7 downto 0); -- holds the data to be output on the data bus
signal data_in	: std_logic_vector(7 downto 0); -- holds the data to be input to the chip


-- State signals for target state machine
signal prs_state, next_state : STATE_TYPE;					

-- Register Enable Lines
signal addr_en 		: std_logic;	-- smbus address register is selected
signal cntrl_en		: std_logic;	-- control register is selected
signal stat_en		: std_logic;	-- status register is selected
signal data_en		: std_logic;	-- data register is selected			



begin

        -- Interrupt signal to uProcessor
        irq <= '0' when (mien = '1') and (mif = '1') else 'Z';
	
	-- Bi-directional Data bus
	data_bus <= data_out when (rd_n = '0' and cs_n = '0') else (others => 'Z');
	data_in <= data_bus;

	-- Process:   SYNCH_INPUTS
	-- Function:  To register value of WE_N
	--SYNCH_INPUTS: process(reset, clk)
--	begin
--		if reset = RESET_ACTIVE then
--			wen_int <= '1';
--			
--		elsif clk'event and clk = '1' then
--			wen_int <= we_n;	  
--			
--		end if;
--	
--	end process;

	
	-- Process:  SEQUENTIAL
	-- Function: Synchronize target state machine
	SEQUENTIAL: process (clk, reset)
	begin
		if reset = RESET_ACTIVE then
			prs_state <= IDLE;
		
		elsif clk'event and clk = '1' then
			prs_state <= next_state;
			
		end if;
	
	end process;
	
	
	
	-- Process:   COMBINATIONAL
	-- Function:  Contains the synchronous target state machine to mediate 
	--	      the handshaking taking place with the uProc parallel bus
	COMBINATIONAL: process (prs_state, cs_n, bs_n, rd_wrn, we_n, rd_n)
	
	begin
	
	next_state <= prs_state;
	rdy_n	<= '1';
	
	
	case prs_state is
	
		------------- IDLE State (00) -------------
		when IDLE =>
			
		        -- Wait for assertion of chip select and bus cycle
			if cs_n = '0' and bs_n = '0' then
				-- Since both CS_N and BS_N were asserted, this
				-- module is being addressed 
				-- next clock (state) contains valid data
				next_state <= ADDR_VALID;
			end if;

		
		------------ ADDR_VALID State (01) --------------
		when ADDR_VALID =>
			-- register enables are decided in this state
			if (rd_wrn = '0' and we_n = '0') or (rd_wrn = '1' and rd_n = '0') then
				next_state <= READ_WRITE;
			end if;
			
			
		---------- READ_WRITE State (10) ------------
		when READ_WRITE =>
			rdy_n <= '0';
		        -- Read or write from enabled register
			-- go back to IDLE
			if (rd_wrn = '0' and we_n = '1') or (rd_wrn = '1' and rd_n = '1') then
		        	next_state <= IDLE;
			end if;
			
			  			
		-------- Default State ----------
		when others =>
		        next_state <= IDLE;
		
         end case;
		
	end process;


	-- Process:  ADDR_DECODE
	-- Function:  Mapping address from uProc to enable appropriate register
	ADDR_DECODE: process (reset, clk, prs_state)
	begin
	        if reset = RESET_ACTIVE then
		  	addr_en <= '0';
			cntrl_en <= '0';
			stat_en <= '0';
			data_en <= '0';
		  
		-- Synchronize with rising edge of clock
		elsif clk'event and (clk = '1') then

		  -- SMBUS bus is specified by uProc and address is stable
		  if (prs_state = ADDR_VALID) then
		  
		    -- Check appropriate register address
		    case addr_bus(7 downto 0) is
		      
		      when MADR_ADDR =>  addr_en <= '1';
					   	cntrl_en <= '0';
					   	stat_en <= '0';
					   	data_en <= '0';

		      when MBCR_ADDR =>  cntrl_en <= '1';
						addr_en <= '0';
					   	stat_en <= '0';
					   	data_en <= '0';

		      when MBSR_ADDR =>  stat_en <= '1';
						addr_en <= '0';
					   	cntrl_en <= '0';
					   	data_en <= '0';

		      when MBDR_ADDR =>  data_en <= '1';
						addr_en <= '0';
					   	cntrl_en <= '0';
					   	stat_en <= '0';

		      when others => addr_en <= '0';
					   cntrl_en <= '0';
					   stat_en <= '0';
					   data_en <= '0';
				     
		    end case;
		  else
			-- this device is not addressed
			addr_en <= '0';
			cntrl_en <= '0';
			stat_en <= '0';
			data_en <= '0';
	
		  end if;
		  
		end if;
		
	end process;
	
	
	-- Process:  DATA_DIR
	-- Function: Read from or write to appropriate registers specified 
	--	     by uProc address
	DATA_DIR: process(clk, reset, msta_rst, rsta_rst)
	begin

		-- Initialize all internal registers upon reset
		if reset = RESET_ACTIVE then
		
			-- Address Register
			madr <= (others => '0');
			
			-- Control Register
			men  <= '0';
			mien <= '0';
			msta <= '0';
			mtx  <= '0';
			txak <= '0';
			rsta <= '0';

			mbcr_wr <= '0';
			
			-- Status Register
			mal_bit_reset  <= '0';
			mif_bit_reset  <= '0';
			
			-- Data Register
			mbdr_micro <= (others => '0');
			mbdr_read <= '0';

			-- Initialize data bus
			data_out <= (others => '0');
	
		-- Check for rising edge of clock
		elsif clk'event and (clk = '1') then

		  if (prs_state = IDLE) then
			-- reset signals that indicate read from mbdr or write to mbcr
			mbcr_wr <= '0';
			mbdr_read <= '0';

		  -- Check for data transfer state
		  elsif (prs_state = READ_WRITE) then
		
		    	-- Address register
			if addr_en = '1' then


			  						              
			  	if rd_wrn = '0' then
			
					-- uC write
					madr <= data_in(7 downto 1) & '0';
				else
					-- since RD_N is used as output enable, set data out bus 
					-- to this register
		  	    		data_out <= madr;
			    
			  	end if;    
			end if;

		     	-- Control Register
		    	if cntrl_en = '1' then

			  	if rd_wrn = '0' then
					-- uC write		       
			       		mbcr_wr <= '1';
			       		men  <= data_in(7);
			       		mien <= data_in(6);
			       		msta <= data_in(5);
			       		mtx  <= data_in(4);
			       		txak <= data_in(3);
			       		rsta <= data_in(2);
		       
			  	else
					-- uC read
			       		mbcr_wr <= '0'; 
					-- since RD_N is used as output enable, set data out bus 
					-- to this register
			  	 	data_out <= men & mien & msta & mtx & 
				       		txak & rsta & "0" & "0";
			  	end if;
			else
				mbcr_wr <= '0';

			end if;

		    	-- Status Register
		    	if stat_en = '1' then

			  	if rd_wrn = '0' then
			       
                        	  	-- uC write to these bits generates a reset
			       		if data_in(4) = '0' then
				    		mal_bit_reset <= '1';
			       		end if;

			       		if data_in(2) = '0' then
				    		mif_bit_reset <= '1';
			       		end if;
			  	else
			       		mal_bit_reset <= '0';
			       		mif_bit_reset <= '0';
					-- since RD_N is used as output enable, set data out bus 
					-- to this register
			  		data_out <= mcf & maas & mbb & mal & 
				      			"0" & srw & mif & rxak;

			  	end if;
			else
					mal_bit_reset <= '0';
					mif_bit_reset <= '0';
			end if;	    		

		    	-- Data Register
		    	if data_en = '1' then

		    		if rd_wrn = '0' then
				    -- uC write
				     mbdr_read <= '0';
				     mbdr_micro <= data_in;
		    		else
				     -- uC Read
				     	mbdr_read <= '1';
					-- since RD_N is used as output enable, set data out bus 
					-- to this register
			     		data_out <= mbdr_smbus;
		    		end if;
			else
				mbdr_read <= '0';
			end if;
			
		  end if;
		  
		  -- if arbitration is lost, the SMBUS Control component will generate a reset for the
		  -- MSTA bit to force the design to slave mode 
		  -- will do this reset synchronously

		  if msta_rst = '1' then
			msta <= '0';
		  end if;

		  --If a repeated start has been completed by the smbus master, reset the rsta bit
		  --This prevents the repeated start from continually reoccurring
		  if rsta_rst = RESET_ACTIVE then
			rsta <= '0';
		  end if;

		  --If a repeated start has been completed by the smbus master, reset the rsta bit
		  --This prevents the repeated start from continually reoccurring
		  if men_bit_reset = RESET_ACTIVE then
			men <= '0';
		  end if;

		end if;
	
	end process;
	


end BEHAVIOUR;
  












⌨️ 快捷键说明

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