------------------------------------------------------------------------------ -- This file is a part of the GRLIB VHDL IP LIBRARY -- Copyright (C) 2003 - 2008, Gaisler Research -- Copyright (C) 2008 - 2010, Aeroflex Gaisler -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ----------------------------------------------------------------------------- -- Package: amba -- File: amba.vhd -- Author: Jiri Gaisler, Gaisler Research -- Modified by: Jan Andersson, Aeroflex Gaisler -- Description: AMBA 2.0 bus signal definitions + support for plug&play ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- pragma translate_off use std.textio.all; -- pragma translate_on library grlib; use grlib.config.all; use grlib.stdlib.all; package amba is ------------------------------------------------------------------------------- -- AMBA configuration ------------------------------------------------------------------------------- -- AHBDW - AHB data with -- -- Valid values are 32, 64, 128 and 256 -- -- The value here sets the width of the AMBA AHB data vectors for all -- cores in the library. -- constant AHBDW : integer := CFG_AHBDW; -- CORE_ACDM - Enable AMBA Compliant Data Muxing in cores -- -- Valid values are 0 and 1 -- -- 0: All GRLIB cores that use the ahbread* programs defined in this package -- will read their data from the low part of the AHB data vector. -- -- 1: All GRLIB cores that use the ahbread* programs defined in this package -- will select valid data, as defined in the AMBA AHB standard, from the -- AHB data vectors based on the address input. If a core uses a function -- that does not have the address input, a failure will be asserted. -- constant CORE_ACDM : integer := CFG_AHB_ACDM; constant NAHBMST : integer := 16; -- maximum AHB masters constant NAHBSLV : integer := 16; -- maximum AHB slaves constant NAPBSLV : integer := 16; -- maximum APB slaves constant NAHBIRQ : integer := 32; -- maximum interrupts constant NAHBAMR : integer := 4; -- maximum address mapping registers constant NAHBIR : integer := 4; -- maximum AHB identification registers constant NAHBCFG : integer := NAHBIR + NAHBAMR; -- words in AHB config block constant NAPBIR : integer := 1; -- maximum APB configuration words constant NAPBAMR : integer := 1; -- maximum APB configuration words constant NAPBCFG : integer := NAPBIR + NAPBAMR; -- words in APB config block constant NBUS : integer := 4; ------------------------------------------------------------------------------- -- AMBA interface type declarations and constant ------------------------------------------------------------------------------- subtype amba_config_word is std_logic_vector(31 downto 0); type ahb_config_type is array (0 to NAHBCFG-1) of amba_config_word; type apb_config_type is array (0 to NAPBCFG-1) of amba_config_word; -- AHB master inputs type ahb_mst_in_type is record hgrant : std_logic_vector(0 to NAHBMST-1); -- bus grant hready : std_ulogic; -- transfer done hresp : std_logic_vector(1 downto 0); -- response type hrdata : std_logic_vector(AHBDW-1 downto 0); -- read data bus hcache : std_ulogic; -- cacheable hirq : std_logic_vector(NAHBIRQ-1 downto 0); -- interrupt result bus testen : std_ulogic; -- scan test enable testrst : std_ulogic; -- scan test reset scanen : std_ulogic; -- scan enable testoen : std_ulogic; -- test output enable end record; -- AHB master outputs type ahb_mst_out_type is record hbusreq : std_ulogic; -- bus request hlock : std_ulogic; -- lock request htrans : std_logic_vector(1 downto 0); -- transfer type haddr : std_logic_vector(31 downto 0); -- address bus (byte) hwrite : std_ulogic; -- read/write hsize : std_logic_vector(2 downto 0); -- transfer size hburst : std_logic_vector(2 downto 0); -- burst type hprot : std_logic_vector(3 downto 0); -- protection control hwdata : std_logic_vector(AHBDW-1 downto 0); -- write data bus hirq : std_logic_vector(NAHBIRQ-1 downto 0); -- interrupt bus hconfig : ahb_config_type; -- memory access reg. hindex : integer range 0 to NAHBMST-1; -- diagnostic use only end record; -- AHB slave inputs type ahb_slv_in_type is record hsel : std_logic_vector(0 to NAHBSLV-1); -- slave select haddr : std_logic_vector(31 downto 0); -- address bus (byte) hwrite : std_ulogic; -- read/write htrans : std_logic_vector(1 downto 0); -- transfer type hsize : std_logic_vector(2 downto 0); -- transfer size hburst : std_logic_vector(2 downto 0); -- burst type hwdata : std_logic_vector(AHBDW-1 downto 0); -- write data bus hprot : std_logic_vector(3 downto 0); -- protection control hready : std_ulogic; -- transfer done hmaster : std_logic_vector(3 downto 0); -- current master hmastlock : std_ulogic; -- locked access hmbsel : std_logic_vector(0 to NAHBAMR-1); -- memory bank select hcache : std_ulogic; -- cacheable hirq : std_logic_vector(NAHBIRQ-1 downto 0); -- interrupt result bus testen : std_ulogic; -- scan test enable testrst : std_ulogic; -- scan test reset scanen : std_ulogic; -- scan enable testoen : std_ulogic; -- test output enable end record; -- AHB slave outputs type ahb_slv_out_type is record hready : std_ulogic; -- transfer done hresp : std_logic_vector(1 downto 0); -- response type hrdata : std_logic_vector(AHBDW-1 downto 0); -- read data bus hsplit : std_logic_vector(15 downto 0); -- split completion hcache : std_ulogic; -- cacheable hirq : std_logic_vector(NAHBIRQ-1 downto 0); -- interrupt bus hconfig : ahb_config_type; -- memory access reg. hindex : integer range 0 to NAHBSLV-1; -- diagnostic use only end record; -- array types type ahb_mst_out_vector_type is array (natural range <>) of ahb_mst_out_type; type ahb_mst_in_vector_type is array (natural range <>) of ahb_mst_in_type; type ahb_slv_out_vector_type is array (natural range <>) of ahb_slv_out_type; type ahb_slv_in_vector_type is array (natural range <>) of ahb_slv_in_type; subtype ahb_mst_out_vector is ahb_mst_out_vector_type(NAHBMST-1 downto 0); subtype ahb_slv_out_vector is ahb_slv_out_vector_type(NAHBSLV-1 downto 0); type ahb_mst_out_bus_vector is array (0 to NBUS-1) of ahb_mst_out_vector; type ahb_slv_out_bus_vector is array (0 to NBUS-1) of ahb_slv_out_vector; -- constants constant HTRANS_IDLE: std_logic_vector(1 downto 0) := "00"; constant HTRANS_BUSY: std_logic_vector(1 downto 0) := "01"; constant HTRANS_NONSEQ: std_logic_vector(1 downto 0) := "10"; constant HTRANS_SEQ: std_logic_vector(1 downto 0) := "11"; constant HBURST_SINGLE: std_logic_vector(2 downto 0) := "000"; constant HBURST_INCR: std_logic_vector(2 downto 0) := "001"; constant HBURST_WRAP4: std_logic_vector(2 downto 0) := "010"; constant HBURST_INCR4: std_logic_vector(2 downto 0) := "011"; constant HBURST_WRAP8: std_logic_vector(2 downto 0) := "100"; constant HBURST_INCR8: std_logic_vector(2 downto 0) := "101"; constant HBURST_WRAP16: std_logic_vector(2 downto 0) := "110"; constant HBURST_INCR16: std_logic_vector(2 downto 0) := "111"; constant HSIZE_BYTE: std_logic_vector(2 downto 0) := "000"; constant HSIZE_HWORD: std_logic_vector(2 downto 0) := "001"; constant HSIZE_WORD: std_logic_vector(2 downto 0) := "010"; constant HSIZE_DWORD: std_logic_vector(2 downto 0) := "011"; constant HSIZE_4WORD: std_logic_vector(2 downto 0) := "100"; constant HSIZE_8WORD: std_logic_vector(2 downto 0) := "101"; constant HSIZE_16WORD: std_logic_vector(2 downto 0) := "110"; constant HSIZE_32WORD: std_logic_vector(2 downto 0) := "111"; constant HRESP_OKAY: std_logic_vector(1 downto 0) := "00"; constant HRESP_ERROR: std_logic_vector(1 downto 0) := "01"; constant HRESP_RETRY: std_logic_vector(1 downto 0) := "10"; constant HRESP_SPLIT: std_logic_vector(1 downto 0) := "11"; -- APB slave inputs type apb_slv_in_type is record psel : std_logic_vector(0 to NAPBSLV-1); -- slave select penable : std_ulogic; -- strobe paddr : std_logic_vector(31 downto 0); -- address bus (byte) pwrite : std_ulogic; -- write pwdata : std_logic_vector(31 downto 0); -- write data bus pirq : std_logic_vector(NAHBIRQ-1 downto 0); -- interrupt result bus testen : std_ulogic; -- scan test enable testrst : std_ulogic; -- scan test reset scanen : std_ulogic; -- scan enable testoen : std_ulogic; -- test output enable end record; -- APB slave outputs type apb_slv_out_type is record prdata : std_logic_vector(31 downto 0); -- read data bus pirq : std_logic_vector(NAHBIRQ-1 downto 0); -- interrupt bus pconfig : apb_config_type; -- memory access reg. pindex : integer range 0 to NAPBSLV -1; -- diag use only end record; -- array types type apb_slv_out_vector is array (0 to NAPBSLV-1) of apb_slv_out_type; -- support for plug&play configuration constant AMBA_CONFIG_VER0 : std_logic_vector(1 downto 0) := "00"; subtype amba_vendor_type is integer range 0 to 16#ff#; subtype amba_device_type is integer range 0 to 16#3ff#; subtype amba_version_type is integer range 0 to 16#3f#; subtype amba_cfgver_type is integer range 0 to 3; subtype amba_irq_type is integer range 0 to NAHBIRQ-1; subtype ahb_addr_type is integer range 0 to 16#fff#; constant zx : std_logic_vector(31 downto 0) := (others => '0'); constant zahbdw : std_logic_vector(AHBDW-1 downto 0) := (others => '0'); constant zxirq : std_logic_vector(NAHBIRQ-1 downto 0) := (others => '0'); constant zy : std_logic_vector(0 to 31) := (others => '0'); constant apb_none : apb_slv_out_type := (zx, zxirq(NAHBIRQ-1 downto 0), (others => zx), 0); constant ahbm_none : ahb_mst_out_type := ( '0', '0', "00", zx, '0', "000", "000", "0000", zahbdw, zxirq(NAHBIRQ-1 downto 0), (others => zx), 0); constant ahbm_in_none : ahb_mst_in_type := ((others => '0'), '0', (others => '0'), zahbdw, '0', zxirq(NAHBIRQ-1 downto 0), '0', '0', '0', '0'); constant ahbs_none : ahb_slv_out_type := ( '1', "00", zahbdw, zx(15 downto 0), '0', zxirq(NAHBIRQ-1 downto 0), (others => zx), 0); constant ahbs_in_none : ahb_slv_in_type := ( zy(0 to NAHBSLV-1), zx, '0', "00", "000", "000", zahbdw, "0000", '1', "0000", '0', zy(0 to NAHBAMR-1), '0', zxirq(NAHBIRQ-1 downto 0), '0', '0', '0', '0'); constant ahbsv_none : ahb_slv_out_vector := (others => ahbs_none); constant apb_slv_in_none : apb_slv_in_type := ((others => '0'), '0', (others => '0'), '0', (others => '0'), (others => '0'), '0', '0', '0', '0'); ------------------------------------------------------------------------------- -- Subprograms ------------------------------------------------------------------------------- function ahb_device_reg(vendor : amba_vendor_type; device : amba_device_type; cfgver : amba_cfgver_type; version : amba_version_type; interrupt : amba_irq_type) return std_logic_vector; function ahb_membar(memaddr : ahb_addr_type; prefetch, cache : std_ulogic; addrmask : ahb_addr_type) return std_logic_vector; function ahb_membar_opt(memaddr : ahb_addr_type; prefetch, cache : std_ulogic; addrmask : ahb_addr_type; enable : integer) return std_logic_vector; function ahb_iobar(memaddr : ahb_addr_type; addrmask : ahb_addr_type) return std_logic_vector; function apb_iobar(memaddr : ahb_addr_type; addrmask : ahb_addr_type) return std_logic_vector; function ahb_slv_dec_cache(haddr : std_logic_vector(31 downto 0); ahbso : ahb_slv_out_vector; cached : integer) return std_ulogic; function ahb_slv_dec_pfetch(haddr : std_logic_vector(31 downto 0); ahbso : ahb_slv_out_vector) return std_ulogic; function ahb_membar_size (addrmask : ahb_addr_type) return integer; function ahb_iobar_size (addrmask : ahb_addr_type) return integer; function ahbdrivedata (hdata : std_logic_vector) return std_logic_vector; function ahbselectdata (hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2); hsize : std_logic_vector(2 downto 0)) return std_logic_vector; function ahbreadword ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector; procedure ahbreadword ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(31 downto 0)); function ahbreadword ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector; procedure ahbreadword ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(31 downto 0)); function ahbreaddword ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector; procedure ahbreaddword ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(63 downto 0)); function ahbreaddword ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector; procedure ahbreaddword ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(63 downto 0)); function ahbread4word ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector; procedure ahbread4word ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(127 downto 0)); function ahbread4word ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector; procedure ahbread4word ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(127 downto 0)); function ahbread8word ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector; procedure ahbread8word ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(255 downto 0)); function ahbread8word ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector; procedure ahbread8word ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(255 downto 0)); function ahbreaddata ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2); hsize : std_logic_vector(2 downto 0)) return std_logic_vector; function ahbreaddata ( hdata : std_logic_vector(AHBDW-1 downto 0); hsize : std_logic_vector(2 downto 0)) return std_logic_vector; procedure ahbmomux ( signal ai : in ahb_mst_out_type; signal ao : out ahb_mst_out_type; signal en : in std_ulogic); procedure ahbsomux ( signal ai : in ahb_slv_out_type; signal ao : out ahb_slv_out_type; signal en : in std_ulogic); procedure apbsomux ( signal ai : in apb_slv_out_type; signal ao : out apb_slv_out_type; signal en : in std_ulogic); ------------------------------------------------------------------------------- -- Components ------------------------------------------------------------------------------- component ahbctrl generic ( defmast : integer := 0; -- default master split : integer := 0; -- split support rrobin : integer := 0; -- round-robin arbitration timeout : integer range 0 to 255 := 0; -- HREADY timeout ioaddr : ahb_addr_type := 16#fff#; -- I/O area MSB address iomask : ahb_addr_type := 16#fff#; -- I/O area address mask cfgaddr : ahb_addr_type := 16#ff0#; -- config area MSB address cfgmask : ahb_addr_type := 16#ff0#; -- config area address mask nahbm : integer range 1 to NAHBMST := NAHBMST; -- number of masters nahbs : integer range 1 to NAHBSLV := NAHBSLV; -- number of slaves ioen : integer range 0 to 15 := 1; -- enable I/O area disirq : integer range 0 to 1 := 0; -- disable interrupt routing fixbrst : integer range 0 to 1 := 0; -- support fix-length bursts debug : integer range 0 to 2 := 2; -- print config to console fpnpen : integer range 0 to 1 := 0; -- full PnP configuration decoding icheck : integer range 0 to 1 := 1; devid : integer := 0; -- unique device ID enbusmon : integer range 0 to 1 := 0; --enable bus monitor assertwarn : integer range 0 to 1 := 0; --enable assertions for warnings asserterr : integer range 0 to 1 := 0; --enable assertions for errors hmstdisable : integer := 0; --disable master checks hslvdisable : integer := 0; --disable slave checks arbdisable : integer := 0; --disable arbiter checks mprio : integer := 0; --master with highest priority mcheck : integer := 1; --check memory map for intersects ccheck : integer range 0 to 1 := 1; --perform sanity checks on pnp config acdm : integer := 0; --AMBA compliant data muxing (for hsize > word) index : integer := 0; --index for trace print-out ahbtrace : integer := 0 --AHB trace enable ); port ( rst : in std_ulogic; clk : in std_ulogic; msti : out ahb_mst_in_type; msto : in ahb_mst_out_vector; slvi : out ahb_slv_in_type; slvo : in ahb_slv_out_vector; testen : in std_ulogic := '0'; testrst : in std_ulogic := '1'; scanen : in std_ulogic := '0'; testoen : in std_ulogic := '1' ); end component; component apbctrl generic ( hindex : integer := 0; haddr : integer := 0; hmask : integer := 16#fff#; nslaves : integer range 1 to NAPBSLV := NAPBSLV; debug : integer range 0 to 2 := 2; -- print config to console icheck : integer range 0 to 1 := 1; enbusmon : integer range 0 to 1 := 0; asserterr : integer range 0 to 1 := 0; assertwarn : integer range 0 to 1 := 0; pslvdisable : integer := 0; mcheck : integer range 0 to 1 := 1; ccheck : integer range 0 to 1 := 1 ); port ( rst : in std_ulogic; clk : in std_ulogic; ahbi : in ahb_slv_in_type; ahbo : out ahb_slv_out_type; apbi : out apb_slv_in_type; apbo : in apb_slv_out_vector ); end component; component ahbctrl_mb generic ( defmast : integer := 0; -- default master split : integer := 0; -- split support rrobin : integer := 0; -- round-robin arbitration timeout : integer range 0 to 255 := 0; -- HREADY timeout ioaddr : ahb_addr_type := 16#fff#; -- I/O area MSB address iomask : ahb_addr_type := 16#fff#; -- I/O area address mask cfgaddr : ahb_addr_type := 16#ff0#; -- config area MSB address cfgmask : ahb_addr_type := 16#ff0#; -- config area address mask nahbm : integer range 1 to NAHBMST := NAHBMST; -- number of masters nahbs : integer range 1 to NAHBSLV := NAHBSLV; -- number of slaves ioen : integer range 0 to 15 := 1; -- enable I/O area disirq : integer range 0 to 1 := 0; -- disable interrupt routing fixbrst : integer range 0 to 1 := 0; -- support fix-length bursts debug : integer range 0 to 2 := 2; -- report cores to console fpnpen : integer range 0 to 1 := 0; -- full PnP configuration decoding busndx : integer range 0 to 3 := 0; icheck : integer range 0 to 1 := 1; devid : integer := 0; -- unique device ID enbusmon : integer range 0 to 1 := 0; --enable bus monitor assertwarn : integer range 0 to 1 := 0; --enable assertions for warnings asserterr : integer range 0 to 1 := 0; --enable assertions for errors hmstdisable : integer := 0; --disable master checks hslvdisable : integer := 0; --disable slave checks arbdisable : integer := 0; --disable arbiter checks mprio : integer := 0; --master with highest priority mcheck : integer := 1; --check memory map for intersect ccheck : integer range 0 to 1 := 1; --perform sanity checks on pnp config acdm : integer := 0 --AMBA compliant data muxing (for hsize > word) ); port ( rst : in std_ulogic; clk : in std_ulogic; msti : out ahb_mst_in_type; msto : in ahb_mst_out_bus_vector; slvi : out ahb_slv_in_type; slvo : in ahb_slv_out_bus_vector; testen : in std_ulogic := '0'; testrst : in std_ulogic := '1'; scanen : in std_ulogic := '0'; testoen : in std_ulogic := '1' ); end component; component ahbdefmst generic ( hindex : integer range 0 to NAHBMST-1 := 0); port ( ahbmo : out ahb_mst_out_type); end component; -- pragma translate_off component ahbmon is generic( asserterr : integer range 0 to 1 := 1; assertwarn : integer range 0 to 1 := 1; hmstdisable : integer := 0; hslvdisable : integer := 0; arbdisable : integer := 0; nahbm : integer range 0 to NAHBMST := NAHBMST; nahbs : integer range 0 to NAHBSLV := NAHBSLV; ebterm : integer range 0 to 1 := 0 ); port( rst : in std_ulogic; clk : in std_ulogic; ahbmi : in ahb_mst_in_type; ahbmo : in ahb_mst_out_vector; ahbsi : in ahb_slv_in_type; ahbso : in ahb_slv_out_vector; err : out std_ulogic); end component; component apbmon is generic( asserterr : integer range 0 to 1 := 1; assertwarn : integer range 0 to 1 := 1; pslvdisable : integer := 0; napb : integer range 0 to NAPBSLV := NAPBSLV ); port( rst : in std_ulogic; clk : in std_ulogic; apbi : in apb_slv_in_type; apbo : in apb_slv_out_vector; err : out std_ulogic); end component; component ambamon is generic( asserterr : integer range 0 to 1 := 1; assertwarn : integer range 0 to 1 := 1; hmstdisable : integer := 0; hslvdisable : integer := 0; pslvdisable : integer := 0; arbdisable : integer := 0; nahbm : integer range 0 to NAHBMST := NAHBMST; nahbs : integer range 0 to NAHBSLV := NAHBSLV; napb : integer range 0 to NAPBSLV := NAPBSLV; ebterm : integer range 0 to 1 := 0 ); port( rst : in std_ulogic; clk : in std_ulogic; ahbmi : in ahb_mst_in_type; ahbmo : in ahb_mst_out_vector; ahbsi : in ahb_slv_in_type; ahbso : in ahb_slv_out_vector; apbi : in apb_slv_in_type; apbo : in apb_slv_out_vector; err : out std_ulogic); end component; subtype vendor_description is string(1 to 24); subtype device_description is string(1 to 31); type device_table_type is array (0 to 1023) of device_description; type vendor_library_type is record vendorid : amba_vendor_type; vendordesc : vendor_description; device_table : device_table_type; end record; type device_array is array (0 to 255) of vendor_library_type; -- pragma translate_on end; package body amba is function ahb_device_reg(vendor : amba_vendor_type; device : amba_device_type; cfgver : amba_cfgver_type; version : amba_version_type; interrupt : amba_irq_type) return std_logic_vector is variable cfg : std_logic_vector(31 downto 0); begin case cfgver is when 0 => cfg(31 downto 24) := std_logic_vector(to_unsigned(vendor, 8)); cfg(23 downto 12) := std_logic_vector(to_unsigned(device, 12)); cfg(11 downto 10) := std_logic_vector(to_unsigned(cfgver, 2)); cfg( 9 downto 5) := std_logic_vector(to_unsigned(version, 5)); cfg( 4 downto 0) := std_logic_vector(to_unsigned(interrupt, 5)); when others => cfg := (others => '0'); end case; return(cfg); end; function ahb_membar(memaddr : ahb_addr_type; prefetch, cache : std_ulogic; addrmask : ahb_addr_type) return std_logic_vector is variable cfg : std_logic_vector(31 downto 0); begin cfg(31 downto 20) := std_logic_vector(to_unsigned(memaddr, 12)); cfg(19 downto 16) := "00" & prefetch & cache; cfg(15 downto 4) := std_logic_vector(to_unsigned(addrmask, 12)); cfg( 3 downto 0) := "0010"; return(cfg); end; function ahb_membar_opt(memaddr : ahb_addr_type; prefetch, cache : std_ulogic; addrmask : ahb_addr_type; enable : integer) return std_logic_vector is variable cfg : std_logic_vector(31 downto 0); begin cfg := (others => '0'); if enable /= 0 then return (ahb_membar(memaddr, prefetch, cache, addrmask)); else return(cfg); end if; end; function ahb_iobar(memaddr : ahb_addr_type; addrmask : ahb_addr_type) return std_logic_vector is variable cfg : std_logic_vector(31 downto 0); begin cfg(31 downto 20) := std_logic_vector(to_unsigned(memaddr, 12)); cfg(19 downto 16) := "0000"; cfg(15 downto 4) := std_logic_vector(to_unsigned(addrmask, 12)); cfg( 3 downto 0) := "0011"; return(cfg); end; function apb_iobar(memaddr : ahb_addr_type; addrmask : ahb_addr_type) return std_logic_vector is variable cfg : std_logic_vector(31 downto 0); begin cfg(31 downto 20) := std_logic_vector(to_unsigned(memaddr, 12)); cfg(19 downto 16) := "0000"; cfg(15 downto 4) := std_logic_vector(to_unsigned(addrmask, 12)); cfg( 3 downto 0) := "0001"; return(cfg); end; function ahb_slv_dec_cache(haddr : std_logic_vector(31 downto 0); ahbso : ahb_slv_out_vector; cached : integer) return std_ulogic is variable hcache : std_ulogic; variable ctbl : std_logic_vector(15 downto 0); begin hcache := '0'; ctbl := (others => '0'); if cached = 0 then for i in 0 to NAHBSLV-1 loop for j in NAHBAMR to NAHBCFG-1 loop if (ahbso(i).hconfig(j)(16) = '1') and (ahbso(i).hconfig(j)(15 downto 4) /= "000000000000") then if (haddr(31 downto 20) and ahbso(i).hconfig(j)(15 downto 4)) = (ahbso(i).hconfig(j)(31 downto 20) and ahbso(i).hconfig(j)(15 downto 4)) then hcache := '1'; end if; end if; end loop; end loop; else ctbl := conv_std_logic_vector(cached, 16); hcache := ctbl(conv_integer(haddr(31 downto 28))); end if; return(hcache); end; function ahb_slv_dec_pfetch(haddr : std_logic_vector(31 downto 0); ahbso : ahb_slv_out_vector) return std_ulogic is variable pfetch : std_ulogic; begin pfetch := '0'; for i in 0 to NAHBSLV-1 loop for j in NAHBAMR to NAHBCFG-1 loop if ((ahbso(i).hconfig(j)(17) = '1') and (ahbso(i).hconfig(j)(15 downto 4) /= "000000000000")) then if (haddr(31 downto 20) and ahbso(i).hconfig(j)(15 downto 4)) = (ahbso(i).hconfig(j)(31 downto 20) and ahbso(i).hconfig(j)(15 downto 4)) then pfetch := '1'; end if; end if; end loop; end loop; return(pfetch); end; function ahb_membar_size (addrmask : ahb_addr_type) return integer is begin if addrmask = 0 then return 0; end if; return (4096 - addrmask) * 1024 * 1024; end; function ahb_iobar_size (addrmask : ahb_addr_type) return integer is begin return (4096 - addrmask) * 256; end; -- purpose: Duplicates 'hdata' to suite AHB data width. If the input vector's -- length exceeds AHBDW the low part is returned. function ahbdrivedata ( hdata : std_logic_vector) return std_logic_vector is variable data : std_logic_vector(AHBDW-1 downto 0); begin -- ahbdrivedata if AHBDW < hdata'length then data := hdata(AHBDW+hdata'low-1 downto hdata'low); else for i in 0 to AHBDW/hdata'length-1 loop data(hdata'length-1+hdata'length*i downto hdata'length*i) := hdata; end loop; end if; return data; end ahbdrivedata; -- Takes in AHB data vector 'hdata' and returns valid data on the full -- data vector output based on 'haddr' and 'hsize' inputs together with -- GRLIB AHB bus width. The function works down to word granularity. function ahbselectdata ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2); hsize : std_logic_vector(2 downto 0)) return std_logic_vector is variable ret : std_logic_vector(AHBDW-1 downto 0); begin -- ahbselectdata case hsize is when HSIZE_8WORD => if AHBDW = 256 then ret := hdata; end if; when HSIZE_4WORD => if AHBDW = 256 then if haddr(4) = '0' then ret := ahbdrivedata(hdata(AHBDW-1 downto AHBDW/2)); else ret := ahbdrivedata(hdata(AHBDW/2-1 downto 0)); end if; elsif AHBDW = 128 then ret := hdata; end if; when HSIZE_DWORD => if AHBDW = 256 then case haddr(4 downto 3) is when "00" => ret := ahbdrivedata(hdata(4*(AHBDW/4)-1 downto 3*(AHBDW/4))); when "01" => ret := ahbdrivedata(hdata(3*(AHBDW/4)-1 downto 2*(AHBDW/4))); when "10" => ret := ahbdrivedata(hdata(2*(AHBDW/4)-1 downto 1*(AHBDW/4))); when others => ret := ahbdrivedata(hdata(1*(AHBDW/4)-1 downto 0*(AHBDW/4))); end case; elsif AHBDW = 128 then if haddr(3) = '0' then ret := ahbdrivedata(hdata(AHBDW-1 downto AHBDW/2)); else ret := ahbdrivedata(hdata(AHBDW/2-1 downto 0)); end if; elsif AHBDW = 64 then ret := hdata; end if; when others => if AHBDW = 256 then case haddr(4 downto 2) is when "000" => ret := ahbdrivedata(hdata(8*(AHBDW/8)-1 downto 7*(AHBDW/8))); when "001" => ret := ahbdrivedata(hdata(7*(AHBDW/8)-1 downto 6*(AHBDW/8))); when "010" => ret := ahbdrivedata(hdata(6*(AHBDW/8)-1 downto 5*(AHBDW/8))); when "011" => ret := ahbdrivedata(hdata(5*(AHBDW/8)-1 downto 4*(AHBDW/8))); when "100" => ret := ahbdrivedata(hdata(4*(AHBDW/8)-1 downto 3*(AHBDW/8))); when "101" => ret := ahbdrivedata(hdata(3*(AHBDW/8)-1 downto 2*(AHBDW/8))); when "110" => ret := ahbdrivedata(hdata(2*(AHBDW/8)-1 downto 1*(AHBDW/8))); when others => ret := ahbdrivedata(hdata(1*(AHBDW/8)-1 downto 0*(AHBDW/8))); end case; elsif AHBDW = 128 then case haddr(3 downto 2) is when "00" => ret := ahbdrivedata(hdata(4*(AHBDW/4)-1 downto 3*(AHBDW/4))); when "01" => ret := ahbdrivedata(hdata(3*(AHBDW/4)-1 downto 2*(AHBDW/4))); when "10" => ret := ahbdrivedata(hdata(2*(AHBDW/4)-1 downto 1*(AHBDW/4))); when others => ret := ahbdrivedata(hdata(1*(AHBDW/4)-1 downto 0*(AHBDW/4))); end case; elsif AHBDW = 64 then if haddr(2) = '0' then ret := ahbdrivedata(hdata(AHBDW-1 downto AHBDW/2)); else ret := ahbdrivedata(hdata(AHBDW/2-1 downto 0)); end if; else ret := hdata; end if; end case; return ret; end ahbselectdata; -- Description of ahbread* functions and procedures. -- -- The ahbread* subprograms with an 'haddr' input selects the valid slice of -- data from the AHB data vector, 'hdata', based on the 'haddr' input if -- CORE_ACDM is set to 1 (see top of this package). Otherwise the low part of -- the AHB data vector will be returned. -- -- The ahbread* subprograms that do not have a 'haddr' input will always -- return the low slice of the 'hdata' input. These subprograms will assert a -- failure if CORE_ACDM is set to 1. -- function ahbreadword ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector is variable data : std_logic_vector(31 downto 0); begin if CORE_ACDM = 1 then data := ahbselectdata(hdata, haddr, HSIZE_WORD)(31 downto 0); else data := hdata(31 downto 0); end if; return data; end ahbreadword; procedure ahbreadword ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(31 downto 0)) is begin data := ahbreadword(hdata, haddr); end ahbreadword; function ahbreadword ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector is variable data : std_logic_vector(31 downto 0); begin -- pragma translate_off assert CORE_ACDM = 0 report "ahbreadword without address input used when CORE_ACDM /= 0" severity failure; -- pragma translate_on data := hdata(31 downto 0); return data; end ahbreadword; procedure ahbreadword ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(31 downto 0)) is begin data := ahbreadword(hdata); end ahbreadword; function ahbreaddword ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector is variable data : std_logic_vector(255 downto 0); begin -- pragma translate_off assert AHBDW > 32 report "ahbreaddword can not be used in system with AHB data width < 64" severity failure; -- pragma translate_on if AHBDW = 256 then if CORE_ACDM = 1 then data(AHBDW/4-1 downto 0) := ahbselectdata(hdata, haddr, HSIZE_DWORD)(AHBDW/4-1 downto 0); else data(AHBDW/4-1 downto 0) := hdata(AHBDW/4-1 downto 0); end if; elsif AHBDW = 128 then if CORE_ACDM = 1 then data(AHBDW/2-1 downto 0) := ahbselectdata(hdata, haddr, HSIZE_DWORD)(AHBDW/2-1 downto 0); else data(AHBDW/2-1 downto 0) := hdata(AHBDW/2-1 downto 0); end if; elsif AHBDW = 64 then if CORE_ACDM = 1 then data(AHBDW-1 downto 0) := ahbselectdata(hdata, haddr, HSIZE_DWORD)(AHBDW-1 downto 0); else data(AHBDW-1 downto 0) := hdata(AHBDW-1 downto 0); end if; end if; return data(63 downto 0); end ahbreaddword; procedure ahbreaddword ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(63 downto 0)) is begin data := ahbreaddword(hdata, haddr); end ahbreaddword; function ahbreaddword ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector is variable data : std_logic_vector(255 downto 0); begin -- pragma translate_off assert AHBDW > 32 report "ahbreaddword can not be used in system with AHB data width < 64" severity failure; assert CORE_ACDM = 0 report "ahbreaddword without address input used when CORE_ACDM /= 0" severity failure; -- pragma translate_on if AHBDW = 256 then data(AHBDW/4-1 downto 0) := hdata(AHBDW/4-1 downto 0); elsif AHBDW = 128 then data(AHBDW/2-1 downto 0) := hdata(AHBDW/2-1 downto 0); elsif AHBDW = 64 then data(AHBDW-1 downto 0) := hdata(AHBDW-1 downto 0); end if; return data(63 downto 0); end ahbreaddword; procedure ahbreaddword ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(63 downto 0)) is begin data := ahbreaddword(hdata); end ahbreaddword; function ahbread4word ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector is variable data : std_logic_vector(255 downto 0); begin -- pragma translate_off assert AHBDW > 64 report "ahbread4word can not be used in system with AHB data width < 128 bits" severity failure; -- pragma translate_on if AHBDW = 256 then if CORE_ACDM = 1 then data(AHBDW/2-1 downto 0) := ahbselectdata(hdata, haddr, HSIZE_4WORD)(AHBDW/2-1 downto 0); else data(AHBDW/2-1 downto 0) := hdata(AHBDW/2-1 downto 0); end if; elsif AHBDW = 128 then if CORE_ACDM = 1 then data(AHBDW-1 downto 0) := ahbselectdata(hdata, haddr, HSIZE_4WORD)(AHBDW-1 downto 0); else data(AHBDW-1 downto 0) := hdata(AHBDW-1 downto 0); end if; end if; return data(127 downto 0); end ahbread4word; procedure ahbread4word ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(127 downto 0)) is begin data := ahbread4word(hdata, haddr); end ahbread4word; function ahbread4word ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector is variable data : std_logic_vector(255 downto 0); begin -- pragma translate_off assert AHBDW > 64 report "ahbread4word can not be used in system with AHB data width < 128 bits" severity failure; assert CORE_ACDM = 0 report "ahbread4word without address input used when CORE_ACDM /= 0" severity failure; -- pragma translate_on if AHBDW = 256 then data(AHBDW/2-1 downto 0) := hdata(AHBDW/2-1 downto 0); elsif AHBDW = 128 then data(AHBDW-1 downto 0) := hdata(AHBDW-1 downto 0); end if; return data(127 downto 0); end ahbread4word; procedure ahbread4word ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(127 downto 0)) is begin data := ahbread4word(hdata); end ahbread4word; function ahbread8word ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2)) return std_logic_vector is variable data : std_logic_vector(AHBDW-1 downto 0); begin -- pragma translate_off assert AHBDW > 128 report "ahbread8word can not be used in system with AHB data width < 256 bits" severity failure; -- pragma translate_on if CORE_ACDM = 1 then data(AHBDW-1 downto 0) := ahbselectdata(hdata, haddr, HSIZE_8WORD)(AHBDW-1 downto 0); else data(AHBDW-1 downto 0) := hdata(AHBDW-1 downto 0); end if; return data; end ahbread8word; procedure ahbread8word ( hdata : in std_logic_vector(AHBDW-1 downto 0); haddr : in std_logic_vector(4 downto 2); data : out std_logic_vector(255 downto 0)) is begin data := ahbread8word(hdata, haddr); end ahbread8word; function ahbread8word ( hdata : std_logic_vector(AHBDW-1 downto 0)) return std_logic_vector is variable data : std_logic_vector(AHBDW-1 downto 0); begin -- pragma translate_off assert AHBDW > 128 report "ahbread8word can not be used in system with AHB data width < 256 bits" severity failure; assert CORE_ACDM = 0 report "ahbread8word without address input used when CORE_ACDM /= 0" severity failure; -- pragma translate_on data(AHBDW-1 downto 0) := hdata(AHBDW-1 downto 0); return data; end ahbread8word; procedure ahbread8word ( hdata : in std_logic_vector(AHBDW-1 downto 0); data : out std_logic_vector(255 downto 0)) is begin data := ahbread8word(hdata); end ahbread8word; function ahbreaddata ( hdata : std_logic_vector(AHBDW-1 downto 0); haddr : std_logic_vector(4 downto 2); hsize : std_logic_vector(2 downto 0)) return std_logic_vector is begin case hsize is when HSIZE_8WORD => return ahbread8word(hdata, haddr); when HSIZE_4WORD => return ahbread4word(hdata, haddr); when HSIZE_DWORD => return ahbreaddword(hdata, haddr); when others => null; end case; return ahbreadword(hdata, haddr); end ahbreaddata; function ahbreaddata ( hdata : std_logic_vector(AHBDW-1 downto 0); hsize : std_logic_vector(2 downto 0)) return std_logic_vector is begin case hsize is when HSIZE_8WORD => return ahbread8word(hdata); when HSIZE_4WORD => return ahbread4word(hdata); when HSIZE_DWORD => return ahbreaddword(hdata); when others => null; end case; return ahbreadword(hdata); end ahbreaddata; -- a*mux below drives their amba output records with the amba input record if -- the en input is '1'. Otherwise the amba output record is driven to an idle -- state. Plug'n'play information is kept constant. procedure ahbmomux ( signal ai : in ahb_mst_out_type; signal ao : out ahb_mst_out_type; signal en : in std_ulogic) is begin if en = '1' then ao <= ai; else ao <= ahbm_none; end if; ao.hconfig <= ai.hconfig; ao.hindex <= ai.hindex; end ahbmomux; procedure ahbsomux ( signal ai : in ahb_slv_out_type; signal ao : out ahb_slv_out_type; signal en : in std_ulogic) is begin if en = '1' then ao <= ai; else ao <= ahbs_none; end if; ao.hconfig <= ai.hconfig; ao.hindex <= ai.hindex; end ahbsomux; procedure apbsomux ( signal ai : in apb_slv_out_type; signal ao : out apb_slv_out_type; signal en : in std_ulogic) is begin if en = '1' then ao <= ai; else ao <= apb_none; end if; ao.pconfig <= ai.pconfig; ao.pindex <= ai.pindex; end apbsomux; end;