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