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

Subversion Repositories core_arm

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /core_arm/trunk/vhdl/bus
    from Rev 2 to Rev 4
    Reverse comparison

Rev 2 → Rev 4

/ahbarb.vhd
0,0 → 1,238
 
 
 
 
----------------------------------------------------------------------------
-- This file is a part of the LEON VHDL model
-- Copyright (C) 1999 European Space Agency (ESA)
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser 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.LGPL for the full details of the license.
 
 
-----------------------------------------------------------------------------
-- Entity: ahbarb
-- File: ahbarb.vhd
-- Author: Jiri Gaisler - Gaisler Research
-- Description: AMBA AHB arbiter and decoder
------------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.leon_target.all;
use work.leon_config.all;
use work.leon_iface.all;
use work.amba.all;
 
 
entity ahbarb is
generic (
masters : integer := 2; -- number of masters
defmast : integer := 0 -- default master
);
port (
rst : in std_logic;
clk : in clk_type;
msti : out ahb_mst_in_vector(0 to masters-1);
msto : in ahb_mst_out_vector(0 to masters-1);
slvi : out ahb_slv_in_vector(0 to AHB_SLV_MAX-1);
slvo : in ahb_slv_out_vector(0 to AHB_SLV_MAX)
);
end;
 
architecture rtl of ahbarb is
 
type reg_type is record
hmaster : integer range 0 to masters-1;
hmasterd : integer range 0 to masters-1;
hslave : integer range 0 to AHB_SLV_MAX;
hready : std_logic; -- needed for two-cycle error response
hlock : std_logic;
hmasterlock : std_logic;
htrans : std_logic_vector(1 downto 0); -- transfer type
end record;
 
constant ahbmin : integer := AHB_SLV_ADDR_MSB-1;
type nmstarr is array ( 1 to 5) of integer range 0 to masters-1;
type nvalarr is array ( 1 to 5) of boolean;
signal r, rin : reg_type;
signal rsplit, rsplitin : std_logic_vector(masters-1 downto 0);
 
begin
 
comb : process(rst, msto, slvo, r, rsplit)
variable rv : reg_type;
variable nhmaster, hmaster : integer range 0 to masters -1;
variable haddr : std_logic_vector(31 downto 0); -- address bus
variable hrdata : std_logic_vector(31 downto 0); -- read data bus
variable htrans : std_logic_vector(1 downto 0); -- transfer type
variable hresp : std_logic_vector(1 downto 0); -- respons type
variable hwrite : std_logic; -- read/write
variable hsize : std_logic_vector(2 downto 0); -- transfer size
variable hprot : std_logic_vector(3 downto 0); -- protection info
variable hburst : std_logic_vector(2 downto 0); -- burst type
variable hwdata : std_logic_vector(31 downto 0); -- write data
variable hgrant : std_logic_vector(0 to masters-1); -- bus grant
variable hsel : std_logic_vector(0 to AHB_SLV_MAX); -- slave select
variable hready : std_logic; -- ready
variable hmastlock : std_logic;
variable nslave : natural range 0 to AHB_SLV_MAX;
variable ahbaddr : std_logic_vector(ahbmin downto 0);
variable vsplit : std_logic_vector(masters-1 downto 0);
variable nmst : nmstarr;
variable nvalid : nvalarr;
variable htmp : std_logic_vector(3 downto 0);
begin
 
rv := r; rv.hready := '0';
 
-- bus multiplexers
 
haddr := msto(r.hmaster).haddr;
htrans := msto(r.hmaster).htrans;
hwrite := msto(r.hmaster).hwrite;
hsize := msto(r.hmaster).hsize;
hprot := msto(r.hmaster).hprot;
hburst := msto(r.hmaster).hburst;
hmastlock := msto(r.hmaster).hlock;
hwdata := msto(r.hmasterd).hwdata;
hready := slvo(r.hslave).hready;
hrdata := slvo(r.hslave).hrdata;
hresp := slvo(r.hslave).hresp ;
 
if r.hslave = AHB_SLV_MAX then
-- default slave
if (r.htrans = HTRANS_IDLE) or (r.htrans = HTRANS_BUSY) then
hresp := HRESP_OKAY; hready := '1';
else
-- return two-cycle error in case of unimplemented slave access
hresp := HRESP_ERROR; hready := r.hready; rv.hready := not r.hready;
end if;
end if;
 
 
-- Find next master:
-- * priority is fixed, highest index has highest priority
-- * splitted masters are not granted
-- * burst transfers cannot be interrupted
-- * low-priority masters will be granted if they drive SEQ or NONSEQ
-- on HTRANS, and high-priority masters only drive IDLE
 
nvalid(1 to 4) := (others => false); nvalid(5) := true;
nmst(1 to 4) := (others => 0); nmst(5) := defmast; nhmaster := r.hmaster;
 
if (r.hmasterlock = '0') and (
(msto(r.hmaster).htrans = HTRANS_IDLE) or
( (msto(r.hmaster).htrans = HTRANS_NONSEQ) and
(msto(r.hmaster).hburst = HBURST_SINGLE) ) ) then
for i in 0 to (masters -1) loop
if ((rsplit(i) = '0') or not AHB_SPLIT) then
if (msto(i).hbusreq = '1') and (msto(i).htrans(1) = '1') then
nmst(2) := i; nvalid(2) := true;
end if;
if (msto(i).hbusreq = '1') then
nmst(3) := i; nvalid(3) := true;
end if;
if not ((nmst(4) = defmast) and nvalid(4)) then
nmst(4) := i; nvalid(4) := true;
end if;
end if;
end loop;
for i in 1 to 5 loop
if nvalid(i) then nhmaster := nmst(i); exit; end if;
end loop;
end if;
 
rv.hlock := msto(nhmaster).hlock;
 
hgrant := (others => '0'); hgrant(nhmaster) := '1';
 
-- select slave
ahbaddr := haddr(31 downto (31 - ahbmin));
-- pragma translate_off
if not is_x(haddr(31 downto (31 - AHB_SLV_ADDR_MSB +1))) then
-- pragma translate_on
nslave := AHBSLVADDR(conv_integer(unsigned(haddr(31 downto (31 - AHB_SLV_ADDR_MSB +1)))));
-- pragma translate_off
end if;
-- pragma translate_on
 
-- if htrans = HTRANS_IDLE then nslave := AHB_SLV_MAX; end if;
 
hsel := (others => '0'); hsel(nslave) := '1';
 
-- latch active master and slave
if hready = '1' then
rv.hmaster := nhmaster; rv.hmasterd := r.hmaster;
rv.hslave := nslave; rv.htrans := htrans; rv.hmasterlock := r.hlock;
end if;
 
-- latch HLOCK
 
-- split support
vsplit := (others => '0');
if AHB_SPLIT then
vsplit := rsplit;
if hresp = HRESP_SPLIT then vsplit(r.hmasterd) := '1'; end if;
for i in AHBSLVSPLIT'range loop --'
if AHBSLVSPLIT(i) = 1 then
vsplit := vsplit and not slvo(i).hsplit(masters-1 downto 0);
end if;
end loop;
end if;
 
-- reset operation
if (rst = '0') then
rv.hmaster := 0; rv.hmasterlock := '0'; rv.hslave := AHB_SLV_MAX;
hsel := (others => '0'); rv.htrans := HTRANS_IDLE;
hready := '1'; vsplit := (others => '0');
end if;
-- drive master inputs
for i in 0 to (masters -1) loop
msti(i).hgrant <= hgrant(i);
msti(i).hready <= hready;
msti(i).hrdata <= hrdata;
msti(i).hresp <= hresp;
end loop;
 
-- drive slave inputs
for i in 0 to (AHB_SLV_MAX-1) loop
slvi(i).haddr <= haddr;
slvi(i).htrans <= htrans;
slvi(i).hwrite <= hwrite;
slvi(i).hsize <= hsize;
slvi(i).hburst <= hburst;
slvi(i).hready <= hready;
slvi(i).hwdata <= hwdata;
slvi(i).hprot <= hprot;
slvi(i).hsel <= hsel(i);
slvi(i).hmaster <= std_logic_vector(conv_unsigned(r.hmaster, 4));
slvi(i).hmastlock <= r.hmasterlock;
end loop;
 
-- assign register inputs
rin <= rv;
rsplitin <= vsplit;
 
end process;
 
 
reg0 : process(clk)
begin if rising_edge(clk) then r <= rin; end if; end process;
 
splitreg : if AHB_SPLIT generate
reg1 : process(clk)
begin if rising_edge(clk) then rsplit <= rsplitin; end if; end process;
end generate;
 
 
end;
 
/amba.vhd
0,0 → 1,264
--============================================================================--
-- Design unit : AMBA (Package declaration)
--
-- File name : amba.vhd
--
-- Purpose : This package declares types to be used with the
-- Advanced Microcontroller Bus Architecture (AMBA).
--
-- Reference : AMBA(TM) Specification (Rev 2.0), ARM IHI 0011A,
-- 13th May 1999, issue A, first release, ARM Limited
--
-- The document can be retrieved from http://www.arm.com
--
-- AMBA is a trademark of ARM Limited.
-- ARM is a registered trademark of ARM Limited.
--
-- Note : Naming convention according to AMBA(TM) Specification:
-- Signal names are in upper case, except for the following:
-- A lower case 'n' in the name indicates that the signal
-- is active low.
-- Constant names are in upper case.
--
-- The least significant bit of an array is located to the right,
-- carrying the index number zero.
--
-- Library : AMBA_Lib {recommended}
--
-- Author : European Space Agency (ESA)
-- P.O. Box 299
-- NL-2200 AG Noordwijk ZH
-- The Netherlands
--
-- Contact : mailto:microelectronics@estec.esa.int
-- http://www.estec.esa.int/microelectronics
--
-- Copyright (C): European Space Agency (ESA) 2000.
-- This source code is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2 of the License, or (at your option) any
-- later version. For full details of the license see file
-- http://www.estec.esa.int/microelectronics/core/copying.lgpl
--
-- It is recommended that any use of this VHDL source code is
-- reported to the European Space Agency. It is also recommended
-- that any use of the VHDL source code properly acknowledges the
-- European Space Agency as originator.
--
-- Disclaimer : All information is provided "as is", there is no warranty that
-- the information is correct or suitable for any purpose,
-- neither implicit nor explicit. This information does not
-- necessarily reflect the policy of the European Space Agency.
--------------------------------------------------------------------------------
-- Version Author Date Changes
--
-- 0.2 ESA 5 Jul 2000 Package created
-- 0.3 ESA 10 Jul 2000 Additional HREADY slave input,
-- Std_ULogic usage for non-array signals,
-- Additional comments on casing and addressing
-- 0.4 ESA 14 Jul 2000 HRESETn removed from AHB Slave input record
-- Additional comments on clocking and reset
-- Additional comments on AHB endianness
-- Additional comments on APB addressing
-- 0.5 ESA 30 Aug 2000 Vector types for AHB arbiter/decoder and
-- APB bridge refined and corresponding
-- record types removed
-- Name suffix 'x' removed
-- ESA 04 Feb 2002 Changed copyright text
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.Std_Logic_1164.all;
 
package AMBA is
-----------------------------------------------------------------------------
-- Definitions for AMBA(TM) Advanced High-performance Bus (AHB)
-----------------------------------------------------------------------------
-- Records are defined for the input and output of an AHB Master, as well as
-- for an AHB Slave. These records are grouped in arrays, for scalability,
-- and new records using these arrays are defined for the input and output of
-- an AHB Arbiter/Decoder.
--
-- The routing of the clock and reset signals defined in the AMBA(TM)
-- Specification is not covered in this package, since being dependent on
-- the clock and reset conventions defined at system level.
--
-- The HCLK and HRESETn signals are routed separately:
-- HCLK: Std_ULogic; -- rising edge
-- HRESETn: Std_ULogic; -- active low reset
--
-- The address bus HADDR contains byte addresses. The relation between the
-- byte address and the n-byte data bus HDATA can either be little-endian or
-- big-endian according to the AMBA(TM) Specification.
--
-- It is recommended that only big-endian modules are implemented using
-- this package.
--
-----------------------------------------------------------------------------
-- Constant definitions for AMBA(TM) AHB
-----------------------------------------------------------------------------
constant HDMAX: Positive range 32 to 1024 := 32; -- data width
constant HAMAX: Positive range 32 to 32 := 32; -- address width
 
-----------------------------------------------------------------------------
-- Definitions for AMBA(TM) AHB Masters
-----------------------------------------------------------------------------
-- AHB master inputs (HCLK and HRESETn routed separately)
type AHB_Mst_In_Type is
record
HGRANT: Std_ULogic; -- bus grant
HREADY: Std_ULogic; -- transfer done
HRESP: Std_Logic_Vector(1 downto 0); -- response type
HRDATA: Std_Logic_Vector(HDMAX-1 downto 0); -- read data bus
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(HAMAX-1 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(HDMAX-1 downto 0); -- write data bus
end record;
 
-----------------------------------------------------------------------------
-- Definitions for AMBA(TM) AHB Slaves
-----------------------------------------------------------------------------
-- AHB slave inputs (HCLK and HRESETn routed separately)
type AHB_Slv_In_Type is
record
HSEL: Std_ULogic; -- slave select
HADDR: Std_Logic_Vector(HAMAX-1 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(HDMAX-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
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(HDMAX-1 downto 0); -- read data bus
HSPLIT: Std_Logic_Vector(15 downto 0); -- split completion
end record;
 
-----------------------------------------------------------------------------
-- Definitions for AMBA(TM) AHB Arbiter/Decoder
-----------------------------------------------------------------------------
-- supporting array types
type AHB_Mst_In_Vector is array (Natural range <> ) of AHB_Mst_In_Type;
type AHB_Mst_Out_Vector is array (Natural range <> ) of AHB_Mst_Out_Type;
type AHB_Slv_In_Vector is array (Natural range <> ) of AHB_Slv_In_Type;
type AHB_Slv_Out_Vector is array (Natural range <> ) of AHB_Slv_Out_Type;
 
-----------------------------------------------------------------------------
-- Auxiliary constant definitions for AMBA(TM) AHB
-----------------------------------------------------------------------------
-- constants for HTRANS (transition type, slave output)
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";
 
-- constants for HBURST (burst type, master output)
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";
 
-- constants for HSIZE (transfer size, master output)
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";
 
-- constants for HRESP (response, slave output)
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";
 
-----------------------------------------------------------------------------
-- Definitions for AMBA(TM) Advanced Peripheral Bus (APB)
-----------------------------------------------------------------------------
-- Records are defined for the input and output of an APB Slave. These
-- records are grouped in arrays, for scalability, and new records using
-- these arrays are defined for the input and output of an APB Bridge.
--
-- The routing of the clock and reset signals defined in the AMBA(TM)
-- Specification is not covered in this package, since being dependent on
-- the clock and reset conventions defined at system level.
--
-- The PCLK and PRESETn signals are routed separately:
-- PCLK: Std_ULogic; -- rising edge
-- PRESETn: Std_ULogic; -- active low reset
--
-- The characteristics of the address bus PADDR are undefined in the
-- AMBA(TM) Specification.
--
-- When implementing modules with this package, it is recommended that the
-- information on the address bus PADDR is interpreted as byte addresses, but
-- it should only be used for 32-bit word addressing, i.e. the value of
-- address bits 0 and 1 should always be logical 0. For modules not
-- supporting full 32-bit words on the data bus PDATA, e.g. only supporting
-- 16-bit halfwords or 8-bit bytes, the addressing will still be word based.
-- Consequently, one halfword or byte will be accessed for each word address.
-- Modules only supporting byte sized data should exchange data on bit 7 to 0
-- on the PDATA data bus. Modules only supporting halfword sized data should
-- exchange data on bit 15 to 0 on the PDATA data bus. Modules supporting
-- word sized data should exchange data on bit 31 to 0 on the PDATA data bus.
--
-----------------------------------------------------------------------------
-- Constant definitions for AMBA(TM) APB
-----------------------------------------------------------------------------
constant PDMAX: Positive range 8 to 32 := 32; -- data width
constant PAMAX: Positive range 8 to 32 := 32; -- address width
 
-----------------------------------------------------------------------------
-- Definitions for AMBA(TM) APB Slaves
-----------------------------------------------------------------------------
-- APB slave inputs (PCLK and PRESETn routed separately)
type APB_Slv_In_Type is
record
PSEL: Std_ULogic; -- slave select
PENABLE: Std_ULogic; -- strobe
PADDR: Std_Logic_Vector(PAMAX-1 downto 0); -- address bus (byte)
PWRITE: Std_ULogic; -- write
PWDATA: Std_Logic_Vector(PDMAX-1 downto 0); -- write data bus
end record;
 
-- APB slave outputs
type APB_Slv_Out_Type is
record
PRDATA: Std_Logic_Vector(PDMAX-1 downto 0); -- read data bus
end record;
 
-----------------------------------------------------------------------------
-- Definitions for AMBA(TM) APB Bridge
-----------------------------------------------------------------------------
-- supporting array types
type APB_Slv_In_Vector is array (Natural range <> ) of APB_Slv_In_Type;
type APB_Slv_Out_Vector is array (Natural range <> ) of APB_Slv_Out_Type;
 
end AMBA; --==================================================================--
/c_model/ahbarb.c
0,0 → 1,51
#include <tmki.h>
#include "ahbarb.h"
 
ahbarb *ahbarb_create() {
ahbarb *m;
m = (ahbarb *) ti_alloc(sizeof(ahbarb));
if (!m) { return 0; }
ti_print_err("\
Create ahbarb model (0x%x):\n\
Max slaves : %i\n\n",
m,AHBARB_MAXSLAVE);
return m;
}
 
ahbarb *ahbarb_add(ahbarb *m,ahb_write w,ahb_read r, unsigned int start, unsigned int end) {
int i;
for (i = 0;i < AHBARB_MAXSLAVE;i++) {
if (m ->slaves[i].start == 0 &&
m ->slaves[i].end == 0) {
m ->slaves[i].start = start;
m ->slaves[i].end = end;
m ->slaves[i].read = r;
m ->slaves[i].write = w;
}
}
}
 
int ahbarb_read(ahbarb *m,unsigned int addr, unsigned int *data) {
int i;
for (i = 0;i < AHBARB_MAXSLAVE;i++) {
if (m ->slaves[i].start <= addr &&
m ->slaves[i].end > addr) {
return m ->slaves[i].read(addr,data);
}
}
return 0;
}
 
int ahbarb_write(ahbarb *m,unsigned int addr, unsigned int data) {
int i;
for (i = 0;i < AHBARB_MAXSLAVE;i++) {
if (m ->slaves[i].start <= addr &&
m ->slaves[i].end > addr) {
return m ->slaves[i].write(addr,data);
}
}
return 0;
}
/c_model/ahbarb.h
0,0 → 1,24
#ifndef AHBARB_H
#define AHBARB_H
 
#define AHBARB_MAXMASTER 2
#define AHBARB_MAXSLAVE 2
 
 
typedef int (* ahb_write)();
typedef int (* ahb_read)();
 
typedef struct _ahb_slave {
ahb_write write;
ahb_read read;
unsigned int start, end;
void *c;
} ahb_slave;
 
typedef struct _ahbarb {
ahb_slave slaves[AHBARB_MAXSLAVE];
} ahbarb;
 
 
#endif
/c_model/apbmst.c
0,0 → 1,51
#include <tmki.h>
#include "apbmst.h"
 
apbmst *apbmst_create() {
apbmst *m;
m = (apbmst *) ti_alloc(sizeof(apbmst));
if (!m) { return 0; }
ti_print_err("\
Create apbmst model (0x%x):\n\
Max peripherals : %i\n\n",
m,APBMST_MAXSLAVE);
return m;
}
 
void apbmst_add(apbmst *m,apb_write w,apb_read r, unsigned int start, unsigned int end) {
int i;
for (i = 0;i < APBMST_MAXSLAVE;i++) {
if (m ->slaves[i].start == 0 &&
m ->slaves[i].end == 0) {
m ->slaves[i].start = start;
m ->slaves[i].end = end;
m ->slaves[i].read = r;
m ->slaves[i].write = w;
}
}
}
 
int apbmst_read(apbmst *m,unsigned int addr, unsigned int *data) {
int i;
for (i = 0;i < APBMST_MAXSLAVE;i++) {
if (m ->slaves[i].start <= addr &&
m ->slaves[i].end > addr) {
return m ->slaves[i].read(addr,data);
}
}
return 0;
}
 
int apbmst_write(apbmst *m,unsigned int addr, unsigned int data) {
int i;
for (i = 0;i < APBMST_MAXSLAVE;i++) {
if (m ->slaves[i].start <= addr &&
m ->slaves[i].end > addr) {
return m ->slaves[i].write(addr,data);
}
}
return 0;
}
/c_model/apbmst.h
0,0 → 1,22
#ifndef APBMST_H
#define APBMST_H
 
#define APBMST_MAXSLAVE 2
 
 
typedef int (* apb_write)();
typedef int (* apb_read)();
 
typedef struct _apb_slave {
apb_write write;
apb_read read;
unsigned int start, end;
void *c;
} apb_slave;
 
typedef struct _apbmst {
apb_slave slaves[APBMST_MAXSLAVE];
} apbmst;
 
#endif
/c_model/Makefile
0,0 → 1,10
targets = amba
 
amba_target = amba.a
amba_files = ahbarb.o apbmst.o
amba_hostcompile =
amba_subdirs =
 
LOCAL_CFLAGS += -I $(TOPDIR)/soft/sim/ti
 
 
/apbmst.vhd
0,0 → 1,191
 
 
 
 
----------------------------------------------------------------------------
-- This file is a part of the LEON VHDL model
-- Copyright (C) 1999 European Space Agency (ESA)
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser 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.LGPL for the full details of the license.
 
 
-----------------------------------------------------------------------------
-- Entity: apbmst
-- File: apbmst.vhd
-- Author: Jiri Gaisler - ESA/ESTEC
-- Description: AMBA AHB/APB bridge
------------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.leon_target.all;
use work.leon_config.all;
use work.leon_iface.all;
use work.amba.all;
 
 
entity apbmst is
port (
rst : in std_logic;
clk : in std_logic;
ahbi : in ahb_slv_in_type;
ahbo : out ahb_slv_out_type;
apbi : out apb_slv_in_vector(0 to APB_SLV_MAX-1);
apbo : in apb_slv_out_vector(0 to APB_SLV_MAX-1)
);
end;
 
architecture rtl of apbmst is
 
-- registers
type reg_type is record
haddr : std_logic_vector(APB_SLV_ADDR_BITS -1 downto 2); -- address bus
hsel : std_logic;
hwrite : std_logic; -- read/write
hready : std_logic; -- ready
hready2 : std_logic; -- ready
penable : std_logic;
end record;
 
signal r, rin : reg_type;
 
constant apbmax : integer := APB_SLV_ADDR_BITS -1;
begin
comb : process(ahbi, apbo, r, rst)
variable v : reg_type;
variable psel : std_logic_vector(0 to APB_SLV_MAX-1);
variable prdata : std_logic_vector(31 downto 0);
variable pwdata : std_logic_vector(31 downto 0);
variable apbaddr : std_logic_vector(apbmax downto 2);
variable apbaddr2 : std_logic_vector(31 downto 0);
variable bindex : integer range 0 to APB_SLV_MAX-1;
variable esel : std_logic;
begin
 
v := r; v.hready2 := '1';
 
-- detect start of cycle
if (ahbi.hready = '1') then
if ((ahbi.htrans = HTRANS_NONSEQ) or (ahbi.htrans = HTRANS_SEQ)) and
(ahbi.hsel = '1')
then
v.hready := '0'; v.hwrite := ahbi.hwrite; v.hsel := '1';
v.hwrite := ahbi.hwrite; v.hready2 := not ahbi.hwrite;
v.haddr(apbmax downto 2) := ahbi.haddr(apbmax downto 2);
else v.hsel := '0'; end if;
end if;
 
-- generate hready and penable
if (r.hsel and r.hready2 and (not r.hready)) = '1' then
v.penable := '1'; v.hready := '1';
else v.penable := '0'; end if;
 
-- generate psel and select APB read data
psel := (others => '0'); prdata := (others => '-');
apbaddr := r.haddr(apbmax downto 2);
bindex := 0; esel := '0';
 
case apbaddr is
-- memory controller, 0x00 - 0x08
when "00000000" | "00000001" | "00000010" =>
esel := '1'; bindex := 0;
-- AHB status reg., 0x0C - 0x10
when "00000011" | "00000100" =>
esel := '1'; bindex := 1;
-- cache controller, 0x14 - 0x18
when "00000101" | "00000110" =>
esel := '1'; bindex := 2;
-- write protection, 0x1C - 0x20
when "00000111" | "00001000" =>
if WPROTEN then esel := '1'; bindex := 3; end if;
-- config register, 0x24 - 0x24
when "00001001" =>
if CFGREG then esel := '1'; bindex := 4; end if;
-- timers, 0x40 - 0x6C
when "00010000" | "00010001" | "00010010" | "00010011" |
"00010100" | "00010101" | "00010110" | "00010111" |
"00011000" | "00011001" | "00011010" | "00011011" =>
esel := '1'; bindex := 5;
-- uart1, 0x70 - 0x7C
when "00011100" | "00011101" | "00011110" | "00011111" =>
esel := '1'; bindex := 6;
-- uart2, 0x80 - 0x8C
when "00100000" | "00100001" | "00100010" | "00100011" =>
esel := '1'; bindex := 7;
-- interrupt ctrl 0x90 - 0x9C
when "00100100" | "00100101" | "00100110" | "00100111" =>
esel := '1'; bindex := 8;
-- I/O port 0xA0 - 0xAC
when "00101000" | "00101001" | "00101010" | "00101011" =>
esel := '1'; bindex := 9;
-- 2nd interrupt ctrl 0xB0 - 0xBC
when "00101100" | "00101101" | "00101110" | "00101111" =>
if IRQ2EN then esel := '1'; bindex := 10; end if;
-- DSU uart 0xC0 - 0xCC
when "00110000" | "00110001" | "00110010" | "00110011" =>
if DEBUG_UNIT then esel := '1'; bindex := 11; end if;
when others =>
if PCIEN and ( r.haddr(apbmax downto apbmax-1) = "01") then
esel := '1'; bindex := 12;
end if;
if PCIARBEN and ( r.haddr(apbmax downto apbmax-1) = "10") then
esel := '1'; bindex := 13;
end if;
end case;
 
prdata := apbo(bindex).prdata; psel(bindex) := esel;
-- for i in APB_TABLE'range loop --'
-- if APB_TABLE(i).enable and
-- (apbaddr >= APB_TABLE(i).firstaddr(apbmax downto 2)) and
-- (apbaddr <= APB_TABLE(i).lastaddr(apbmax downto 2))
-- then
-- prdata := apbo(APB_TABLE(i).index).prdata;
-- psel(APB_TABLE(i).index) := '1';
-- end if;
-- end loop;
 
-- AHB respons
ahbo.hresp <= HRESP_OKAY;
ahbo.hready <= r.hready;
ahbo.hrdata <= prdata;
ahbo.hsplit <= (others => '0');
 
if rst = '0' then
v.penable := '0'; v.hready := '1'; v.hsel := '0';
-- pragma translate_off
v.haddr := (others => '0');
-- pragma translate_on
end if;
 
rin <= v;
 
-- tie write data to zero if not used to save power (not testable)
if r.hsel = '1' then pwdata := ahbi.hwdata;
else pwdata := (others => '0'); end if;
 
-- drive APB bus
apbaddr2 := (others => '0');
apbaddr2(apbmax downto 2) := r.haddr(apbmax downto 2);
for i in 0 to APB_SLV_MAX-1 loop
apbi(i).paddr <= apbaddr2;
apbi(i).pwdata <= pwdata;
apbi(i).pwrite <= r.hwrite;
apbi(i).penable <= r.penable;
apbi(i).psel <= psel(i) and r.hsel and r.hready2;
end loop;
 
end process;
 
 
reg : process(clk)
begin if rising_edge(clk) then r <= rin; end if; end process;
 
 
end;
 
/bus_comp.vhd
0,0 → 1,86
-- $(lic)
-- $(help_generic)
-- $(help_local)
 
library IEEE;
use IEEE.std_logic_1164.all;
use work.leon_target.all;
use work.amba.all;
use work.memdef.all;
 
package bus_comp is
 
type ahbmst_mp_in is record
req : std_logic;
address : std_logic_vector(31 downto 0);
data : std_logic_vector(31 downto 0);
size : lmd_memsize;
burst : std_logic;
read : std_logic;
lock : std_logic;
end record;
type ahbmst_mp_in_a is array (natural range <>) of ahbmst_mp_in;
 
type ahbmst_mp_out is record
data : std_logic_vector(31 downto 0); -- memory data
ready : std_logic; -- cycle ready
grant : std_logic; --
retry : std_logic; --
mexc : std_logic; -- memory exception
cache : std_logic; -- cacheable data
end record;
type ahbmst_mp_out_a is array (natural range <>) of ahbmst_mp_out;
 
component ahbmst_mp
generic ( AHBMST_PORTS : integer := 4 );
port (
rst : in std_logic;
clk : in std_logic;
i : in ahbmst_mp_in_a(AHBMST_PORTS-1 downto 0);
o : out ahbmst_mp_out_a(AHBMST_PORTS-1 downto 0);
ahbi : in ahb_mst_in_type;
ahbo : out ahb_mst_out_type
);
end component;
 
component ahbarb
generic (
masters : integer := 2; -- number of masters
defmast : integer := 0 -- default master
);
port (
rst : in std_logic;
clk : in std_logic;
msti : out ahb_mst_in_vector(0 to masters-1);
msto : in ahb_mst_out_vector(0 to masters-1);
slvi : out ahb_slv_in_vector(0 to AHB_SLV_MAX-1);
slvo : in ahb_slv_out_vector(0 to AHB_SLV_MAX)
);
end component;
 
component apbmst
port (
rst : in std_logic;
clk : in std_logic;
ahbi : in ahb_slv_in_type;
ahbo : out ahb_slv_out_type;
apbi : out apb_slv_in_vector(0 to APB_SLV_MAX-1);
apbo : in apb_slv_out_vector(0 to APB_SLV_MAX-1)
);
end component;
 
end bus_comp;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/ahbmst_mp.vhd
0,0 → 1,245
-- $(lic)
-- $(help_generic)
-- $(help_local)
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned."+";
use IEEE.std_logic_arith.conv_unsigned;
use work.amba.all;
use work.memdef.all;
use work.int.all;
use work.bus_comp.all;
 
entity ahbmst_mp is
generic ( AHBMST_PORTS : integer := 4 );
port (
rst : in std_logic;
clk : in std_logic;
i : in ahbmst_mp_in_a(AHBMST_PORTS-1 downto 0);
o : out ahbmst_mp_out_a(AHBMST_PORTS-1 downto 0);
ahbi : in ahb_mst_in_type;
ahbo : out ahb_mst_out_type
);
end;
 
architecture rtl of ahbmst_mp is
 
constant AHBMST_PORTS_BITSZ : integer := lin_log2x(AHBMST_PORTS);
constant NBO_ZERO : std_logic_vector(AHBMST_PORTS-1 downto 0) := (others => '0');
type ahbmst_mp_tmp_type is record
ahbo : ahb_mst_out_type;
bo_i,nbo_i : integer;
o_ready, o_grant, o_mexc : std_logic_vector(AHBMST_PORTS-1 downto 0);
o_retry, o_cache, hold, nboreq : std_logic_vector(AHBMST_PORTS-1 downto 0);
nbo : std_logic_vector(AHBMST_PORTS_BITSZ-1 downto 0);
num : std_logic_vector(AHBMST_PORTS_BITSZ-1 downto 0);
end record;
type ahbmst_mp_reg_type is record
retry, cache : std_logic;
bo : std_logic_vector(AHBMST_PORTS_BITSZ-1 downto 0);
ba, bg : std_logic;
end record;
type ahbmst_mp_dbg_type is record
dummy : std_logic;
-- pragma translate_off
dbg : ahbmst_mp_tmp_type;
-- pragma translate_on
end record;
signal r, c : ahbmst_mp_reg_type;
signal rdbg, cdbg : ahbmst_mp_dbg_type;
 
begin
p0 : process(ahbi, r, rst, i)
variable v : ahbmst_mp_reg_type;
variable t : ahbmst_mp_tmp_type;
variable vdbg : ahbmst_mp_dbg_type;
begin
 
-- $(init(t:ahbmst_mp_tmp_type))
 
v := r;
 
t.o_ready := (others => '0');
t.o_grant := (others => '0');
t.o_retry := (others => '0');
t.o_cache := (others => '0');
t.o_mexc := (others => '0');
 
-- owner hold
t.num := (others => '0');
t.hold := (others => '0');
for j in AHBMST_PORTS-1 downto 0 loop
t.num := std_logic_vector(conv_unsigned(j, AHBMST_PORTS_BITSZ));
if (r.ba = '1') and
(i(j).req = '1') and
(r.bo = t.num) then
t.hold(j) := '1';
end if;
end loop; -- i
-- next bus owner req
for k in AHBMST_PORTS-1 downto 0 loop
t.nboreq(k) := i(k).req;
for j in AHBMST_PORTS-1 downto 0 loop
if k /= j then
if t.hold(j) = '1' then
t.nboreq(k) := '0';
end if;
end if;
end loop;
end loop;
 
-- priority
t.nbo_i := 0;
l1: for j in AHBMST_PORTS-1 downto 0 loop
if t.nboreq(j) = '1' then
t.nbo_i := j;
exit l1;
end if;
end loop;
 
-- lock (only per ahb)
t.ahbo.hlock := '0';
for j in AHBMST_PORTS-1 downto 0 loop
if i(j).lock = '1' then
t.ahbo.hlock := '1';
end if;
end loop;
-- ahb signals
t.ahbo.hbusreq := '0';
t.ahbo.htrans := HTRANS_IDLE;
t.ahbo.haddr := i(0).address;
if not (t.nboreq = NBO_ZERO) then
t.nbo := std_logic_vector(conv_unsigned(t.nbo_i, AHBMST_PORTS_BITSZ));
t.ahbo.hbusreq := i(t.nbo_i).req;
t.ahbo.haddr := i(t.nbo_i).address;
t.ahbo.htrans := HTRANS_NONSEQ;
t.ahbo.hwrite := not i(t.nbo_i).read;
t.ahbo.hsize := lmd_toamba(i(t.nbo_i).size);
t.ahbo.hburst := HBURST_SINGLE;
if i(t.nbo_i).burst = '1' then
t.ahbo.hburst := HBURST_INCR;
end if;
 
-- burst
if (r.bo = t.nbo) then
if (i(t.nbo_i).req = '1') and (r.ba = '1') then
if ((not r.retry) = '1') then
if i(t.nbo_i).burst = '1' then
t.ahbo.htrans := HTRANS_SEQ;
-- todo: 1k boundary check
t.ahbo.hburst := HBURST_INCR;
end if;
end if;
end if;
end if;
-- grant
if (r.bg = '1') then
if (ahbi.hready = '1') and (i(t.nbo_i).req = '1') then
if ((not r.retry) = '1') then
t.o_grant(t.nbo_i) := '1';
end if;
end if;
end if;
end if;
 
-- retry
v.retry := '0';
if (r.ba = '1') and
((ahbi.hresp = HRESP_RETRY) or
(ahbi.hresp = HRESP_SPLIT))
then
v.retry := not ahbi.hready;
end if;
if r.retry = '1' then
t.ahbo.htrans := HTRANS_IDLE;
end if;
 
-- ahb return
t.bo_i := lin_convint(r.bo);
t.ahbo.hwdata := i(t.bo_i).data;
if r.ba = '1' then
t.o_cache(t.bo_i) := r.cache;
if ahbi.hready = '1' then
case ahbi.hresp is
when HRESP_OKAY => t.o_ready(t.bo_i) := '1';
when HRESP_RETRY | HRESP_SPLIT=> t.o_retry(t.bo_i) := '1';
when others => t.o_ready(t.bo_i) := '1'; t.o_mexc(t.bo_i) := '1';
end case;
end if;
end if;
 
-- next
if ahbi.hready = '1' then
v.bo := t.nbo;
v.bg := ahbi.hgrant;
v.ba := '0';
if (t.ahbo.htrans = HTRANS_NONSEQ) or (t.ahbo.htrans = HTRANS_SEQ) then
v.ba := r.bg;
end if;
end if;
-- reset
if rst = '0' then
v.retry := '0';
v.cache := '0';
v.bo := (others => '0');
v.ba := '0';
v.bg := '0';
end if;
c <= v;
 
for i in AHBMST_PORTS-1 downto 0 loop
o(i).grant <= t.o_grant(i);
o(i).ready <= t.o_ready(i);
o(i).mexc <= t.o_mexc(i);
o(i).retry <= t.o_retry(i);
o(i).data <= ahbi.hrdata;
end loop;
ahbo <= t.ahbo;
-- pragma translate_off
vdbg := rdbg;
vdbg.dbg := t;
cdbg <= vdbg;
-- pragma translate_on end process p0;
 
end process p0;
 
 
pregs : process (clk, c)
begin
if rising_edge(clk) then
r <= c;
-- pragma translate_off
rdbg <= cdbg;
-- pragma translate_on
end if;
end process;
 
 
end;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/config.in
0,0 → 1,12
 
 
mainmenu_option next_comment
comment 'Amba bus '
 
int 'Default AHB master' CONFIG_AHB_DEFMST 0
bool 'AHB split-transaction support ' CONFIG_AHB_SPLIT
 
bool 'AHB status register ' CONFIG_PERI_AHBSTAT
endmenu

powered by: WebSVN 2.1.0

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