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

📄 int_handl_m8.vhd

📁 Lattice 超精简8位软核CPU--Mico8
💻 VHD
字号:
-----------------------------------------------------------------------
-- INT_Handl_M8.vhd
-- --------------------------------------------------------------------
-- >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
-- --------------------------------------------------------------------
-- Copyright (c) 2005 by Lattice Semiconductor Corporation
-- --------------------------------------------------------------------
--
-- Permission:
--
--   Lattice Semiconductor grants permission to use this code for use
--   in synthesis for any Lattice programmable logic product.  Other
--   use of this code, including the selling or duplication of any
--   portion is strictly prohibited.
--
-- Disclaimer:
--
--   This VHDL or Verilog source code is intended as a design reference
--   which illustrates how these types of functions can be implemented.
--   It is the user's responsibility to verify their design for
--   consistency and functionality through the use of formal
--   verification methods.  Lattice Semiconductor provides no warranty
--   regarding the use or functionality of this code.
--
-- --------------------------------------------------------------------
--           
--                     Lattice Semiconductor Corporation
--                     5555 NE Moore Court
--                     Hillsboro, OR 97214
--                     U.S.A
--
--                     TEL: 1-800-Lattice (USA and Canada)
--                          408-826-6000 (other locations)
--
--                     web: http://www.latticesemi.com/
--                     email: techsupport@latticesemi.com
--
-- --------------------------------------------------------------------
--
-- This is an interrupt handler for 1-4 Mico8 peripherals
-- Address map:
-- 00010000: Interrupt source register
-- 00010001: Data register Peripheral 1
-- 00010010: Data register Peripheral 2
-- 00010011: Data register Peripheral 3
-- 00010100: Data register Peripheral 4
--
-- When a peripheral has data for Mico8, it can flag an interrupt.
-- All peripheral interrupts are connected to this Interrupt Handler Peripheral.
-- The INT_HAndl_M8 will generate an interrupt to Mico8.
-- Mico8 can read the Interrupt source register to determine
-- the source of the interrupt.
-- Once Mico8 has read the corresponding data register, the corresponding
-- interrupt source bit is cleared in the Interrupt source register and
-- that peripheral can generate new interrupt requests.
-- Once the Mico8 has finalised its interrupt routine it will release the interrupt aknowledge.
-- At that moment the interrupt handler will release the interrupt to Mico8, EVEN
-- if there is a peripheral with a remaining or new interrupt request.
-- The interrupt handler will wait for a given amount of clock cycles before
-- generating a new interrupt request to Mico8.
--
-- The interrupt handler accepts only one interrupt event for each peripheral.
-- As a result, when a new interrupt request is generated by a peripheral while
-- the interrupt handler has a pending interrupt for that same peripheral, the
-- new request is ignored and the new data may get lost.
--
-- --------------------------------------------------------------------
--
-- Revision History :
-- --------------------------------------------------------------------
--   Ver  :| Author            :| Mod. Date :| Changes Made:
--   V1.0 :| G.M.              :| 10/01/08  :| Release
-- --------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity INT_Handl_M8 is
port (
	Clk : 		in std_logic;
	Reset : 	in std_logic;
	IRQ0:		in std_logic;				-- interrupts from peripherals
	Peri0_Data: 	in std_logic_vector(7 downto 0);
	IRQ1:		in std_logic;				-- interrupts from peripherals
	Peri1_Data: 	in std_logic_vector(7 downto 0);
	IRQ2:		in std_logic;				-- interrupts from peripherals
	Peri2_Data: 	in std_logic_vector(7 downto 0);
	IRQ3:		in std_logic;				-- interrupts from peripherals
	Peri3_Data: 	in std_logic_vector(7 downto 0);
	Mico8_RD:	in std_logic;
	Mico8_Addr:	in std_logic_vector(7 downto 0);
	Mico8_IntAck: 	in std_logic;
	Mico8_INT:	out std_logic;
	Mico8_Data: 	out std_logic_vector(7 downto 0)
	);
end INT_Handl_M8;

architecture behave of INT_Handl_M8 is

constant 	INT_REG_ADDR: 	std_logic_vector(7 downto 0) := "00010000";
constant 	PER0_REG_ADDR: 	std_logic_vector(7 downto 0) := "00010001";
constant 	PER1_REG_ADDR: 	std_logic_vector(7 downto 0) := "00010010";
constant 	PER2_REG_ADDR: 	std_logic_vector(7 downto 0) := "00010011";
constant 	PER3_REG_ADDR: 	std_logic_vector(7 downto 0) := "00010100";
signal		INT_REG: 	std_logic_vector(7 downto 0);
signal		PER0_REG: 	std_logic_vector(7 downto 0);
signal		PER1_REG: 	std_logic_vector(7 downto 0);
signal		PER2_REG: 	std_logic_vector(7 downto 0);
signal		PER3_REG: 	std_logic_vector(7 downto 0);
signal		count:		integer range 0 to 31;
type 		state is (idle, active, delay);
signal		INT_contr:	state;
signal		INT_Set:	std_logic;

attribute pgroup : string;
attribute pgroup of behave : architecture is "INT_Handl";

begin

Mico8_Reads: process (clk, reset, Mico8_RD, Mico8_Addr, INT_REG, IRQ0, IRQ1, IRQ2, IRQ3, Peri0_Data, Peri1_Data, Peri2_Data, Peri3_Data)
begin
	if reset = '1' then
--		Mico8_Data <= (others => '0');
		INT_REG <= (others => '0');
		PER0_REG <= (others => '0');
		PER1_REG <= (others => '0');
		PER2_REG <= (others => '0');
		PER3_REG <= (others => '0');
	elsif clk'event and clk = '1' then	
		if Mico8_RD = '1' then
			case Mico8_Addr is
				when INT_REG_ADDR =>
--					Mico8_Data <= INT_REG;
					null;
				when PER0_REG_ADDR =>
--					Mico8_Data <= PER0_REG;
					if IRQ0 = '0' then				-- no new interrupt so we can clear the bit
						INT_REG(0) <= '0';
					elsif IRQ0 = '1' then				-- new interrupt while mico reads the previous one
						PER0_REG <= Peri0_Data;			-- immediately fill the register with new data
						INT_REG(0) <= '1';			-- set or keep the register bit = re-armed
					end if;
				when PER1_REG_ADDR =>
--					Mico8_Data <= PER1_REG;
					if IRQ1 = '0' then
						INT_REG(1) <= '0';
					elsif IRQ1 = '1' then				-- new interrupt while mico reads the previous one
						PER1_REG <= Peri1_Data;			-- immediately fill the register with new data
						INT_REG(1) <= '1';			-- set or keep the register bit = re-armed
					end if;
				when PER2_REG_ADDR =>
--					Mico8_Data <= PER2_REG;
					if IRQ2 = '0' then
						INT_REG(2) <= '0';
					elsif IRQ2 = '1' then				-- new interrupt while mico reads the previous one
						PER2_REG <= Peri2_Data;			-- immediately fill the register with new data
						INT_REG(2) <= '1';			-- set or keep the register bit = re-armed
					end if;
				when PER3_REG_ADDR =>
--					Mico8_Data <= PER3_REG;
					if IRQ3 = '0' then
						INT_REG(3) <= '0';
					elsif IRQ3 = '1' then				-- new interrupt while mico reads the previous one
						PER3_REG <= Peri3_Data;			-- immediately fill the register with new data
						INT_REG(3) <= '1';			-- set or keep the register bit = re-armed
					end if;
				when others =>
					null;
			end case;
		else
			if IRQ0 = '1' and INT_REG(0) = '0' then			-- only accept interrupt data if no pending interrupt
				PER0_REG <= Peri0_Data;
				INT_REG(0) <= '1';
			end if;
			if IRQ1 = '1' and INT_REG(1) = '0' then			-- only accept interrupt data if no pending interrupt
				PER1_REG <= Peri1_Data;
				INT_REG(1) <= '1';
			end if;
			if IRQ2 = '1' and INT_REG(2) = '0' then			-- only accept interrupt data if no pending interrupt
				PER2_REG <= Peri2_Data;
				INT_REG(2) <= '1';
			end if;
			if IRQ3 = '1' and INT_REG(3) = '0' then			-- only accept interrupt data if no pending interrupt
				PER3_REG <= Peri3_Data;
				INT_REG(3) <= '1';
			end if;
		end if;
	end if;
end process;


Mico8_interrupt: process (clk, reset, INT_Reg, Mico8_IntAck, INT_contr, count)
begin
	if reset = '1' then
		INT_Set <= '0';
		INT_contr <= Idle;
		Count <= 0;
		Mico8_INT <= '0';
	elsif clk'event and clk = '1' then
		case INT_contr IS
			WHEN idle =>	
				IF INT_REG /= "00000000" THEN
					Mico8_INT <= '1';
				END IF;	
				if Mico8_IntAck = '1' then
					INT_contr <= active;
				end if;
			WHEN active =>
				Mico8_INT <= '0';
				if Mico8_IntAck = '0' then
					if INT_REG /= "00000000" then		-- still pending interrupts, re-arm interrupt output
--						INT_Set <= '0';
						INT_contr <= delay;
						count <= 0;
					else
--						INT_Set <= '0';
						INT_Contr <= Idle;
					end if;
				end if;
			when delay =>
				count <= count + 1;
				if count = 15 then
					if INT_REG /= "00000000" then
						INT_Contr <= active;
						Mico8_INT <= '1';
					else
						INT_Contr <= Idle;
						Mico8_INT <= '0';
					end if;
				end if;
			when others =>
				INT_Contr <= Idle;
		end case;
	end if;
end process;

--Mico8_INT <= (Mico8_IntAck or INT_Set);

Mico8_Data <= 	INT_REG 	when ((Mico8_Addr = INT_REG_ADDR) and (Mico8_RD = '1')) else
		PER0_REG	when ((Mico8_Addr = PER0_REG_ADDR) and (Mico8_RD = '1')) else
		PER1_REG	when ((Mico8_Addr = PER1_REG_ADDR) and (Mico8_RD = '1')) else
		PER2_REG	when ((Mico8_Addr = PER2_REG_ADDR) and (Mico8_RD = '1')) else
		PER3_REG	when ((Mico8_Addr = PER3_REG_ADDR) and (Mico8_RD = '1')) else
		"00000000";


end behave;

⌨️ 快捷键说明

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