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

Subversion Repositories rio

[/] [rio/] [branches/] [2.0.0-development/] [rtl/] [vhdl/] [RioWbBridge.vhd] - Rev 47

Go to most recent revision | Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- 
-- RapidIO IP Library Core
-- 
-- This file is part of the RapidIO IP library project
-- http://www.opencores.org/cores/rio/
-- 
-- Description
-- Containing a bridge between a RapidIO network and a Wishbone bus. Packets
-- NWRITE, NWRITER and NREAD are currently supported.
-- 
-- To Do:
-- - Move packet handlers to RioLogicalPackets and make them symetrical.
-- - Add support for addressing to implementation defined config space by
--   adding interface to top entity.
-- - Set the stb_o to '0' in between read accesses to conform better to a
--   block transfer in the Wishbone standard.
-- - Clean up cyc-signals, only stb-signals are needed (between
--   RioLogicalCommon and the packet handlers).
-- - Add support for the lock_o to be sure to transfer all the packet
--   content atomically?
-- - Add support for EXTENDED_ADDRESS.
-- - Use the baseDeviceId when sending packets? Currently, all responses
--   are sent with destination<->source exchanged so the baseDeviceId is not
--   needed.
-- - Support inbound data with full bandwidth, not just half, applies to
--   RioLogicalCommon and the packet handlers.
-- - Move the packet handlers to seperate files.
-- - Increase the priority of the response-packet when sent?
-- - Implement error indications if erronous packets are received.
-- - Implement error indications if err_i is received on the Wishbone bus.
-- - Add support for extended features to dynamically configure the status
--   from the port this block is connected to. Needed for the discovered- and
--   masterEnable-bits.
-- - Add support for outbound doorbells connected to interrupt input pins.
-- 
-- Author(s): 
-- - Magnus Rosenius, magro732@opencores.org
-- 
-------------------------------------------------------------------------------
-- 
-- Copyright (C) 2013 Authors and OPENCORES.ORG 
-- 
-- This source file may be used and distributed without 
-- restriction provided that this copyright statement is not 
-- removed from the file and that any derivative work contains 
-- the original copyright notice and the associated disclaimer. 
-- 
-- This source file is free software; you can redistribute it 
-- and/or modify it under the terms of the GNU Lesser General 
-- Public License as published by the Free Software Foundation; 
-- either version 2.1 of the License, or (at your option) any 
-- later version. 
-- 
-- This source 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 Lesser General Public License for more 
-- details. 
-- 
-- You should have received a copy of the GNU Lesser General 
-- Public License along with this source; if not, download it 
-- from http://www.opencores.org/lgpl.shtml 
-- 
-------------------------------------------------------------------------------
 
 
-------------------------------------------------------------------------------
-- RioWbBridge.
-- This block acts as an RapidIO endpoint and converts packets into Wishbone
-- accesses.
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.rio_common.all;
 
-------------------------------------------------------------------------------
-- Entity for RioWbBridge.
-------------------------------------------------------------------------------
entity RioWbBridge is
  generic(
    EXTENDED_ADDRESS : natural range 0 to 2 := 0;
    DEVICE_IDENTITY : std_logic_vector(15 downto 0);
    DEVICE_VENDOR_IDENTITY : std_logic_vector(15 downto 0);
    DEVICE_REV : std_logic_vector(31 downto 0);
    ASSY_IDENTITY : std_logic_vector(15 downto 0);
    ASSY_VENDOR_IDENTITY : std_logic_vector(15 downto 0);
    ASSY_REV : std_logic_vector(15 downto 0));
  port(
    clk : in std_logic;
    areset_n : in std_logic;
    enable : in std_logic;
 
    readFrameEmpty_i : in std_logic;
    readFrame_o : out std_logic;
    readContent_o : out std_logic;
    readContentEnd_i : in std_logic;
    readContentData_i : in std_logic_vector(31 downto 0);
    writeFrameFull_i : in std_logic;
    writeFrame_o : out std_logic;
    writeFrameAbort_o : out std_logic;
    writeContent_o : out std_logic;
    writeContentData_o : out std_logic_vector(31 downto 0);
 
    cyc_o : out std_logic;
    stb_o : out std_logic;
    we_o : out std_logic;
    adr_o : out std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
    sel_o : out std_logic_vector(7 downto 0); 
    dat_o : out std_logic_vector(63 downto 0);
    dat_i : in std_logic_vector(63 downto 0);
    err_i : in std_logic;
    ack_i : in std_logic);
end entity;
 
 
-------------------------------------------------------------------------------
-- Architecture for RioWbBridge.
-------------------------------------------------------------------------------
architecture RioWbBridgeImpl of RioWbBridge is
 
  component RequestClassInbound is
    generic(
      EXTENDED_ADDRESS : natural range 0 to 2 := 0);
    port(
      clk : in std_logic;
      areset_n : in std_logic;
      enable : in std_logic;
 
      ready_o : out std_logic;
      vc_o : out std_logic;
      crf_o : out std_logic;
      prio_o : out std_logic_vector(1 downto 0);
      tt_o : out std_logic_vector(1 downto 0);
      dstId_o : out std_logic_vector(31 downto 0);
      srcId_o : out std_logic_vector(31 downto 0);
      tid_o : out std_logic_vector(7 downto 0);
      address_o : out std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
      length_o : out std_logic_vector(4 downto 0);
      select_o : out std_logic_vector(7 downto 0);
      done_i : in std_logic;
 
      inboundCyc_i : in std_logic;
      inboundStb_i : in std_logic;
      inboundAdr_i : in std_logic_vector(7 downto 0);
      inboundDat_i : in std_logic_vector(31 downto 0);
      inboundAck_o : out std_logic);
  end component;
 
  component WriteClassInbound is
    generic(
      EXTENDED_ADDRESS : natural range 0 to 2 := 0);
    port(
      clk : in std_logic;
      areset_n : in std_logic;
      enable : in std_logic;
 
      ready_o : out std_logic;
      responseNeeded_o : out std_logic;
      vc_o : out std_logic;
      crf_o : out std_logic;
      prio_o : out std_logic_vector(1 downto 0);
      tt_o : out std_logic_vector(1 downto 0);
      dstId_o : out std_logic_vector(31 downto 0);
      srcId_o : out std_logic_vector(31 downto 0);
      tid_o : out std_logic_vector(7 downto 0);
      address_o : out std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
      length_o : out std_logic_vector(4 downto 0);
      select_o : out std_logic_vector(7 downto 0);
      payloadRead_i : in std_logic;
      payloadIndex_i : in std_logic_vector(4 downto 0);
      payload_o : out std_logic_vector(63 downto 0);
      done_i : in std_logic;
 
      inboundCyc_i : in std_logic;
      inboundStb_i : in std_logic;
      inboundAdr_i : in std_logic_vector(7 downto 0);
      inboundDat_i : in std_logic_vector(31 downto 0);
      inboundAck_o : out std_logic);
  end component;
 
  component ResponseClassOutbound is
    port(
      clk : in std_logic;
      areset_n : in std_logic;
      enable : in std_logic;
 
      ready_i : in std_logic;
      vc_i : in std_logic;
      crf_i : in std_logic;
      prio_i : in std_logic_vector(1 downto 0);
      tt_i : in std_logic_vector(1 downto 0);
      dstid_i : in std_logic_vector(31 downto 0);
      srcid_i : in std_logic_vector(31 downto 0);
      tid_i : in std_logic_vector(7 downto 0);
      error_i : in std_logic;
      payloadPresent_i :  in std_logic;
      payloadLength_i : in std_logic_vector(4 downto 0);
      payloadWrite_i : in std_logic;
      payloadIndex_i : in std_logic_vector(4 downto 0);
      payload_i : in std_logic_vector(63 downto 0);
      done_o : out std_logic;
 
      outboundCyc_o : out std_logic;
      outboundStb_o : out std_logic;
      outboundDat_o : out std_logic_vector(31 downto 0);
      outboundAck_i : in std_logic);
  end component;
 
  constant PORTS : natural := 2;
 
  type StateType is (IDLE,
                     REQUEST_CLASS, REQUEST_CLASS_RESPONSE,
                     WRITE_CLASS, WRITE_CLASS_ACCESS, WRITE_CLASS_ACK, WRITE_CLASS_RESPONSE);
  signal state : StateType;
 
  signal adr : std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
  signal datOut : std_logic_vector(63 downto 0);
 
  signal payloadUpdate : std_logic;
  signal payloadIndex : std_logic_vector(4 downto 0);
 
  signal requestReady : std_logic;
  signal requestVc : std_logic;
  signal requestCrf : std_logic;
  signal requestPrio : std_logic_vector(1 downto 0);
  signal requestTt : std_logic_vector(1 downto 0);
  signal requestDstId : std_logic_vector(31 downto 0);
  signal requestSrcId : std_logic_vector(31 downto 0);
  signal requestTid : std_logic_vector(7 downto 0);
  signal requestAddress : std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
  signal requestLength : std_logic_vector(4 downto 0);
  signal requestSelect : std_logic_vector(7 downto 0);
  signal requestDone : std_logic;
  signal requestAck : std_logic;
 
  signal writeReady : std_logic;
  signal writeResponse : std_logic;
  signal writeVc : std_logic;
  signal writeCrf : std_logic;
  signal writePrio : std_logic_vector(1 downto 0);
  signal writeTt : std_logic_vector(1 downto 0);
  signal writeDstId : std_logic_vector(31 downto 0);
  signal writeSrcId : std_logic_vector(31 downto 0);
  signal writeTid : std_logic_vector(7 downto 0);
  signal writeAddress : std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
  signal writeLength : std_logic_vector(4 downto 0);
  signal writeSelect : std_logic_vector(7 downto 0);
  signal writePayload : std_logic_vector(63 downto 0);
  signal writeDone : std_logic;
  signal writeAck : std_logic;
 
  signal responseReady : std_logic;
  signal responseVc : std_logic;
  signal responseCrf : std_logic;
  signal responsePrio : std_logic_vector(1 downto 0);
  signal responseTt : std_logic_vector(1 downto 0);
  signal responseDstId : std_logic_vector(31 downto 0);
  signal responseSrcId : std_logic_vector(31 downto 0);
  signal responseTid : std_logic_vector(7 downto 0);
  signal responseError : std_logic;
  signal responsePayloadPresent : std_logic;
  signal responsePayload : std_logic_vector(63 downto 0);
  signal responseDone : std_logic;
 
  signal readRequestInbound : std_logic;
  signal writeRequestInbound : std_logic;
  signal vcInbound : std_logic;
  signal crfInbound : std_logic;
  signal prioInbound : std_logic_vector(1 downto 0);
  signal ttInbound : std_logic_vector(1 downto 0);
  signal dstIdInbound : std_logic_vector(31 downto 0);
  signal srcIdInbound : std_logic_vector(31 downto 0);
  signal sizeInbound : std_logic_vector(3 downto 0);
  signal tidInbound : std_logic_vector(7 downto 0);
  signal offsetInbound : std_logic_vector(20 downto 0);
  signal wdptrInbound : std_logic;
  signal payloadLengthInbound : std_logic_vector(2 downto 0);
  signal payloadInbound : std_logic_vector(63 downto 0);
 
  signal readResponseMaint : std_logic;
  signal writeResponseMaint : std_logic;
  signal statusMaint : std_logic_vector(3 downto 0);
  signal payloadLengthMaint : std_logic_vector(2 downto 0);
  signal payloadIndexMaint : std_logic_vector(2 downto 0);
  signal payloadMaint : std_logic_vector(63 downto 0);
  signal doneMaint : std_logic;
 
  signal payloadIndexOutbound : std_logic_vector(2 downto 0);
  signal doneOutbound : std_logic;
 
  signal configStb : std_logic;
  signal configWe : std_logic;
  signal configAdr : std_logic_vector(21 downto 0);
  signal configAdrByte : std_logic_vector(23 downto 0);
  signal configDatWrite : std_logic_vector(31 downto 0);
  signal configDatRead : std_logic_vector(31 downto 0);
  signal configAck : std_logic;
  signal maintenanceAck : std_logic;
 
  signal inboundCyc : std_logic;
  signal inboundStb : std_logic;
  signal inboundAdr : std_logic_vector(7 downto 0);
  signal inboundDat : std_logic_vector(31 downto 0);
  signal inboundAck : std_logic;
 
  signal outboundCyc : std_logic_vector(PORTS-1 downto 0);
  signal outboundStb : std_logic_vector(PORTS-1 downto 0);
  signal outboundDat : std_logic_vector(32*PORTS-1 downto 0);
  signal outboundAck : std_logic_vector(PORTS-1 downto 0);
 
begin
 
  responseVc <= requestVc when (responsePayloadPresent = '1') else writeVc;
  responseCrf <= requestCrf when (responsePayloadPresent = '1') else writeCrf;
  responsePrio <= requestPrio when (responsePayloadPresent = '1') else writePrio;
  responseTt <= requestTt when (responsePayloadPresent = '1') else writeTt;
  responseDstId <= requestSrcId when (responsePayloadPresent = '1') else writeSrcId;
  responseSrcId <= requestDstId when (responsePayloadPresent = '1') else writeDstId;
  responseTid <= requestTid when (responsePayloadPresent = '1') else writeTid;
 
  -----------------------------------------------------------------------------
  -- 
  -----------------------------------------------------------------------------
  adr_o <= adr;
  dat_o <= datOut;
 
  Bridge: process(clk, areset_n)
  begin
    if (areset_n = '0') then
      cyc_o <= '0';
      stb_o <= '0';
      we_o <= '0';
      adr <= (others=>'0');
      datOut <= (others=>'0');
 
      payloadUpdate <= '0';
      payloadIndex <= (others=>'0');
 
      requestDone <= '0';
 
      writeDone <= '0';
 
      responseReady <= '0';
      responseError <= '0';
      responsePayloadPresent <= '0';
      responsePayload <= (others=>'0');
    elsif (clk'event and clk = '1') then
      if (enable = '1') then
        requestDone <= '0';
        writeDone <= '0';
        responseReady <= '0';
 
        payloadUpdate <= '0';
        if (payloadUpdate = '1') then
          payloadIndex <= std_logic_vector(unsigned(payloadIndex) + 1);
        end if;
 
        case state is
          when IDLE =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            if (requestReady = '1') then
              cyc_o <= '1';
              stb_o <= '1';
              we_o <= '0';
              adr <= requestAddress;
              sel_o <= requestSelect;
 
              payloadIndex <= (others=>'0');
 
              responsePayloadPresent <= '1';
              state <= REQUEST_CLASS;
            elsif (writeReady = '1') then
              adr <= writeAddress;
 
              payloadUpdate <= '1';
              payloadIndex <= (others=>'0');
 
              responsePayloadPresent <= '0';
              state <= WRITE_CLASS;
            end if;          
 
          when REQUEST_CLASS =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            if (ack_i = '1') then
              -- Note that responsePayloadIndex is updated after the write has been made.
              payloadUpdate <= '1';
              responsePayload <= dat_i;
 
              adr <= std_logic_vector(unsigned(adr) + 1);
 
              if (payloadIndex = requestLength) then
                requestDone <= '1';
                cyc_o <= '0';
                stb_o <= '0';
                state <= REQUEST_CLASS_RESPONSE;
              end if;
--          elsif(err_i = '1') then
--            REMARK: Implement error indication from wb-bus...
            end if;
 
          when REQUEST_CLASS_RESPONSE =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            if (responseDone = '1') then
              responseReady <= '0';
              state <= IDLE;
            else
              responseReady <= '1';
            end if;
 
          when WRITE_CLASS =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            state <= WRITE_CLASS_ACCESS;
 
          when WRITE_CLASS_ACCESS =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            cyc_o <= '1';
            stb_o <= '1';
            we_o <= '1';
            sel_o <= writeSelect;
            datOut <= writePayload;
            payloadUpdate <= '1';
 
            state <= WRITE_CLASS_ACK;
 
          when WRITE_CLASS_ACK =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            if (ack_i = '1') then
              adr <= std_logic_vector(unsigned(adr) + 1);
 
              if (unsigned(payloadIndex) /= (unsigned(writeLength)+2)) then
                stb_o <= '0';
                state <= WRITE_CLASS_ACCESS;
              else
                writeDone <= '1';
                cyc_o <= '0';
                stb_o <= '0';
                state <= WRITE_CLASS_RESPONSE;
              end if;
            end if;
 
          when WRITE_CLASS_RESPONSE =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            if (responseDone = '1') or (writeResponse = '0') then
              responseReady <= '0';
              state <= IDLE;
            else
              responseReady <= '1';
            end if;
 
          when others =>
 
        end case;
      end if;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  -- Packet handlers.
  -----------------------------------------------------------------------------
 
  RequestClassInboundInst: RequestClassInbound
    generic map(
      EXTENDED_ADDRESS=>EXTENDED_ADDRESS)
    port map(
      clk=>clk,
      areset_n=>areset_n,
      enable=>enable,
      ready_o=>requestReady,
      vc_o=>requestVc,
      crf_o=>requestCrf,
      prio_o=>requestPrio,
      tt_o=>requestTt,
      dstId_o=>requestDstId,
      srcId_o=>requestSrcId,
      tid_o=>requestTid,
      address_o=>requestAddress,
      length_o=>requestLength,
      select_o=>requestSelect,
      done_i=>requestDone,
      inboundCyc_i=>inboundCyc,
      inboundStb_i=>inboundStb,
      inboundAdr_i=>inboundAdr,
      inboundDat_i=>inboundDat,
      inboundAck_o=>requestAck);
 
  WriteClassInboundInst: WriteClassInbound
    generic map(
      EXTENDED_ADDRESS=>EXTENDED_ADDRESS)
    port map(
      clk=>clk, 
      areset_n=>areset_n, 
      enable=>enable, 
      ready_o=>writeReady, 
      responseNeeded_o=>writeResponse,
      vc_o=>writeVc, 
      crf_o=>writeCrf, 
      prio_o=>writePrio, 
      tt_o=>writeTt, 
      dstId_o=>writeDstId, 
      srcId_o=>writeSrcId, 
      tid_o=>writeTid, 
      address_o=>writeAddress, 
      length_o=>writeLength, 
      select_o=>writeSelect, 
      payloadRead_i=>payloadUpdate, 
      payloadIndex_i=>payloadIndex, 
      payload_o=>writePayload, 
      done_i=>writeDone, 
      inboundCyc_i=>inboundCyc, 
      inboundStb_i=>inboundStb, 
      inboundAdr_i=>inboundAdr, 
      inboundDat_i=>inboundDat, 
      inboundAck_o=>writeAck);
 
  ResponseClassOutboundInst: ResponseClassOutbound
    port map(
      clk=>clk,
      areset_n=>areset_n,
      enable=>enable,
      ready_i=>responseReady,
      vc_i=>responseVc,
      crf_i=>responseCrf,
      prio_i=>responsePrio,
      tt_i=>responseTt,
      dstid_i=>responseDstId,
      srcid_i=>responseSrcId,
      tid_i=>responseTid,
      error_i=>responseError,
      payloadPresent_i=>responsePayloadPresent,
      payloadLength_i=>requestLength,
      payloadWrite_i=>payloadUpdate,
      payloadIndex_i=>payloadIndex,
      payload_i=>responsePayload,
      done_o=>responseDone,
      outboundCyc_o=>outboundCyc(0),
      outboundStb_o=>outboundStb(0),
      outboundDat_o=>outboundDat(31 downto 0),
      outboundAck_i=>outboundAck(0));
 
  -----------------------------------------------------------------------------
  -- Maintenance packet processing.
  -----------------------------------------------------------------------------
  InboundMaintenance: MaintenanceInbound
    port map(
      clk=>clk, areset_n=>areset_n, enable=>enable, 
      readRequestReady_o=>readRequestInbound,
      writeRequestReady_o=>writeRequestInbound,
      readResponseReady_o=>open,
      writeResponseReady_o=>open,
      portWriteReady_o=>open,
      vc_o=>vcInbound, 
      crf_o=>crfInbound, 
      prio_o=>prioInbound, 
      tt_o=>ttInbound, 
      dstid_o=>dstIdInbound, 
      srcid_o=>srcIdInbound,
      size_o=>sizeInbound,
      status_o=>open,
      tid_o=>tidInbound,
      hop_o=>open,
      offset_o=>offsetInbound,
      wdptr_o=>wdptrInbound,
      payloadLength_o=>payloadLengthInbound, 
      payloadIndex_i=>payloadIndexMaint, 
      payload_o=>payloadInbound, 
      done_i=>doneMaint, 
      inboundCyc_i=>inboundCyc, 
      inboundStb_i=>inboundStb, 
      inboundAdr_i=>inboundAdr, 
      inboundDat_i=>inboundDat, 
      inboundAck_o=>maintenanceAck);
 
  OutboundMaintenance: MaintenanceOutbound
    port map(
      clk=>clk, areset_n=>areset_n, enable=>enable, 
      readRequestReady_i=>'0',
      writeRequestReady_i=>'0',
      readResponseReady_i=>readResponseMaint, 
      writeResponseReady_i=>writeResponseMaint, 
      portWriteReady_i=>'0',
      vc_i=>vcInbound, 
      crf_i=>crfInbound, 
      prio_i=>prioInbound, 
      tt_i=>ttInbound, 
      dstid_i=>srcIdInbound, 
      srcid_i=>dstIdInbound,
      size_i=>(others=>'0'),
      status_i=>statusMaint,
      tid_i=>tidInbound,
      hop_i=>x"ff",
      offset_i=>(others=>'0'),
      wdptr_i=>'0',
      payloadLength_i=>payloadLengthMaint, 
      payloadIndex_o=>payloadIndexOutbound, 
      payload_i=>payloadMaint,
      done_o=>doneOutbound, 
      outboundCyc_o=>outboundCyc(1), 
      outboundStb_o=>outboundStb(1), 
      outboundDat_o=>outboundDat(63 downto 32), 
      outboundAck_i=>outboundAck(1));
 
  MaintenanceBridge: RioLogicalMaintenance
    port map(
      clk=>clk, areset_n=>areset_n, enable=>enable, 
      readRequestReady_i=>readRequestInbound, 
      writeRequestReady_i=>writeRequestInbound,
      size_i=>sizeInbound,
      offset_i=>offsetInbound, 
      wdptr_i=>wdptrInbound, 
      payloadLength_i=>payloadLengthInbound, 
      payloadIndex_o=>payloadIndexMaint, 
      payload_i=>payloadInbound, 
      done_o=>doneMaint,
      readResponseReady_o=>readResponseMaint, 
      writeResponseReady_o=>writeResponseMaint,
      status_o=>statusMaint, 
      payloadLength_o=>payloadLengthMaint, 
      payloadIndex_i=>payloadIndexOutbound, 
      payload_o=>payloadMaint, 
      done_i=>doneOutbound, 
      configStb_o=>configStb, 
      configWe_o=>configWe, 
      configAdr_o=>configAdr, 
      configDat_o=>configDatWrite, 
      configDat_i=>configDatRead, 
      configAck_i=>configAck);
 
  -----------------------------------------------------------------------------
  -- Common interface toward the packet queues.
  -----------------------------------------------------------------------------
 
  inboundAck <= requestAck or writeAck or maintenanceAck;
  RioLogicalCommonInst: RioLogicalCommon
    generic map(PORTS=>PORTS)
    port map(
      clk=>clk,
      areset_n=>areset_n,
      enable=>enable,
      readFrameEmpty_i=>readFrameEmpty_i,
      readFrame_o=>readFrame_o,
      readContent_o=>readContent_o,
      readContentEnd_i=>readContentEnd_i,
      readContentData_i=>readContentData_i,
      writeFrameFull_i=>writeFrameFull_i,
      writeFrame_o=>writeFrame_o,
      writeFrameAbort_o=>writeFrameAbort_o,
      writeContent_o=>writeContent_o,
      writeContentData_o=>writeContentData_o,
      inboundCyc_o=>inboundCyc,
      inboundStb_o=>inboundStb,
      inboundAdr_o=>inboundAdr,
      inboundDat_o=>inboundDat,
      inboundAck_i=>inboundAck,
      outboundCyc_i=>outboundCyc,
      outboundStb_i=>outboundStb,
      outboundDat_i=>outboundDat,
      outboundAck_o=>outboundAck);
 
  -----------------------------------------------------------------------------
  -- Configuration memory.
  -----------------------------------------------------------------------------
  configAdrByte <= configAdr & "00";
  memoryConfig : process(clk, areset_n)
    variable componentTag : std_logic_vector(31 downto 0);
    variable hostBaseDeviceIdLocked : std_logic;
    variable hostBaseDeviceId : std_logic_vector(15 downto 0);
  begin
    if (areset_n = '0') then
      componentTag := (others => '0');
      hostBaseDeviceIdLocked := '0';
      hostBaseDeviceId := (others => '1');
 
      configDatRead <= (others => '0');
      configAck <= '0';
    elsif (clk'event and clk = '1') then
      if (configAck = '0') then
        if (configStb = '1') then
          configAck <= '1';
          configDatRead <= (others=>'0');
 
          -- Check the address the access is for.
          case (configAdrByte) is
            when x"000000" =>
              -----------------------------------------------------------------
              -- Device Identity CAR. Read-only.
              -----------------------------------------------------------------
              configDatRead(31 downto 16) <= DEVICE_IDENTITY;
              configDatRead(15 downto 0) <= DEVICE_VENDOR_IDENTITY;
 
            when x"000004" =>
              -----------------------------------------------------------------
              -- Device Information CAR. Read-only.
              -----------------------------------------------------------------
              configDatRead(31 downto 0) <= DEVICE_REV;
 
            when x"000008" =>
              -----------------------------------------------------------------
              -- Assembly Identity CAR. Read-only.
              -----------------------------------------------------------------
              configDatRead(31 downto 16) <= ASSY_IDENTITY;
              configDatRead(15 downto 0) <= ASSY_VENDOR_IDENTITY;
 
            when x"00000c" =>
              -----------------------------------------------------------------
              -- Assembly Information CAR. Read-only.
              -----------------------------------------------------------------
              configDatRead(31 downto 16) <= ASSY_REV;
 
            when x"000010" =>
              -----------------------------------------------------------------
              -- Processing Element Features CAR. Read-only.
              -----------------------------------------------------------------
              -- Bridge.
              configDatRead(31) <= '1';
              -- Extended addressing support, 34-bit addresses.
              configDatRead(2 downto 0) <= "001";
 
            when x"000018" =>
              -----------------------------------------------------------------
              -- Source Operations CAR. Read-only.
              -----------------------------------------------------------------
              -- Cannot act as a source of any packets.
 
            when x"00001c" =>
              -----------------------------------------------------------------
              -- Destination Operations CAR. Read-only.
              -----------------------------------------------------------------
              -- Read, supported.
              configDatRead(15) <= '1';
              -- Write, supported.
              configDatRead(14) <= '1';
              -- Write-with-response, supported.
              configDatRead(12) <= '1';
 
            when x"00004c" =>
              -----------------------------------------------------------------
              -- Processing Element Logical Layer Control CSR.
              -----------------------------------------------------------------
              -- Extended addressing control, PE supports 34 bits addresses.
              configDatRead(2 downto 0) <= "001";
 
            when x"000060" =>
              -----------------------------------------------------------------
              -- Base Device ID CSR.
              -----------------------------------------------------------------
              -- This is not used since this endpoint only replies to packets
              -- and it can then use the destination deviceId as a source.
 
            when x"000068" =>
              -----------------------------------------------------------------
              -- Host Base Device ID Lock CSR.
              -----------------------------------------------------------------
 
              -- Check if writing.
              if (configWe = '1') then
                -- Write access.
 
                -- Check if this field has been written before.
                if (hostBaseDeviceIdLocked = '0') then
                  -- The field has not been written.
                  -- Lock the field and set the host base device id.
                  hostBaseDeviceIdLocked := '1';
                  hostBaseDeviceId := configDatWrite(15 downto 0);
                else
                  -- The field has been written.
                  -- Check if the written data is the same as the stored.
                  if (hostBaseDeviceId = configDatWrite(15 downto 0)) then
                    -- Same as stored, reset the value to its initial value.
                    hostBaseDeviceIdLocked := '0';
                    hostBaseDeviceId := (others => '1');
                  else
                    -- Not writing the same as the stored value.
                    -- Ignore the write.
                  end if;
                end if;
              end if;
 
              configDatRead(15 downto 0) <= hostBaseDeviceId;
 
            when x"00006C" =>
              -----------------------------------------------------------------
              -- Component TAG CSR.
              -----------------------------------------------------------------
              if (configWe = '1') then
                componentTag := configDatWrite;
              end if;
 
              configDatRead <= componentTag;
 
            when others =>
              -----------------------------------------------------------------
              -- Other access.
              -----------------------------------------------------------------
              -- Respond with all zeros.
              configDatRead <= (others => '0');
          end case;
        end if;
      else
        configAck <= '0';
      end if;
    end if;
  end process;
 
end architecture;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
-- REMARK: Extended addresses are not supported yet...
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.rio_common.all;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
entity RequestClassInbound is
  generic(
    EXTENDED_ADDRESS : natural range 0 to 2 := 0);
  port(
    clk : in std_logic;
    areset_n : in std_logic;
    enable : in std_logic;
 
    ready_o : out std_logic;
    vc_o : out std_logic;
    crf_o : out std_logic;
    prio_o : out std_logic_vector(1 downto 0);
    tt_o : out std_logic_vector(1 downto 0);
    dstId_o : out std_logic_vector(31 downto 0);
    srcId_o : out std_logic_vector(31 downto 0);
    tid_o : out std_logic_vector(7 downto 0);
    address_o : out std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
    length_o : out std_logic_vector(4 downto 0);
    select_o : out std_logic_vector(7 downto 0);
    done_i : in std_logic;
 
    inboundCyc_i : in std_logic;
    inboundStb_i : in std_logic;
    inboundAdr_i : in std_logic_vector(7 downto 0);
    inboundDat_i : in std_logic_vector(31 downto 0);
    inboundAck_o : out std_logic);
end entity;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
architecture RequestClassInbound of RequestClassInbound is
  type StateType is (RECEIVE_PACKET, READY);
  signal state : StateType;
 
  signal rdsize : std_logic_vector(3 downto 0);
  signal wdptr : std_logic;
 
  signal inboundAck : std_logic;
  signal complete : std_logic;
 
  signal packetIndex : natural range 0 to 69;
 
begin
 
  inboundAck_o <= inboundAck;
 
  ready_o <= complete when (state = READY) else '0';
 
  RequestClass: process(clk, areset_n)
  begin
    if (areset_n = '0') then
      state <= RECEIVE_PACKET;
 
      rdsize <= (others=>'0');
      wdptr <= '0';
 
      inboundAck <= '0';
      complete <= '0';
 
      packetIndex <= 0;
 
      vc_o <= '0';
      crf_o <= '0';
      prio_o <= "00";
      tt_o <= "00";
      dstId_o <= (others=>'0');
      srcId_o <= (others=>'0');
      tid_o <= (others=>'0');
      address_o <= (others=>'0');
    elsif (clk'event and clk = '1') then
      case state is
        when RECEIVE_PACKET =>
          ---------------------------------------------------------------------
          -- This state waits for a new REQUEST class packet, receives it
          -- and parses it.
          ---------------------------------------------------------------------
          if (inboundCyc_i = '1') then
            if (inboundAck = '0') then
              if (inboundStb_i = '1') then
                if (inboundAdr_i = x"24") then
                  -------------------------------------------------------------
                  -- NREAD packet parser.
                  -------------------------------------------------------------
                  case (packetIndex) is
                    when 0 =>
                      -- x"0000" & ackid & vc & crf & prio & tt & ftype
                      vc_o <= inboundDat_i(9);
                      crf_o <= inboundDat_i(8);
                      prio_o <= inboundDat_i(7 downto 6);
                      tt_o <= inboundDat_i(5 downto 4);
                      packetIndex <= packetIndex + 1;
                    when 1 =>
                      -- dstid
                      dstId_o <= inboundDat_i;
                      packetIndex <= packetIndex + 1;
                    when 2 =>
                      -- srcid
                      srcId_o <= inboundDat_i;
                      packetIndex <= packetIndex + 1;
                    when 3 =>
                      -- transaction(3:0) & rdsize(3:0) & srcTID(7:0) & address(28:13)
                      rdsize <= inboundDat_i(27 downto 24);
                      tid_o <= inboundDat_i(23 downto 16);
                      address_o(28 downto 13) <= inboundDat_i(15 downto 0);
                      packetIndex <= packetIndex + 1;
                    when 4 =>
                      -- address(12:0) & wdptr & xamsbs(1:0) & crc(15:0)
                      address_o(12 downto 0) <= inboundDat_i(31 downto 19);
                      wdptr <= inboundDat_i(18);
                      address_o(30 downto 29) <= inboundDat_i(17 downto 16);
                      packetIndex <= packetIndex + 1;
                      complete <= '1';
                    when others =>
                      -- There should be no more content in an NREAD.
                      -- Discard.
                  end case;
                  inboundAck <= '1';
                end if;
              end if;
            else
              inboundAck <= '0';
            end if;
          else
            if (complete = '1') then
              state <= READY;
            end if;
            packetIndex <= 0;
          end if;
 
        when READY =>
          ---------------------------------------------------------------------
          -- Wait for the handler of the packet to signal that it has been
          -- processed.
          ---------------------------------------------------------------------
          if (done_i = '1') then
            complete <= '0';
            state <= RECEIVE_PACKET;
          end if;
 
        when others =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
 
      end case;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  -- Transformation of rdsize and wdptr into length of access and byte lanes.
  -----------------------------------------------------------------------------
 
  process(clk, areset_n)
  begin
    if (areset_n = '0') then
      length_o <= "00000";
      select_o <= (others=>'0');
    elsif (clk'event and clk = '1') then
      if (complete = '1') then
        if (wdptr = '0') then
          case rdsize is
            when "0000" =>
              length_o <= "00000";
              select_o <= "10000000";
            when "0001" =>
              length_o <= "00000";
              select_o <= "01000000";
            when "0010" =>
              length_o <= "00000";
              select_o <= "00100000";
            when "0011" =>
              length_o <= "00000";
              select_o <= "00010000";
            when "0100" =>
              length_o <= "00000";
              select_o <= "11000000";
            when "0101" =>
              length_o <= "00000";
              select_o <= "11100000";
            when "0110" =>
              length_o <= "00000";
              select_o <= "00110000";
            when "0111" =>
              length_o <= "00000";
              select_o <= "11111000";
            when "1000" =>
              length_o <= "00000";
              select_o <= "11110000";
            when "1001" =>
              length_o <= "00000";
              select_o <= "11111100";
            when "1010" =>
              length_o <= "00000";
              select_o <= "11111110";
            when "1011" =>
              length_o <= "00000";
              select_o <= "11111111";
            when "1100" =>
              length_o <= "00011";
              select_o <= "11111111";
            when "1101" =>
              length_o <= "01011";
              select_o <= "11111111";
            when "1110" =>
              length_o <= "10011";
              select_o <= "11111111";
            when others =>
              length_o <= "11011";
              select_o <= "11111111";
          end case;
        else
          case rdsize is
            when "0000" =>
              length_o <= "00000";
              select_o <= "00001000";
            when "0001" =>
              length_o <= "00000";
              select_o <= "00000100";
            when "0010" =>
              length_o <= "00000";
              select_o <= "00000010";
            when "0011" =>
              length_o <= "00000";
              select_o <= "00000001";
            when "0100" =>
              length_o <= "00000";
              select_o <= "00001100";
            when "0101" =>
              length_o <= "00000";
              select_o <= "00000111";
            when "0110" =>
              length_o <= "00000";
              select_o <= "00000011";
            when "0111" =>
              length_o <= "00000";
              select_o <= "00011111";
            when "1000" =>
              length_o <= "00000";
              select_o <= "00001111";
            when "1001" =>
              length_o <= "00000";
              select_o <= "00111111";
            when "1010" =>
              length_o <= "00000";
              select_o <= "01111111";
            when "1011" =>
              length_o <= "00001";
              select_o <= "11111111";
            when "1100" =>
              length_o <= "00111";
              select_o <= "11111111";
            when "1101" =>
              length_o <= "01111";
              select_o <= "11111111";
            when "1110" =>
              length_o <= "10111";
              select_o <= "11111111";
            when others =>
              length_o <= "11111";
              select_o <= "11111111";
          end case;
        end if;
      end if;
    end if;
  end process;
 
end architecture;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.rio_common.all;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
entity WriteClassInbound is
  generic(
    EXTENDED_ADDRESS : natural range 0 to 2 := 0);
  port(
    clk : in std_logic;
    areset_n : in std_logic;
    enable : in std_logic;
 
    ready_o : out std_logic;
    responseNeeded_o : out std_logic;
    vc_o : out std_logic;
    crf_o : out std_logic;
    prio_o : out std_logic_vector(1 downto 0);
    tt_o : out std_logic_vector(1 downto 0);
    dstId_o : out std_logic_vector(31 downto 0);
    srcId_o : out std_logic_vector(31 downto 0);
    tid_o : out std_logic_vector(7 downto 0);
    address_o : out std_logic_vector(16*EXTENDED_ADDRESS+30 downto 0);
    length_o : out std_logic_vector(4 downto 0);
    select_o : out std_logic_vector(7 downto 0);
    payloadRead_i : in std_logic;
    payloadIndex_i : in std_logic_vector(4 downto 0);
    payload_o : out std_logic_vector(63 downto 0);
    done_i : in std_logic;
 
    inboundCyc_i : in std_logic;
    inboundStb_i : in std_logic;
    inboundAdr_i : in std_logic_vector(7 downto 0);
    inboundDat_i : in std_logic_vector(31 downto 0);
    inboundAck_o : out std_logic);
end entity;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
architecture WriteClassInbound of WriteClassInbound is
  type StateType is (RECEIVE_PACKET, READY);
  signal state : StateType;
 
  signal wdptr : std_logic;
  signal wrsize : std_logic_vector(3 downto 0);
 
  signal inboundAck : std_logic;
  signal complete : std_logic;
 
  signal packetIndex : natural range 0 to 69;
 
  signal doubleWord : std_logic_vector(63 downto 16);
 
  signal memoryWrite : std_logic;
  signal memoryAddress : std_logic_vector(4 downto 0);
  signal memoryDataIn : std_logic_vector(63 downto 0);
 
 
begin
 
  inboundAck_o <= inboundAck;
 
  ready_o <= complete when (state = READY) else '0';
 
  WriteClass: process(clk, areset_n)
  begin
    if (areset_n = '0') then
      state <= RECEIVE_PACKET;
 
      wdptr <= '0';
      wrsize <= (others=>'0');
 
      inboundAck <= '0';
      complete <= '0';
      responseNeeded_o <= '0';
 
      packetIndex <= 0;
      doubleWord <= (others=>'0');
 
      memoryWrite <= '0';
      memoryAddress <= (others=>'0');
      memoryDataIn <= (others=>'0');
 
      vc_o <= '0';
      crf_o <= '0';
      prio_o <= "00";
      tt_o <= "00";
      dstId_o <= (others=>'0');
      srcId_o <= (others=>'0');
      tid_o <= (others=>'0');
      address_o <= (others=>'0');
    elsif (clk'event and clk = '1') then
      case state is
        when RECEIVE_PACKET =>
          if (inboundCyc_i = '1') then
            if (inboundAck = '0') then
              if (inboundStb_i = '1') then
                if ((inboundAdr_i = x"55") or (inboundAdr_i = x"54")) then
                  -------------------------------------------------------------
                  -- NWRITE/NWRITER packet parser.
                  -------------------------------------------------------------
                  case (packetIndex) is
                    when 0 =>
                      -- x"0000" & ackid & vc & crf & prio & tt & ftype
                      vc_o <= inboundDat_i(9);
                      crf_o <= inboundDat_i(8);
                      prio_o <= inboundDat_i(7 downto 6);
                      tt_o <= inboundDat_i(5 downto 4);
                      packetIndex <= packetIndex + 1;
                    when 1 =>
                      -- destId
                      dstId_o <= inboundDat_i;
                      packetIndex <= packetIndex + 1;
                    when 2 =>
                      -- srcId
                      srcId_o <= inboundDat_i;
                      packetIndex <= packetIndex + 1;
                    when 3 =>
                      -- transaction & wrsize & srcTID & address(28:13)
                      -- REMARK: Add support for extended addresses here...
                      if (inboundDat_i(31 downto 28) = "0101") then
                        responseNeeded_o <= '1';
                      else
                        responseNeeded_o <= '0';
                      end if;
                      wrsize <= inboundDat_i(27 downto 24);
                      tid_o <= inboundDat_i(23 downto 16);
                      address_o(28 downto 13) <= inboundDat_i(15 downto 0);
                      packetIndex <= packetIndex + 1;
                    when 4 =>
                      -- address(12:0) & wdptr & xamsbs(1:0) & double-word(63:48)
                      address_o(12 downto 0) <= inboundDat_i(31 downto 19);
                      wdptr <= inboundDat_i(18);
                      address_o(30 downto 29) <= inboundDat_i(17 downto 16);
                      doubleWord(63 downto 48) <= inboundDat_i(15 downto 0);
                      packetIndex <= packetIndex + 1;
                    when 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | 25 | 27 | 29 | 31  | 33 | 35 |
                      37 | 39 | 41 | 43 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 63 | 65 | 67 =>
                      -- double-word(47:16)
                      doubleWord(47 downto 16) <= inboundDat_i;
                      packetIndex <= packetIndex + 1;
                    when 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32  | 34 |
                      36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 =>
                      -- double-word(15:0) & double-word(63:48)
                      doubleWord(63 downto 48) <= inboundDat_i(15 downto 0);
                      packetIndex <= packetIndex + 1;
 
                      memoryWrite <= '1';
                      memoryDataIn <= doubleWord(63 downto 16) & inboundDat_i(31 downto 16);
                    when others =>
                      -- There should be no more content in an NWRITE/NWRITER request.
                      -- Discard.
                  end case;
                  inboundAck <= '1';
                end if;
              end if;
            else
              if (memoryWrite = '1') then
                memoryAddress <= std_logic_vector(unsigned(memoryAddress) + 1);
              end if;
 
              memoryWrite <= '0';
              inboundAck <= '0';
            end if;
          else
            if (packetIndex >= 6) then
              complete <= '1';
              state <= READY;
            else
              packetIndex <= 0;
              memoryAddress <= (others=>'0');
            end if;
          end if;
 
        when READY =>
          ---------------------------------------------------------------------
          -- Wait for the handler of the packet to signal that it has been
          -- processed.
          ---------------------------------------------------------------------
          if (done_i = '1') then
            packetIndex <= 0;
            memoryAddress <= (others=>'0');
            complete <= '0';
            state <= RECEIVE_PACKET;
          end if;
 
        when others =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
 
      end case;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  -- Transformation of wrsize and wdptr into length of access and byte lanes.
  -----------------------------------------------------------------------------
 
  process(clk, areset_n)
  begin
    if (areset_n = '0') then
      length_o <= "00000";
      select_o <= (others=>'0');
    elsif (clk'event and clk = '1') then
      if (complete = '1') then
        if (wdptr = '0') then
          case wrsize is
            when "0000" =>
              length_o <= "00000";
              select_o <= "10000000";
            when "0001" =>
              length_o <= "00000";
              select_o <= "01000000";
            when "0010" =>
              length_o <= "00000";
              select_o <= "00100000";
            when "0011" =>
              length_o <= "00000";
              select_o <= "00010000";
            when "0100" =>
              length_o <= "00000";
              select_o <= "11000000";
            when "0101" =>
              length_o <= "00000";
              select_o <= "11100000";
            when "0110" =>
              length_o <= "00000";
              select_o <= "00110000";
            when "0111" =>
              length_o <= "00000";
              select_o <= "11111000";
            when "1000" =>
              length_o <= "00000";
              select_o <= "11110000";
            when "1001" =>
              length_o <= "00000";
              select_o <= "11111100";
            when "1010" =>
              length_o <= "00000";
              select_o <= "11111110";
            when "1011" =>
              length_o <= "00000";
              select_o <= "11111111";
            when others =>
              length_o <= std_logic_vector(unsigned(memoryAddress)-1);
              select_o <= "11111111";
          end case;
        else
          case wrsize is
            when "0000" =>
              length_o <= "00000";
              select_o <= "00001000";
            when "0001" =>
              length_o <= "00000";
              select_o <= "00000100";
            when "0010" =>
              length_o <= "00000";
              select_o <= "00000010";
            when "0011" =>
              length_o <= "00000";
              select_o <= "00000001";
            when "0100" =>
              length_o <= "00000";
              select_o <= "00001100";
            when "0101" =>
              length_o <= "00000";
              select_o <= "00000111";
            when "0110" =>
              length_o <= "00000";
              select_o <= "00000011";
            when "0111" =>
              length_o <= "00000";
              select_o <= "00011111";
            when "1000" =>
              length_o <= "00000";
              select_o <= "00001111";
            when "1001" =>
              length_o <= "00000";
              select_o <= "00111111";
            when "1010" =>
              length_o <= "00000";
              select_o <= "01111111";
            when others =>
              length_o <= std_logic_vector(unsigned(memoryAddress)-1);
              select_o <= "11111111";
          end case;
        end if;
      end if;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  -- Payload content memory.
  -----------------------------------------------------------------------------
 
  PayloadMemory: MemorySimpleDualPort
    generic map(ADDRESS_WIDTH=>5, DATA_WIDTH=>64)
    port map(clkA_i=>clk,
             enableA_i=>memoryWrite,
             addressA_i=>memoryAddress,
             dataA_i=>memoryDataIn,
             clkB_i=>clk,
             enableB_i=>payloadRead_i,
             addressB_i=>payloadIndex_i,
             dataB_o=>payload_o);
 
end architecture;
 
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.rio_common.all;
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
entity ResponseClassOutbound is
  port(
    clk : in std_logic;
    areset_n : in std_logic;
    enable : in std_logic;
 
    ready_i : in std_logic;
    vc_i : in std_logic;
    crf_i : in std_logic;
    prio_i : in std_logic_vector(1 downto 0);
    tt_i : in std_logic_vector(1 downto 0);
    dstid_i : in std_logic_vector(31 downto 0);
    srcid_i : in std_logic_vector(31 downto 0);
    tid_i : in std_logic_vector(7 downto 0);
    error_i : in std_logic;
    payloadPresent_i :  in std_logic;
    payloadLength_i : in std_logic_vector(4 downto 0);
    payloadWrite_i : in std_logic;
    payloadIndex_i : in std_logic_vector(4 downto 0);
    payload_i : in std_logic_vector(63 downto 0);
    done_o : out std_logic;
 
    outboundCyc_o : out std_logic;
    outboundStb_o : out std_logic;
    outboundDat_o : out std_logic_vector(31 downto 0);
    outboundAck_i : in std_logic);
end entity;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
architecture ResponseClassOutbound of ResponseClassOutbound is
  signal header : std_logic_vector(31 downto 0);
 
  type StateType is (WAIT_PACKET, SEND_RESPONSE, 
                     WAIT_COMPLETE, RESPONSE_DONE);
  signal state : StateType;
 
  signal packetIndex : natural range 0 to 68;
 
  signal responsePayloadIndex : std_logic_vector(4 downto 0);
  signal responsePayload : std_logic_vector(15 downto 0);
 
  signal memoryEnable : std_logic;
  signal memoryAddress : std_logic_vector(4 downto 0);
  signal memoryDataRead : std_logic_vector(63 downto 0);
 
begin
 
  header <= x"0000" & "000000" & vc_i & crf_i & prio_i & tt_i & x"d";
 
  Response: process(clk, areset_n)
  begin
    if (areset_n = '0') then
      state <= WAIT_PACKET;
 
      packetIndex <= 0;
 
      responsePayloadIndex <= (others=>'0');
      responsePayload <= (others=>'0');
 
      memoryEnable <= '0';
      memoryAddress <= (others=>'0');
 
      done_o <= '0';
 
      outboundCyc_o <= '0';
      outboundStb_o <= '0';
      outboundDat_o <= (others=>'0');
    elsif (clk'event and clk = '1') then
      if (enable = '1') then
        case state is
          when WAIT_PACKET =>
            -------------------------------------------------------------------
            -- 
            -------------------------------------------------------------------
            if (ready_i = '1') then
              outboundCyc_o <= '1';
              outboundStb_o <= '1';
              outboundDat_o <= header;
 
              packetIndex <= 1;
              responsePayloadIndex <= (others=>'0');
 
              memoryEnable <= '1';
              memoryAddress <= (others=>'0');
 
              state <= SEND_RESPONSE;
            end if;
 
          when SEND_RESPONSE =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            if (outboundAck_i = '1') then
              case (packetIndex) is
                when 1 =>
                  -- destination
                  outboundDat_o <= dstId_i;
                  packetIndex <= packetIndex + 1;
                when 2 =>
                  -- source 
                  outboundDat_o <= srcId_i;
                  packetIndex <= packetIndex + 1;
                when 3 =>
                  -- transaction & status & targetTID & double-word0(63:48)
                  if (error_i = '0') then
                    if (payloadPresent_i = '0') then
                      outboundDat_o <= "0000" & "0000" & tid_i & x"0000";
                      state <= WAIT_COMPLETE;
                    else
                      outboundDat_o <= "1000" & "0000" & tid_i & memoryDataRead(63 downto 48);
                    end if;
                  else
                    outboundDat_o <= "0000" & "0111" & tid_i & x"0000";
                    state <= WAIT_COMPLETE;
                  end if;
                  packetIndex <= packetIndex + 1;
                when 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 |
                  36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 =>
                  -- double-wordN(47:16)
                  outboundDat_o <= memoryDataRead(47 downto 16);
                  responsePayload <= memoryDataRead(15 downto 0);
                  memoryAddress <= std_logic_vector(unsigned(memoryAddress) + 1);
                  packetIndex <= packetIndex + 1;
                when 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | 25 | 27 | 29 | 31 | 33 | 35 |
                  37 | 39 | 41 | 43 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 63 | 65 | 67 =>
                  -- double-wordN(15:0) & double-wordN(63:48)
                  outboundDat_o <= responsePayload & memoryDataRead(63 downto 48);
                  packetIndex <= packetIndex + 1;
 
                  responsePayloadIndex <=
                    std_logic_vector(unsigned(responsePayloadIndex) + 1);
 
                  if (responsePayloadIndex = payloadLength_i) then
                    state <= WAIT_COMPLETE;
                  else
                    packetIndex <= packetIndex + 1;
                  end if;
                when others =>
                  -- Unallowed response length.
                  -- Dont do anything.
              end case;
            end if;
 
          when WAIT_COMPLETE =>
            -------------------------------------------------------------------
            -- 
            -------------------------------------------------------------------
            if (outboundAck_i = '1') then
              outboundCyc_o <= '0';
              outboundStb_o <= '0';
              state <= RESPONSE_DONE;
            end if;
 
          when RESPONSE_DONE =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            memoryEnable <= '0';
            if (ready_i = '0') then
              state <= WAIT_PACKET;
              done_o <= '0';
            else
              done_o <= '1';
            end if;
 
          when others =>
            ---------------------------------------------------------------------
            -- 
            ---------------------------------------------------------------------
            state <= WAIT_PACKET;
 
        end case;
      end if;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  -- Payload content memory.
  -----------------------------------------------------------------------------
  PayloadMemory: MemorySimpleDualPort
    generic map(ADDRESS_WIDTH=>5, DATA_WIDTH=>64)
    port map(clkA_i=>clk,
             enableA_i=>payloadWrite_i,
             addressA_i=>payloadIndex_i,
             dataA_i=>payload_i,
             clkB_i=>clk,
             enableB_i=>memoryEnable,
             addressB_i=>memoryAddress,
             dataB_o=>memoryDataRead);
 
end architecture;
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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