📄 int_handl_m8.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 + -