| 1 | 2 | dimamali | ------------------------------------------------------------------------------
 | 
      
         | 2 |  |  | --  This file is a part of the GRLIB VHDL IP LIBRARY
 | 
      
         | 3 |  |  | --  Copyright (C) 2003, Gaisler Research
 | 
      
         | 4 |  |  | --
 | 
      
         | 5 |  |  | --  This program is free software; you can redistribute it and/or modify
 | 
      
         | 6 |  |  | --  it under the terms of the GNU General Public License as published by
 | 
      
         | 7 |  |  | --  the Free Software Foundation; either version 2 of the License, or
 | 
      
         | 8 |  |  | --  (at your option) any later version.
 | 
      
         | 9 |  |  | --
 | 
      
         | 10 |  |  | --  This program is distributed in the hope that it will be useful,
 | 
      
         | 11 |  |  | --  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
      
         | 12 |  |  | --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
      
         | 13 |  |  | --  GNU General Public License for more details.
 | 
      
         | 14 |  |  | --
 | 
      
         | 15 |  |  | --  You should have received a copy of the GNU General Public License
 | 
      
         | 16 |  |  | --  along with this program; if not, write to the Free Software
 | 
      
         | 17 |  |  | --  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 | 
      
         | 18 |  |  | ----------------------------------------------------------------------------   
 | 
      
         | 19 |  |  | -- Entity:      ahbctrl
 | 
      
         | 20 |  |  | -- File:        ahbctrl.vhd
 | 
      
         | 21 |  |  | -- Author:      Jiri Gaisler, Gaisler Research
 | 
      
         | 22 |  |  | -- Modified:    Edvin Catovic, Gaisler Research
 | 
      
         | 23 |  |  | -- Description: AMBA arbiter, decoder and multiplexer with plug&play support
 | 
      
         | 24 |  |  | ------------------------------------------------------------------------------ 
 | 
      
         | 25 |  |  |  
 | 
      
         | 26 |  |  | library ieee;
 | 
      
         | 27 |  |  | use ieee.std_logic_1164.all;
 | 
      
         | 28 |  |  | library grlib;
 | 
      
         | 29 |  |  | use grlib.stdlib.all;
 | 
      
         | 30 |  |  | use grlib.amba.all;
 | 
      
         | 31 |  |  | -- pragma translate_off
 | 
      
         | 32 |  |  | use grlib.devices.all;
 | 
      
         | 33 |  |  | use std.textio.all;
 | 
      
         | 34 |  |  | -- pragma translate_on
 | 
      
         | 35 |  |  |  
 | 
      
         | 36 |  |  | entity ahbctrl is
 | 
      
         | 37 |  |  |   generic (
 | 
      
         | 38 |  |  |     defmast     : integer := 0;          -- default master
 | 
      
         | 39 |  |  |     split       : integer := 0;          -- split support
 | 
      
         | 40 |  |  |     rrobin      : integer := 0;          -- round-robin arbitration
 | 
      
         | 41 |  |  |     timeout     : integer range 0 to 255 := 0;  -- HREADY timeout
 | 
      
         | 42 |  |  |     ioaddr      : ahb_addr_type := 16#fff#;  -- I/O area MSB address
 | 
      
         | 43 |  |  |     iomask      : ahb_addr_type := 16#fff#;  -- I/O area address mask
 | 
      
         | 44 |  |  |     cfgaddr     : ahb_addr_type := 16#ff0#;  -- config area MSB address
 | 
      
         | 45 |  |  |     cfgmask     : ahb_addr_type := 16#ff0#;  -- config area address mask
 | 
      
         | 46 |  |  |     nahbm       : integer range 1 to NAHBMST := NAHBMST; -- number of masters
 | 
      
         | 47 |  |  |     nahbs       : integer range 1 to NAHBSLV := NAHBSLV; -- number of slaves
 | 
      
         | 48 |  |  |     ioen        : integer range 0 to 15 := 1;    -- enable I/O area
 | 
      
         | 49 |  |  |     disirq      : integer range 0 to 1 := 0;     -- disable interrupt routing
 | 
      
         | 50 |  |  |     fixbrst     : integer range 0 to 1 := 0;     -- support fix-length bursts
 | 
      
         | 51 |  |  |     debug       : integer range 0 to 2 := 2;     -- report cores to console
 | 
      
         | 52 |  |  |     fpnpen      : integer range 0 to 1 := 0; -- full PnP configuration decoding
 | 
      
         | 53 |  |  |     icheck      : integer range 0 to 1 := 1;
 | 
      
         | 54 |  |  |     devid       : integer := 0;               -- unique device ID
 | 
      
         | 55 |  |  |     enbusmon    : integer range 0 to 1 := 0; --enable bus monitor
 | 
      
         | 56 |  |  |     assertwarn  : integer range 0 to 1 := 0; --enable assertions for warnings 
 | 
      
         | 57 |  |  |     asserterr   : integer range 0 to 1 := 0; --enable assertions for errors
 | 
      
         | 58 |  |  |     hmstdisable : integer := 0; --disable master checks           
 | 
      
         | 59 |  |  |     hslvdisable : integer := 0; --disable slave checks
 | 
      
         | 60 |  |  |     arbdisable  : integer := 0; --disable arbiter checks
 | 
      
         | 61 |  |  |     mprio       : integer := 0; --master with highest priority
 | 
      
         | 62 |  |  |     enebterm    : integer range 0 to 1 := 0  --enable early burst termination
 | 
      
         | 63 |  |  |   );
 | 
      
         | 64 |  |  |   port (
 | 
      
         | 65 |  |  |     rst     : in  std_ulogic;
 | 
      
         | 66 |  |  |     clk     : in  std_ulogic;
 | 
      
         | 67 |  |  |     msti    : out ahb_mst_in_type;
 | 
      
         | 68 |  |  |     msto    : in  ahb_mst_out_vector;
 | 
      
         | 69 |  |  |     slvi    : out ahb_slv_in_type;
 | 
      
         | 70 |  |  |     slvo    : in  ahb_slv_out_vector;
 | 
      
         | 71 |  |  |     testen  : in  std_ulogic := '0';
 | 
      
         | 72 |  |  |     testrst : in  std_ulogic := '1';
 | 
      
         | 73 |  |  |     scanen  : in  std_ulogic := '0';
 | 
      
         | 74 |  |  |     testoen : in  std_ulogic := '1'
 | 
      
         | 75 |  |  |   );
 | 
      
         | 76 |  |  | end;
 | 
      
         | 77 |  |  |  
 | 
      
         | 78 |  |  | architecture rtl of ahbctrl is
 | 
      
         | 79 |  |  |  
 | 
      
         | 80 |  |  | constant nahbmx : integer := 2**log2(nahbm);
 | 
      
         | 81 |  |  | type nmstarr is array (1 to 3) of integer range 0 to nahbmx-1;
 | 
      
         | 82 |  |  | type nvalarr is array (1 to 3) of boolean;
 | 
      
         | 83 |  |  |  
 | 
      
         | 84 |  |  | type reg_type is record
 | 
      
         | 85 |  |  |   hmaster      : integer range 0 to nahbmx -1;
 | 
      
         | 86 |  |  |   hmasterd     : integer range 0 to nahbmx -1;
 | 
      
         | 87 |  |  |   hslave       : integer range 0 to nahbs-1;
 | 
      
         | 88 |  |  |   hmasterlock  : std_ulogic;
 | 
      
         | 89 |  |  |   hmasterlockd : std_ulogic;
 | 
      
         | 90 |  |  |   hready       : std_ulogic;
 | 
      
         | 91 |  |  |   defslv       : std_ulogic;
 | 
      
         | 92 |  |  |   htrans       : std_logic_vector(1 downto 0);
 | 
      
         | 93 |  |  |   haddr        : std_logic_vector(15 downto 2);
 | 
      
         | 94 |  |  |   cfgsel       : std_ulogic;
 | 
      
         | 95 |  |  |   cfga11       : std_ulogic;
 | 
      
         | 96 |  |  |   hrdatam      : std_logic_vector(31 downto 0);
 | 
      
         | 97 |  |  |   hrdatas      : std_logic_vector(31 downto 0);
 | 
      
         | 98 |  |  |   beat         : std_logic_vector(3 downto 0);
 | 
      
         | 99 |  |  |   defmst       : std_ulogic;
 | 
      
         | 100 |  |  |   ldefmst      : std_ulogic;
 | 
      
         | 101 |  |  | end record;
 | 
      
         | 102 |  |  |  
 | 
      
         | 103 |  |  |   constant primst : std_logic_vector(NAHBMST downto 0) := conv_std_logic_vector(mprio, NAHBMST+1);
 | 
      
         | 104 |  |  |   type l0_type is array (0 to 15) of std_logic_vector(2 downto 0);
 | 
      
         | 105 |  |  |   type l1_type is array (0 to 7) of std_logic_vector(3 downto 0);
 | 
      
         | 106 |  |  |   type l2_type is array (0 to 3) of std_logic_vector(4 downto 0);
 | 
      
         | 107 |  |  |   type l3_type is array (0 to 1) of std_logic_vector(5 downto 0);
 | 
      
         | 108 |  |  |  
 | 
      
         | 109 |  |  |   type tztab_type is array (0 to 15) of std_logic_vector(2 downto 0);
 | 
      
         | 110 |  |  |  
 | 
      
         | 111 |  |  |  
 | 
      
         | 112 |  |  |   --returns the index number of the highest priority request
 | 
      
         | 113 |  |  |   --signal in the two lsb bits when indexed with a 4-bit
 | 
      
         | 114 |  |  |   --request vector with the highest priority signal on the
 | 
      
         | 115 |  |  |   --lsb. the returned msb bit indicates if a request was
 | 
      
         | 116 |  |  |   --active ('1' = no request active corresponds to "0000")
 | 
      
         | 117 |  |  |   constant tztab : tztab_type := ("100", "000", "001", "000",
 | 
      
         | 118 |  |  |                                   "010", "000", "001", "000",
 | 
      
         | 119 |  |  |                                   "011", "000", "001", "000",
 | 
      
         | 120 |  |  |                                   "010", "000", "001", "000");
 | 
      
         | 121 |  |  |  
 | 
      
         | 122 |  |  |  
 | 
      
         | 123 |  |  |   --calculate the number of the highest priority request signal(up to 64
 | 
      
         | 124 |  |  |   --requests are supported) in vect_in using a divide and conquer
 | 
      
         | 125 |  |  |   --algorithm. The lower the index in the vector the higher the priority
 | 
      
         | 126 |  |  |   --of the signal. First 4-bit slices are indexed in tztab and the msb
 | 
      
         | 127 |  |  |   --indicates whether there is an active request or not. Then the resulting
 | 
      
         | 128 |  |  |   --3 bit vectors are compared in pairs (the one corresponding to (3:0) with
 | 
      
         | 129 |  |  |   --(7:4), (11:8) with (15:12) and so on). If the least significant of the two
 | 
      
         | 130 |  |  |   --contains an active signal a '0' is added to the msb side (the vector
 | 
      
         | 131 |  |  |   --becomes one bit wider at each level) to the next level to indicate that
 | 
      
         | 132 |  |  |   --there are active signals in the lower nibble of the two. Otherwise
 | 
      
         | 133 |  |  |   --the msb is removed from the vector corresponding to the higher nibble
 | 
      
         | 134 |  |  |   --and "10" is added if it does not contain active requests and "01" if
 | 
      
         | 135 |  |  |   --does contain active signals. Thus the msb still indicates if the new
 | 
      
         | 136 |  |  |   --slice contains active signals and a '1' is added if it is the higher
 | 
      
         | 137 |  |  |   --part. This results in a 6-bit vector containing the index number
 | 
      
         | 138 |  |  |   --of the highest priority master in 5:0 if bit 6 is '0' otherwise
 | 
      
         | 139 |  |  |   --no master requested the bus.
 | 
      
         | 140 |  |  |   function tz(vect_in : std_logic_vector) return std_logic_vector is
 | 
      
         | 141 |  |  |     variable vect : std_logic_vector(63 downto 0);
 | 
      
         | 142 |  |  |     variable l0 : l0_type;
 | 
      
         | 143 |  |  |     variable l1 : l1_type;
 | 
      
         | 144 |  |  |     variable l2 : l2_type;
 | 
      
         | 145 |  |  |     variable l3 : l3_type;
 | 
      
         | 146 |  |  |     variable l4 : std_logic_vector(6 downto 0);
 | 
      
         | 147 |  |  |     variable bci_lsb, bci_msb : std_logic_vector(3 downto 0);
 | 
      
         | 148 |  |  |     variable bco_lsb, bco_msb : std_logic_vector(2 downto 0);
 | 
      
         | 149 |  |  |     variable sel : std_logic;
 | 
      
         | 150 |  |  |   begin
 | 
      
         | 151 |  |  |  
 | 
      
         | 152 |  |  |     vect := (others => '1');
 | 
      
         | 153 |  |  |     vect(vect_in'length-1 downto 0) := vect_in;
 | 
      
         | 154 |  |  |  
 | 
      
         | 155 |  |  |     -- level 0
 | 
      
         | 156 |  |  |     for i in 0 to 7 loop
 | 
      
         | 157 |  |  |       bci_lsb := vect(8*i+3 downto 8*i);
 | 
      
         | 158 |  |  |       bci_msb := vect(8*i+7 downto 8*i+4);
 | 
      
         | 159 |  |  |       --lookup the highest priority request in each nibble
 | 
      
         | 160 |  |  |       bco_lsb := tztab(conv_integer(bci_lsb));
 | 
      
         | 161 |  |  |       bco_msb := tztab(conv_integer(bci_msb));
 | 
      
         | 162 |  |  |       --select which of two nibbles contain the highest priority ACTIVE
 | 
      
         | 163 |  |  |       --signal, and forward the corresponding vector to the next level
 | 
      
         | 164 |  |  |       sel := bco_lsb(2);
 | 
      
         | 165 |  |  |       if sel = '0' then l1(i) := '0' & bco_lsb;
 | 
      
         | 166 |  |  |       else l1(i) := bco_msb(2) & not bco_msb(2) & bco_msb(1 downto 0); end if;
 | 
      
         | 167 |  |  |     end loop;
 | 
      
         | 168 |  |  |  
 | 
      
         | 169 |  |  |     -- level 1
 | 
      
         | 170 |  |  |     for i in 0 to 3 loop
 | 
      
         | 171 |  |  |       sel := l1(2*i)(3);
 | 
      
         | 172 |  |  |       --select which of two 8-bit vectors contain the
 | 
      
         | 173 |  |  |       --highest priority ACTIVE signal. the msb set at the previous level
 | 
      
         | 174 |  |  |       --for each 8-bit slice determines this
 | 
      
         | 175 |  |  |       if sel = '0' then l2(i) := '0' & l1(2*i);
 | 
      
         | 176 |  |  |       else
 | 
      
         | 177 |  |  |         l2(i) := l1(2*i+1)(3) & not l1(2*i+1)(3) & l1(2*i+1)(2 downto 0);
 | 
      
         | 178 |  |  |       end if;
 | 
      
         | 179 |  |  |     end loop;
 | 
      
         | 180 |  |  |  
 | 
      
         | 181 |  |  |     -- level 2
 | 
      
         | 182 |  |  |     for i in 0 to 1 loop
 | 
      
         | 183 |  |  |       --16-bit vectors, the msb set at the previous level for each 16-bit
 | 
      
         | 184 |  |  |       --slice determines the higher priority slice
 | 
      
         | 185 |  |  |       sel := l2(2*i)(4);
 | 
      
         | 186 |  |  |       if sel = '0' then l3(i) := '0' & l2(2*i);
 | 
      
         | 187 |  |  |       else
 | 
      
         | 188 |  |  |         l3(i) := l2(2*i+1)(4) & not l2(2*i+1)(4) & l2(2*i+1)(3 downto 0);
 | 
      
         | 189 |  |  |       end if;
 | 
      
         | 190 |  |  |     end loop;
 | 
      
         | 191 |  |  |  
 | 
      
         | 192 |  |  |     --level 3
 | 
      
         | 193 |  |  |     --32-bit vectors, the msb set at the previous level for each 32-bit
 | 
      
         | 194 |  |  |     --slice determines the higher priority slice
 | 
      
         | 195 |  |  |     if l3(0)(5) = '0' then l4 := '0' & l3(0);
 | 
      
         | 196 |  |  |     else l4 := l3(1)(5) & not l3(1)(5) & l3(1)(4 downto 0); end if;
 | 
      
         | 197 |  |  |  
 | 
      
         | 198 |  |  |     return(l4);
 | 
      
         | 199 |  |  |   end;
 | 
      
         | 200 |  |  |  
 | 
      
         | 201 |  |  |   --invert the bit order of the hbusreq signals located in vect_in
 | 
      
         | 202 |  |  |   --since the highest hbusreq has the highest priority but the
 | 
      
         | 203 |  |  |   --algorithm in tz has the highest priority on lsb
 | 
      
         | 204 |  |  |   function lz(vect_in : std_logic_vector) return std_logic_vector is
 | 
      
         | 205 |  |  |     variable vect : std_logic_vector(vect_in'length-1 downto 0);
 | 
      
         | 206 |  |  |     variable vect2 : std_logic_vector(vect_in'length-1 downto 0);
 | 
      
         | 207 |  |  |   begin
 | 
      
         | 208 |  |  |     vect := vect_in;
 | 
      
         | 209 |  |  |     for i in vect'right to vect'left loop
 | 
      
         | 210 |  |  |       vect2(i) := vect(vect'left-i);
 | 
      
         | 211 |  |  |     end loop;
 | 
      
         | 212 |  |  |     return(tz(vect2));
 | 
      
         | 213 |  |  |   end;
 | 
      
         | 214 |  |  |  
 | 
      
         | 215 |  |  | -- Find next master:
 | 
      
         | 216 |  |  | --   * 2 arbitration policies: fixed priority or round-robin
 | 
      
         | 217 |  |  | --   * Fixed priority: priority is fixed, highest index has highest priority
 | 
      
         | 218 |  |  | --   * Round-robin: arbiter maintains circular queue of masters
 | 
      
         | 219 |  |  | --   * (master 0, master 1, ..., master (nahbmx-1)). First requesting master
 | 
      
         | 220 |  |  | --   * in the queue is granted access to the bus and moved to the end of the queue.  
 | 
      
         | 221 |  |  | --   * splitted masters are not granted
 | 
      
         | 222 |  |  | --   * bus is re-arbited when current owner does not request the bus,
 | 
      
         | 223 |  |  | --     or when it performs non-burst accesses
 | 
      
         | 224 |  |  | --   * fix length burst transfers will not be interrupted
 | 
      
         | 225 |  |  | --   * incremental bursts should assert hbusreq until last access
 | 
      
         | 226 |  |  |  
 | 
      
         | 227 |  |  |   procedure selmast(r      : in reg_type;
 | 
      
         | 228 |  |  |                   msto   : in ahb_mst_out_vector;
 | 
      
         | 229 |  |  |                   rsplit : in std_logic_vector(0 to nahbmx-1);
 | 
      
         | 230 |  |  |                   mast   : out integer range 0 to nahbmx-1;
 | 
      
         | 231 |  |  |                   defmst : out std_ulogic) is
 | 
      
         | 232 |  |  |   variable nmst    : nmstarr;
 | 
      
         | 233 |  |  |   variable nvalid  : nvalarr;
 | 
      
         | 234 |  |  |  
 | 
      
         | 235 |  |  |   variable rrvec : std_logic_vector(nahbmx*2-1 downto 0);
 | 
      
         | 236 |  |  |   variable zcnt  : std_logic_vector(log2(nahbmx)+1 downto 0);
 | 
      
         | 237 |  |  |   variable hpvec : std_logic_vector(nahbmx-1 downto 0);
 | 
      
         | 238 |  |  |   variable zcnt2 : std_logic_vector(log2(nahbmx) downto 0);
 | 
      
         | 239 |  |  |  
 | 
      
         | 240 |  |  |   begin
 | 
      
         | 241 |  |  |  
 | 
      
         | 242 |  |  |     nvalid(1 to 3) := (others => false); nmst(1 to 3) := (others => 0);
 | 
      
         | 243 |  |  |     mast := r.hmaster;
 | 
      
         | 244 |  |  |     defmst := '0';
 | 
      
         | 245 |  |  |  
 | 
      
         | 246 |  |  |     if nahbm = 1 then
 | 
      
         | 247 |  |  |       mast := 0;
 | 
      
         | 248 |  |  |     elsif rrobin = 0 then
 | 
      
         | 249 |  |  |       hpvec := (others => '0');
 | 
      
         | 250 |  |  |       for i in 0 to nahbmx-1 loop
 | 
      
         | 251 |  |  |         --masters which have received split are not granted
 | 
      
         | 252 |  |  |         if ((rsplit(i) = '0') or (split = 0)) then
 | 
      
         | 253 |  |  |           hpvec(i) := msto(i).hbusreq;
 | 
      
         | 254 |  |  |         end if;
 | 
      
         | 255 |  |  |       end loop;
 | 
      
         | 256 |  |  |       --check if any bus requests are active (nvalid(2) set to true)
 | 
      
         | 257 |  |  |       --and determine the index (zcnt2) of the highest priority master
 | 
      
         | 258 |  |  |       zcnt2 := lz(hpvec)(log2(nahbmx) downto 0);
 | 
      
         | 259 |  |  |       if zcnt2(log2(nahbmx)) = '0' then nvalid(2) := true; end if;
 | 
      
         | 260 |  |  |       nmst(2) := conv_integer(not (zcnt2(log2(nahbmx)-1 downto 0)));
 | 
      
         | 261 |  |  |       --find the default master number
 | 
      
         | 262 |  |  |       for i in 0 to nahbmx-1 loop
 | 
      
         | 263 |  |  |         if not ((nmst(3) = defmast) and nvalid(3)) then
 | 
      
         | 264 |  |  |           nmst(3) := i; nvalid(3) := true;
 | 
      
         | 265 |  |  |         end if;
 | 
      
         | 266 |  |  |       end loop;
 | 
      
         | 267 |  |  |     else
 | 
      
         | 268 |  |  |       rrvec := (others => '0');
 | 
      
         | 269 |  |  |       --mask requests up to and including current master. Concatenate
 | 
      
         | 270 |  |  |       --an unmasked request vector above the masked vector. Otherwise
 | 
      
         | 271 |  |  |       --the rules are the same as for fixed priority
 | 
      
         | 272 |  |  |       for i in 0 to nahbmx-1 loop
 | 
      
         | 273 |  |  |         if ((rsplit(i) = '0') or (split = 0)) then
 | 
      
         | 274 |  |  |           if (i <= r.hmaster) then rrvec(i) := '0';
 | 
      
         | 275 |  |  |           else rrvec(i) := msto(i).hbusreq; end if;
 | 
      
         | 276 |  |  |           rrvec(nahbmx+i) := msto(i).hbusreq;
 | 
      
         | 277 |  |  |         end if;
 | 
      
         | 278 |  |  |       end loop;
 | 
      
         | 279 |  |  |       --find the next master uzing tz which gives priority to lower
 | 
      
         | 280 |  |  |       --indexes
 | 
      
         | 281 |  |  |       zcnt := tz(rrvec)(log2(nahbmx)+1 downto 0);
 | 
      
         | 282 |  |  |       --was there a master requesting the bus?
 | 
      
         | 283 |  |  |       if zcnt(log2(nahbmx)+1) = '0' then nvalid(2) := true; end if;
 | 
      
         | 284 |  |  |       nmst(2) := conv_integer(zcnt(log2(nahbmx)-1 downto 0));
 | 
      
         | 285 |  |  |       --if no other master is requesting the bus select the current one
 | 
      
         | 286 |  |  |       nmst(3) := r.hmaster; nvalid(3) := true;
 | 
      
         | 287 |  |  |       --check if any masters configured with higher priority are requesting
 | 
      
         | 288 |  |  |       --the bus
 | 
      
         | 289 |  |  |       if mprio /= 0 then
 | 
      
         | 290 |  |  |         for i in 0 to nahbm-1 loop
 | 
      
         | 291 |  |  |           if (((rsplit(i) = '0') or (split = 0)) and (primst(i) = '1')) then
 | 
      
         | 292 |  |  |             if msto(i).hbusreq = '1' then nmst(1) := i; nvalid(1) := true; end if;
 | 
      
         | 293 |  |  |           end if;
 | 
      
         | 294 |  |  |         end loop;
 | 
      
         | 295 |  |  |       end if;
 | 
      
         | 296 |  |  |     end if;
 | 
      
         | 297 |  |  |  
 | 
      
         | 298 |  |  |     --select the next master. If for round robin a high priority master
 | 
      
         | 299 |  |  |     --(mprio) requested the bus if nvalid(1) is true. Otherwise
 | 
      
         | 300 |  |  |     --if nvalid(2) is true at least one master was requesting the bus
 | 
      
         | 301 |  |  |     --and the one with highest priority was selected. If none of these
 | 
      
         | 302 |  |  |     --were true then the default master is selected (nvalid(3) true)
 | 
      
         | 303 |  |  |     for i in 1 to 3 loop
 | 
      
         | 304 |  |  |       if nvalid(i) then mast := nmst(i); exit; end if;
 | 
      
         | 305 |  |  |     end loop;
 | 
      
         | 306 |  |  |  
 | 
      
         | 307 |  |  |     --if no master was requesting the bus and split is enabled
 | 
      
         | 308 |  |  |     --then select builtin dummy master which only does
 | 
      
         | 309 |  |  |     --idle transfers
 | 
      
         | 310 |  |  |     if (not (nvalid(1) or nvalid(2))) and (split /= 0) then
 | 
      
         | 311 |  |  |       defmst := orv(rsplit);
 | 
      
         | 312 |  |  |     end if;
 | 
      
         | 313 |  |  |  
 | 
      
         | 314 |  |  |   end;
 | 
      
         | 315 |  |  |  
 | 
      
         | 316 |  |  |   constant MIMAX : integer := log2x(nahbmx) - 1;
 | 
      
         | 317 |  |  |   constant SIMAX : integer := log2x(nahbs) - 1;
 | 
      
         | 318 |  |  |   constant IOAREA : std_logic_vector(11 downto 0) :=
 | 
      
         | 319 |  |  |         conv_std_logic_vector(ioaddr, 12);
 | 
      
         | 320 |  |  |   constant IOMSK  : std_logic_vector(11 downto 0) :=
 | 
      
         | 321 |  |  |         conv_std_logic_vector(iomask, 12);
 | 
      
         | 322 |  |  |   constant CFGAREA : std_logic_vector(11 downto 0) :=
 | 
      
         | 323 |  |  |         conv_std_logic_vector(cfgaddr, 12);
 | 
      
         | 324 |  |  |   constant CFGMSK  : std_logic_vector(11 downto 0) :=
 | 
      
         | 325 |  |  |         conv_std_logic_vector(cfgmask, 12);
 | 
      
         | 326 |  |  |   constant FULLPNP : boolean := (fpnpen /= 0);
 | 
      
         | 327 |  |  |  
 | 
      
         | 328 |  |  |   signal r, rin : reg_type;
 | 
      
         | 329 |  |  |   signal rsplit, rsplitin : std_logic_vector(0 to nahbmx-1);
 | 
      
         | 330 |  |  |  
 | 
      
         | 331 |  |  | -- pragma translate_off
 | 
      
         | 332 |  |  |   signal lmsti : ahb_mst_in_type;
 | 
      
         | 333 |  |  |   signal lslvi : ahb_slv_in_type;
 | 
      
         | 334 |  |  | -- pragma translate_on
 | 
      
         | 335 |  |  |  
 | 
      
         | 336 |  |  | begin
 | 
      
         | 337 |  |  |  
 | 
      
         | 338 |  |  |   comb : process(rst, msto, slvo, r, rsplit, testen, testrst, scanen, testoen)
 | 
      
         | 339 |  |  |   variable v : reg_type;
 | 
      
         | 340 |  |  |   variable nhmaster, hmaster : integer range 0 to nahbmx -1;
 | 
      
         | 341 |  |  |   variable hgrant  : std_logic_vector(0 to NAHBMST-1);   -- bus grant
 | 
      
         | 342 |  |  |   variable hsel    : std_logic_vector(0 to 31);   -- slave select
 | 
      
         | 343 |  |  |   variable hmbsel  : std_logic_vector(0 to NAHBAMR-1);
 | 
      
         | 344 |  |  |   variable nslave  : natural range 0 to 31;
 | 
      
         | 345 |  |  |   variable vsplit  : std_logic_vector(0 to nahbmx-1);
 | 
      
         | 346 |  |  |   variable bnslave : std_logic_vector(3 downto 0);
 | 
      
         | 347 |  |  |   variable area    : std_logic_vector(1 downto 0);
 | 
      
         | 348 |  |  |   variable hready  : std_ulogic;
 | 
      
         | 349 |  |  |   variable defslv  : std_ulogic;
 | 
      
         | 350 |  |  |   variable cfgsel  : std_ulogic;
 | 
      
         | 351 |  |  |   variable hcache  : std_ulogic;
 | 
      
         | 352 |  |  |   variable hresp   : std_logic_vector(1 downto 0);
 | 
      
         | 353 |  |  |   variable hrdata  : std_logic_vector(31 downto 0);
 | 
      
         | 354 |  |  |   variable haddr   : std_logic_vector(31 downto 0);
 | 
      
         | 355 |  |  |   variable hirq    : std_logic_vector(NAHBIRQ-1 downto 0);
 | 
      
         | 356 |  |  |   variable arb     : std_ulogic;
 | 
      
         | 357 |  |  |   variable hconfndx : integer range 0 to 7;
 | 
      
         | 358 |  |  |   variable vslvi   : ahb_slv_in_type;
 | 
      
         | 359 |  |  |   variable defmst   : std_ulogic;
 | 
      
         | 360 |  |  |   variable tmpv     : std_logic_vector(0 to nahbmx-1);
 | 
      
         | 361 |  |  |  
 | 
      
         | 362 |  |  |   begin
 | 
      
         | 363 |  |  |  
 | 
      
         | 364 |  |  |     v := r; hgrant := (others => '0'); defmst := '0';
 | 
      
         | 365 |  |  |     haddr := msto(r.hmaster).haddr;
 | 
      
         | 366 |  |  |  
 | 
      
         | 367 |  |  |     nhmaster := r.hmaster;
 | 
      
         | 368 |  |  |  
 | 
      
         | 369 |  |  |     --determine if bus should be rearbitrated. This is done if the current
 | 
      
         | 370 |  |  |     --master is not performing a locked transfer and if not in the middle
 | 
      
         | 371 |  |  |     --of burst
 | 
      
         | 372 |  |  |     arb := '0';
 | 
      
         | 373 |  |  |     if (r.hmasterlock or r.ldefmst) = '0' then
 | 
      
         | 374 |  |  |       case msto(r.hmaster).htrans is
 | 
      
         | 375 |  |  |         when HTRANS_IDLE => arb := '1';
 | 
      
         | 376 |  |  |         when HTRANS_NONSEQ =>
 | 
      
         | 377 |  |  |           case msto(r.hmaster).hburst is
 | 
      
         | 378 |  |  |             when HBURST_SINGLE => arb := '1';
 | 
      
         | 379 |  |  |             when HBURST_INCR => arb := not msto(r.hmaster).hbusreq;
 | 
      
         | 380 |  |  |             when others =>
 | 
      
         | 381 |  |  |           end case;
 | 
      
         | 382 |  |  |         when HTRANS_SEQ =>
 | 
      
         | 383 |  |  |           case msto(r.hmaster).hburst is
 | 
      
         | 384 |  |  |             when HBURST_WRAP4  | HBURST_INCR4  => if (fixbrst = 1) and (r.beat(1 downto 0) = "11")   then arb := '1'; end if;
 | 
      
         | 385 |  |  |             when HBURST_WRAP8  | HBURST_INCR8  => if (fixbrst = 1) and (r.beat(2 downto 0) = "111")  then arb := '1'; end if;
 | 
      
         | 386 |  |  |             when HBURST_WRAP16 | HBURST_INCR16 => if (fixbrst = 1) and (r.beat(3 downto 0) = "1111") then arb := '1'; end if;
 | 
      
         | 387 |  |  |             when HBURST_INCR => arb := not msto(r.hmaster).hbusreq;
 | 
      
         | 388 |  |  |             when others =>
 | 
      
         | 389 |  |  |           end case;
 | 
      
         | 390 |  |  |         when others => arb := '0';
 | 
      
         | 391 |  |  |       end case;
 | 
      
         | 392 |  |  | -- pragma translate_off 
 | 
      
         | 393 |  |  |       if enebterm = 1 then arb := '1'; end if;
 | 
      
         | 394 |  |  | -- pragma translate_on
 | 
      
         | 395 |  |  |     end if;
 | 
      
         | 396 |  |  |  
 | 
      
         | 397 |  |  |     if (split /= 0) then
 | 
      
         | 398 |  |  |       for i in 0 to nahbmx-1 loop
 | 
      
         | 399 |  |  |         tmpv(i) := (msto(i).htrans(1) or (msto(i).hbusreq)) and not rsplit(i) and not r.ldefmst;
 | 
      
         | 400 |  |  |       end loop;
 | 
      
         | 401 |  |  |       if (r.defmst and orv(tmpv))  = '1' then arb := '1'; end if;
 | 
      
         | 402 |  |  |     end if;
 | 
      
         | 403 |  |  |  
 | 
      
         | 404 |  |  |     --rearbitrate bus with selmast. If not arbitrated one must
 | 
      
         | 405 |  |  |     --ensure that the dummy master is selected for locked splits. 
 | 
      
         | 406 |  |  |     if (arb = '1') then
 | 
      
         | 407 |  |  |       selmast(r, msto, rsplit, nhmaster, defmst);
 | 
      
         | 408 |  |  |     elsif (split /= 0) then
 | 
      
         | 409 |  |  |       defmst := r.defmst;
 | 
      
         | 410 |  |  |     end if;
 | 
      
         | 411 |  |  |  
 | 
      
         | 412 |  |  |     -- slave decoding
 | 
      
         | 413 |  |  |  
 | 
      
         | 414 |  |  |     hsel := (others => '0'); hmbsel := (others => '0');
 | 
      
         | 415 |  |  |  
 | 
      
         | 416 |  |  |     for i in 0 to nahbs-1 loop
 | 
      
         | 417 |  |  |       for j in NAHBIR to NAHBCFG-1 loop
 | 
      
         | 418 |  |  |         area := slvo(i).hconfig(j)(1 downto 0);
 | 
      
         | 419 |  |  |         case area is
 | 
      
         | 420 |  |  |         when "10" =>
 | 
      
         | 421 |  |  |           if ((ioen = 0) or ((IOAREA and IOMSK) /= (haddr(31 downto 20) and IOMSK))) and
 | 
      
         | 422 |  |  |              ((slvo(i).hconfig(j)(31 downto 20) and slvo(i).hconfig(j)(15 downto 4)) =
 | 
      
         | 423 |  |  |               (haddr(31 downto 20) and slvo(i).hconfig(j)(15 downto 4))) and
 | 
      
         | 424 |  |  |               (slvo(i).hconfig(j)(15 downto 4) /= "000000000000")
 | 
      
         | 425 |  |  |           then hsel(i) := '1'; hmbsel(j-NAHBIR) := '1'; end if;
 | 
      
         | 426 |  |  |         when "11" =>
 | 
      
         | 427 |  |  |           if ((ioen /= 0) and ((IOAREA and IOMSK) = (haddr(31 downto 20) and IOMSK))) and
 | 
      
         | 428 |  |  |              ((slvo(i).hconfig(j)(31 downto 20) and slvo(i).hconfig(j)(15 downto 4)) =
 | 
      
         | 429 |  |  |               (haddr(19 downto  8) and slvo(i).hconfig(j)(15 downto 4))) and
 | 
      
         | 430 |  |  |               (slvo(i).hconfig(j)(15 downto 4) /= "000000000000")
 | 
      
         | 431 |  |  |           then hsel(i) := '1'; hmbsel(j-NAHBIR) := '1'; end if;
 | 
      
         | 432 |  |  |         when others =>
 | 
      
         | 433 |  |  |         end case;
 | 
      
         | 434 |  |  |       end loop;
 | 
      
         | 435 |  |  |     end loop;
 | 
      
         | 436 |  |  |  
 | 
      
         | 437 |  |  |     if r.defmst = '1' then hsel := (others => '0'); end if;
 | 
      
         | 438 |  |  |  
 | 
      
         | 439 |  |  |     bnslave(0) := hsel(1) or hsel(3) or hsel(5) or hsel(7) or
 | 
      
         | 440 |  |  |                   hsel(9) or hsel(11) or hsel(13) or hsel(15);
 | 
      
         | 441 |  |  |     bnslave(1) := hsel(2) or hsel(3) or hsel(6) or hsel(7) or
 | 
      
         | 442 |  |  |                   hsel(10) or hsel(11) or hsel(14) or hsel(15);
 | 
      
         | 443 |  |  |     bnslave(2) := hsel(4) or hsel(5) or hsel(6) or hsel(7) or
 | 
      
         | 444 |  |  |                   hsel(12) or hsel(13) or hsel(14) or hsel(15);
 | 
      
         | 445 |  |  |     bnslave(3) := hsel(8) or hsel(9) or hsel(10) or hsel(11) or
 | 
      
         | 446 |  |  |                   hsel(12) or hsel(13) or hsel(14) or hsel(15);
 | 
      
         | 447 |  |  |     nslave := conv_integer(bnslave(SIMAX downto 0));
 | 
      
         | 448 |  |  |  
 | 
      
         | 449 |  |  |     if ((((IOAREA and IOMSK) = (haddr(31 downto 20) and IOMSK)) and (ioen /= 0))
 | 
      
         | 450 |  |  |       or ((IOAREA = haddr(31 downto 20)) and (ioen = 0))) and
 | 
      
         | 451 |  |  |        ((CFGAREA and CFGMSK) = (haddr(19 downto  8) and CFGMSK))
 | 
      
         | 452 |  |  |        and (cfgmask /= 0)
 | 
      
         | 453 |  |  |     then cfgsel := '1'; hsel := (others => '0');
 | 
      
         | 454 |  |  |     else cfgsel := '0'; end if;
 | 
      
         | 455 |  |  |  
 | 
      
         | 456 |  |  |     if (nslave = 0) and (hsel(0) = '0') and (cfgsel = '0') then defslv := '1';
 | 
      
         | 457 |  |  |     else defslv := '0'; end if;
 | 
      
         | 458 |  |  |  
 | 
      
         | 459 |  |  |     if r.defmst = '1' then
 | 
      
         | 460 |  |  |       cfgsel := '0'; defslv := '1';
 | 
      
         | 461 |  |  |     end if;
 | 
      
         | 462 |  |  |  
 | 
      
         | 463 |  |  | -- error response on undecoded area
 | 
      
         | 464 |  |  |  
 | 
      
         | 465 |  |  |     v.hready := '0';
 | 
      
         | 466 |  |  |     hready := slvo(r.hslave).hready; hresp := slvo(r.hslave).hresp;
 | 
      
         | 467 |  |  |     if r.defslv = '1' then
 | 
      
         | 468 |  |  |       -- default slave
 | 
      
         | 469 |  |  |       if (r.htrans = HTRANS_IDLE) or (r.htrans = HTRANS_BUSY) then
 | 
      
         | 470 |  |  |         hresp := HRESP_OKAY; hready := '1';
 | 
      
         | 471 |  |  |       else
 | 
      
         | 472 |  |  |         -- return two-cycle error in case of unimplemented slave access
 | 
      
         | 473 |  |  |         hresp := HRESP_ERROR; hready := r.hready; v.hready := not r.hready;
 | 
      
         | 474 |  |  |       end if;
 | 
      
         | 475 |  |  |     end if;
 | 
      
         | 476 |  |  |  
 | 
      
         | 477 |  |  |     hrdata := slvo(r.hslave).hrdata;
 | 
      
         | 478 |  |  |  
 | 
      
         | 479 |  |  |     if cfgmask /= 0 then
 | 
      
         | 480 |  |  | --      v.hrdatam := msto(conv_integer(r.haddr(MIMAX+5 downto 5))).hconfig(conv_integer(r.haddr(4 downto 2)));
 | 
      
         | 481 |  |  | --      if r.haddr(11 downto MIMAX+6) /= zero32(11 downto MIMAX+6) then v.hrdatam := (others => '0'); end if;
 | 
      
         | 482 |  |  |  
 | 
      
         | 483 |  |  | --       if (r.haddr(10 downto MIMAX+6) = zero32(10 downto MIMAX+6)) and (r.haddr(4 downto 2) = "000")
 | 
      
         | 484 |  |  |       if FULLPNP then hconfndx := conv_integer(r.haddr(4 downto 2)); else hconfndx := 0; end if;
 | 
      
         | 485 |  |  |       if (r.haddr(10 downto MIMAX+6) = zero32(10 downto MIMAX+6)) and (FULLPNP or (r.haddr(4 downto 2) = "000"))
 | 
      
         | 486 |  |  |       then v.hrdatam := msto(conv_integer(r.haddr(MIMAX+5 downto 5))).hconfig(hconfndx);
 | 
      
         | 487 |  |  |       else v.hrdatam := (others => '0'); end if;
 | 
      
         | 488 |  |  |  
 | 
      
         | 489 |  |  | --      v.hrdatas := slvo(conv_integer(r.haddr(SIMAX+5 downto 5))).hconfig(conv_integer(r.haddr(4 downto 2)));
 | 
      
         | 490 |  |  | --      if r.haddr(11 downto SIMAX+6) /= ('1' & zero32(10 downto SIMAX+6)) then v.hrdatas := (others => '0'); end if;
 | 
      
         | 491 |  |  |  
 | 
      
         | 492 |  |  |       --if (r.haddr(10 downto SIMAX+6) = zero32(10 downto SIMAX+6)) and
 | 
      
         | 493 |  |  |       if (r.haddr(10 downto SIMAX+6) = zero32(10 downto SIMAX+6)) and
 | 
      
         | 494 |  |  |         (FULLPNP or (r.haddr(4 downto 2) = "000") or (r.haddr(4) = '1'))
 | 
      
         | 495 |  |  |       then v.hrdatas := slvo(conv_integer(r.haddr(SIMAX+5 downto 5))).hconfig(conv_integer(r.haddr(4 downto 2)));
 | 
      
         | 496 |  |  |       else v.hrdatas := (others => '0'); end if;
 | 
      
         | 497 |  |  |  
 | 
      
         | 498 |  |  |       if r.haddr(10 downto 4) = "1111111" then
 | 
      
         | 499 |  |  |          v.hrdatas(15 downto 0) := conv_std_logic_vector(LIBVHDL_BUILD, 16);
 | 
      
         | 500 |  |  |          v.hrdatas(31 downto 16) := conv_std_logic_vector(devid, 16);
 | 
      
         | 501 |  |  |       end if;
 | 
      
         | 502 |  |  |       if r.cfgsel = '1' then
 | 
      
         | 503 |  |  |         hrdata := (others => '0');
 | 
      
         | 504 |  |  |         -- default slave
 | 
      
         | 505 |  |  |         if (r.htrans = HTRANS_IDLE) or (r.htrans = HTRANS_BUSY) then
 | 
      
         | 506 |  |  |           hresp := HRESP_OKAY; hready := '1';
 | 
      
         | 507 |  |  |         else
 | 
      
         | 508 |  |  |           -- return two-cycle read/write respons
 | 
      
         | 509 |  |  |           hresp := HRESP_OKAY; hready := r.hready; v.hready := not r.hready;
 | 
      
         | 510 |  |  |         end if;
 | 
      
         | 511 |  |  |         if r.cfga11 = '0' then hrdata := r.hrdatam;
 | 
      
         | 512 |  |  |         else hrdata := r.hrdatas; end if;
 | 
      
         | 513 |  |  |       end if;
 | 
      
         | 514 |  |  |     end if;
 | 
      
         | 515 |  |  |  
 | 
      
         | 516 |  |  |     --degrant all masters when split occurs for locked access
 | 
      
         | 517 |  |  |     if (r.hmasterlockd = '1') then
 | 
      
         | 518 |  |  |       if (hresp = HRESP_RETRY) or ((split /= 0) and (hresp = HRESP_SPLIT)) then
 | 
      
         | 519 |  |  |         nhmaster := r.hmaster;
 | 
      
         | 520 |  |  |       end if;
 | 
      
         | 521 |  |  |       if split /= 0 then
 | 
      
         | 522 |  |  |         if hresp = HRESP_SPLIT then
 | 
      
         | 523 |  |  |           v.ldefmst := '1'; defmst := '1';
 | 
      
         | 524 |  |  |         end if;
 | 
      
         | 525 |  |  |       end if;
 | 
      
         | 526 |  |  |     end if;
 | 
      
         | 527 |  |  |  
 | 
      
         | 528 |  |  |     if r.ldefmst = '1' then
 | 
      
         | 529 |  |  |       if orv(rsplit) = '0' then
 | 
      
         | 530 |  |  |         v.ldefmst := '0'; defmst := '0';
 | 
      
         | 531 |  |  |       end if;
 | 
      
         | 532 |  |  |     end if;
 | 
      
         | 533 |  |  |  
 | 
      
         | 534 |  |  |     if (split = 0) or (defmst = '0') then hgrant(nhmaster) := '1'; end if;
 | 
      
         | 535 |  |  |  
 | 
      
         | 536 |  |  |     -- latch active master and slave
 | 
      
         | 537 |  |  |     if hready = '1' then
 | 
      
         | 538 |  |  |       v.hmaster := nhmaster; v.hmasterd := r.hmaster;
 | 
      
         | 539 |  |  |       v.hslave := nslave; v.defslv := defslv;
 | 
      
         | 540 |  |  |       v.hmasterlockd := r.hmasterlock;
 | 
      
         | 541 |  |  |       if (split = 0) or (r.defmst = '0') then v.htrans := msto(r.hmaster).htrans;
 | 
      
         | 542 |  |  |       else v.htrans := HTRANS_IDLE; end if;
 | 
      
         | 543 |  |  |       v.cfgsel := cfgsel;
 | 
      
         | 544 |  |  |       v.cfga11 := msto(r.hmaster).haddr(11);
 | 
      
         | 545 |  |  |       v.haddr := msto(r.hmaster).haddr(15 downto 2);
 | 
      
         | 546 |  |  |       if (msto(r.hmaster).htrans = HTRANS_NONSEQ) or (msto(r.hmaster).htrans = HTRANS_IDLE) then
 | 
      
         | 547 |  |  |         v.beat := "0001";
 | 
      
         | 548 |  |  |       elsif (msto(r.hmaster).htrans = HTRANS_SEQ) then
 | 
      
         | 549 |  |  |         if (fixbrst = 1) then v.beat := r.beat + 1; end if;
 | 
      
         | 550 |  |  |       end if;
 | 
      
         | 551 |  |  |       if (split /= 0) then v.defmst := defmst; end if;
 | 
      
         | 552 |  |  |     end if;
 | 
      
         | 553 |  |  |  
 | 
      
         | 554 |  |  |     --assign new hmasterlock, v.hmaster is used because if hready
 | 
      
         | 555 |  |  |     --then master can have changed, and when not hready then the
 | 
      
         | 556 |  |  |     --previous master will still be selected
 | 
      
         | 557 |  |  |     v.hmasterlock := msto(v.hmaster).hlock or (r.hmasterlock and not hready);
 | 
      
         | 558 |  |  |  
 | 
      
         | 559 |  |  |     -- split support
 | 
      
         | 560 |  |  |     vsplit := (others => '0');
 | 
      
         | 561 |  |  |     if SPLIT /= 0 then
 | 
      
         | 562 |  |  |       vsplit := rsplit;
 | 
      
         | 563 |  |  |       if slvo(r.hslave).hresp = HRESP_SPLIT then vsplit(r.hmasterd) := '1'; end if;
 | 
      
         | 564 |  |  |       for i in 0 to nahbs-1 loop
 | 
      
         | 565 |  |  |         for j in 0 to nahbmx-1 loop
 | 
      
         | 566 |  |  |           vsplit(j) := vsplit(j) and not slvo(i).hsplit(j);
 | 
      
         | 567 |  |  |         end loop;
 | 
      
         | 568 |  |  |       end loop;
 | 
      
         | 569 |  |  |     end if;
 | 
      
         | 570 |  |  |  
 | 
      
         | 571 |  |  |     if r.cfgsel = '1' then hcache := '1'; else hcache := slvo(v.hslave).hcache; end if;
 | 
      
         | 572 |  |  |  
 | 
      
         | 573 |  |  |     -- interrupt merging
 | 
      
         | 574 |  |  |     hirq := (others => '0');
 | 
      
         | 575 |  |  |     if disirq = 0 then
 | 
      
         | 576 |  |  |       for i in 0 to nahbs-1 loop hirq := hirq or slvo(i).hirq; end loop;
 | 
      
         | 577 |  |  |       for i in 0 to nahbm-1 loop hirq := hirq or msto(i).hirq; end loop;
 | 
      
         | 578 |  |  |     end if;
 | 
      
         | 579 |  |  |  
 | 
      
         | 580 |  |  |     if (split = 0) or (r.defmst = '0') then
 | 
      
         | 581 |  |  |       vslvi.haddr      := haddr;
 | 
      
         | 582 |  |  |       vslvi.htrans     := msto(r.hmaster).htrans;
 | 
      
         | 583 |  |  |       vslvi.hwrite     := msto(r.hmaster).hwrite;
 | 
      
         | 584 |  |  |       vslvi.hsize      := msto(r.hmaster).hsize;
 | 
      
         | 585 |  |  |       vslvi.hburst     := msto(r.hmaster).hburst;
 | 
      
         | 586 |  |  |       vslvi.hready     := hready;
 | 
      
         | 587 |  |  |       vslvi.hwdata     := msto(r.hmasterd).hwdata;
 | 
      
         | 588 |  |  |       vslvi.hprot      := msto(r.hmaster).hprot;
 | 
      
         | 589 |  |  | --      vslvi.hmastlock  := msto(r.hmaster).hlock;
 | 
      
         | 590 |  |  |       vslvi.hmastlock  := r.hmasterlock;
 | 
      
         | 591 |  |  |       vslvi.hmaster    := conv_std_logic_vector(r.hmaster, 4);
 | 
      
         | 592 |  |  |       vslvi.hsel       := hsel(0 to NAHBSLV-1);
 | 
      
         | 593 |  |  |       vslvi.hmbsel     := hmbsel;
 | 
      
         | 594 |  |  |       vslvi.hcache     := hcache;
 | 
      
         | 595 |  |  |       vslvi.hirq       := hirq;
 | 
      
         | 596 |  |  |     else
 | 
      
         | 597 |  |  |       vslvi := ahbs_in_none;
 | 
      
         | 598 |  |  |       vslvi.hready := hready;
 | 
      
         | 599 |  |  |       vslvi.hwdata := msto(r.hmasterd).hwdata;
 | 
      
         | 600 |  |  |       vslvi.hirq   := hirq;
 | 
      
         | 601 |  |  |     end if;
 | 
      
         | 602 |  |  |     vslvi.testen  := testen;
 | 
      
         | 603 |  |  |     vslvi.testrst := testrst;
 | 
      
         | 604 |  |  |     vslvi.scanen  := scanen and testen;
 | 
      
         | 605 |  |  |     vslvi.testoen := testoen;
 | 
      
         | 606 |  |  |  
 | 
      
         | 607 |  |  |     -- reset operation
 | 
      
         | 608 |  |  |     if (rst = '0') then
 | 
      
         | 609 |  |  |       v.hmaster := 0; v.hmasterlock := '0'; vsplit := (others => '0');
 | 
      
         | 610 |  |  |       v.htrans := HTRANS_IDLE;  v.defslv := '0'; -- v.beat := "0001";
 | 
      
         | 611 |  |  |       v.hslave := 0; v.cfgsel := '0'; v.defmst := '0';
 | 
      
         | 612 |  |  |       v.ldefmst := '0';
 | 
      
         | 613 |  |  |     end if;
 | 
      
         | 614 |  |  |  
 | 
      
         | 615 |  |  |     -- drive master inputs
 | 
      
         | 616 |  |  |     msti.hgrant  <= hgrant;
 | 
      
         | 617 |  |  |     msti.hready  <= hready;
 | 
      
         | 618 |  |  |     msti.hresp   <= hresp;
 | 
      
         | 619 |  |  |     msti.hrdata  <= hrdata;
 | 
      
         | 620 |  |  |     msti.hcache  <= hcache;
 | 
      
         | 621 |  |  |     msti.hirq    <= hirq;
 | 
      
         | 622 |  |  |     msti.testen  <= testen;
 | 
      
         | 623 |  |  |     msti.testrst <= testrst;
 | 
      
         | 624 |  |  |     msti.scanen  <= scanen and testen;
 | 
      
         | 625 |  |  |     msti.testoen <= testoen;
 | 
      
         | 626 |  |  |  
 | 
      
         | 627 |  |  |     -- drive slave inputs
 | 
      
         | 628 |  |  |     slvi     <= vslvi;
 | 
      
         | 629 |  |  |  
 | 
      
         | 630 |  |  | -- pragma translate_off
 | 
      
         | 631 |  |  |     --drive internal signals to bus monitor
 | 
      
         | 632 |  |  |     lslvi         <= vslvi;
 | 
      
         | 633 |  |  |  
 | 
      
         | 634 |  |  |     lmsti.hgrant  <= hgrant;
 | 
      
         | 635 |  |  |     lmsti.hready  <= hready;
 | 
      
         | 636 |  |  |     lmsti.hresp   <= hresp;
 | 
      
         | 637 |  |  |     lmsti.hrdata  <= hrdata;
 | 
      
         | 638 |  |  |     lmsti.hcache  <= hcache;
 | 
      
         | 639 |  |  |     lmsti.hirq    <= hirq;
 | 
      
         | 640 |  |  | -- pragma translate_on
 | 
      
         | 641 |  |  |  
 | 
      
         | 642 |  |  |     rin <= v; rsplitin <= vsplit;
 | 
      
         | 643 |  |  |  
 | 
      
         | 644 |  |  |   end process;
 | 
      
         | 645 |  |  |  
 | 
      
         | 646 |  |  |  
 | 
      
         | 647 |  |  |   reg0 : process(clk)
 | 
      
         | 648 |  |  |   begin
 | 
      
         | 649 |  |  |     if rising_edge(clk) then r <= rin; end if;
 | 
      
         | 650 |  |  |     if (split = 0) then r.defmst <= '0'; end if;
 | 
      
         | 651 |  |  |   end process;
 | 
      
         | 652 |  |  |  
 | 
      
         | 653 |  |  |   splitreg : if SPLIT /= 0 generate
 | 
      
         | 654 |  |  |     reg1 : process(clk)
 | 
      
         | 655 |  |  |     begin if rising_edge(clk) then rsplit <= rsplitin; end if; end process;
 | 
      
         | 656 |  |  |   end generate;
 | 
      
         | 657 |  |  |  
 | 
      
         | 658 |  |  |   nosplitreg : if SPLIT = 0 generate
 | 
      
         | 659 |  |  |     rsplit <= (others => '0');
 | 
      
         | 660 |  |  |   end generate;
 | 
      
         | 661 |  |  |  
 | 
      
         | 662 |  |  | -- pragma translate_off
 | 
      
         | 663 |  |  | --  diag : process
 | 
      
         | 664 |  |  | --  variable k : integer;
 | 
      
         | 665 |  |  | --  variable mask : std_logic_vector(11 downto 0);
 | 
      
         | 666 |  |  | --  variable iostart : std_logic_vector(11 downto 0) := IOAREA and IOMSK;
 | 
      
         | 667 |  |  | --  variable cfgstart : std_logic_vector(11 downto 0) := CFGAREA and CFGMSK;
 | 
      
         | 668 |  |  | --  begin
 | 
      
         | 669 |  |  | --    wait for 2 ns;
 | 
      
         | 670 |  |  | --    k := 0; mask := IOMSK;
 | 
      
         | 671 |  |  | --    while (k<12) and (mask(k) = '0') loop k := k+1; end loop; 
 | 
      
         | 672 |  |  | --    print("ahbctrl: AHB arbiter/multiplexer rev 1");
 | 
      
         | 673 |  |  | --    if ioen /= 0 then
 | 
      
         | 674 |  |  | --      print("ahbctrl: Common I/O area at " & tost(iostart) & "00000, " & tost(2**k) & " Mbyte");
 | 
      
         | 675 |  |  | --    else
 | 
      
         | 676 |  |  | --      print("ahbctrl: Common I/O area disabled");
 | 
      
         | 677 |  |  | --    end if;
 | 
      
         | 678 |  |  | --    if cfgmask /= 0 then
 | 
      
         | 679 |  |  | --      print("ahbctrl: Configuration area at " & tost(iostart & cfgstart) & "00, 4 kbyte");
 | 
      
         | 680 |  |  | --    else
 | 
      
         | 681 |  |  | --      print("ahbctrl: Configuration area disabled");
 | 
      
         | 682 |  |  | --    end if;
 | 
      
         | 683 |  |  | --    wait;
 | 
      
         | 684 |  |  | --  end process;
 | 
      
         | 685 |  |  |  
 | 
      
         | 686 |  |  |   mon0 : if enbusmon /= 0 generate
 | 
      
         | 687 |  |  |     mon : ahbmon
 | 
      
         | 688 |  |  |       generic map(
 | 
      
         | 689 |  |  |         asserterr   => asserterr,
 | 
      
         | 690 |  |  |         assertwarn  => assertwarn,
 | 
      
         | 691 |  |  |         hmstdisable => hmstdisable,
 | 
      
         | 692 |  |  |         hslvdisable => hslvdisable,
 | 
      
         | 693 |  |  |         arbdisable  => arbdisable,
 | 
      
         | 694 |  |  |         nahbm       => nahbm,
 | 
      
         | 695 |  |  |         nahbs       => nahbs)
 | 
      
         | 696 |  |  |       port map(
 | 
      
         | 697 |  |  |         rst         => rst,
 | 
      
         | 698 |  |  |         clk         => clk,
 | 
      
         | 699 |  |  |         ahbmi       => lmsti,
 | 
      
         | 700 |  |  |         ahbmo       => msto,
 | 
      
         | 701 |  |  |         ahbsi       => lslvi,
 | 
      
         | 702 |  |  |         ahbso       => slvo,
 | 
      
         | 703 |  |  |         err         => open);
 | 
      
         | 704 |  |  |   end generate;
 | 
      
         | 705 |  |  |  
 | 
      
         | 706 |  |  |   diag : process
 | 
      
         | 707 |  |  |   variable k : integer;
 | 
      
         | 708 |  |  |   variable mask : std_logic_vector(11 downto 0);
 | 
      
         | 709 |  |  |   variable device : std_logic_vector(11 downto 0);
 | 
      
         | 710 |  |  |   variable devicei : integer;
 | 
      
         | 711 |  |  |   variable vendor : std_logic_vector( 7 downto 0);
 | 
      
         | 712 |  |  |   variable area : std_logic_vector( 1 downto 0);
 | 
      
         | 713 |  |  |   variable vendori : integer;
 | 
      
         | 714 |  |  |   variable iosize, tmp : integer;
 | 
      
         | 715 |  |  |   variable iounit : string(1 to 5) := " byte";
 | 
      
         | 716 |  |  |   variable memtype : string(1 to 9);
 | 
      
         | 717 |  |  |   variable iostart : std_logic_vector(11 downto 0) := IOAREA and IOMSK;
 | 
      
         | 718 |  |  |   variable cfgstart : std_logic_vector(11 downto 0) := CFGAREA and CFGMSK;
 | 
      
         | 719 |  |  |   variable L1 : line := new string'("");
 | 
      
         | 720 |  |  |   variable S1 : string(1 to 255);
 | 
      
         | 721 |  |  |  
 | 
      
         | 722 |  |  |   begin
 | 
      
         | 723 |  |  |     wait for 2 ns;
 | 
      
         | 724 |  |  |     if debug = 0 then wait; end if;
 | 
      
         | 725 |  |  |     k := 0; mask := IOMSK;
 | 
      
         | 726 |  |  |     while (k<12) and (mask(k) = '0') loop k := k+1; end loop;
 | 
      
         | 727 |  |  |     print("ahbctrl: AHB arbiter/multiplexer rev 1");
 | 
      
         | 728 |  |  |     if ioen /= 0 then
 | 
      
         | 729 |  |  |       print("ahbctrl: Common I/O area at " & tost(iostart) & "00000, " & tost(2**k) & " Mbyte");
 | 
      
         | 730 |  |  |     else
 | 
      
         | 731 |  |  |       print("ahbctrl: Common I/O area disabled");
 | 
      
         | 732 |  |  |     end if;
 | 
      
         | 733 |  |  |     print("ahbctrl: AHB masters: " & tost(nahbm) & ", AHB slaves: " & tost(nahbs));
 | 
      
         | 734 |  |  |     if cfgmask /= 0 then
 | 
      
         | 735 |  |  |       print("ahbctrl: Configuration area at " & tost(iostart & cfgstart) & "00, 4 kbyte");
 | 
      
         | 736 |  |  |     else
 | 
      
         | 737 |  |  |       print("ahbctrl: Configuration area disabled");
 | 
      
         | 738 |  |  |     end if;
 | 
      
         | 739 |  |  |     if debug = 1 then wait; end if;
 | 
      
         | 740 |  |  |     for i in 0 to nahbm-1 loop
 | 
      
         | 741 |  |  |       vendor := msto(i).hconfig(0)(31 downto 24);
 | 
      
         | 742 |  |  |       vendori := conv_integer(vendor);
 | 
      
         | 743 |  |  |       if vendori /= 0 then
 | 
      
         | 744 |  |  |         device := msto(i).hconfig(0)(23 downto 12);
 | 
      
         | 745 |  |  |         devicei := conv_integer(device);
 | 
      
         | 746 |  |  |         print("ahbctrl: mst" & tost(i) & ": " & iptable(vendori).vendordesc &
 | 
      
         | 747 |  |  |            iptable(vendori).device_table(devicei));
 | 
      
         | 748 |  |  |         assert (msto(i).hindex = i) or (icheck = 0)
 | 
      
         | 749 |  |  |         report "AHB master index error on master " & tost(i) severity failure;
 | 
      
         | 750 |  |  |       end if;
 | 
      
         | 751 |  |  |     end loop;
 | 
      
         | 752 |  |  |     for i in 0 to nahbs-1 loop
 | 
      
         | 753 |  |  |       vendor := slvo(i).hconfig(0)(31 downto 24);
 | 
      
         | 754 |  |  |       vendori := conv_integer(vendor);
 | 
      
         | 755 |  |  |       if vendori /= 0 then
 | 
      
         | 756 |  |  |         device := slvo(i).hconfig(0)(23 downto 12);
 | 
      
         | 757 |  |  |         devicei := conv_integer(device);
 | 
      
         | 758 |  |  |         std.textio.write(L1, "ahbctrl: slv" & tost(i) & ": " & iptable(vendori).vendordesc &
 | 
      
         | 759 |  |  |            iptable(vendori).device_table(devicei));
 | 
      
         | 760 |  |  |         std.textio.writeline(OUTPUT, L1);
 | 
      
         | 761 |  |  |         for j in NAHBIR to NAHBCFG-1 loop
 | 
      
         | 762 |  |  |           area := slvo(i).hconfig(j)(1 downto 0);
 | 
      
         | 763 |  |  |           mask := slvo(i).hconfig(j)(15 downto 4);
 | 
      
         | 764 |  |  |           if (mask /= "000000000000") then
 | 
      
         | 765 |  |  |             case area is
 | 
      
         | 766 |  |  |             when "01" =>
 | 
      
         | 767 |  |  |             when "10" =>
 | 
      
         | 768 |  |  |               k := 0;
 | 
      
         | 769 |  |  |               while (k<15) and (mask(k) = '0') loop k := k+1; end loop;
 | 
      
         | 770 |  |  |               std.textio.write(L1, "ahbctrl:       memory at " & tost( slvo(i).hconfig(j)(31 downto 20))&
 | 
      
         | 771 |  |  |                 "00000, size "& tost(2**k) & " Mbyte");
 | 
      
         | 772 |  |  |               if slvo(i).hconfig(j)(16) = '1' then
 | 
      
         | 773 |  |  |                 std.textio.write(L1, string'(", cacheable"));
 | 
      
         | 774 |  |  |               end if;
 | 
      
         | 775 |  |  |               if slvo(i).hconfig(j)(17) = '1' then
 | 
      
         | 776 |  |  |                 std.textio.write(L1, string'(", prefetch"));
 | 
      
         | 777 |  |  |                end if;
 | 
      
         | 778 |  |  |               std.textio.writeline(OUTPUT, L1);
 | 
      
         | 779 |  |  |             when "11" =>
 | 
      
         | 780 |  |  |               if ioen /= 0 then
 | 
      
         | 781 |  |  |                 k := 0;
 | 
      
         | 782 |  |  |                 while (k<15) and (mask(k) = '0') loop k := k+1; end loop;
 | 
      
         | 783 |  |  |                 iosize := 256 * 2**k; iounit(1) := ' ';
 | 
      
         | 784 |  |  |                 if (iosize > 1023) then
 | 
      
         | 785 |  |  |                   iosize := iosize/1024; iounit(1) := 'k';
 | 
      
         | 786 |  |  |                 end if;
 | 
      
         | 787 |  |  |                 print("ahbctrl:       I/O port at " & tost( iostart &
 | 
      
         | 788 |  |  |                   ((slvo(i).hconfig(j)(31 downto 20)) and slvo(i).hconfig(j)(15 downto 4))) &
 | 
      
         | 789 |  |  |                   "00, size "& tost(iosize) & iounit);
 | 
      
         | 790 |  |  |               end if;
 | 
      
         | 791 |  |  |             when others =>
 | 
      
         | 792 |  |  |             end case;
 | 
      
         | 793 |  |  |           end if;
 | 
      
         | 794 |  |  |         end loop;
 | 
      
         | 795 |  |  |         assert (slvo(i).hindex = i) or (icheck = 0)
 | 
      
         | 796 |  |  |         report "AHB slave index error on slave " & tost(i) severity failure;
 | 
      
         | 797 |  |  |       end if;
 | 
      
         | 798 |  |  |     end loop;
 | 
      
         | 799 |  |  |     wait;
 | 
      
         | 800 |  |  |   end process;
 | 
      
         | 801 |  |  |  
 | 
      
         | 802 |  |  | -- pragma translate_on
 | 
      
         | 803 |  |  |  
 | 
      
         | 804 |  |  | end;
 | 
      
         | 805 |  |  |  
 |