ahbctrl.vhd
来自「The GRLIB IP Library is an integrated se」· VHDL 代码 · 共 496 行 · 第 1/2 页
VHD
496 行
------------------------------------------------------------------------------ This file is a part of the GRLIB VHDL IP LIBRARY-- Copyright (C) 2004 GAISLER RESEARCH---- 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.---- See the file COPYING for the full details of the license.------------------------------------------------------------------------------ -- Entity: ahbctrl-- File: ahbctrl.vhd-- Author: Jiri Gaisler, Gaisler Research-- Modified: Edvin Catovic, Gaisler Research-- Description: AMBA arbiter, decoder and multiplexer with plug&play support------------------------------------------------------------------------------ library IEEE;use IEEE.std_logic_1164.all;library grlib;use grlib.stdlib.all;use grlib.amba.all;entity ahbctrl is 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 ); 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 );end;architecture rtl of ahbctrl isconstant nahbmx : integer := 2**log2(nahbm);type nmstarr is array (1 to 3) of integer range 0 to nahbmx-1;type nvalarr is array (1 to 3) of boolean;type reg_type is record hmaster : integer range 0 to nahbmx -1; hmasterd : integer range 0 to nahbmx -1; hslave : integer range 0 to nahbs-1; hmasterlock : std_ulogic; hready : std_ulogic; defslv : std_ulogic; htrans : std_logic_vector(1 downto 0); haddr : std_logic_vector(15 downto 2); cfgsel : std_ulogic; cfga11 : std_ulogic; hrdatam : std_logic_vector(31 downto 0); hrdatas : std_logic_vector(31 downto 0); beat : std_logic_vector(3 downto 0);end record; type l0_type is array (0 to 15) of std_logic_vector(2 downto 0); type l1_type is array (0 to 7) of std_logic_vector(3 downto 0); type l2_type is array (0 to 3) of std_logic_vector(4 downto 0); type l3_type is array (0 to 1) of std_logic_vector(5 downto 0); type tztab_type is array (0 to 15) of std_logic_vector(2 downto 0); constant tztab : tztab_type := ("100", "000", "001", "000", "010", "000", "001", "000", "011", "000", "001", "000", "010", "000", "001", "000"); function tz(vect_in : std_logic_vector) return std_logic_vector is variable vect : std_logic_vector(63 downto 0); variable l0 : l0_type; variable l1 : l1_type; variable l2 : l2_type; variable l3 : l3_type; variable l4 : std_logic_vector(6 downto 0); variable bci_lsb, bci_msb : std_logic_vector(3 downto 0); variable bco_lsb, bco_msb : std_logic_vector(2 downto 0); variable sel : std_logic; begin vect := (others => '1'); vect(vect_in'length-1 downto 0) := vect_in; -- level 0 for i in 0 to 7 loop bci_lsb := vect(8*i+3 downto 8*i); bci_msb := vect(8*i+7 downto 8*i+4); bco_lsb := tztab(conv_integer(bci_lsb)); bco_msb := tztab(conv_integer(bci_msb)); sel := bco_lsb(2); if sel = '0' then l1(i) := '0' & bco_lsb; else l1(i) := bco_msb(2) & not bco_msb(2) & bco_msb(1 downto 0); end if; end loop; -- level 1 for i in 0 to 3 loop sel := l1(2*i)(3); if sel = '0' then l2(i) := '0' & l1(2*i); else l2(i) := l1(2*i+1)(3) & not l1(2*i+1)(3) & l1(2*i+1)(2 downto 0); end if; end loop; -- level 2 for i in 0 to 1 loop sel := l2(2*i)(4); if sel = '0' then l3(i) := '0' & l2(2*i); else l3(i) := l2(2*i+1)(4) & not l2(2*i+1)(4) & l2(2*i+1)(3 downto 0); end if; end loop; --level 3 if l3(0)(5) = '0' then l4 := '0' & l3(0); else l4 := l3(1)(5) & not l3(1)(5) & l3(1)(4 downto 0); end if; return(l4); end; function lz(vect_in : std_logic_vector) return std_logic_vector is variable vect : std_logic_vector(vect_in'length-1 downto 0); variable vect2 : std_logic_vector(vect_in'length-1 downto 0); begin vect := vect_in; for i in vect'right to vect'left loop vect2(i) := vect(vect'left-i); end loop; return(tz(vect2)); end;-- Find next master:-- * 2 arbitration policies: fixed priority or round-robin-- * Fixed priority: priority is fixed, highest index has highest priority-- * Round-robin: arbiter maintains circular queue of masters-- * (master 0, master 1, ..., master (nahbmx-1)). First requesting master-- * in the queue is granted access to the bus and moved to the end of the queue. -- * splitted masters are not granted-- * bus is re-arbited when current owner does not request the bus,-- or when it performs non-burst accesses-- * fix length burst transfers will not be interrupted-- * incremental bursts should assert hbusreq until last access procedure selmast(r : in reg_type; msto : in ahb_mst_out_vector; rsplit : in std_logic_vector(0 to nahbmx-1); mast : out integer range 0 to nahbmx-1) is variable nmst : nmstarr; variable nvalid : nvalarr; variable rrvec : std_logic_vector(nahbmx*2-1 downto 0); variable zcnt : std_logic_vector(log2(nahbmx)+1 downto 0); variable hpvec : std_logic_vector(nahbmx-1 downto 0); variable zcnt2 : std_logic_vector(log2(nahbmx) downto 0); begin nvalid(1 to 3) := (others => false); nmst(1 to 3) := (others => 0); mast := r.hmaster; if nahbm = 1 then mast := 0; elsif rrobin = 0 then hpvec := (others => '0'); for i in 0 to nahbmx-1 loop if ((rsplit(i) = '0') or (split = 0)) then hpvec(i) := msto(i).hbusreq and msto(i).htrans(1); end if; end loop; zcnt2 := lz(hpvec)(log2(nahbmx) downto 0); if zcnt2(log2(nahbmx)) = '0' then nvalid(1) := true; end if; nmst(1) := conv_integer(not (zcnt2(log2(nahbmx)-1 downto 0))); hpvec := (others => '0'); for i in 0 to nahbmx-1 loop if ((rsplit(i) = '0') or (split = 0)) then hpvec(i) := msto(i).hbusreq; end if; end loop; zcnt2 := lz(hpvec)(log2(nahbmx) downto 0); if zcnt2(log2(nahbmx)) = '0' then nvalid(2) := true; end if; nmst(2) := conv_integer(not (zcnt2(log2(nahbmx)-1 downto 0))); for i in 0 to nahbmx-1 loop if not ((nmst(3) = defmast) and nvalid(3)) then nmst(3) := i; nvalid(3) := true; end if; end loop; else rrvec := (others => '0'); for i in 0 to nahbmx-1 loop if (rsplit(i) = '0') or (split = 0) then if (i <= r.hmaster) then rrvec(i) := '0'; else rrvec(i) := msto(i).hbusreq; end if; rrvec(nahbmx+i) := msto(i).hbusreq; end if; end loop; zcnt := tz(rrvec)(log2(nahbmx)+1 downto 0); if zcnt(log2(nahbmx)+1) = '0' then nvalid(1) := true; end if; nmst(1) := conv_integer(zcnt(log2(nahbmx)-1 downto 0)); rrvec := (others => '0'); for i in 0 to nahbmx-1 loop if (rsplit(i) = '0') or (split = 0) then if (i <= r.hmaster) then rrvec(i) := '0'; else rrvec(i) := msto(i).hbusreq; end if; rrvec(nahbmx+i) := msto(i).hbusreq; end if; end loop; zcnt := tz(rrvec)(log2(nahbmx)+1 downto 0); if zcnt(log2(nahbmx)+1) = '0' then nvalid(2) := true; end if; nmst(2) := conv_integer(zcnt(log2(nahbmx)-1 downto 0)); nmst(3) := r.hmaster; nvalid(3) := true; end if; for i in 1 to 3 loop if nvalid(i) then mast := nmst(i); exit; end if; end loop; end; constant MIMAX : integer := log2x(nahbmx) - 1; constant SIMAX : integer := log2x(nahbs) - 1; constant IOAREA : std_logic_vector(11 downto 0) := conv_std_logic_vector(ioaddr, 12); constant IOMSK : std_logic_vector(11 downto 0) := conv_std_logic_vector(iomask, 12); constant CFGAREA : std_logic_vector(11 downto 0) :=
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?