URL
https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk
Subversion Repositories riscv_vhdl
[/] [riscv_vhdl/] [trunk/] [rtl/] [ambalib/] [types_amba4.vhd] - Rev 5
Compare with Previous | Blame | View Log
----------------------------------------------------------------------------- --! @file --! @copyright Copyright 2015 GNSS Sensor Ltd. All right reserved. --! @author Sergey Khabarov - sergeykhbr@gmail.com --! @brief Declaration and common methods implementation of the types_nasti --! package. --! @details This file defines bus interface constants that have to be --! used by any periphery device implementation in order --! to provide compatibility in a wide range of possible settings. --! For better implementation use the AXI4 register bank and --! implemented tasks from this file. ------------------------------------------------------------------------------ --! Standard library library ieee; --! Standard signal types import use ieee.std_logic_1164.all; --! Standard numerical types import use ieee.numeric_std.all; --! Common constants and data conversion functions library library commonlib; --! Import SoC specific types common for all devices use commonlib.types_common.all; --! @brief System bus AMBA AXI(NASTI) types definition. --! @details This package provides general constants, data structures and --! and functions description that define behaviour of all --! peripheries devices implementing AXI4 interface. package types_amba4 is --! @defgroup scala_cfg_group SCALA generated parameters --! @ingroup axi4_config_generic_group --! @details This constant must correspond to Scala defined ones. --! @{ --! User defined address ID bitwidth (aw_id / ar_id fields). constant CFG_ROCKET_ID_BITS : integer := 5; --! Data bus bits width. constant CFG_NASTI_DATA_BITS : integer := 64;--128; --! Data bus bytes width constant CFG_NASTI_DATA_BYTES : integer := CFG_NASTI_DATA_BITS / 8; --! Address bus bits width. constant CFG_NASTI_ADDR_BITS : integer := 32; --! Definition of number of bits in address bus per one data transaction. constant CFG_NASTI_ADDR_OFFSET : integer := log2(CFG_NASTI_DATA_BYTES); --! @brief Number of address bits used for device addressing. --! @details Default is 12 bits = 4 KB of address space minimum per each --! mapped device. constant CFG_NASTI_CFG_ADDR_BITS : integer := CFG_NASTI_ADDR_BITS-12; --! @brief Global alignment is set 32 bits. constant CFG_ALIGN_BYTES : integer := 4; --! @brief Number of parallel access to the atomic data. constant CFG_WORDS_ON_BUS : integer := CFG_NASTI_DATA_BYTES/CFG_ALIGN_BYTES; --! @} --! @defgroup slave_id_group AMBA AXI slaves generic IDs. --! @ingroup axi4_config_generic_group --! @details Each module in a SoC has to be indexed by unique identificator. --! In current implementation it is used sequential indexing for it. --! Indexes are used to specify a device bus item in a vectors. --! @{ --! @brief Configuration index of the Boot ROM module visible by the firmware. constant CFG_NASTI_SLAVE_BOOTROM : integer := 0; --! Configuration index of the Firmware ROM Image module. constant CFG_NASTI_SLAVE_ROMIMAGE : integer := CFG_NASTI_SLAVE_BOOTROM+1; --! Configuration index of the SRAM module visible by the firmware. constant CFG_NASTI_SLAVE_SRAM : integer := CFG_NASTI_SLAVE_ROMIMAGE+1; --! Configuration index of the UART module. constant CFG_NASTI_SLAVE_UART1 : integer := CFG_NASTI_SLAVE_SRAM+1; --! Configuration index of the GPIO (General Purpose In/Out) module. constant CFG_NASTI_SLAVE_GPIO : integer := CFG_NASTI_SLAVE_UART1+1; --! Configuration index of the Interrupt Controller module. constant CFG_NASTI_SLAVE_IRQCTRL : integer := CFG_NASTI_SLAVE_GPIO+1; --! Configuration index of the Satellite Navigation Engine. constant CFG_NASTI_SLAVE_ENGINE : integer := CFG_NASTI_SLAVE_IRQCTRL+1; --! Configuration index of the RF front-end controller. constant CFG_NASTI_SLAVE_RFCTRL : integer := CFG_NASTI_SLAVE_ENGINE+1; --! Configuration index of the GPS-CA Fast Search Engine module. constant CFG_NASTI_SLAVE_FSE_GPS : integer := CFG_NASTI_SLAVE_RFCTRL+1; --! Configuration index of the Ethernet MAC module. constant CFG_NASTI_SLAVE_ETHMAC : integer := CFG_NASTI_SLAVE_FSE_GPS+1; --! Configuration index of the Debug Support Unit module. constant CFG_NASTI_SLAVE_DSU : integer := CFG_NASTI_SLAVE_ETHMAC+1; --! Configuration index of the Debug Support Unit module. constant CFG_NASTI_SLAVE_GPTIMERS : integer := CFG_NASTI_SLAVE_DSU+1; --! Configuration index of the Plug-n-Play module. constant CFG_NASTI_SLAVE_PNP : integer := CFG_NASTI_SLAVE_GPTIMERS+1; --! Total number of the slaves devices. constant CFG_NASTI_SLAVES_TOTAL : integer := CFG_NASTI_SLAVE_PNP+1; --! @} --! @defgroup master_id_group AXI4 masters generic IDs. --! @ingroup axi4_config_generic_group --! @details Each master must be assigned to a specific ID that used --! as an index in the vector array of AXI master bus. --! @{ --! Cached TileLinkIO bus. constant CFG_NASTI_MASTER_CACHED : integer := 0; --! Uncached TileLinkIO bus. constant CFG_NASTI_MASTER_UNCACHED : integer := CFG_NASTI_MASTER_CACHED+1; --! Ethernet MAC master interface generic index. constant CFG_NASTI_MASTER_ETHMAC : integer := CFG_NASTI_MASTER_UNCACHED+1; --! Tap via UART (debug port) generic index. constant CFG_NASTI_MASTER_MSTUART : integer := CFG_NASTI_MASTER_ETHMAC+1; --! Tap via JTAG generic index. constant CFG_AXI_MASTER_JTAG : integer := CFG_NASTI_MASTER_MSTUART+1; --! Total Number of master devices on system bus. constant CFG_NASTI_MASTER_TOTAL : integer := CFG_AXI_MASTER_JTAG+1; --! @} --! @defgroup irq_id_group AXI4 interrupt generic IDs. --! @ingroup axi4_config_generic_group --! @details Unique indentificator of the interrupt pin also used --! as an index in the interrupts bus. --! @{ --! Zero interrupt index must be unused. constant CFG_IRQ_UNUSED : integer := 0; --! UART_A interrupt pin. constant CFG_IRQ_UART1 : integer := CFG_IRQ_UNUSED + 1; --! Ethernet MAC interrupt pin. constant CFG_IRQ_ETHMAC : integer := CFG_IRQ_UART1 + 1; --! GP Timers interrupt pin constant CFG_IRQ_GPTIMERS : integer := CFG_IRQ_ETHMAC + 1; --! Memory miss access. constant CFG_IRQ_MISS_ACCESS : integer := CFG_IRQ_GPTIMERS + 1; --! GNSS Engine IRQ pin that generates 1 msec pulses. constant CFG_IRQ_GNSSENGINE : integer := CFG_IRQ_MISS_ACCESS + 1; --! Total number of used interrupts in a system constant CFG_IRQ_TOTAL : integer := CFG_IRQ_GNSSENGINE + 1; --! @} --! @name AXI Response values --! @brief AMBA 4.0 specified response types from a slave device. --! @{ --! @brief Normal access success. --! @details Indicates that a normal access has been --! successful. Can also indicate an exclusive access has failed. constant NASTI_RESP_OKAY : std_logic_vector(1 downto 0) := "00"; --! @brief Exclusive access okay. --! @details Indicates that either the read or write --! portion of an exclusive access has been successful. constant NASTI_RESP_EXOKAY : std_logic_vector(1 downto 0) := "01"; --! @brief Slave error. --! @details Used when the access has reached the slave successfully, --! but the slave wishes to return an error condition to the originating --! master. constant NASTI_RESP_SLVERR : std_logic_vector(1 downto 0) := "10"; --! @brief Decode error. --! @details Generated, typically by an interconnect component, --! to indicate that there is no slave at the transaction address. constant NASTI_RESP_DECERR : std_logic_vector(1 downto 0) := "11"; --! @} --! @name AXI burst request type. --! @brief AMBA 4.0 specified burst operation request types. --! @{ --! @brief Fixed address burst operation. --! @details The address is the same for every transfer in the burst --! (FIFO type) constant NASTI_BURST_FIXED : std_logic_vector(1 downto 0) := "00"; --! @brief Burst operation with address increment. --! @details The address for each transfer in the burst is an increment of --! the address for the previous transfer. The increment value depends --! on the size of the transfer. constant NASTI_BURST_INCR : std_logic_vector(1 downto 0) := "01"; --! @brief Burst operation with address increment and wrapping. --! @details A wrapping burst is similar to an incrementing burst, except that --! the address wraps around to a lower address if an upper address --! limit is reached constant NASTI_BURST_WRAP : std_logic_vector(1 downto 0) := "10"; --! @} --! @name Vendor IDs defintion. --! @{ --! GNSS Sensor Ltd. vendor identificator. constant VENDOR_GNSSSENSOR : std_logic_vector(15 downto 0) := X"00F1"; --! @} --! @name Master Device IDs definition: --! @{ --! Empty master slot device constant MST_DID_EMPTY : std_logic_vector(15 downto 0) := X"7755"; --! RISC-V "Rocket-chip" core Cached TileLink master device. constant RISCV_CACHED_TILELINK : std_logic_vector(15 downto 0) := X"0500"; --! RISC-V "Rocket-chip" core Uncached TileLink master device. constant RISCV_UNCACHED_TILELINK : std_logic_vector(15 downto 0) := X"0501"; --! Ethernet MAC master device. constant GAISLER_ETH_MAC_MASTER : std_logic_vector(15 downto 0) := X"0502"; --! Ethernet MAC master debug interface (EDCL). constant GAISLER_ETH_EDCL_MASTER : std_logic_vector(15 downto 0) := X"0503"; --! "River" CPU Device ID. constant RISCV_RIVER_CPU : std_logic_vector(15 downto 0) := X"0505"; --! UART with DMA: Test Access Point (TAP) constant GNSSSENSOR_UART_TAP : std_logic_vector(15 downto 0) := X"050A"; --! JTAG Test Access Point (TAP) constant GNSSSENSOR_JTAG_TAP : std_logic_vector(15 downto 0) := X"050B"; --! @} --! @name Slave Device IDs definition: --! @{ --! Empty slave slot device constant SLV_DID_EMPTY : std_logic_vector(15 downto 0) := X"5577"; --! GNSS Engine Stub device constant GNSSSENSOR_ENGINE_STUB : std_logic_vector(15 downto 0) := X"0068"; --! Fast Search Engines Device ID provided by gnsslib constant GNSSSENSOR_FSE_V2_GPS : std_logic_vector(15 downto 0) := X"0069"; --! Boot ROM Device ID constant GNSSSENSOR_BOOTROM : std_logic_vector(15 downto 0) := X"0071"; --! FW ROM image Device ID constant GNSSSENSOR_FWIMAGE : std_logic_vector(15 downto 0) := X"0072"; --! Internal SRAM block Device ID constant GNSSSENSOR_SRAM : std_logic_vector(15 downto 0) := X"0073"; --! Configuration Registers Module Device ID provided by gnsslib constant GNSSSENSOR_PNP : std_logic_vector(15 downto 0) := X"0074"; --! SD-card controller Device ID provided by gnsslib constant GNSSSENSOR_SPI_FLASH : std_logic_vector(15 downto 0) := X"0075"; --! General purpose IOs Device ID provided by gnsslib constant GNSSSENSOR_GPIO : std_logic_vector(15 downto 0) := X"0076"; --! RF front-end controller Device ID provided by gnsslib constant GNSSSENSOR_RF_CONTROL : std_logic_vector(15 downto 0) := X"0077"; --! GNSS Engine Device ID provided by gnsslib constant GNSSSENSOR_ENGINE : std_logic_vector(15 downto 0) := X"0078"; --! rs-232 UART Device ID constant GNSSSENSOR_UART : std_logic_vector(15 downto 0) := X"007a"; --! Accelerometer Device ID provided by gnsslib constant GNSSSENSOR_ACCELEROMETER : std_logic_vector(15 downto 0) := X"007b"; --! Gyroscope Device ID provided by gnsslib constant GNSSSENSOR_GYROSCOPE : std_logic_vector(15 downto 0) := X"007c"; --! Interrupt controller constant GNSSSENSOR_IRQCTRL : std_logic_vector(15 downto 0) := X"007d"; --! Ethernet MAC inherited from Gaisler greth module. constant GNSSSENSOR_ETHMAC : std_logic_vector(15 downto 0) := X"007f"; --! Debug Support Unit device id. constant GNSSSENSOR_DSU : std_logic_vector(15 downto 0) := X"0080"; --! GP Timers device id. constant GNSSSENSOR_GPTIMERS : std_logic_vector(15 downto 0) := X"0081"; --! ADC samples recorder constant GNSSSENSOR_ADC_RECORDER : std_logic_vector(15 downto 0) := X"0082"; --! @} --! @name Decoder of the transaction size. --! @{ --! Burst length size decoder constant XSIZE_TOTAL : integer := 8; --! Definition of the AXI bytes converter. type xsize_type is array (0 to XSIZE_TOTAL-1) of integer; --! Decoder of the transaction bytes from AXI format to Bytes. constant XSizeToBytes : xsize_type := ( 0 => 1, 1 => 2, 2 => 4, 3 => 8, 4 => 16, 5 => 32, 6 => 64, 7 => 128 ); --! @} --! @name Plug'n'Play descriptor constants. --! @{ --! Undefined type of the descriptor (empty device). constant PNP_CFG_TYPE_INVALID : std_logic_vector := "00"; --! AXI slave device standard descriptor. constant PNP_CFG_TYPE_MASTER : std_logic_vector := "01"; --! AXI master device standard descriptor. constant PNP_CFG_TYPE_SLAVE : std_logic_vector := "10"; --! @brief Size in bytes of the standard slave descriptor.. --! @details Firmware uses this value instead of sizeof(nasti_slave_config_type). constant PNP_CFG_SLAVE_DESCR_BYTES : std_logic_vector(7 downto 0) := X"10"; --! @brief Size in bytes of the standard master descriptor. --! @details Firmware uses this value instead of sizeof(nasti_master_config_type). constant PNP_CFG_MASTER_DESCR_BYTES : std_logic_vector(7 downto 0) := X"08"; --! @} --! @brief Plug-n-play descriptor structure for slave device. --! @details Each slave device must generates this datatype output that --! is connected directly to the 'pnp' slave module on system bus. type nasti_slave_config_type is record --! Descriptor size in bytes. descrsize : std_logic_vector(7 downto 0); --! Descriptor type. descrtype : std_logic_vector(1 downto 0); --! Descriptor size in bytes. irq_idx : integer; --! Base address value. xaddr : std_logic_vector(CFG_NASTI_CFG_ADDR_BITS-1 downto 0); --! Maskable bits of the base address. xmask : std_logic_vector(CFG_NASTI_CFG_ADDR_BITS-1 downto 0); --! Vendor ID. vid : std_logic_vector(15 downto 0); --! Device ID. did : std_logic_vector(15 downto 0); end record; --! @brief Arrays of the plug-n-play descriptors. --! @details Configuration bus vector from all slaves to plug'n'play --! NASTI device (pnp). type nasti_slave_cfg_vector is array (0 to CFG_NASTI_SLAVES_TOTAL-1) of nasti_slave_config_type; --! @brief Default slave config value. --! @default This value corresponds to an empty device and often used --! as assignment of outputs for the disabled device. constant nasti_slave_config_none : nasti_slave_config_type := ( PNP_CFG_SLAVE_DESCR_BYTES, PNP_CFG_TYPE_SLAVE, 0, (others => '0'), (others => '0'), VENDOR_GNSSSENSOR, SLV_DID_EMPTY); --! @brief Plug-n-play descriptor structure for master device. --! @details Each master device must generates this datatype output that --! is connected directly to the 'pnp' slave module on system bus. type nasti_master_config_type is record --! Descriptor size in bytes. descrsize : std_logic_vector(7 downto 0); --! Descriptor type. descrtype : std_logic_vector(1 downto 0); --! Vendor ID. vid : std_logic_vector(15 downto 0); --! Device ID. did : std_logic_vector(15 downto 0); end record; --! @brief Arrays of the plug-n-play descriptors. --! @details Configuration bus vector from all slaves to plug'n'play --! NASTI device (pnp). type nasti_master_cfg_vector is array (0 to CFG_NASTI_MASTER_TOTAL-1) of nasti_master_config_type; --! @brief Default master config value. constant nasti_master_config_none : nasti_master_config_type := ( PNP_CFG_MASTER_DESCR_BYTES, PNP_CFG_TYPE_MASTER, VENDOR_GNSSSENSOR, MST_DID_EMPTY); --! @brief AMBA AXI4 compliant data structure. type nasti_metadata_type is record --! @brief Read address. --! @details The read address gives the address of the first transfer --! in a read burst transaction. addr : std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0); --! @brief Burst length. --! @details This signal indicates the exact number of transfers in --! a burst. This changes between AXI3 and AXI4. nastiXLenBits=8 so --! this is an AXI4 implementation. --! Burst_Length = len[7:0] + 1 len : std_logic_vector(7 downto 0); --! @brief Burst size. --! @details This signal indicates the size of each transfer --! in the burst: 0=1 byte; ..., 6=64 bytes; 7=128 bytes; size : std_logic_vector(2 downto 0); --! @brief Read response. --! @details This signal indicates the status of the read transfer. --! The responses are: --! 0b00 FIXED - In a fixed burst, the address is the same for every transfer --! in the burst. Typically is used for FIFO. --! 0b01 INCR - Incrementing. In an incrementing burst, the address for each --! transfer in the burst is an increment of the address for the --! previous transfer. The increment value depends on the size of --! the transfer. --! 0b10 WRAP - A wrapping burst is similar to an incrementing burst, except --! that the address wraps around to a lower address if an upper address --! limit is reached. --! 0b11 resrved. burst : std_logic_vector(1 downto 0); --! @brief Lock type. --! @details Not supported in AXI4. lock : std_logic; --! @brief Memory type. --! @details See table for write and read transactions. cache : std_logic_vector(3 downto 0); --! @brief Protection type. --! @details This signal indicates the privilege and security level --! of the transaction, and whether the transaction is a data access --! or an instruction access: --! [0] : 0 = Unpriviledge access --! 1 = Priviledge access --! [1] : 0 = Secure access --! 1 = Non-secure access --! [2] : 0 = Data access --! 1 = Instruction access prot : std_logic_vector(2 downto 0); --! @brief Quality of Service, QoS. --! @details QoS identifier sent for each read transaction. --! Implemented only in AXI4: --! 0b0000 - default value. Indicates that the interface is --! not participating in any QoS scheme. qos : std_logic_vector(3 downto 0); --! @brief Region identifier. --! @details Permits a single physical interface on a slave to be used for --! multiple logical interfaces. Implemented only in AXI4. This is --! similar to the banks implementation in Leon3 without address --! decoding. region : std_logic_vector(3 downto 0); end record; --! @brief Empty metadata value. constant META_NONE : nasti_metadata_type := ( (others =>'0'), X"00", "000", NASTI_BURST_INCR, '0', X"0", "000", "0000", "0000" ); --! @brief Master device output signals type nasti_master_out_type is record --! Write Address channel: aw_valid : std_logic; --! metadata of the read channel. aw_bits : nasti_metadata_type; --! Write address ID. Identification tag used for a trasaction ordering. aw_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); --! Optional user defined signal in a write address channel. aw_user : std_logic; --! Write Data channel valid flag w_valid : std_logic; --! Write channel data value w_data : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); --! Write Data channel last address in a burst marker. w_last : std_logic; --! Write Data channel strob signals selecting certain bytes. w_strb : std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0); --! Optional user defined signal in write channel. w_user : std_logic; --! Write Response channel accepted by master. b_ready : std_logic; --! Read Address Channel data valid. ar_valid : std_logic; --! Read Address channel metadata. ar_bits : nasti_metadata_type; --! Read address ID. Identification tag used for a trasaction ordering. ar_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); --! Optional user defined signal in read address channel. ar_user : std_logic; --! Read Data channel: r_ready : std_logic; end record; --! @brief Master device empty value. --! @warning If the master is not connected to the vector then vector value --! MUST BE initialized by this value. constant nasti_master_out_none : nasti_master_out_type := ( '0', META_NONE, (others=>'0'), '0', '0', (others=>'0'), '0', (others=>'0'), '0', '0', '0', META_NONE, (others=>'0'), '0', '0'); --! @brief Array of all masters outputs. type nasti_master_out_vector is array (0 to CFG_NASTI_MASTER_TOTAL-1) of nasti_master_out_type; --! @brief Master device input signals. type nasti_master_in_type is record --! Write Address channel. aw_ready : std_logic; --! Write Data channel. w_ready : std_logic; --! Write Response channel: b_valid : std_logic; b_resp : std_logic_vector(1 downto 0); b_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); b_user : std_logic; --! Read Address Channel ar_ready : std_logic; --! Read valid. r_valid : std_logic; --! @brief Read response. --! @details This signal indicates the status of the read transfer. --! The responses are: --! 0b00 OKAY - Normal access success. Indicates that a normal access has --! been successful. Can also indicate an exclusive access --! has failed. --! 0b01 EXOKAY - Exclusive access okay. Indicates that either the read or --! write portion of an exclusive access has been successful. --! 0b10 SLVERR - Slave error. Used when the access has reached the slave --! successfully, but the slave wishes to return an error --! condition to the originating master. --! 0b11 DECERR - Decode error. Generated, typically by an interconnect --! component, to indicate that there is no slave at the --! transaction address. r_resp : std_logic_vector(1 downto 0); --! Read data r_data : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); --! @brief Read last. --! @details This signal indicates the last transfer in a read burst. r_last : std_logic; --! @brief Read ID tag. --! @details This signal is the identification tag for the read data --! group of signals generated by the slave. r_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); --! @brief User signal. --! @details Optional User-defined signal in the read channel. Supported --! only in AXI4. r_user : std_logic; end record; constant nasti_master_in_none : nasti_master_in_type := ( '0', '0', '0', NASTI_RESP_OKAY, (others=>'0'), '0', '0', '0', NASTI_RESP_OKAY, (others=>'0'), '0', (others=>'0'), '0'); type nasti_master_in_vector is array (0 to CFG_NASTI_MASTER_TOTAL-1) of nasti_master_in_type; --! @brief Slave device AMBA AXI input signals. type nasti_slave_in_type is record --! Write Address channel: aw_valid : std_logic; aw_bits : nasti_metadata_type; aw_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); aw_user : std_logic; --! Write Data channel: w_valid : std_logic; w_data : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); w_last : std_logic; w_strb : std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0); w_user : std_logic; --! Write Response channel: b_ready : std_logic; --! Read Address Channel: ar_valid : std_logic; ar_bits : nasti_metadata_type; ar_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); ar_user : std_logic; --! Read Data channel: r_ready : std_logic; end record; constant nasti_slave_in_none : nasti_slave_in_type := ( '0', META_NONE, (others=>'0'), '0', '0', (others=>'0'), '0', (others=>'0'), '0', '0', '0', META_NONE, (others=>'0'), '0', '0'); type nasti_slave_in_vector is array (0 to CFG_NASTI_SLAVES_TOTAL-1) of nasti_slave_in_type; --! @brief Slave device AMBA AXI output signals. type nasti_slave_out_type is record --! Write Address channel: aw_ready : std_logic; --! Write Data channel: w_ready : std_logic; --! Write Response channel: b_valid : std_logic; b_resp : std_logic_vector(1 downto 0); b_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); b_user : std_logic; --! Read Address Channel ar_ready : std_logic; --! Read Data channel: r_valid : std_logic; --! @brief Read response. --! @details This signal indicates the status of the read transfer. --! The responses are: --! 0b00 OKAY - Normal access success. Indicates that a normal access has --! been successful. Can also indicate an exclusive access --! has failed. --! 0b01 EXOKAY - Exclusive access okay. Indicates that either the read or --! write portion of an exclusive access has been successful. --! 0b10 SLVERR - Slave error. Used when the access has reached the slave --! successfully, but the slave wishes to return an error --! condition to the originating master. --! 0b11 DECERR - Decode error. Generated, typically by an interconnect --! component, to indicate that there is no slave at the --! transaction address. r_resp : std_logic_vector(1 downto 0); --! Read data r_data : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); --! Read last. This signal indicates the last transfer in a read burst. r_last : std_logic; --! @brief Read ID tag. --! @details This signal is the identification tag for the read data --! group of signals generated by the slave. r_id : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); --! @brief User signal. --! @details Optinal User-defined signal in the read channel. Supported --! only in AXI4. r_user : std_logic;--_vector(0 downto 0); end record; --! @brief Slave output signals connected to system bus. --! @details If the slave is not connected to the vector then vector value --! MUST BE initialized by this value. constant nasti_slave_out_none : nasti_slave_out_type := ( '0', '0', '0', NASTI_RESP_EXOKAY, (others=>'0'), '0', '0', '0', NASTI_RESP_EXOKAY, (others=>'1'), '0', (others=>'0'), '0'); --! Array of all slaves outputs. type nasti_slaves_out_vector is array (0 to CFG_NASTI_SLAVES_TOTAL-1) of nasti_slave_out_type; --! Array of addresses providing word aligned access. type global_addr_array_type is array (0 to CFG_WORDS_ON_BUS-1) of std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0); --! Slave device states during reading value operation. type nasti_slave_rstatetype is (rwait, rtrans); --! Slave device states during writting data operation. type nasti_slave_wstatetype is (wwait, wtrans); --! @brief Template bank of registers for any slave device. type nasti_slave_bank_type is record rstate : nasti_slave_rstatetype; wstate : nasti_slave_wstatetype; rburst : std_logic_vector(1 downto 0); rsize : integer; raddr : global_addr_array_type; rlen : integer; --! AXI4 supports 256 burst operation rid : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); rresp : std_logic_vector(1 downto 0); --! OK=0 ruser : std_logic; rwait_while_write : std_logic; --! Writing request has higher priority than read and can interrupt reading rwaitready : std_logic; --! Reading wait state flag: 0=waiting. User's waitstates wburst : std_logic_vector(1 downto 0); -- 0=INCREMENT wsize : integer; -- code in range 0=1 Bytes upto 7=128 Bytes. waddr : global_addr_array_type; --! 4 KB bank wlen : integer; --! AXI4 supports 256 burst operation wid : std_logic_vector(CFG_ROCKET_ID_BITS-1 downto 0); wresp : std_logic_vector(1 downto 0); --! OK=0 wuser : std_logic; b_valid : std_logic; end record; --! Reset value of the template bank of registers of a slave device. constant NASTI_SLAVE_BANK_RESET : nasti_slave_bank_type := ( rwait, wwait, NASTI_BURST_FIXED, 0, (others=>(others=>'0')), 0, (others=>'0'), NASTI_RESP_OKAY, '0', '0', '1', NASTI_BURST_FIXED, 0, (others=>(others=>'0')), 0, (others=>'0'), NASTI_RESP_OKAY, '0', '0' ); type dma_state_type is ( DMA_STATE_IDLE, DMA_STATE_R_WAIT_RESP, DMA_STATE_R_WAIT_NEXT, DMA_STATE_W, DMA_STATE_W_WAIT_REQ, DMA_STATE_B ); --! @brief Master device to DMA engine request signals type dma_request_type is record valid : std_logic; -- response is valid ready : std_logic; -- ready to accept response write : std_logic; addr : std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0); bytes : std_logic_vector(10 downto 0); size : std_logic_vector(2 downto 0); -- 010=4 bytes; 011=8 bytes wdata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); end record; --! @brief DMA engine to Master device response signals type dma_response_type is record ready : std_logic; -- ready to accespt request valid : std_logic; -- response is valid rdata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); end record; --! DMA engine registers bank type dma_bank_type is record state : dma_state_type; addr2 : std_logic; -- addr[2] bits to select low/high dword len : integer range 0 to 255; -- burst (length-1) op32 : std_logic; wdata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); end record; constant DMA_BANK_RESET : dma_bank_type := (DMA_STATE_IDLE, '0', 0, '0', (others => '0')); --! Device's DMA engine template procedure with AXI interface. --! @param [in] i_request Device to DMA engine request. --! @param [out] o_response DMA Engine to Device response. --! @param [in] i_bank Bank of registers implemented by master device. --! @param [out] o_bank Updated value for the master bank of registers. --! @param [in] i_msti AMBA to AXI master device signal. --! @param [out] o_msto AXI master device signal to AMBA controller signals. procedure procedureAxi4DMA( i_request : in dma_request_type; o_response : out dma_response_type; i_bank : in dma_bank_type; o_bank : out dma_bank_type; i_msti : in nasti_master_in_type; o_msto : out nasti_master_out_type ); --! Read/write access state machines implementation for the slave device. --! @param [in] i Slave input signal passed from system bus. --! @param [in] cfg Slave confguration descriptor defining memory base address. --! @param [in] i_bank Bank of registers implemented by each slave device. --! @param [out] o_bank Updated value for the slave bank of registers. procedure procedureAxi4( i : in nasti_slave_in_type; cfg : in nasti_slave_config_type; i_bank : in nasti_slave_bank_type; o_bank : out nasti_slave_bank_type ); --! @brief Reordering elements of the address to provide 4-bytes memory access. --! @param[in] mux Reordering control bits. --! @param[in] iaddr Input addresses array. --! @return Reordered addresses array. function functionAddressReorder( mux : std_logic_vector; iaddr : global_addr_array_type) return global_addr_array_type; procedure procedureWriteReorder( ena : in std_logic; mux : in std_logic_vector(1 downto 0); iwaddr : in global_addr_array_type; iwstrb : in std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0); iwdata : in std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); owaddr : out global_addr_array_type; owstrb : out std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0); owdata : out std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0) ); --! @brief Complementary to address data reordring. --! @details This function restore data bus as there wasn't address reordering. --! @param[in] mux Reordering control bits. --! @param[in] idata Input data array. --! @return Restored data array. function functionDataRestoreOrder( mux : std_logic_vector; idata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0)) return std_logic_vector; --! Convert slave bank registers into bus output signals. --! @param[in] r Bank of registers of the slave device. --! @param[in] rd_val Formed by slave device read data value. --! @return Slave device output signals connected to system bus. function functionAxi4Output( r : nasti_slave_bank_type; rd_val : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0)) return nasti_slave_out_type; --! @brief AXI bus controller. --! @param [in] watchdog_memop --! @param [in] i_clk System bus clock. --! @param [in] i_nrst Reset with active LOW level. --! @param [in] i_slvcfg Slaves configuration vector. --! @param [in] i_slvo Vector of slaves output signals. --! @param [in] i_msto Vector of masters output signals. --! @param [out] o_slvi Vector of slave inputs. --! @param [out] o_msti Vector of master inputs. --! @param [out] o_miss_irq Memory miss access signal. May be used as a interrupt or for debugging --! @param [out] o_miss_addr Miss access last address (debug purpose) --! @param [out] o_bus_util_w Write access bus utilization --! @param [out] o_bus_util_r Read access bus utilization --! @todo Round-robin priority algorithm. component axictrl is generic ( watchdog_memop : integer := 0 ); port ( i_clk : in std_logic; i_nrst : in std_logic; i_slvcfg : in nasti_slave_cfg_vector; i_slvo : in nasti_slaves_out_vector; i_msto : in nasti_master_out_vector; o_slvi : out nasti_slave_in_vector; o_msti : out nasti_master_in_vector; o_miss_irq : out std_logic; o_miss_addr : out std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0); o_bus_util_w : out std_logic_vector(CFG_NASTI_MASTER_TOTAL-1 downto 0); o_bus_util_r : out std_logic_vector(CFG_NASTI_MASTER_TOTAL-1 downto 0) ); end component; end; -- package declaration --! Implementation of the declared sub-programs (functions and --! procedures). package body types_amba4 is --! Device's DMA engine template procedure with AXI interface. --! @param [in] i_request Device to DMA engine request. --! @param [out] o_response DMA Engine to Device response. --! @param [in] i_bank Bank of registers implemented by master device. --! @param [out] o_bank Updated value for the master bank of registers. --! @param [in] i_msti AMBA to AXI master device signal. --! @param [out] o_msto AXI master device signal to AMBA controller signals. procedure procedureAxi4DMA( i_request : in dma_request_type; o_response : out dma_response_type; i_bank : in dma_bank_type; o_bank : out dma_bank_type; i_msti : in nasti_master_in_type; o_msto : out nasti_master_out_type ) is variable tmp_len : integer; begin o_bank := i_bank; o_msto := nasti_master_out_none; o_msto.ar_user := '0'; o_msto.ar_id := conv_std_logic_vector(0, CFG_ROCKET_ID_BITS); o_msto.ar_bits.size := (others => '0'); o_msto.ar_bits.burst := NASTI_BURST_INCR; o_msto.aw_user := '0'; o_msto.aw_id := conv_std_logic_vector(0, CFG_ROCKET_ID_BITS); o_msto.aw_bits.size := (others => '0'); o_msto.aw_bits.burst := NASTI_BURST_INCR; o_response.ready := '0'; o_response.valid := '0'; o_response.rdata := (others => '0'); case i_bank.state is when DMA_STATE_IDLE => o_msto.ar_valid := i_request.valid and not i_request.write; o_msto.aw_valid := i_request.valid and i_request.write; tmp_len := conv_integer(i_request.bytes(10 downto 2)) - 1; if i_request.valid = '1' and i_request.write = '1' then o_msto.aw_bits.addr := i_request.addr(CFG_NASTI_ADDR_BITS-1 downto 3) & "000"; o_bank.addr2 := i_request.addr(2); o_bank.len := tmp_len; o_msto.aw_bits.size := i_request.size; -- 4/8 bytes o_msto.aw_bits.len := conv_std_logic_vector(tmp_len, 8); o_bank.wdata := i_request.wdata; if i_msti.aw_ready = '1' then o_response.ready := '1'; o_bank.state := DMA_STATE_W; end if; elsif i_request.valid = '1' and i_request.write = '0' then o_msto.ar_bits.addr := i_request.addr; o_bank.addr2 := i_request.addr(2); o_bank.len := tmp_len; o_msto.ar_bits.size := i_request.size; -- 4/8 bytes o_msto.ar_bits.len := conv_std_logic_vector(tmp_len, 8); if i_msti.ar_ready = '1' then o_response.ready := '1'; o_bank.state := DMA_STATE_R_WAIT_RESP; end if; end if; if i_request.size = "010" then o_bank.op32 := '1'; else o_bank.op32 := '0'; end if; when DMA_STATE_R_WAIT_RESP => o_msto.r_ready := i_request.ready; o_response.valid := i_msti.r_valid; if (i_request.ready and i_msti.r_valid) = '1' then if i_bank.op32 = '1' and i_bank.addr2 = '1' then o_response.rdata := i_msti.r_data(63 downto 32) & i_msti.r_data(31 downto 0); else o_response.rdata := i_msti.r_data; end if; if i_msti.r_last = '1' then o_bank.state := DMA_STATE_IDLE; else if i_request.valid = '1' and i_request.write = '0' then o_response.ready := '1'; else o_bank.state := DMA_STATE_R_WAIT_NEXT; end if; end if; end if; when DMA_STATE_R_WAIT_NEXT => if i_request.valid = '1' and i_request.write = '0' then o_response.ready := '1'; o_bank.state := DMA_STATE_R_WAIT_RESP; end if; when DMA_STATE_W => o_msto.w_valid := '1'; if i_bank.op32 = '1' then case i_bank.addr2 is when '0' => o_msto.w_strb := X"0f"; when '1' => o_msto.w_strb := X"f0"; when others => end case; else o_msto.w_strb := X"ff"; end if; o_msto.w_data := i_bank.wdata; if i_msti.w_ready = '1' then if i_bank.len = 0 then o_bank.state := DMA_STATE_B; o_msto.w_last := '1'; elsif i_request.valid = '1' and i_request.write = '1' then o_bank.len := i_bank.len - 1; o_bank.wdata := i_request.wdata; o_response.ready := '1'; -- Address will be incremented on slave side --v.waddr2 := not r.waddr2; else o_bank.state := DMA_STATE_W_WAIT_REQ; end if; end if; when DMA_STATE_W_WAIT_REQ => if i_request.valid = '1' and i_request.write = '1' then o_bank.len := i_bank.len - 1; o_bank.wdata := i_request.wdata; o_response.ready := '1'; o_bank.state := DMA_STATE_W; end if; when DMA_STATE_B => o_msto.w_last := '0'; o_msto.b_ready := '1'; if i_msti.b_valid = '1' then o_bank.state := DMA_STATE_IDLE; end if; when others => end case; end; -- procedure --! Read/write access state machines implementation. --! @param [in] i Slave input signal passed from system bus. --! @param [in] cfg Slave confguration descriptor defining memory base address. --! @param [in] i_bank Bank of registers implemented by each slave device. --! @param [out] o_bank Updated value for the slave bank of registers. procedure procedureAxi4( i : in nasti_slave_in_type; cfg : in nasti_slave_config_type; i_bank : in nasti_slave_bank_type; o_bank : out nasti_slave_bank_type ) is variable traddr : std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0); variable twaddr : std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0); begin o_bank := i_bank; traddr := (i.ar_bits.addr(CFG_NASTI_ADDR_BITS-1 downto 12) and (not cfg.xmask)) & i.ar_bits.addr(11 downto 0); o_bank.rwait_while_write := '0'; -- Reading state machine: case i_bank.rstate is when rwait => if i.ar_valid = '1' and i_bank.wstate /= wtrans then o_bank.rstate := rtrans; for n in 0 to CFG_WORDS_ON_BUS-1 loop o_bank.raddr(n) := traddr + n*CFG_ALIGN_BYTES; end loop; o_bank.rsize := XSizeToBytes(conv_integer(i.ar_bits.size)); o_bank.rburst := i.ar_bits.burst; o_bank.rlen := conv_integer(i.ar_bits.len); o_bank.rid := i.ar_id; o_bank.rresp := NASTI_RESP_OKAY; o_bank.ruser := i.ar_user; --! No Wait States by default for reading operation. --! --! User can re-assign this value directly in module to implement --! reading wait states. --! Example: see axi2fse.vhd bridge implementation o_bank.rwaitready := '1'; o_bank.rwait_while_write := i.aw_valid; end if; when rtrans => o_bank.rwait_while_write := i.aw_valid or i.w_valid; if i.r_ready = '1' and i_bank.rwaitready = '1' and i_bank.rwait_while_write = '0' then o_bank.rlen := i_bank.rlen - 1; if i_bank.rburst = NASTI_BURST_INCR then for n in 0 to CFG_WORDS_ON_BUS-1 loop o_bank.raddr(n) := i_bank.raddr(n) + i_bank.rsize; end loop; end if; -- End of transaction (or process another one): if i_bank.rlen = 0 then if i.ar_valid = '0' then o_bank.rstate := rwait; else for n in 0 to CFG_WORDS_ON_BUS-1 loop o_bank.raddr(n) := traddr + n*CFG_ALIGN_BYTES; end loop; o_bank.rsize := XSizeToBytes(conv_integer(i.ar_bits.size)); o_bank.rburst := i.ar_bits.burst; o_bank.rlen := conv_integer(i.ar_bits.len); o_bank.rid := i.ar_id; o_bank.rresp := NASTI_RESP_OKAY; o_bank.ruser := i.ar_user; o_bank.rwaitready := '1'; end if; end if; end if; end case; -- Writting state machine: case i_bank.wstate is when wwait => if i.aw_valid = '1' then o_bank.wstate := wtrans; twaddr := (i.aw_bits.addr(CFG_NASTI_ADDR_BITS-1 downto 12) and (not cfg.xmask)) & i.aw_bits.addr(11 downto 0); for n in 0 to CFG_WORDS_ON_BUS-1 loop o_bank.waddr(n) := twaddr + n*CFG_ALIGN_BYTES; end loop; o_bank.wsize := XSizeToBytes(conv_integer(i.aw_bits.size)); o_bank.wburst := i.aw_bits.burst; o_bank.wlen := conv_integer(i.aw_bits.len); o_bank.wid := i.aw_id; o_bank.wresp := NASTI_RESP_OKAY; o_bank.wuser := i.aw_user; end if; when wtrans => if i.w_valid = '1' then o_bank.wlen := i_bank.wlen - 1; if i_bank.wburst = NASTI_BURST_INCR then for n in 0 to CFG_WORDS_ON_BUS-1 loop o_bank.waddr(n) := i_bank.waddr(n) + i_bank.wsize; end loop; end if; -- End of transaction: if i_bank.wlen = 0 then o_bank.wstate := wwait; o_bank.b_valid := '1'; end if; end if; end case; if i.b_ready = '1' and i_bank.b_valid = '1' then o_bank.b_valid := '0'; end if; end; -- procedure --! @brief Reordering elements of the address to provide 4-bytes memory access. --! @param[in] mux Reordering control bits. --! @param[in] iaddr Input addresses array. --! @return Reordered addresses array. function functionAddressReorder( mux : std_logic_vector; iaddr : global_addr_array_type) return global_addr_array_type is variable oaddr : global_addr_array_type; begin if CFG_NASTI_DATA_BITS = 128 then if mux = "00" then oaddr := iaddr; elsif mux = "01" then oaddr(0) := iaddr(3); oaddr(1) := iaddr(0); oaddr(2) := iaddr(1); oaddr(3) := iaddr(2); elsif mux = "10" then oaddr(0) := iaddr(2); oaddr(1) := iaddr(3); oaddr(2) := iaddr(0); oaddr(3) := iaddr(1); else oaddr(0) := iaddr(1); oaddr(1) := iaddr(2); oaddr(2) := iaddr(3); oaddr(3) := iaddr(0); end if; elsif CFG_NASTI_DATA_BITS = 64 then if mux(2) = '0' then oaddr := iaddr; else oaddr(0) := iaddr(1); oaddr(1) := iaddr(0); end if; end if; return oaddr; end; --! @brief Reordering elements of the write transaction to provide 4-bytes memory access. procedure procedureWriteReorder( ena : in std_logic; mux : in std_logic_vector(1 downto 0); iwaddr : in global_addr_array_type; iwstrb : in std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0); iwdata : in std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); owaddr : out global_addr_array_type; owstrb : out std_logic_vector(CFG_NASTI_DATA_BYTES-1 downto 0); owdata : out std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0)) is begin if CFG_NASTI_DATA_BITS = 128 and ena = '1' then if mux = "00" then owaddr := iwaddr; owdata := iwdata; owstrb := iwstrb; elsif mux = "01" then owaddr(0) := iwaddr(3); owaddr(1) := iwaddr(0); owaddr(2) := iwaddr(1); owaddr(3) := iwaddr(2); owdata(31 downto 0) := iwdata(127 downto 96); owdata(127 downto 32) := iwdata(95 downto 0); owstrb := iwstrb(11 downto 0) & iwstrb(15 downto 12); elsif mux = "10" then owaddr(0) := iwaddr(2); owaddr(1) := iwaddr(3); owaddr(2) := iwaddr(0); owaddr(3) := iwaddr(1); owdata(63 downto 0) := iwdata(127 downto 64); owdata(127 downto 64) := iwdata(63 downto 0); owstrb := iwstrb(7 downto 0) & iwstrb(15 downto 8); else owaddr(0) := iwaddr(1); owaddr(1) := iwaddr(2); owaddr(2) := iwaddr(3); owaddr(3) := iwaddr(0); owdata(95 downto 0) := iwdata(127 downto 32); owdata(127 downto 96) := iwdata(31 downto 0); owstrb := iwstrb(3 downto 0) & iwstrb(15 downto 4); end if; elsif CFG_NASTI_DATA_BITS = 64 and ena = '1' then if mux(0) = '0' then owaddr := iwaddr; owdata := iwdata; owstrb := iwstrb; else owaddr(0) := iwaddr(1); owaddr(1) := iwaddr(0); owdata(31 downto 0) := iwdata(63 downto 32); owdata(63 downto 32) := iwdata(31 downto 0); owstrb := iwstrb(3 downto 0) & iwstrb(7 downto 4); end if; else owaddr := (others => (others => '0')); owdata := (others => '0'); owstrb := (others => '0'); end if; end; --! @brief Complementary to address data reordring. --! @details This function restore data bus as there wasn't address reordering. --! @param[in] mux Reordering control bits. --! @param[in] idata Input data array. --! @return Restored data array. function functionDataRestoreOrder( mux : std_logic_vector; idata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0)) return std_logic_vector is variable odata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0); begin if CFG_NASTI_DATA_BITS = 128 then if mux = "00" then odata := idata; elsif mux = "01" then odata(95 downto 0) := idata(127 downto 32); odata(127 downto 96) := idata(31 downto 0); elsif mux = "10" then odata(63 downto 0) := idata(127 downto 64); odata(127 downto 64) := idata(63 downto 0); else odata(31 downto 0) := idata(127 downto 96); odata(127 downto 32) := idata(95 downto 0); end if; elsif CFG_NASTI_DATA_BITS = 64 then if mux(2) = '0' then odata := idata; else odata(31 downto 0) := idata(63 downto 32); odata(63 downto 32) := idata(31 downto 0); end if; end if; return odata; end; --! @brief Convert bank registers into output signals --! @param[in] r Registers bank with the AXI4 state machines --! implementaitons. --! @param[in] rd_val Read value from the device's registers bank. --! This value fully depends of device implementation. --! @return NASTI output signals of the implemented slave device. function functionAxi4Output( r : nasti_slave_bank_type; rd_val : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0)) return nasti_slave_out_type is variable ret : nasti_slave_out_type; begin -- Read transfer: ret.aw_ready := '1'; ret.ar_ready := '1'; ret.r_id := r.rid; if r.rstate = rtrans and r.rlen = 0 then ret.r_last := '1'; else ret.r_last := '0'; end if; ret.r_resp := r.rresp; ret.r_user := r.ruser; if r.rwaitready = '1' and r.rstate = rtrans and r.rwait_while_write = '0' then ret.r_valid := '1'; else ret.r_valid := '0'; end if; ret.r_data := rd_val; -- Write transfer: if r.wstate = wtrans then ret.w_ready := '1'; ret.aw_ready := '0'; ret.ar_ready := '0'; else ret.w_ready := '0'; end if; -- Write Handshaking: ret.b_id := r.wid; ret.b_resp := r.wresp; ret.b_user := r.wuser; ret.b_valid := r.b_valid; return (ret); end; end; -- package body