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

📄 pctosraminterface-sv06.vhd

📁 vhdl code for GIF Image Viewer
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-------------------------------------------------------------------------------
-- pctosraminterface-sv06.vhd
--
-- Author(s):     James Brennan
-- Created:       15 Feb 2001
-- Last Modified: 15 Feb 2001
-- 
-- Provides an interface to the SRAM controller that allows the PC to read
-- and write to the SRAM via the parallel port.
-------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity pctosraminterface is
    port (
        CLK: in STD_LOGIC;
        Resetn : in STD_LOGIC;
        Write: in STD_LOGIC;
        Read: in STD_LOGIC;
        NextSlice: in STD_LOGIC;
        DataIn: in STD_LOGIC_VECTOR (4 downto 0);
        DataOut: out STD_LOGIC_VECTOR (3 downto 0);
        doSRAMWrite: out STD_LOGIC;
        doSRAMRead: out STD_LOGIC;
        canWrite: in STD_LOGIC;
        canRead: in STD_LOGIC;
        writeAddr: out STD_LOGIC_VECTOR (18 downto 0);
        writeData: out STD_LOGIC_VECTOR (15 downto 0);
        readAddr: out STD_LOGIC_VECTOR (18 downto 0);
        readData: in STD_LOGIC_VECTOR (15 downto 0);

		-- Ports used when embedding this interface in
		-- a user design:
		active : out STD_LOGIC;

		-- Ports we expose for debugging purposes:
		-- It was originally intended that these ports would be
		-- removed, but it has been more convenient to leave them in:
    	portInSliceNum : out STD_LOGIC_VECTOR(1 downto 0);
    	portOutSliceNum : out STD_LOGIC_VECTOR(1 downto 0);
    	stateOutput : out STD_LOGIC_VECTOR(3 downto 0)
    );
end pctosraminterface;

architecture pctosraminterface_arch of pctosraminterface is
	-- ========================================
	-- Architecture declarations:
	-- ========================================	
	 
	-- Synchronous versions of the control inputs.
	-- We pass each control signal and the value on DataIn
	-- through a series of flip-flops. To simply the VHDL
	-- we concatenate the control signals and DataIn into
	-- a single STD_LOGIC_VECTOR. Only we the each level
	-- of flip-flops has the same value do we use the
	-- value of the control signals and/or DataIn.
	signal asyncInputs : STD_LOGIC_VECTOR(7 downto 0);
	signal syncInputs1, syncInputs2,
		syncInputs3 : STD_LOGIC_VECTOR(7 downto 0)	;
		
	-- Synchronous versions of the control inputs that
	-- we actually use. For each control signal, when
	-- each flip-flop in the corresponding chain holds the
	-- same value, we copy that value into one of the
	-- following signals:
	signal syncWrite : STD_LOGIC;
	signal syncRead : STD_LOGIC;
	signal syncNextSlice : STD_LOGIC;
	
	-- Register declarations:
	signal dataInReg : STD_LOGIC_VECTOR(4 downto 0);
	signal curAddrReg : STD_LOGIC_VECTOR(18 downto 0);
	signal writeDataReg : STD_LOGIC_VECTOR(15 downto 0);
	signal readDataReg : STD_LOGIC_VECTOR(15 downto 0);

	-- Clock-enable signals for the registers:
	signal regDataIn : STD_LOGIC;
	signal regCurAddr : STD_LOGIC;
	signal regWriteData : STD_LOGIC;
	signal regReadData : STD_LOGIC;
		
	-- Signal to indicate which "slice" we are now waiting
	-- to receive (when we are receiving an address or a 
	-- data value from the PC):
	-- An address is transmitted in three slices of 5 bits
	-- and one slice of 4 bits.
	-- Data values are transmitted in four slices of 4 bits.
	-- The least significant slice (the slice containing the
	-- the least significant bit) is always transmitted
	-- first.
	signal inSliceNum : STD_LOGIC_VECTOR(1 downto 0);
	-- Signal to indicate the current "slice" when
	-- we are sending data to the PC.
	signal outSliceNum : STD_LOGIC_VECTOR(1 downto 0);
	
	-- Other control signals:
	signal incCurAddr : STD_LOGIC;
	signal incInSliceNum : STD_LOGIC;
	signal incOutSliceNum : STD_LOGIC;
	signal clearInSliceNum : STD_LOGIC;
	signal clearOutSliceNum : STD_LOGIC;

	-- Signal declarations for settings:
	-- Settings are simple 1-bit signals that can be thought of
	-- as "preferences" or "configuration data" in hardware.
	-- The PC can set the state of each of these bits. The idea
	-- is that by setting or clearing these bits, the PC can
	-- control the behaviour of this PC-to-SRAM interface.
	-- When getSettings = '1', on the next rising clock edge,
	-- the value in dataInReg
	-- (i.e. effectively the value on DataIn) is copied into
	-- the current settings. This means we can currently
	-- have a maximum of 5 bits worth of settings.
	signal getSettings : STD_LOGIC;
	-- When pcControlEnabled is '1', this PC-to-SRAM interface
	-- requests exclusive access to SRAM. When pcControlEnable = '0',
	-- this PC-to-SRAM interface gives up its access to SRAM.
	-- This setting is visible on the output port "active".
	-- This signal is designed to be used (with supporting entities
	-- and a supporting top-level) to allow this interface
	-- and a different arbitrary design to share access to the
	-- SRAM. A user design simply accesses SRAM through a special
	-- top-level entity. Most of the time this entity allows
	-- full SRAM access to the user design. When pcControlEnabled
	-- = '1', it is expected that the user design will be
	-- "disconnected" from SRAM and this interface "connected" in its
	-- place. This is to allow to contents of SRAM to be accessed
	-- on the PC without having to download a new bit file.
	-- pcControlEnabled is to be loaded with bit 0 of dataInReg.
	signal pcControlEnabled : STD_LOGIC;
	

	-- Signals for FSM controller:
	type typeStateType is (stIdle, stGetAddr1, stDoWrite1, stDoWrite2,
			stDoRead1, stDoRead2, stDoRead3, 
			stGetSettings1, stGetSettings2, stGetSettings3);
	signal presState, nextState: typeStateType;

begin

	-- ========================================
	-- Architecture body:
	-- ========================================

	-- ========================================
	-- Combinational signals
	-- ========================================

	-- Debug connections:
	portInSliceNum <= inSliceNum;
	portOutSliceNum <= outSliceNum;

	writeAddr <= curAddrReg;
	readAddr <= curAddrReg;
	
	writeData <= writeDataReg;	

	-- We concatenate the control signals and DataIn into one
	-- vector for the purposes of passing it through several
	-- levels of flip-flops for synchronization purposes:
	asyncInputs <= NextSlice & Read & Write & DataIn;
	
	-- Multiplex the data presented on DataOut:
	with outSliceNum select
		DataOut <=	readDataReg(3 downto 0) when "00",
					readDataReg(7 downto 4) when "01",
					readDataReg(11 downto 8) when "10",
					readDataReg(15 downto 12) when others;

	active <= pcControlEnabled;
	
	-- ========================================
	-- Process for reset and clock-edge events
	-- ========================================
	process(CLK, Resetn)
	begin
		if Resetn = '0' then
			-- Set defaults for all signals not controlled
			-- by the FSM controller.	
			presState <= stIdle;

			syncInputs1 <= (others => '0');
			syncInputs2 <= (others => '0');
			syncInputs3 <= (others => '0');
			
			syncWrite <= '0';			
			syncRead <= '0';
			syncNextSlice <= '0';

			dataInReg <= (others => '0');			
			curAddrReg <= (others => '0');
			writeDataReg <= (others => '0');
			readDataReg <= (others => '0');
			
			inSliceNum <= (others => '0');
			outSliceNum <= (others => '0');

			pcControlEnabled <= '0';
			
		elsif CLK'EVENT and CLK = '1' then

			-- Update synchronous values of the control
			-- signals:
			syncInputs1 <= asyncInputs;
			syncInputs2 <= syncInputs1;
			syncInputs3 <= syncInputs2;

			-- For the chain of flip-flops associated with
			-- each of the eight incoming asynchronous inputs,
			-- we update the "offical" synchronised value of the
			-- input signal (which we actually use in the
			-- state machine below) only if every flip-flop
			-- in the chain holds the same value:
			if 	(syncInputs1 = syncInputs2) and
				(syncInputs2 = syncInputs3) then
				
				syncNextSlice <= syncInputs3(7);
				syncRead <= syncInputs3(6);
				syncWrite <= syncInputs3(5);
				dataInReg <= syncInputs3(4 downto 0);
			end if;

			-- Handle the clock-enabling of each register:
			if incCurAddr = '1' then
				curAddrReg <= curAddrReg + 1;
			elsif regCurAddr = '1' then
				case inSliceNum is
					when "00" =>
						curAddrReg(4 downto 0) <= dataInReg(4 downto 0);
					when "01" =>
						curAddrReg(9 downto 5) <= dataInReg(4 downto 0);
					when "10" =>
						curAddrReg(14 downto 10) <= dataInReg(4 downto 0);
					when others =>
						curAddrReg(18 downto 15) <= dataInReg(3 downto 0);
				end case;
			end if;
			if regWriteData = '1' then
				case inSliceNum is
					when "00" =>
						writeDataReg(3 downto 0) <= dataInReg(3 downto 0);
					when "01" =>
						writeDataReg(7 downto 4) <= dataInReg(3 downto 0);
					when "10" =>
						writeDataReg(11 downto 8) <= dataInReg(3 downto 0);
					when others =>
						writeDataReg(15 downto 12) <= dataInReg(3 downto 0);
				end case;
			end if;
			if regReadData = '1' then
--				For debug purposes we load the readDataReg directly with the
--				writeDataReg.
--				readDataReg <= writeDataReg;
--				readDataReg(15) <= '0';
--				readDataReg(14 downto 0) <= curAddrReg(18 downto 4);		

				readDataReg <= readData;
			end if;

			if clearInSliceNum = '1' then
				inSliceNum <= (others => '0');
			elsif incInSliceNum = '1' then
				inSliceNum <= inSliceNum + 1;
			end if;

			if clearOutSliceNum = '1' then
				outSliceNum <= (others => '0');
			elsif incOutSliceNum = '1' then
				outSliceNum <= outSliceNum + 1;
			end if;
			
			-- Handle the updating of settings:
			if getSettings = '1' then
				pcControlEnabled <= dataInReg(0);
			end if;
			
			-- Update current state for the controller FSM.
			presState <= nextState;			
		end if;
	end process;

	-- ========================================
	-- Process for FSM of controller
	-- ========================================
	process(presState, syncWrite, syncRead, syncNextSlice,
			inSliceNum, outSliceNum, canWrite, canRead)
	begin
		-- Set the defaults for all the signals this FSM
		-- controls:
		regDataIn <= '0';
		regCurAddr <= '0';
		regWriteData <= '0';
		regReadData <= '0';
		
		incCurAddr <= '0';
		
		incInSliceNum <= '0';
		incOutSliceNum <= '0';
		clearInSliceNum <= '0';
		clearOutSliceNum <= '0';

		doSRAMWrite <= '0';
		doSRAMRead <= '0';

		getSettings <= '0';

		-- Set default value of stateOutput:
		stateOutput <= "1111";

		case presState is
			when stIdle =>
				nextState <= stIdle;
				
				if syncNextSlice = '1' then
					if syncWrite = '1' and syncRead = '1' then
						nextState <= stGetAddr1;
						-- Register slice 0:
						regCurAddr <= '1';
						-- Increment slice number so that we're ready
						-- for the next slice:
						incInSliceNum <= '1';
					elsif syncWrite = '1' then
						nextState <= stDoWrite1;
						-- Register slice 0:
						regWriteData <= '1';
						-- Increment slice number so that we're ready
						-- for the next slice:
						incInSliceNum <= '1';
					elsif syncRead = '1' then
						nextState <= stDoRead1;
						clearOutSliceNum <= '1';

⌨️ 快捷键说明

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