OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [grlib/] [amba/] [apbctrl.vhd] - Rev 2

Compare with Previous | Blame | View Log

------------------------------------------------------------------------------
--  This file is a part of the GRLIB VHDL IP LIBRARY
--  Copyright (C) 2003, 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.
--
--  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 
-----------------------------------------------------------------------------   
-- Entity:      apbctrl
-- File:        apbctrl.vhd
-- Author:      Jiri Gaisler - Gaisler Research
-- Description: AMBA AHB/APB bridge with plug&play support
------------------------------------------------------------------------------ 
 
library ieee;
use ieee.std_logic_1164.all;
library grlib;
use grlib.amba.all;
use grlib.stdlib.all;
-- pragma translate_off
use grlib.devices.all;
use std.textio.all;
-- pragma translate_on
 
entity apbctrl is
  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;
    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);
  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;
 
architecture rtl of apbctrl is
 
constant apbmax : integer := 19;
 
constant VERSION   : amba_version_type := 0;
 
constant hconfig : ahb_config_type := (
  0 => ahb_device_reg ( 1, 6, 0, VERSION, 0),
  4 => ahb_membar(haddr, '0', '0', hmask),
  others => zero32);
 
constant IOAREA : std_logic_vector(11 downto 0) := 
	conv_std_logic_vector(haddr, 12);
constant IOMSK  : std_logic_vector(11 downto 0) := 
	conv_std_logic_vector(hmask, 12);
 
type reg_type is record
  haddr   : std_logic_vector(apbmax downto 0);   -- address bus
  hwrite  : std_logic;  		     -- read/write
  hready  : std_logic;  		     -- ready
  penable : std_logic;
  psel    : std_logic;
  prdata  : std_logic_vector(31 downto 0);   -- read data
  pwdata  : std_logic_vector(31 downto 0);   -- write data
  state   : std_logic_vector(1 downto 0);   -- state
  cfgsel  : std_ulogic;
end record;
 
signal r, rin : reg_type;
--pragma translate_off
signal lapbi  : apb_slv_in_type;
--pragma translate_on
 
begin
  comb : process(ahbi, apbo, r, rst)
  variable v : reg_type;
  variable psel   : std_logic_vector(0 to 31);   
  variable pwdata : std_logic_vector(31 downto 0);
  variable apbaddr : std_logic_vector(apbmax downto 0);
  variable apbaddr2 : std_logic_vector(31 downto 0);
  variable hirq, pirq : std_logic_vector(NAHBIRQ-1 downto 0);
  variable nslave : integer range 0 to nslaves-1;
  variable bnslave : std_logic_vector(3 downto 0);
  begin
 
    v := r; v.psel := '0'; v.penable := '0'; psel := (others => '0');
    hirq := (others => '0');  pirq := (others => '0'); 
 
    -- detect start of cycle
    if (ahbi.hready = '1') then
      if ((ahbi.htrans = HTRANS_NONSEQ) or (ahbi.htrans = HTRANS_SEQ)) and
	  (ahbi.hsel(hindex) = '1')
      then
        v.hready := '0'; v.hwrite := ahbi.hwrite; 
	v.haddr(apbmax downto 0) := ahbi.haddr(apbmax downto 0); 
	v.state := "01"; v.psel := not ahbi.hwrite;
      end if;
    end if;
 
    case r.state is
    when "00" => null;		-- idle
    when "01" =>
      if r.hwrite = '0' then v.penable := '1'; 
      else v.pwdata := ahbi.hwdata; end if;
      v.psel := '1'; v.state := "10";
    when others =>
      if r.penable = '0' then v.psel := '1'; v.penable := '1'; end if;
      v.state := "00"; v.hready := '1';
    end case;
 
    psel := (others => '0');
 
    for i in 0 to nslaves-1 loop
      if ((apbo(i).pconfig(1)(1 downto 0) = "01") and
        ((apbo(i).pconfig(1)(31 downto 20) and apbo(i).pconfig(1)(15 downto 4)) = 
        (r.haddr(19 downto  8) and apbo(i).pconfig(1)(15 downto 4))))
      then psel(i) := '1'; end if;
    end loop;
 
    bnslave(0) := psel(1) or psel(3) or psel(5) or psel(7) or
                  psel(9) or psel(11) or psel(13) or psel(15);
    bnslave(1) := psel(2) or psel(3) or psel(6) or psel(7) or
                  psel(10) or psel(11) or psel(14) or psel(15);
    bnslave(2) := psel(4) or psel(5) or psel(6) or psel(7) or
                  psel(12) or psel(13) or psel(14) or psel(15);
    bnslave(3) := psel(8) or psel(9) or psel(10) or psel(11) or
                  psel(12) or psel(13) or psel(14) or psel(15);
    nslave := conv_integer(bnslave);
 
    if (r.haddr(19 downto  12) = "11111111") then 
     v.cfgsel := '1'; psel := (others => '0'); v.penable := '0';
    else v.cfgsel := '0'; end if;
 
    v.prdata := apbo(nslave).prdata;
 
    if r.cfgsel = '1' then
      v.prdata := apbo(conv_integer(r.haddr(log2x(nslaves)+2 downto 3))).pconfig(conv_integer(r.haddr(2 downto 2)));
    end if;
 
    for i in 0 to nslaves-1 loop pirq := pirq or apbo(i).pirq; end loop;
 
    -- AHB respons
    ahbo.hready <= r.hready;
    ahbo.hrdata <= r.prdata;
    ahbo.hirq   <= pirq;
 
    if rst = '0' then
      v.penable := '0'; v.hready := '1'; v.psel := '0'; v.state := "00";
      v.hwrite := '0';
-- pragma translate_off
      v.haddr := (others => '0');
-- pragma translate_on
    end if;
 
    rin <= v;
 
    -- drive APB bus
    apbaddr2 := (others => '0');
    apbaddr2(apbmax downto 0) := r.haddr(apbmax downto 0);
    apbi.paddr   <= apbaddr2;
    apbi.pwdata  <= r.pwdata;
    apbi.pwrite  <= r.hwrite;
    apbi.penable <= r.penable;
    apbi.pirq    <= ahbi.hirq;
    apbi.testen  <= ahbi.testen;
    apbi.testoen <= ahbi.testoen;
    apbi.scanen <= ahbi.scanen;
    apbi.testrst <= ahbi.testrst;
 
    for i in 0 to nslaves-1 loop apbi.psel(i) <= psel(i) and r.psel; end loop;
 
--pragma translate_off
    lapbi.paddr   <= apbaddr2;
    lapbi.pwdata  <= r.pwdata;
    lapbi.pwrite  <= r.hwrite;
    lapbi.penable <= r.penable;
    lapbi.pirq    <= ahbi.hirq;
 
    for i in 0 to nslaves-1 loop lapbi.psel(i) <= psel(i) and r.psel; end loop;
--pragma translate_on
 
  end process;
 
  ahbo.hindex <= hindex;
  ahbo.hconfig <= hconfig;
  ahbo.hcache <= '0';
  ahbo.hsplit <= (others => '0');
  ahbo.hresp  <= HRESP_OKAY;
 
  reg : process(clk)
  begin if rising_edge(clk) then r <= rin; end if; end process;
 
-- pragma translate_off
 
  mon0 : if enbusmon /= 0 generate
    mon :  apbmon 
      generic map(
        asserterr   => asserterr,
        assertwarn  => assertwarn,
        pslvdisable => pslvdisable,
        napb        => nslaves)
      port map(
        rst         => rst,
        clk         => clk,
        apbi        => lapbi,
        apbo        => apbo,
        err         => open);
  end generate;
 
  diag : process
  variable k : integer;
  variable mask : std_logic_vector(11 downto 0);
  variable device : std_logic_vector(11 downto 0);
  variable devicei : integer;
  variable vendor : std_logic_vector( 7 downto 0);
  variable vendori : integer;
  variable iosize : integer;
  variable iounit : string(1 to 5) := "byte ";
  variable memstart : std_logic_vector(11 downto 0) := IOAREA and IOMSK;
  variable L1 : line := new string'("");
  begin
    wait for 3 ns;
    if debug = 0 then wait; end if;
    print("apbctrl: APB Bridge at " & tost(memstart) & "00000 rev 1");
    if debug = 1 then wait; end if;
    for i in 0 to nslaves-1 loop
      vendor := apbo(i).pconfig(0)(31 downto 24); 
      vendori := conv_integer(vendor);
      if vendori /= 0 then
        device := apbo(i).pconfig(0)(23 downto 12); 
        devicei := conv_integer(device);
	std.textio.write(L1, "apbctrl: slv" & tost(i) & ": " & 
	iptable(vendori).vendordesc  & iptable(vendori).device_table(devicei));
	std.textio.writeline(OUTPUT, L1);
	mask := apbo(i).pconfig(1)(15 downto 4);
	k := 0;
        while (k<15) and (mask(k) = '0') loop k := k+1; end loop; 
	iosize := 256 * 2**k; iounit := "byte ";
	if (iosize > 1023) then iosize := iosize/1024; iounit := "kbyte"; end if;
	print("apbctrl:       I/O ports at " & 
          tost(memstart & (apbo(i).pconfig(1)(31 downto 20) and apbo(i).pconfig(1)(15 downto 4))) &
		"00, size " & tost(iosize) & " " & iounit);
	assert (apbo(i).pindex = i) or (icheck = 0)
	report "APB slave index error on slave " & tost(i) severity failure;
      end if;
    end loop;
    wait;
  end process;
-- pragma translate_on
 
end;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.