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 |
|