##// END OF EJS Templates
temp
temp

File last commit:

r100:fc97c34d69e3 martin
r249:279a122aaba5 JC
Show More
amba_tp.vhd
1684 lines | 70.7 KiB | text/x-vhdl | VhdlLexer
------------------------------------------------------------------------------
-- This file is a part of the GRLIB VHDL IP LIBRARY
-- Copyright (C) 2003 - 2008, Gaisler Research
-- Copyright (C) 2008 - 2010, Aeroflex Gaisler
--
-- 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
--============================================================================--
-- Design unit : AMBA_TestPackage (Package and body declarations)
--
-- File name : amba_tp.vhd
--
-- Purpose : AMBA AHB and APB interface access procedures
--
-- Library : {independent}
--
-- Authors : Aeroflex Gaisler AB
--
-- Contact : mailto:support@gaisler.com
-- http://www.aeroflex.com/gaisler
--
-- 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.
--------------------------------------------------------------------------------
-- Version Author Date Changes
-- 0.1 SH 15 Mar 2002 New package
-- 0.2 SH 17 Mar 2003 Updated most packages
-- 0.3 SH 20 May 2003 Memory based on Integer elements
-- 0.4 SH 1 Jul 2003 Name of package changed
-- Compare function improved
-- AHB 32 bit memory with preload added
-- AHB initialisation added
-- 0.5 SH 21 Jul 2003 AHB 32 memory with diagnostics added
-- 0.6 SH 1 Nov 2003 APB read access data sample made earlier
-- AHB 32 memory extended with byte/halfword
-- 0.7 SH 25 Jan 2004 AHB read access data output corrected
-- AHB 32 memory allows overlay addressing
-- 1.7 SH 1 Oct 2004 Ported to GRLIB
-- 1.8 SH 1 Jul 2005 Added configuration support for memories
-- Modified all procedure declarations
-- 1.9 SH 10 Nov 2005 AHB 32 responds with HREADY=0 when error
-- 1.11 SH 27 Dec 2004 Split support added, using HSPLIT element
-- Proper two-cycle error response implemented
-- 1.12 SH 15 Feb 2006 Added bank select to AHB bus accesses
-- 1.13 SH 1 May 2009 AHBQuite gave incorrect TP on error resps.
--------------------------------------------------------------------------------
library Std;
use Std.Standard.all;
use Std.TextIO.all;
library IEEE;
use IEEE.Std_Logic_1164.all;
library GRLIB;
use GRLIB.AMBA.all;
use GRLIB.StdLib.all;
use GRLIB.StdIO.all;
package AMBA_TestPackage is
-----------------------------------------------------------------------------
-- AMBA APB write access
-----------------------------------------------------------------------------
procedure APBInit(
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
constant InstancePath: in String := "APBInit";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := True);
-----------------------------------------------------------------------------
-- AMBA APB write access
-----------------------------------------------------------------------------
procedure APBWrite(
constant Address: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBWrite";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- AMBA APB read access
-----------------------------------------------------------------------------
procedure APBQuiet(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBQuiet";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- AMBA APB read access
-----------------------------------------------------------------------------
procedure APBRead(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBRead";
constant ScreenOutput: in Boolean := True;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- AMBA APB read access
-----------------------------------------------------------------------------
procedure APBComp(
constant Address: in Std_Logic_Vector(31 downto 0);
constant CxData: in Std_Logic_Vector(31 downto 0);
variable RxData: out Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBComp";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- Initialise AMBA AHB interface
-----------------------------------------------------------------------------
procedure AHBInit(
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
constant InstancePath: in String := "AHBInit";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := True);
-----------------------------------------------------------------------------
-- AMBA AHB write access
-----------------------------------------------------------------------------
procedure AHBWriteQuiet(
constant Address: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBWrite";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- AMBA AHB write access
-----------------------------------------------------------------------------
procedure AHBWrite(
constant Address: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBWrite";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- AMBA AHB read access
-----------------------------------------------------------------------------
procedure AHBQuiet(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBQuiet";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- AMBA AHB read access
-----------------------------------------------------------------------------
procedure AHBRead(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBRead";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- AMBA AHB read access
-----------------------------------------------------------------------------
procedure AHBComp(
constant Address: in Std_Logic_Vector(31 downto 0);
constant CxData: in Std_Logic_Vector(31 downto 0);
variable RxData: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBComp";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0);
-----------------------------------------------------------------------------
-- Diagnstics types for behavioural model of memory with AHB interface
-----------------------------------------------------------------------------
type AHB_Diagnostics_In_Type is
record
HADDR: Std_Logic_Vector(31 downto 0);
HWRITE: Std_ULogic;
HWDATA: Std_Logic_Vector(31 downto 0);
HRESP: Std_Logic_Vector(1 downto 0); -- response type
HSPLIT: Std_Logic_Vector(15 downto 0); -- split completion
end record AHB_Diagnostics_In_Type;
type AHB_Diagnostics_Out_Type is
record
HRDATA: Std_Logic_Vector(31 downto 0);
end record AHB_Diagnostics_Out_Type;
constant AHB_Diagnostics_Init: AHB_Diagnostics_In_Type :=
(X"00000000", '0', X"00000000", HRESP_OKAY, X"0000");
-----------------------------------------------------------------------------
-- Behavioural model of memory with AHB interface, no wait states
-----------------------------------------------------------------------------
procedure AHBMemory(
constant gAWidth: in Positive := 15; -- address width
constant gDWidth: in Positive := 8; -- data width
signal HCLK: in Std_ULogic;
signal HRESETn: in Std_ULogic;
signal AHBIn: in AHB_Slv_In_Type;
signal AHBOut: out AHB_Slv_Out_Type;
constant InstancePath: in String := "AHBMemory";
constant ScreenOutput: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HADDR: in Integer := 0;
constant HMASK: in Integer := 16#FFF#);
-----------------------------------------------------------------------------
-- Behavioural model of memory with AMBA AHB interface, no wait states
-----------------------------------------------------------------------------
procedure AHBMemory32(
constant gAWidth: in Positive := 18; -- address width
signal HCLK: in Std_ULogic;
signal HRESETn: in Std_ULogic;
signal AHBIn: in AHB_Slv_In_Type;
signal AHBOut: out AHB_Slv_Out_Type;
constant InstancePath: in String := "AHBMemory32";
constant ScreenOutput: in Boolean := False;
constant FileName: in String := ""; -- file name
constant HINDEX: in Integer := 0;
constant HADDR: in Integer := 0;
constant HMASK: in Integer := 16#FFF#);
-----------------------------------------------------------------------------
-- Behavioural model of memory with AHB interface, no wait states
-- Supporting byte, halfword and word read/write accesses.
-- Provices diagnostic support.
-----------------------------------------------------------------------------
procedure AHBMemory32(
constant gAWidth: in Positive := 18; -- address width
signal HCLK: in Std_ULogic;
signal HRESETn: in Std_ULogic;
signal AHBIn: in AHB_Slv_In_Type;
signal AHBOut: out AHB_Slv_Out_Type;
signal AHBInDiag: in AHB_Diagnostics_In_Type;
signal AHBOutDiag: out AHB_Diagnostics_Out_Type;
constant InstancePath: in String := "AHBMemory32";
constant ScreenOutput: in Boolean := False;
constant FileName: in String := ""; -- file name
constant HINDEX: in Integer := 0;
constant HADDR: in Integer := 0;
constant HMASK: in Integer := 16#FFF#);
-----------------------------------------------------------------------------
-- Routine for writig data directly to AHB memory
-----------------------------------------------------------------------------
procedure WrAHBMem32(
constant Addr: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False);
-----------------------------------------------------------------------------
-- Routine for reading data directly from AHB memory
-----------------------------------------------------------------------------
procedure RdAHBMem32(
constant Addr: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False);
-----------------------------------------------------------------------------
-- Routine for reading data directly from AHB memory
-----------------------------------------------------------------------------
procedure RcAHBMem32(
constant Addr: in Std_Logic_Vector(31 downto 0);
constant Expected: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False);
-----------------------------------------------------------------------------
-- Routine for generating a split ack from AHB memory
-----------------------------------------------------------------------------
procedure SplitAHBMem32(
constant Split: in Integer range 0 to 15;
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False);
end AMBA_TestPackage;
--============================================================================--
package body AMBA_TestPackage is
-----------------------------------------------------------------------------
-- Compare function handling '-'
-----------------------------------------------------------------------------
function Compare(O, C: in Std_Logic_Vector) return Boolean is
variable T: Std_Logic_Vector(O'Range) := C;
variable Result: Boolean;
begin
Result := True;
for i in O'Range loop
if not (O(i)=T(i) or T(i)='-' or T(i)='U') then
Result := False;
end if;
end loop;
return Result;
end function Compare;
-----------------------------------------------------------------------------
-- Synchronisation with respect to clock and with output offset
-----------------------------------------------------------------------------
procedure Synchronise(
signal Clk: in Std_ULogic;
constant Offset: in Time := 5 ns) is
begin
wait until CLK = '1'; -- Synchronise
wait for Offset; -- output offset delay
end procedure Synchronise;
-----------------------------------------------------------------------------
-- AMBA APB write access
-----------------------------------------------------------------------------
procedure APBInit(
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
constant InstancePath: in String := "APBInit";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := True) is
variable L: Line;
begin
if cBack2Back then
Synchronise(PCLK);
end if;
APBIn.PSEL <= (others => '0');
APBIn.PENABLE <= '0';
APBIn.PADDR <= (others => '0');
APBIn.PWRITE <= '0';
APBIn.PWDATA <= (others => '0');
if ScreenOutput then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : APB initalised"));
WriteLine(Output, L);
end if;
end procedure APBInit;
-----------------------------------------------------------------------------
-- AMBA APB write access
-----------------------------------------------------------------------------
procedure APBWrite(
constant Address: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBWrite";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0) is
variable L: Line;
begin
-- do not Synchronise when a back-to-back access is requested
if not cBack2Back then
Synchronise(PCLK);
end if;
APBIn.PSEL <= (others => '0');
APBIn.PSEL(PINDEX) <= '1'; -- first clock period
APBIn.PENABLE <= '0';
APBIn.PADDR <= Address;
APBIn.PWRITE <= '1';
APBIn.PWDATA <= Data;
Synchronise(PCLK); -- second clock period
APBIn.PENABLE <= '1';
if ScreenOutput then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : APB write access, address: "));
HWrite(L, Address);
Write (L, String'(" : data: "));
HWrite(L, Data);
WriteLine(Output, L);
end if;
Synchronise(PCLK); -- end of access
APBIn.PSEL <= (others => '0');
APBIn.PENABLE <= '0';
APBIn.PADDR <= (others => '-');
APBIn.PWRITE <= '0';
APBIn.PWDATA <= (others => '-');
end procedure APBWrite;
-----------------------------------------------------------------------------
-- AMBA APB read access
-----------------------------------------------------------------------------
procedure APBQuiet(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBQuiet";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0) is
begin
-- do not Synchronise when a back-to-back access is requested
if not cBack2Back then
Synchronise(PCLK);
end if;
APBIn.PSEL <= (others => '0');
APBIn.PSEL(PINDEX) <= '1'; -- first clock period
APBIn.PENABLE <= '0';
APBIn.PADDR <= Address;
APBIn.PWRITE <= '0';
APBIn.PWDATA <= (others => '-');
Synchronise(PCLK); -- second clock period
APBIn.PENABLE <= '1';
wait for 5 ns;
Data := APBOut.PRDATA;
Synchronise(PCLK); -- end of access
APBIn.PSEL <= (others => '0');
APBIn.PENABLE <= '0';
APBIn.PADDR <= (others => '-');
end procedure APBQuiet;
-----------------------------------------------------------------------------
-- AMBA APB read access
-----------------------------------------------------------------------------
procedure APBRead(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBRead";
constant ScreenOutput: in Boolean := True;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0) is
variable L: Line;
variable Temp: Std_Logic_Vector(31 downto 0);
begin
APBQuiet(Address, Temp, PCLK, APBIn, APBOut, TP, InstancePath, False, cBack2Back, PINDEX);
Data := Temp;
if ScreenOutput then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : APB read access, address: "));
HWrite(L, Address);
Write(L, String'(" : data: "));
HWrite(L, Temp);
WriteLine(Output, L);
end if;
end procedure APBRead;
-----------------------------------------------------------------------------
-- AMBA APB read access
-----------------------------------------------------------------------------
procedure APBComp(
constant Address: in Std_Logic_Vector(31 downto 0);
constant CxData: in Std_Logic_Vector(31 downto 0);
variable RxData: out Std_Logic_Vector(31 downto 0);
signal PCLK: in Std_ULogic;
signal APBIn: out APB_Slv_In_Type;
signal APBOut: in APB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "APBComp";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant PINDEX: in Integer := 0) is
variable L: Line;
variable Data: Std_Logic_Vector(31 downto 0);
begin
APBQuiet(Address, Data, PCLK, APBIn, APBOut, TP, InstancePath, False, cBack2Back, PINDEX);
if not Compare(Data, CxData) then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" : data: "));
HWrite(L, Data);
Write(L, String'(" : expected: "));
HWrite(L, CxData);
Write(L, String'(" # Error #"));
WriteLine(Output, L);
TP := False;
elsif ScreenOutput then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" : data: "));
HWrite(L, Data);
WriteLine(Output, L);
end if;
RxData := Data;
end procedure APBComp;
-----------------------------------------------------------------------------
-- Initialise AHB interface
-----------------------------------------------------------------------------
procedure AHBInit(
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
constant InstancePath: in String := "AHBInit";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := True) is
variable L: Line;
begin
if cBack2Back then
Synchronise(HCLK);
end if;
AHBIn.HSEL <= (others => '0');
AHBIn.HADDR <= (others => '0');
AHBIn.HWRITE <= '0';
AHBIn.HTRANS <= HTRANS_IDLE;
AHBIn.HSIZE <= HSIZE_WORD;
AHBIn.HBURST <= HBURST_SINGLE;
AHBIn.HWDATA <= (others => '-');
AHBIn.HPROT <= (others => '0');
AHBIn.HREADY <= '0';
AHBIn.HMASTER <= (others => '0');
AHBIn.HMASTLOCK <= '0';
AHBIn.HMBSEL <= (others => '0');
if ScreenOutput then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB initalised"));
WriteLine(Output, L);
end if;
end procedure AHBInit;
-----------------------------------------------------------------------------
-- AMBA AHB write access
-----------------------------------------------------------------------------
procedure AHBWriteQuiet(
constant Address: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBWrite";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0) is
variable L: Line;
begin
-- do not Synchronise when a back-to-back access is requested
if not cBack2Back then
Synchronise(HCLK); -- first clock period
end if;
AHBIn.HSEL <= (others => '0');
AHBIn.HSEL(HINDEX)<= '1';
AHBIn.HADDR <= Address;
AHBIn.HWRITE <= '1';
AHBIn.HTRANS <= HTRANS_NONSEQ;
AHBIn.HSIZE <= HSIZE_WORD;
AHBIn.HBURST <= HBURST_SINGLE;
AHBIn.HWDATA <= (others => '-');
AHBIn.HPROT <= (others => '0');
AHBIn.HREADY <= '1';
AHBIn.HMASTER <= (others => '0');
AHBIn.HMASTLOCK <= '0';
AHBIn.HMBSEL <= (others => '0');
AHBIn.HMBSEL(HMBINDEX) <= '1';
Synchronise(HCLK); -- second clock period
AHBIn.HSEL <= (others => '0');
AHBIn.HSEL(HINDEX)<= '1';
AHBIn.HADDR <= (others => '-');
AHBIn.HWRITE <= '0';
AHBIn.HTRANS <= HTRANS_IDLE;
AHBIn.HWDATA <= ahbdrivedata(Data);
AHBIn.HREADY <= AHBOut.HREADY;
AHBIn.HMBSEL <= (others => '0');
AHBIn.HMBSEL(HMBINDEX) <= '1';
while AHBOut.HREADY='0' loop
Synchronise(HCLK);
end loop;
if AHBOut.HRESP=HRESP_ERROR then
if ScreenOutput then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB write access, address: "));
HWrite(L, Address);
Write (L, String'(" ERROR response "));
WriteLine(Output, L);
end if;
TP := False;
elsif AHBOut.HRESP=HRESP_RETRY then
if ScreenOutput then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB write access, address: "));
HWrite(L, Address);
Write (L, String'(" RETRY response "));
WriteLine(Output, L);
end if;
TP := False;
elsif AHBOut.HRESP=HRESP_SPLIT then
if ScreenOutput then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB write access, address: "));
HWrite(L, Address);
Write (L, String'(" SPLIT response "));
WriteLine(Output, L);
end if;
TP := False;
else
end if;
Synchronise(HCLK); -- end of access
AHBIn.HSEL <= (others => '0');
AHBIn.HADDR <= (others => '-');
AHBIn.HWRITE <= '1';
AHBIn.HTRANS <= HTRANS_IDLE;
AHBIn.HSIZE <= HSIZE_WORD;
AHBIn.HBURST <= HBURST_SINGLE;
AHBIn.HWDATA <= (others => '-');
AHBIn.HPROT <= (others => '0');
AHBIn.HREADY <= '1';
AHBIn.HMASTER <= (others => '0');
AHBIn.HMASTLOCK <= '0';
AHBIn.HMBSEL <= (others => '0');
end procedure AHBWriteQuiet;
-----------------------------------------------------------------------------
-- AMBA AHB write access
-----------------------------------------------------------------------------
procedure AHBWrite(
constant Address: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBWrite";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0) is
variable OK: Boolean := True;
variable L: Line;
begin
AHBWriteQuiet(Address, Data, HCLK, AHBIn, AHBOut, OK,
InstancePath, False, cBack2Back, HINDEX, HMBINDEX);
if ScreenOutput and OK then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB write access, address: "));
HWrite(L, Address);
Write (L, String'(" : data: "));
HWrite(L, Data);
WriteLine(Output, L);
elsif not OK then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB write access, address: "));
HWrite(L, Address);
Write (L, String'(" : ## Failed ##"));
WriteLine(Output, L);
TP := False;
end if;
end procedure AHBWrite;
-----------------------------------------------------------------------------
-- AMBA AHB read access
-----------------------------------------------------------------------------
procedure AHBQuiet(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBQuiet";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0) is
variable L: Line;
begin
-- do not Synchronise when a back-to-back access is requested
if not cBack2Back then
Synchronise(HCLK);
end if;
AHBIn.HSEL <= (others => '0');
AHBIn.HSEL(HINDEX)<= '1';
AHBIn.HADDR <= Address;
AHBIn.HWRITE <= '0';
AHBIn.HTRANS <= HTRANS_NONSEQ;
AHBIn.HSIZE <= HSIZE_WORD;
AHBIn.HBURST <= HBURST_SINGLE;
AHBIn.HWDATA <= (others => '-');
AHBIn.HPROT <= (others => '0');
AHBIn.HREADY <= '1';
AHBIn.HMASTER <= (others => '0');
AHBIn.HMASTLOCK <= '0';
AHBIn.HMBSEL <= (others => '0');
AHBIn.HMBSEL(HMBINDEX) <= '1';
Synchronise(HCLK); -- second clock period
AHBIn.HSEL <= (others => '0');
AHBIn.HSEL(HINDEX)<= '1';
AHBIn.HADDR <= (others => '-');
AHBIn.HWRITE <= '0';
AHBIn.HTRANS <= HTRANS_IDLE;
AHBIn.HWDATA <= (others => '-');
AHBIn.HREADY <= AHBOut.HREADY;
AHBIn.HMBSEL <= (others => '0');
AHBIn.HMBSEL(HMBINDEX) <= '1';
while AHBOut.HREADY='0' loop
Synchronise(HCLK);
end loop;
Data := AHBOut.HRDATA(31 downto 0);
if AHBOut.HRESP=HRESP_ERROR then
if ScreenOutput then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" ERROR response "));
WriteLine(Output, L);
end if;
TP := False;
elsif AHBOut.HRESP=HRESP_RETRY then
if ScreenOutput then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" RETRY response "));
WriteLine(Output, L);
end if;
TP := False;
elsif AHBOut.HRESP=HRESP_SPLIT then
if ScreenOutput then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" SPLIT response "));
WriteLine(Output, L);
end if;
TP := False;
else
end if;
Synchronise(HCLK); -- end of access
AHBIn.HSEL <= (others => '0');
AHBIn.HADDR <= (others => '-');
AHBIn.HWRITE <= '0';
AHBIn.HTRANS <= HTRANS_IDLE;
AHBIn.HSIZE <= HSIZE_WORD;
AHBIn.HBURST <= HBURST_SINGLE;
AHBIn.HWDATA <= (others => '-');
AHBIn.HPROT <= (others => '0');
AHBIn.HREADY <= '1';
AHBIn.HMASTER <= (others => '0');
AHBIn.HMASTLOCK <= '0';
AHBIn.HMBSEL <= (others => '0');
end procedure AHBQuiet;
-----------------------------------------------------------------------------
-- AMBA AHB read access
-----------------------------------------------------------------------------
procedure AHBRead(
constant Address: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBRead";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0) is
variable OK: Boolean := True;
variable L: Line;
variable Temp: Std_Logic_Vector(31 downto 0);
begin
AHBQuiet(Address, Temp, HCLK, AHBIn, AHBOut, OK,
InstancePath, False, cBack2Back, HINDEX, HMBINDEX);
if ScreenOutput and OK then
Data := Temp;
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" : data: "));
HWrite(L, Temp);
WriteLine(Output, L);
elsif OK then
Data := Temp;
else
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write (L, String'(" : ## Failed ##"));
WriteLine(Output, L);
Data := (others => '-');
TP := False;
end if;
end procedure AHBRead;
-----------------------------------------------------------------------------
-- AMBA AHB read access
-----------------------------------------------------------------------------
procedure AHBComp(
constant Address: in Std_Logic_Vector(31 downto 0);
constant CxData: in Std_Logic_Vector(31 downto 0);
variable RxData: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBIn: out AHB_Slv_In_Type;
signal AHBOut: in AHB_Slv_Out_Type;
variable TP: inout Boolean;
constant InstancePath: in String := "AHBComp";
constant ScreenOutput: in Boolean := False;
constant cBack2Back: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HMBINDEX: in Integer := 0) is
variable OK: Boolean := True;
variable L: Line;
variable Data: Std_Logic_Vector(31 downto 0);
variable Failed: Boolean;
begin
AHBQuiet(Address, Data, HCLK, AHBIn, AHBOut, OK,
InstancePath, False, cBack2Back, HINDEX, HMBINDEX);
if not OK then
Write (L, Now, Right, 15);
Write (L, " : " & InstancePath);
Write (L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write (L, String'(" : ## Failed ##"));
WriteLine(Output, L);
TP := False;
RxData := (others => '-');
elsif not Compare(Data, CxData) then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" : data: "));
HWrite(L, Data);
Write(L, String'(" : expected: "));
HWrite(L, CxData);
Write(L, String'(" # Error #"));
WriteLine(Output, L);
TP := False;
RxData := Data;
elsif ScreenOutput then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath);
Write(L, String'(" : AHB read access, address: "));
HWrite(L, Address);
Write(L, String'(" : data: "));
HWrite(L, Data);
WriteLine(Output, L);
RxData := Data;
else
RxData := Data;
end if;
end procedure AHBComp;
-----------------------------------------------------------------------------
-- Behavioural model of memory with AHB interface, no wait states
-----------------------------------------------------------------------------
procedure AHBMemory(
constant gAWidth: in Positive := 15; -- address width
constant gDWidth: in Positive := 8; -- data width
signal HCLK: in Std_ULogic;
signal HRESETn: in Std_ULogic;
signal AHBIn: in AHB_Slv_In_Type;
signal AHBOut: out AHB_Slv_Out_Type;
constant InstancePath: in String := "AHBMemory";
constant ScreenOutput: in Boolean := False;
constant HINDEX: in Integer := 0;
constant HADDR: in Integer := 0;
constant HMASK: in Integer := 16#FFF#) is
-- memory definition
subtype ARange is Natural range 0 to 2**gAWidth-1;
subtype DRange is Natural range 0 to gDWidth-1;
type MType is array (ARange) of Integer;
-- memory initialisation
function Init return MType is
variable r: MType;
begin
for i in ARange loop
r(i) := -1;
end loop;
return r;
end function Init;
variable M: MType;
variable A: Std_Logic_Vector(gAWidth-1 downto 0);
variable D: Std_Logic_Vector(0 to gDWidth-1);
variable W: Std_Logic;
-- reset values
procedure Reset is
begin
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
AHBOut.HRDATA <= (others => '0');
W := '0';
end procedure Reset;
-- plug&play configuration
constant HCONFIG : ahb_config_type := (
0 => ahb_device_reg (0, 0, 0, gAWidth, 0),
4 => ahb_membar(HADDR, '1', '1', HMASK),
others => zero32);
variable alow : std_logic_vector(1 downto 0);
begin
-- fixed AMBA AHB signals, etc.
AHBOut.HSPLIT <= (others => '0');
AHBOut.HCONFIG <= HCONFIG;
loop
if HRESETn='0' then -- asynchronous reset
Reset;
elsif HCLK'Event and HCLK='1' then -- rising edge
-- data phase
if AHBIn.HREADY='1' then
if W='1' then
alow := A(1 downto 0);
case alow is
when "00" =>
D := AHBIn.HWDATA(31 downto 24);
when "01" =>
D := AHBIn.HWDATA(23 downto 16);
when "10" =>
D := AHBIn.HWDATA(15 downto 8);
when others =>
D := AHBIn.HWDATA( 7 downto 0);
end case;
M(Conv_Integer(A)) := Conv_Integer(D);
W := '0';
end if;
end if;
-- address phase
if AHBIn.HSEL(HINDEX)='1' and
AHBIn.HREADY='1' and
AHBIn.HSIZE=HSIZE_BYTE and
(AHBIn.HTRANS=HTRANS_SEQ or
AHBIn.HTRANS=HTRANS_NONSEQ) and
AHBIn.HMASTLOCK='0' then
W := AHBIn.HWRITE;
A := AHBIn.HADDR(gAWidth-1 downto 0);
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
D := Conv_Std_Logic_Vector(
M(Conv_Integer(A)), D'Length);
case alow is
when "00" =>
AHBOut.HRDATA(31 downto 24) <= D;
when "01" =>
AHBOut.HRDATA(23 downto 16) <= D;
when "10" =>
AHBOut.HRDATA(15 downto 8) <= D;
when others =>
AHBOut.HRDATA( 7 downto 0) <= D;
end case;
else
w :='0';
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
end if;
end if;
-- signal sensitivity
wait on HCLK, HRESETn;
end loop;
end procedure AHBMemory;
-----------------------------------------------------------------------------
-- Behavioural model of memory with AHB interface, no wait states
-----------------------------------------------------------------------------
procedure AHBMemory32(
constant gAWidth: in Positive := 18; -- address width
signal HCLK: in Std_ULogic;
signal HRESETn: in Std_ULogic;
signal AHBIn: in AHB_Slv_In_Type;
signal AHBOut: out AHB_Slv_Out_Type;
constant InstancePath: in String := "AHBMemory32";
constant ScreenOutput: in Boolean := False;
constant FileName: in String := ""; -- File name
constant HINDEX: in Integer := 0;
constant HADDR: in Integer := 0;
constant HMASK: in Integer := 16#FFF#) is
-- memory definition
type MType is array (0 to 2**(gAWidth-2)-1) of
Std_Logic_Vector(31 downto 0);
--------------------------------------------------------------------------
-- Load memory contents
--------------------------------------------------------------------------
-- ## Does not warn if there is insufficient data in a line.
-- Address read from file is always byte oriented, always 32 bit wide
-- For 16 and 32 bit wide data, each data word read from file must be on a
-- single line and without white space between the characters. For 8 bit
-- wide date, no restrictions apply. Files generated for 32 bit wide data
-- can always be read by 16 or 8 bit memories. The byte/halfwrod address
-- is incremented internally.
--------------------------------------------------------------------------
-- -----------------------------------------------------------------------
-- -- PROM Initialisation Example
-- -----------------------------------------------------------------------
-- -- Supports by 8, 16, 32 bit wide memories
-- 00000000 00010203
-- 00000004 04050607 08090A0B
-- 0000000C 0C0D0E0F
--
-- -- Supported by 8, 16 bit wide memories
-- 00000010 1011 1213
-- 00000014 1415
-- 00000016 1617 1819 1A1B 1C1D 1E1F 2021
-- 00000022 2223 2425 2627 2829 2A2B 2C2D 2E2F
--
-- -- Supported by 8 bit wide memories
-- 00000030 30 31 32 33 3435 3637 3839 3A3B 3C3D 3E3F
-- 00000040 40
-- 00000041 41
-- 00000042 42 43
-- 00000044 4445
-- 00000046 46474849
-- 0000004A 4A4B 4C4D4E4F
--------------------------------------------------------------------------
impure function Initialise(
constant FileName: in String := "";
constant AWidth: in Natural;
constant DWidth: in Natural)
return MType is
variable L: Line;
variable Address: Std_Logic_Vector(31 downto 0);
variable Data: Std_Logic_Vector(31 downto 0);
variable Byte: Std_Logic_Vector( 7 downto 0);
variable Addr: Natural range 0 to 2**AWidth-1;
file ReadFile: Text;
variable Test: Boolean;
variable Result: MType;
begin
-- initialse all data to all zeros
Result := (others => (others => 'U'));
-- load contents from file only if a file name has been provided
if FileName /= "" then
File_Open(ReadFile, FileName, Read_Mode);
-- read data from file
while not EndFile(ReadFile) loop
-- read line
ReadLine(ReadFile, L);
-- read address, always byte oriented, always 32 bit wide
HRead(L, Address, Test);
if Test then -- address read
-- check whether byte address aligned with data width
if Conv_Integer(Address) mod (DWidth/8) /= 0 then
report "Unaligned data in memory initalisation file: " &
FileName
severity Failure;
Test := False;
else -- convert address
-- adapt byte address to address corresponding to the data
-- width of the memory
Addr := (Conv_Integer(Address)/(DWidth/8)) mod
(2**AWidth);
end if;
else -- comment detected
null;
end if;
while Test loop
-- read data
HRead(L, Data(DWidth-1 downto 0), Test);
if Test then
-- initialize memory element
Result(Addr) := Data(DWidth-1 downto 0);
-- increment address, with the memory width
Addr := (Addr + 1) mod (2**AWidth);
end if;
end loop;
end loop;
File_Close(ReadFile);
end if;
return Result;
end function Initialise;
-- memory contents
variable M: MType := Initialise(FileName, gAWidth-2, 32);
variable A: Std_Logic_Vector(gAWidth-1 downto 2);
variable W: Std_Logic;
-- reset values
procedure Reset is
begin
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
AHBOut.HRDATA <= (others => '0');
W := '0';
end procedure Reset;
-- plug&play configuration
constant HCONFIG : ahb_config_type := (
0 => ahb_device_reg (0, 0, 0, gAWidth, 0),
4 => ahb_membar(HADDR, '1', '1', HMASK),
others => zero32);
begin
-- fixed AMBA AHB signals, etc.
AHBOut.HSPLIT <= (others => '0');
AHBOut.HCONFIG <= HCONFIG;
loop
if HRESETn='0' then -- asynchronous reset
Reset;
elsif HCLK'Event and HCLK='1' then -- rising edge
-- data phase
if AHBIn.HREADY='1' then
if W='1' then
M(Conv_Integer(A)) := AHBIn.HWDATA(31 downto 0);
W := '0';
end if;
end if;
-- address phase
if AHBIn.HSEL(HINDEX)='1' and
AHBIn.HREADY='1' and
AHBIn.HSIZE=HSIZE_WORD and
(AHBIn.HTRANS=HTRANS_SEQ or
AHBIn.HTRANS=HTRANS_NONSEQ) and
AHBIn.HMASTLOCK='0' then
W := AHBIn.HWRITE;
A := AHBIn.HADDR(gAWidth-1 downto 2);
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
AHBOut.HRDATA <= ahbdrivedata(M(Conv_Integer(A)));
else
W :='0';
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
end if;
end if;
-- signal sensitivity
wait on HCLK, HRESETn;
end loop;
end procedure AHBMemory32;
-----------------------------------------------------------------------------
-- Behavioural model of memory with AHB interface, no wait states
-- Supporting byte, halfword and word read/write accesses.
-- Provices diagnostic support.
-----------------------------------------------------------------------------
procedure AHBMemory32(
constant gAWidth: in Positive := 18; -- address width
signal HCLK: in Std_ULogic;
signal HRESETn: in Std_ULogic;
signal AHBIn: in AHB_Slv_In_Type;
signal AHBOut: out AHB_Slv_Out_Type;
signal AHBInDiag: in AHB_Diagnostics_In_Type;
signal AHBOutDiag: out AHB_Diagnostics_Out_Type;
constant InstancePath: in String := "AHBMemory32";
constant ScreenOutput: in Boolean := False;
constant FileName: in String := ""; -- File name
constant HINDEX: in Integer := 0;
constant HADDR: in Integer := 0;
constant HMASK: in Integer := 16#FFF#) is
-- memory definition
type MType is array (0 to 2**(gAWidth-2)-1) of
Std_Logic_Vector(31 downto 0);
variable L: Line;
constant Padding: Std_ULogic_Vector(1 to
(4-((gAWidth-2) mod 4))) :=
(others => '0');
--------------------------------------------------------------------------
-- Load memory contents
--------------------------------------------------------------------------
-- ## Does not warn if there is insufficient data in a line.
-- Address read from file is always byte oriented, always 32 bit wide
-- For 16 and 32 bit wide data, each data word read from file must be on a
-- single line and without white space between the characters. For 8 bit
-- wide date, no restrictions apply. Files generated for 32 bit wide data
-- can always be read by 16 or 8 bit memories. The byte/halfwrod address
-- is incremented internally.
--------------------------------------------------------------------------
-- -----------------------------------------------------------------------
-- -- PROM Initialisation Example
-- -----------------------------------------------------------------------
-- -- Supports by 8, 16, 32 bit wide memories
-- 00000000 00010203
-- 00000004 04050607 08090A0B
-- 0000000C 0C0D0E0F
--
-- -- Supported by 8, 16 bit wide memories
-- 00000010 1011 1213
-- 00000014 1415
-- 00000016 1617 1819 1A1B 1C1D 1E1F 2021
-- 00000022 2223 2425 2627 2829 2A2B 2C2D 2E2F
--
-- -- Supported by 8 bit wide memories
-- 00000030 30 31 32 33 3435 3637 3839 3A3B 3C3D 3E3F
-- 00000040 40
-- 00000041 41
-- 00000042 42 43
-- 00000044 4445
-- 00000046 46474849
-- 0000004A 4A4B 4C4D4E4F
--------------------------------------------------------------------------
impure function Initialise(
constant FileName: in String := "";
constant AWidth: in Natural;
constant DWidth: in Natural)
return MType is
variable L: Line;
variable Address: Std_Logic_Vector(31 downto 0);
variable Data: Std_Logic_Vector(31 downto 0);
variable Byte: Std_Logic_Vector( 7 downto 0);
variable Addr: Natural range 0 to 2**AWidth-1;
file ReadFile: Text;
variable Test: Boolean;
variable Result: MType;
begin
-- initialse all data to all zeros
Result := (others => (others => 'U'));
-- load contents from file only if a file name has been provided
if FileName /= "" then
File_Open(ReadFile, FileName, Read_Mode);
-- read data from file
while not EndFile(ReadFile) loop
-- read line
ReadLine(ReadFile, L);
-- read address, always byte oriented, always 32 bit wide
HRead(L, Address, Test);
if Test then -- address read
-- check whether byte address aligned with data width
if Conv_Integer(Address) mod (DWidth/8) /= 0 then
report "Unaligned data in memory initalisation file: " &
FileName
severity Failure;
Test := False;
else -- convert address
-- adapt byte address to address corresponding to the data
-- width of the memory
Addr := (Conv_Integer(Address)/(DWidth/8)) mod
(2**AWidth);
end if;
else -- comment detected
null;
end if;
while Test loop
-- read data
HRead(L, Data(DWidth-1 downto 0), Test);
if Test then
-- initialize memory element
Result(Addr) := Data(DWidth-1 downto 0);
-- increment address, with the memory width
Addr := (Addr + 1) mod (2**AWidth);
end if;
end loop;
end loop;
File_Close(ReadFile);
end if;
return Result;
end function Initialise;
-- memory contents
variable M: MType := Initialise(FileName, gAWidth-2, 32);
variable A: Std_Logic_Vector(gAWidth-1 downto 2);
variable B: Std_Logic_Vector(1 downto 0);
variable W: Std_Logic;
variable S: Std_Logic_Vector(2 downto 0);
variable D: Std_Logic_Vector(31 downto 0);
variable twocycle:Boolean := False;
-- reset values
procedure Reset is
begin
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
AHBOut.HRDATA <= (others => '0');
W := '0';
twocycle := False;
end procedure Reset;
-- plug&play configuration
constant HCONFIG : ahb_config_type := (
0 => ahb_device_reg (0, 0, 0, gAWidth, 0),
4 => ahb_membar(HADDR, '1', '1', HMASK),
others => zero32);
begin
-- fixed AMBA AHB signals, etc.
AHBOut.HSPLIT <= (others => '0');
AHBOut.HCONFIG <= HCONFIG;
loop
if HRESETn='0' then -- asynchronous reset
Reset;
elsif HCLK'Event and HCLK='1' then -- rising edge
-- data phase
if AHBIn.HREADY='1' then
if W='1' then
-- read back memory
D := M(Conv_Integer(A));
-- replace with new data
if S="000" then -- byte
if B(1 downto 0)="00" then
D := AHBIn.HWDATA(31 downto 24) &
D(23 downto 0);
elsif B(1 downto 0)="01" then
D := D(31 downto 24) &
AHBIn.HWDATA(23 downto 16) &
D(15 downto 0);
elsif B(1 downto 0)="10" then
D := D(31 downto 16) &
AHBIn.HWDATA(15 downto 8) &
D(7 downto 0);
elsif B(1 downto 0)="11" then
D := D(31 downto 8) &
AHBIn.HWDATA(7 downto 0);
end if;
elsif S="001" then -- halfword
if B(1 downto 0)="00" then
D := AHBIn.HWDATA(31 downto 16) &
D(15 downto 0);
elsif B(1 downto 0)="10" then
D := D(31 downto 16) &
AHBIn.HWDATA(15 downto 0);
end if;
else
D := AHBIn.HWDATA(31 downto 0);
end if;
-- write back memory
M(Conv_Integer(A)) := D;
W := '0';
-- comment
if ScreenOutput then
Write(L, Now, Right, 15);
Write(L, " : " & InstancePath & " Write acces to address :");
if Padding'Length > 0 and Padding'Length < 4 then
HWrite(L, Std_Logic_Vector(Padding) & Std_Logic_Vector(A));
else
HWrite(L, Std_Logic_Vector(A));
end if;
Write(L, String'(" data :"));
HWrite(L, D);
Write(L, String'(" data :"));
Write(L, To_BitVector(D));
Write(L, String'(" size :"));
HWrite(L, "0" & S);
WriteLine(Output, L);
end if;
end if;
end if;
-- address phase
if AHBIn.HSEL(HINDEX)='1' and
AHBIn.HREADY='1' and
(AHBIn.HSIZE=HSIZE_BYTE or
AHBIn.HSIZE=HSIZE_HWORD or
AHBIn.HSIZE=HSIZE_WORD) and
(AHBIn.HTRANS=HTRANS_SEQ or
AHBIn.HTRANS=HTRANS_NONSEQ) and
AHBIn.HMASTLOCK='0' then
if AHBInDiag.HRESP=HRESP_OKAY then
W := AHBIn.HWRITE;
S := AHBIn.HSIZE;
B := AHBIn.HADDR( 1 downto 0);
A := AHBIn.HADDR(gAWidth-1 downto 2);
AHBOut.HREADY <= '1';
AHBOut.HRESP <= HRESP_OKAY;
AHBOut.HRDATA <= ahbdrivedata(M(Conv_Integer(A)));
elsif AHBInDiag.HRESP=HRESP_RETRY then
W :='0';
AHBOut.HREADY <= '0';
AHBOut.HRESP <= HRESP_RETRY;
AHBOut.HRDATA <= (others => 'X');
twocycle := True;
elsif AHBInDiag.HRESP=HRESP_SPLIT then
W :='0';
AHBOut.HREADY <= '0';
AHBOut.HRESP <= HRESP_SPLIT;
AHBOut.HRDATA <= (others => 'X');
twocycle := True;
else
W :='0';
AHBOut.HREADY <= '0';
AHBOut.HRESP <= HRESP_ERROR;
AHBOut.HRDATA <= (others => 'X');
twocycle := True;
end if;
else
W :='0';
AHBOut.HREADY <= '1';
if twocycle then
twocycle := False;
else
AHBOut.HRESP <= HRESP_OKAY;
end if;
end if;
end if;
if HCLK'Event and HCLK='1' then -- rising edge
-- diagnostics
AHBOutDiag.HRData <= M((Conv_Integer(AHBInDiag.HAddr)/4) mod (2**(gAWidth-2)));
if AHBInDiag.HWrite='1' then
M((Conv_Integer(AHBInDiag.HAddr)/4) mod (2**(gAWidth-2))) := AHBInDiag.HWData;
-- Print("Diagnostic write to memory, address: " &
-- Integer'Image(Conv_Integer(AHBInDiag.HAddr)) &
-- " data: " &
-- Integer'Image(Conv_Integer(AHBInDiag.HWData)));
end if;
AHBOut.HSPLIT <= AHBInDiag.HSplit;
end if;
-- signal sensitivity
wait on HCLK, HRESETn;
end loop;
end procedure AHBMemory32;
-----------------------------------------------------------------------------
-- Routine for writig data directly to AHB memory
-----------------------------------------------------------------------------
procedure WrAHBMem32(
constant Addr: in Std_Logic_Vector(31 downto 0);
constant Data: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False) is
variable L: Line;
begin
Synchronise(HCLK);
if Screen then
Write(L, Now, Right, 15);
Write(L, String'(" : WrAHBMem32: "));
HWrite(L, Std_Logic_Vector(Addr));
Write(L, String'(" : "));
HWrite(L, Std_Logic_Vector(Data));
if Comment /= "" then
Write(L, " : " & Comment);
end if;
WriteLine(Output, L);
end if;
AHBInDiag.HAddr <= Addr;
AHBInDiag.HWData <= Data;
AHBInDiag.HWrite <= '1';
Synchronise(HCLK);
AHBInDiag.HWrite <= '0';
end procedure WrAHBMem32;
-----------------------------------------------------------------------------
-- Routine for reading data directly from AHB memory
-----------------------------------------------------------------------------
procedure RdAHBMem32(
constant Addr: in Std_Logic_Vector(31 downto 0);
variable Data: out Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False) is
variable L: Line;
begin
Synchronise(HCLK);
AHBInDiag.HAddr <= Addr;
AHBInDiag.HWrite <= '0';
Synchronise(HCLK);
Data := AHBOutDiag.HRData;
if Screen then
Write(L, Now, Right, 15);
Write(L, String'(" : RdAHBMem32: "));
HWrite(L, Std_Logic_Vector(Addr));
Write(L, String'(" : "));
HWrite(L, Std_Logic_Vector(AHBOutDiag.HRData));
if Comment /= "" then
Write(L, " : " & Comment);
end if;
WriteLine(Output, L);
end if;
end procedure RdAHBMem32;
-----------------------------------------------------------------------------
-- Routine for reading data directly from AHB memory
-----------------------------------------------------------------------------
procedure RcAHBMem32(
constant Addr: in Std_Logic_Vector(31 downto 0);
constant Expected: in Std_Logic_Vector(31 downto 0);
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False) is
variable Data: Std_Logic_Vector(31 downto 0);
variable L: Line;
begin
Synchronise(HCLK);
AHBInDiag.HAddr <= Addr;
AHBInDiag.HWrite <= '0';
Synchronise(HCLK);
Data := AHBOutDiag.HRData;
if not Compare(Data, Expected) then
Write(L, Now, Right, 15);
Write(L, String'(" : RcAHBMem32: "));
HWrite(L, Std_Logic_Vector(Addr));
Write(L, String'(", value: "));
HWrite(L, Std_Logic_Vector(Data));
Write(L, String'(", expected: "));
HWrite(L, Std_Logic_Vector(Expected));
Write(L, String'(" # Error "));
if Comment /= "" then
Write(L, " : " & Comment);
end if;
WriteLine(Output, L);
TP := False;
elsif Screen then
Write(L, Now, Right, 15);
Write(L, String'(" : RcAHBMem32: "));
HWrite(L, Std_Logic_Vector(Addr));
Write(L, String'(" : "));
HWrite(L, Std_Logic_Vector(Data));
Write(L, String'(" : "));
HWrite(L, Std_Logic_Vector(Expected));
if Comment /= "" then
Write(L, " : " & Comment);
end if;
WriteLine(Output, L);
end if;
end procedure RcAHBMem32;
-----------------------------------------------------------------------------
-- Routine for generating a split ack from AHB memory
-----------------------------------------------------------------------------
procedure SplitAHBMem32(
constant Split: in Integer range 0 to 15;
signal HCLK: in Std_ULogic;
signal AHBInDiag: out AHB_Diagnostics_In_Type;
signal AHBOutDiag: in AHB_Diagnostics_Out_Type;
variable TP: inout Boolean;
constant Comment: in String := "";
constant Screen: in Boolean := False) is
variable L: Line;
begin
Synchronise(HCLK);
AHBInDiag.HSPLIT <= (others => '0');
AHBInDiag.HSPLIT(Split) <= '1';
Synchronise(HCLK);
AHBInDiag.HSPLIT <= (others => '0');
if Screen then
Write(L, Now, Right, 15);
Write(L, String'(" : SplitAHBMem32: split acknowledge to master: "));
Write(L, Split);
if Comment /= "" then
Write(L, " : " & Comment);
end if;
WriteLine(Output, L);
end if;
end procedure SplitAHBMem32;
end package body AMBA_TestPackage; --=========================================--