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 + -
显示快捷键?