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

Subversion Repositories rio

[/] [rio/] [branches/] [2.0.0-development/] [rtl/] [vhdl/] [RioLogicalCommon.vhd] - Rev 35

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

-------------------------------------------------------------------------------
-- RioLogicalCommon.
-------------------------------------------------------------------------------
-- Ingress:
-- * Removes in-the-middle and trailing CRC.
-- * Forwards packets to logical-layer handlers depending on ftype and
--   transaction (output as address).
-- * Outputs header and deviceIDs in seperate accesses to facilitate 8- and
--   16-bit deviceAddress support. All fields are right-justified.
-- Egress:
-- * Adds in-the-middle and trailing CRC.
-- * Receives packets from logical-layer handlers.
-- * Receives header and deviceIDs in seperate accesses to facilitate 8- and
--   16-bit deviceAddress support. All fields are right-justified.
-------------------------------------------------------------------------------
-- REMARK: Egress; Places packets in different queues depending on the packet priority?
-- REMARK: Use inputOutput/message/maintenance/gsm/...-strobes instead?
-- REMARK: If the deviceId:s are removed, it will work for both 8/16-bit deviceIds.
--          case (ftype) is
--            when x"1" =>
--              -- Intervention-request class.
--              gsmStb_o <= '1';
--            when x"2" =>
--              -- Request-class.
--              if ((transaction = "0100") or
--                  (transaction = "1100") or (transaction = "1101") or
--                  (transaction = "1110") or (transaction = "1111")) then
--                inputOutputStb_o <= '1';
--              else
--                gsmStb_o <= '1';
--              end if;
--            when x"5" =>
--              -- Write-class.
--              if ((transaction = "0100") or (transaction = "0101") or 
--                  (transaction = "1100") or (transaction = "1101") or
--                  (transaction = "1110")) then
--                inputOutputStb_o <= '1';
--              elsif ((transaction = "0000") or (transaction = "0001")) then
--                gsmStb_o <= '1';
--              end if;
--            when x"6" =>
--              -- Streaming-Write class.
--              inputOutputStb_o <= '1';
--            when x"7" =>
--              -- Flow-control class.
--              flowControlStb_o <= '1';
--            when x"8" =>
--              -- Maintenance class.
--              maintenanceStb_o <= '1';
--            when x"9" =>
--              -- Data-Streaming class.
--              dataStreamingStb_o <= '1';
--            when x"a" =>
--              -- Doorbell class.
--              -- REMARK: Make this belong to input/output since the packets
--              -- and their responses look the same?
--              messagePassingStb_o <= '1';
--            when x"b" =>
--              -- Message class.
--              messagePassingStb_o <= '1';
--            when x"d" =>
--              -- Response class.
--              -- REMARK: Seperate strobe for this???
--              if ((transaction = "0000") or (transaction = "1000")) then
--                -- REMARK: Doorbell-response going in here as well... *sigh*
--                -- REMARK: GSM-responses going in here as well...
--                responseStb_o <= '1';
--              elsif (transaction = "0001") then
--                messagePassing <= '1';
--              end if;
--            when others =>
--              -- Unsupported ftype.
--              -- REMARK: Discard this packet.
--          end case;
 
-- tt=00
-- 0: header(15:0);dest(7:0);src(7:0);
-- 1: transaction(3:0)
-- shifter: 32 (32 empty)
-- tt=01
-- 0: header(15:0);dest(15:0);
-- 1: src(15:0);transaction(3:0)
-- shifter: 16 (48 empty)
 
-------------------------------------------------------------------------------
-- RioLogicalCommonIngress.
-------------------------------------------------------------------------------
-- REMARK: Check the destination address to see if it matches the one configured???
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.rio_common.all;
 
-------------------------------------------------------------------------------
-- Entity for RioLogicalCommonIngress.
-------------------------------------------------------------------------------
entity RioLogicalCommonIngress is
  port(
    clk : in std_logic;
    areset_n : 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);
 
    masterCyc_o : out std_logic;
    masterStb_o : out std_logic;
    masterAdr_o : out std_logic_vector(7 downto 0);
    masterSel_o : out std_logic_vector(3 downto 0);
    masterDat_o : out std_logic_vector(31 downto 0);
    masterAck_i : in std_logic);
end entity;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
architecture RioLogicalCommonIngress of RioLogicalCommonIngress is
 
begin
 
  process(clk, areset_n)
  begin
    if (areset_n = '0') then
 
    elsif (clk'event and clk = '1') then
      readContent_o <= '0';
 
      case state is
        when IDLE =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          packetPosition <= 0;
          if (readFrameEmpty_i = '0') then
            readContent_o <= '1';
            state <= WAIT_HEADER_0;
          end if;
 
        when WAIT_HEADER_0 =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          readContent_o <= '1';
          state <= HEADER_0;
 
        when HEADER_0 =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          packetContent <= packetContent(31 downto 0) & readContentData_i;
          packetPosition <= packetPosition + 1;
          readContent_o <= '1';
 
          tt <= readContentData_i(21 downto 20);
          ftype <= readContentData_i(19 downto 16);
 
          state <= HEADER_1;
 
        when HEADER_1 =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          packetContent <= packetContent(31 downto 0) & readContentData_i;
          packetPosition <= packetPosition + 1;
 
          if (tt = "00") then
            transaction <= readContentData_i(31 downto 28);
          elsif (tt = "01") then
            transaction <= readContentData_i(15 downto 12);
          end if;
 
          state <= SEND_HEADER;
 
        when SEND_HEADER =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          masterStb_o <= '1';
          masterAdr_o <= ftype & transaction;
          masterSel_o <= x"0011";
          masterDat_o <= x"0000" & packetContent(63 downto 48);
          packetContent <= packetContent(47 downto 0) & x"0000";
 
          state <= SEND_DESTINATION;
 
        when SEND_DESTINATION =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (masterAck_i = '1') then
            if (tt = "00") then
              masterSel_o <= x"0001";
              masterDat_o <= x"000000" & packetContent(63 downto 56);
              packetContent <= packetContent(55 downto 0) & x"00";
            elsif (tt = "01") then
              masterSel_o <= x"0011";
              masterDat_o <= x"0000" & packetContent(63 downto 48);
              packetContent <= packetContent(31 downto 0) & readContentData_i;
              readContent_o <= '1';
            end if;
 
            state <= SEND_SOURCE;
          end if;
 
        when SEND_SOURCE =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (masterAck_i = '1') then
            if (tt = "00") then
              masterSel_o <= x"0001";
              masterDat_o <= x"000000" & packetContent(63 downto 56);
              packetContent <= packetContent(55 downto 0) & x"00";
            elsif (tt = "01") then
              masterSel_o <= x"0011";
              masterDat_o <= x"0000" & packetContent(63 downto 48);
              packetContent <= packetContent(47 downto 0) & x"0000";
            end if;
 
            state <= FORWARD;
          end if;
 
        when FORWARD =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (masterAck_i = '1') then
            masterSel_o <= x"1111";
            masterDat_o <= packetContent(63 downto 32);
 
            packetPosition <= packetPosition + 1;
 
            -- REMARK: Rewrite depending on tt-field to compensate for
            -- different number of valid bits in the shifter...
            if (packetPosition < 20) then
              packetContent <=
                packetContent(31 downto 0) & readContentData_i;
            elsif (packetPosition = 20) then
              packetContent <=
                packetContent(31 downto 0) & readContentData_i(15 downto 0) & x"0000";
            else
              packetContent <=
                packetContent(15 downto 0) & readContentData_i & x"0000";
            end if;
 
            if (readContentEnd_i = '0') then
              readContent_o <= '1';
            else
              readFrame_o <= '1';
              state <= FORWARD_LAST;
            end if;
          end if;
 
        when FORWARD_LAST =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          -- REMARK: The last always contain the CRC?
          if (masterAck_i = '1') then
            masterSel_o <= x"1111";
            masterDat_o <= packetContent(63 downto 32);
            state <= END_PACKET;
          end if;
 
        when END_PACKET =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (masterAck_i = '1') then
            state <= IDLE;
          end if;
 
        when others =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          state <= IDLE;
      end case;
    end if;
  end process;
 
end architecture;
 
 
-------------------------------------------------------------------------------
-- RioLogicalCommonEgress.
-- Only 8-bit and 16-bit deviceId are supported. The first write must contain
-- the 16-bit header, the second write must contain the destination address and
-- the third must contain the source address.
-- CRC is calculated during the transfer and inserted at byte 81 and 82 and
-- appended to the packet when it ends.
-- slaveSelect_i - four bits indicating valid bytes in slaveData_i.
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.rio_common.all;
 
-------------------------------------------------------------------------------
-- Entity for RioLogicalCommonEgress.
-------------------------------------------------------------------------------
entity RioLogicalCommonEgress is
  port(
    clk : in std_logic;
    areset_n : in std_logic;
 
    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);
 
    slaveCyc_i : in std_logic;
    slaveStb_i : in std_logic;
    slaveSel_i : in std_logic_vector(3 downto 0);
    slaveDat_i : in std_logic_vector(31 downto 0);
    slaveAck_o : out std_logic);
end entity;
 
 
-------------------------------------------------------------------------------
-- Architecture for RioLogicalCommonEgress.
-------------------------------------------------------------------------------
architecture RioLogicalCommonEgress of RioLogicalCommonEgress is
 
  component Crc16CITT is
    port(
      d_i : in  std_logic_vector(15 downto 0);
      crc_i : in  std_logic_vector(15 downto 0);
      crc_o : out std_logic_vector(15 downto 0));
  end component;
 
  signal crc16Current, crc16Temp, crc16Next: std_logic_vector(15 downto 0);
 
begin
 
  process(clk, areset_n)
  begin
    if (areset_n = '0') then
      crc16Current <= x"0000";
      writeContentData <= (others=>'0');
    elsif (clk'event and clk = '1') then
      writeContent_o <= '0';
      writeFrame_o <= '0';
 
      case state is
        when IDLE =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          packetPosition <= 0;
          if (writeFrameFull_i = '0') then
            state <= HEADER_GET;
            crc16Current <= x"ffff";
          end if;
 
        when GET_HEADER =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if ((slaveCyc_i = '1') and (slaveStb_i = '1')) then
            -- REMARK: Only support the header in one position?
            if (slaveSelect_i = "1100") then
              header <= slaveData_i(31 downto 16);
              tt <= slaveData_i(21 downto 20);
            elsif (slaveSelect_i = "0110") then
              header <= slaveData_i(23 downto 8);
              tt <= slaveData_i(13 downto 12);
            elsif (slaveSelect_i = "0011") then
              header <= slaveData_i(15 downto 0);
              tt <= slaveData_i(5 downto 4);
            else
              -- REMARK: Not supported.
            end if;
 
            slaveAck_o <= '1';
 
            state <= HEADER_ACK;
          else
            state <= RESTART_FRAME;
          end if;
 
        when HEADER_ACK =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          slaveAck_o <= '0';
          state <= DESTINATION_GET;
 
        when DESTINATION_GET =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
 
          if ((slaveCyc_i = '1') and (slaveStb_i = '1')) then
            -- REMARK: Only support the destination in one position?
            if (slaveSelect_i = "1000") and (tt = "00") then
              dstAddr <= slaveData_i(31 downto 24);
            elsif (slaveSelect_i = "0100") and (tt = "00") then
              dstAddr <= slaveData_i(23 downto 16);
            elsif (slaveSelect_i = "0010") and (tt = "00") then
              dstAddr <= slaveData_i(15 downto 8);
            elsif (slaveSelect_i = "0001") and (tt = "00") then
              dstAddr <= slaveData_i(7 downto 0);
            elsif (slaveSelect_i = "1100") and (tt = "01") then
              writeContent_o <= '1';
              writeContentData <= header & slaveData_i(31 downto 16);
              packetPosition <= packetPosition + 1;
            elsif (slaveSelect_i = "0110") and (tt = "01") then
              writeContent_o <= '1';
              writeContentData <= header & slaveData_i(24 downto 8);
              packetPosition <= packetPosition + 1;
            elsif (slaveSelect_i = "0011") and (tt = "01") then
              writeContent_o <= '1';
              writeContentData <= header & slaveData_i(15 downto 0);
              packetPosition <= packetPosition + 1;
            else
              -- REMARK: Not supported.
            end if;
 
            slaveAck_o <= '1';
 
            state <= DESTINATION_ACK;
          else
            state <= RESTART_FRAME;
          end if;
 
        when DESTINATION_ACK =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          slaveAck_o <= '0';
          state <= SOURCE_GET;
 
        when SOURCE_GET =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
 
          if ((slaveCyc_i = '1') and (slaveStb_i = '1')) then
            -- REMARK: Only support the source in one position?
            if (slaveSelect_i = "1000") and (tt = "00") then
              halfWordPending <= '0';
              writeContent_o <= '1';
              writeContentData <= header & dstAddr & slaveData_i(31 downto 24);
              packetPosition <= packetPosition + 1;
            elsif (slaveSelect_i = "0100") and (tt = "00") then
              halfWordPending <= '0';
              writeContent_o <= '1';
              writeContentData <= header & dstAddr & slaveData_i(23 downto 16);
              packetPosition <= packetPosition + 1;
            elsif (slaveSelect_i = "0010") and (tt = "00") then
              halfWordPending <= '0';
              writeContent_o <= '1';
              writeContentData <= header & dstAddr & slaveData_i(15 downto 8);
              packetPosition <= packetPosition + 1;
            elsif (slaveSelect_i = "0001") and (tt = "00") then
              halfWordPending <= '0';
              writeContent_o <= '1';
              writeContentData <= header & dstAddr & slaveData_i(7 downto 0);
              packetPosition <= packetPosition + 1;
            elsif (slaveSelect_i = "1100") and (tt = "01") then
              halfWordPending <= '1';
              halfWord <= slaveData_i(31 downto 16);
            elsif (slaveSelect_i = "0110") and (tt = "01") then
              halfWordPending <= '1';
              halfWord <= slaveData_i(24 downto 8);
            elsif (slaveSelect_i = "0011") and (tt = "01") then
              halfWordPending <= '1';
              halfWord <= slaveData_i(15 downto 0);
            else
              -- REMARK: Not supported.
            end if;
 
            slaveAck_o <= '1';
 
            state <= SOURCE_ACK;
          else
            state <= RESTART_FRAME;
          end if;
 
        when SOURCE_ACK =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          slaveAck_o <= '0';
 
          if (tt = "00") then
            crcCurrent <= crcNext;
          end if;
 
          state <= CONTENT_GET;
 
        when CONTENT_GET =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if ((slaveCyc_i = '1') and (slaveStb_i = '1')) then
            -- REMARK: Only support full writes? Not possible with the last
            -- access though.
            if (slaveSelect_i = "1111") then
              if (halfWordPending = '0') then
                writeContent_o <= '1';
                writeContentData <= slaveData_i;
                packetPosition <= packetPosition + 1;
              else
                writeContent_o <= '1';
                writeContentData <= halfWord & slaveData_i(31 downto 16);
                packetPosition <= packetPosition + 1;
                halfWord <= slaveData_i(15 downto 0);
              end if;
            elsif (slaveSelect_i = "1100") then
              if (halfWordPending = '0') then
                halfWordPending <= '1';
                halfWord <= slaveData_i(31 downto 16);
              else
                writeContent_o <= '1';
                writeContentData <= halfWord & slaveData_i(31 downto 16);
                packetPosition <= packetPosition + 1;
                halfWordPending <= '0';
              end if;
            elsif (slaveSelect_i = "0011") then
              if (halfWordPending = '0') then
                halfWordPending <= '1';
                halfWord <= slaveData_i(15 downto 0);
              else
                writeContent_o <= '1';
                writeContentData <= halfWord & slaveData_i(15 downto 0);
                packetPosition <= packetPosition + 1;
                halfWordPending <= '0';
              end if;
            end if;
 
            slaveAck_o <= '1';
 
            state <= CONTENT_ACK;
          else
            state <= CRC_APPEND;
          end if;
 
        when CONTENT_ACK =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          slaveAck_o <= '0';
 
          crc16Current <= crc16Next;
 
          if (packetPosition = 20) then
            if (halfWordPending = '0') then
              halfWordPending <= '1';
              halfWord <= crc16Next;
            else
              -- REMARK: The current CRC has to be updated when this is written.
              writeContent_o <= '1';
              writeContentData <= halfWord & crc16Next;
              packetPosition <= packetPosition + 1;
              halfWordPending <= '0';
              halfWord <= crc16Next;
            end if;
          end if;
 
          state <= CONTENT_GET;
 
        when CRC_APPEND =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (halfWordPending = '0') then
            writeContent_o <= '1';
            writeContentData <= crc16Current & x"0000";
            packetPosition <= packetPosition + 1;
          else
            writeContent_o <= '1';
            writeContentData <= halfWord & crc16Current;
            packetPosition <= packetPosition + 1;
          end if;
 
          state <= SEND_FRAME;
 
        when SEND_FRAME =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          writeFrame_o <= '1';
          state <= WAIT_UPDATE;
 
        when RESTART_FRAME =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          writeFrameAbort_o <= '1';
          state <= WAIT_UPDATE;
 
        when WAIT_UPDATE =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          state <= IDLE;
 
        when others =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
      end case;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  -- Packet CRC calculation.
  -----------------------------------------------------------------------------
 
  Crc16High: Crc16CITT
    port map(
      d_i=>writeContentData(31 downto 16), crc_i=>crc16Current, crc_o=>crc16Temp);
  Crc16Low: Crc16CITT
    port map(
      d_i=>writeContentData(15 downto 0), crc_i=>crc16Temp, crc_o=>crc16Next);
 
end architecture;
 
 
 
 
 
-------------------------------------------------------------------------------
-- RioLogicalMaintenanceRequest
-- This logical layer module handles ingress maintenance requests.
-- Addresses: 0x80 (maint read request) and 0x81 (maint write request).
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.rio_common.all;
 
 
-------------------------------------------------------------------------------
-- Entity for RioLogicalMaintenanceRequest.
-------------------------------------------------------------------------------
entity RioLogicalMaintenanceRequest is
  generic(
    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);
    DEFAULT_BASE_DEVICE_ID : std_logic_vector(15 downto 0) := x"ffff");
  port(
    clk : in std_logic;
    areset_n : in std_logic;
 
    configStb_o : out std_logic;
    configWe_o : out std_logic;
    configAdr_o : out std_logic_vector(23 downto 0);
    configDat_o : out std_logic_vector(63 downto 0);
    configSel_o : out std_logic_vector(7 downto 0);
    configDat_i : in std_logic_vector(63 downto 0);
    configAck_i : in std_logic;
 
    slaveCyc_i : in std_logic;
    slaveStb_i : in std_logic;
    slaveAdr_i : in std_logic_vector(7 downto 0);
    slaveDat_i : in std_logic_vector(31 downto 0);
    slaveAck_o : out std_logic;
 
    masterCyc_o : out std_logic;
    masterStb_o : out std_logic;
    masterDat_o : out std_logic_vector(31 downto 0);
    masterAck_i : in std_logic);
end entity;
 
 
-------------------------------------------------------------------------------
-- 
-------------------------------------------------------------------------------
architecture RioLogicalMaintenanceRequest of RioLogicalMaintenanceRequest is
  component MemorySinglePort is
    generic(
      ADDRESS_WIDTH : natural := 1;
      DATA_WIDTH : natural := 1);
    port(
      clk_i : in std_logic;
      enable_i : in std_logic;
      writeEnable_i : in std_logic;
      address_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0);
      data_i : in std_logic_vector(DATA_WIDTH-1 downto 0);
      data_o : out std_logic_vector(DATA_WIDTH-1 downto 0));
  end component;
 
begin
 
  slaveAck_o <= slaveAck;
  MaintenanceRequest: process(clk, areset_n)
  begin
    if (areset_n = '0') then
 
    elsif (clk'event and clk = '1') then
      case state is
        when WAIT_PACKET =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (slaveCyc_i = '1') then
            if (slaveAck = '0') then
              if (slaveStb_i = '1') then
                if (slaveAddress_i = x"80") then
                  -- Maintenance read request.
                  case (packetIndex) is
                    when 0 =>
                      -- x"0000" & ackid & vc & crf & prio & tt & ftype
                      header <= slaveDat_i(15 downto 0);
                    when 1 =>
                      -- destId
                      destId <= slaveDat_i;
                    when 2 =>
                      -- srcId
                      srcId <= slaveDat_i;
                    when 3 =>
                      -- transaction & rdsize & srcTID & hop & config_offset(20:13)
                      size <= slaveDat_i(27 downto 24);
                      srcTid <= slaveDat_i(23 downto 16);
                      configOffset(20 downto 13) <= slaveDat_i(7 downto 0);
                    when 4 =>
                      -- config_offset(12:0) & wdptr & rsrv & crc(15:0)
                      configOffset(12 downto 0) <= slaveDat_i(31 downto 16);
                      wdptr <= slaveDat_i(18);
                      maintReadComplete <= '1';
                    when others =>
                      -- There should be no more content in a maintenance read request.
                      -- Discard.
                  end case;
                elsif (slaveAddress_i = x"81") then
                  -- Maintenance write request.
                  case (packetIndex) is
                    when 0 =>
                      -- x"0000" & ackid & vc & crf & prio & tt & ftype
                      header <= slaveDat_i(15 downto 0);
                    when 1 =>
                      -- destId
                      destId <= slaveDat_i;
                    when 2 =>
                      -- srcId
                      srcId <= slaveDat_i;
                    when 3 =>
                      -- transaction & wrsize & srcTID & hop & config_offset(20:13)
                      size <= slaveDat_i(27 downto 24);
                      srcTid <= slaveDat_i(23 downto 16);
                      configOffset(20 downto 13) <= slaveDat_i(7 downto 0);
                    when 4 =>
                      -- config_offset(12:0) & wdptr & rsrv & double-word(63:48)
                      configOffset(12 downto 0) <= slaveDat_i(31 downto 16);
                      configData(63 downto 48) <= slaveData_i(15 downto 0);
                      wdptr <= slaveDat_i(18);
                      memoryEnable <= '1';
                      memoryAddress <= 0;
                    when 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | 25 | 27 | 29 | 31 =>
                      -- double-word(47:16)
                      configData(47 downto 16) <= slaveData_i;
                    when 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 =>
                      -- double-word(15:0) & double-word(63:48)
                      memoryAddress <= memoryAddress + 1;
                      memoryWrite <= '1';
                      memoryDataIn <= configData(63 downto 16) & slaveData_i(31 downto 16);
                      configData(63 downto 48) <= slaveData_i(15 downto 0);
                      maintWriteComplete <= '1';
                    when others =>
                      -- There should be no more content in a maintenance read request.
                      -- Discard.
                  end case;
                end if;
                slaveAck <= '1';
              end if;
            else
              packetIndex <= packetIndex + 1;
              slaveAck <= '0';
            end if;
          else
            if (maintReadComplete = '1') then
              state <= CONFIG_READ;
              configIterator <= bytes;
              memoryEnable <= '1';
              memoryAddress <= 0;
            end if;
            if (maintWriteComplete = '1') then
              state <= CONFIG_WRITE;
            end if;
            packetIndex <= 0;
            maintReadComplete <= '0';
            maintWriteComplete <= '0';
          end if;
 
        when CONFIG_READ =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          configStb_o <= '1';
          configWe_o <= '0';
          configAdr_o <= configOffset;
          configSel_o <= byteLanes;
          configIterator <= configIterator - 1;
          configSpaceState <= CONFIG_READ_ACK;
 
        when CONFIG_READ_ACK =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (configAck_i = '1') then
            memoryAddress <= memoryAddress + 1;
            memoryWrite <= '1';
            memoryDataIn <= configSpaceDat_i;
 
            if (configIterator /= 0) then
              configAdr_o <= configAdr_o + 1;
              state <= CONFIG_READ;
            else
              configStb_o <= '0';
              packetIndex <= 0;
              state <= CONFIG_READ_RESPONSE;
            end if;
          end if;
 
        when CONFIG_READ_RESPONSE =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          masterCyc_o <= '1';
          masterStb_o <= '1';
          masterDat_o <= header;
          packetIndex <= packetIndex + 1;
          state <= CONFIG_READ_RESPONSE_ACK;
 
        when CONFIG_READ_RESPONSE_ACK =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (masterAck_i = '1') then
            masterCyc_o <= '1';
            masterStb_o <= '1';
            case (packetIndex) is
              when 0 =>
                -- x"0000" & ackid & vc & crf & prio & tt & ftype
                masterDat_o <= header;
              when 1 =>
                -- destination is the source.
                masterDat_o <= srcId;
              when 2 =>
                -- source is the destination.
                masterDat_o <= destId;
              when 3 =>
                -- transaction & status & targetTID & hop & reserved(7:0)
                masterDat_o <= "0010" & "0000" & srcTid & x"ff" & x"00";
              when 4 =>
                -- reserved(15:0) & double-word0(63:32)
                masterDat_o <= x"0000" & memoryDataOut(63 downto 32);
              when 5 =>
                masterDat_o <= memoryDataOut(31 downto 0) & x"0000";
              -- REMARK: Add more here to send the full response...
              when others =>
                state <= WAIT_PACKET;
            end case;
            packetIndex <= packetIndex + 1;
          end if;
 
        when CONFIG_WRITE =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
 
        when others =>
 
      end case;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  --
  -----------------------------------------------------------------------------
  -- REMARK: Make this a common component?
  -- REMARK: Change bytes to double-words?
  process(wdptr, size)
  begin
    case (wdptr & size) is 
      when "00000" =>
        bytes <= 1;
        byteLanes <= "10000000";
      when "00001" =>
        bytes <= 1;
        byteLanes <= "01000000";
 
      when "00010" =>
        bytes <= 1;
        byteLanes <= "00100000";
      when "00011" =>
        bytes <= 1;
        byteLanes <= "00010000";
 
      when "10000" =>
        bytes <= 1;
        byteLanes <= "00001000";
      when "10001" =>
        bytes <= 1;
        byteLanes <= "00000100";
 
      when "10010" =>
        bytes <= 1;
        byteLanes <= "00000010";
      when "10011" =>
        bytes <= 1;
        byteLanes <= "00000001";
 
      when "00100" =>
        bytes <= 2;
        byteLanes <= "11000000";
      when "00101" =>
        bytes <= 3;
        byteLanes <= "11100000";
 
      when "00110" =>
        bytes <= 2;
        byteLanes <= "00110000";
      when "00111" =>
        bytes <= 5;
        byteLanes <= "11111000";
 
      when "10100" =>
        bytes <= 2;
        byteLanes <= "00001100";
      when "10101" =>
        bytes <= 3;
        byteLanes <= "00000111";
 
      when "10110" =>
        bytes <= 2;
        byteLanes <= "00000011";
      when "10111" =>
        bytes <= 5;
        byteLanes <= "00011111";
 
      when "01000" =>
        bytes <= 4;
        byteLanes <= "11110000";
      when "11000" =>
        bytes <= 4;
        byteLanes <= "00001111";
 
      when "01001" =>
        bytes <= 6;
        byteLanes <= "11111100";
      when "11001" =>
        bytes <= 6;
        byteLanes <= "00111111";
 
      when "01010" =>
        bytes <= 7;
        byteLanes <= "11111110";
      when "11010" =>
        bytes <= 7;
        byteLanes <= "01111111";
 
      when "01011" =>
        bytes <= 8;
        byteLanes <= "11111111";
      when "11011" =>
        bytes <= 16;
        byteLanes <= "11111111";
 
      when "01100" =>
        bytes <= 32;
        byteLanes <= "11111111";
      when "11100" =>
        bytes <= 64;
        byteLanes <= "11111111";
 
      when "01101" =>
        bytes <= 96;
        byteLanes <= "11111111";
      when "11101" =>
        bytes <= 128;
        byteLanes <= "11111111";
 
      when "01110" =>
        bytes <= 160;
        byteLanes <= "11111111";
      when "11110" =>
        bytes <= 192;
        byteLanes <= "11111111";
 
      when "01111" =>
        bytes <= 224;
        byteLanes <= "11111111";
      when "11111" =>
        bytes <= 256;
        byteLanes <= "11111111";
 
    end case;
  end process;
 
end architecture;
 
 
entity MaintenanceReadRequestInbound is
  port(
    clk : in std_logic;
    areset_n : in std_logic;
 
    slaveCyc_i : in std_logic;
    slaveStb_i : in std_logic;
    slaveAdr_i : in std_logic_vector(7 downto 0);
    slaveDat_i : in std_logic_vector(31 downto 0);
    slaveAck_o : out std_logic;
 
    header_o : out std_logic_vector(15 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);
    configOffset_o : out std_logic_vector(21 downto 0);
    configLength_o : out std_logic_vector(3 downto 0);
    configSelect_o : out std_logic_vector(7 downto 0);
    ready_o : out std_logic;
    done_i : in std_logic);
end entity;
 
 
architecture MaintenanceReadRequestInbound of MaintenanceReadRequestInbound is
 
begin
 
  ready_o <= maintReadComplete;
  slaveAck_o <= slaveAck;
  MaintenanceReadRequest: process(clk, areset_n)
  begin
    if (areset_n = '0') then
 
    elsif (clk'event and clk = '1') then
      case state is
        when WAIT_PACKET =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (slaveCyc_i = '1') then
            if (slaveAck = '0') then
              if (slaveStb_i = '1') then
                if (slaveAddress_i = x"80") then
                  case (packetIndex) is
                    when 0 =>
                      -- x"0000" & ackid & vc & crf & prio & tt & ftype
                      header <= slaveDat_i(15 downto 0);
                      packetIndex <= packetIndex + 1;
                    when 1 =>
                      -- destid
                      destId <= slaveDat_i;
                      packetIndex <= packetIndex + 1;
                    when 2 =>
                      -- srcid
                      srcId <= slaveDat_i;
                      packetIndex <= packetIndex + 1;
                    when 3 =>
                      -- transaction & rdsize & srcTID & hop & config_offset(20:13)
                      size <= slaveDat_i(27 downto 24);
                      srcTid <= slaveDat_i(23 downto 16);
                      configOffset(20 downto 13) <= slaveDat_i(7 downto 0);
                      packetIndex <= packetIndex + 1;
                    when 4 =>
                      -- config_offset(12:0) & wdptr & rsrv & crc(15:0)
                      configOffset(12 downto 0) <= slaveDat_i(31 downto 16);
                      wdptr <= slaveDat_i(18);
                      packetIndex <= packetIndex + 1;
                      maintReadComplete <= '1';
                    when others =>
                      -- There should be no more content in a maintenance read request.
                      -- Discard.
                  end case;
                end if;
                slaveAck <= '1';
              end if;
            else
              slaveAck <= '0';
            end if;
          else
            if (maintReadComplete = '1') then
              state <= READY;
            end if;
            packetIndex <= 0;
          end if;
 
        when READY =>
          ---------------------------------------------------------------------
          -- 
          ---------------------------------------------------------------------
          if (done_i = '1') then
            maintReadComplete <= '0';
            state <= WAIT_PACKET;
          end if;
 
        when others =>
 
      end case;
    end if;
  end process;
 
  -----------------------------------------------------------------------------
  --
  -----------------------------------------------------------------------------
  -- REMARK: Make this a common component?
  -- REMARK: Change bytes to double-words?
  process(wdptr, size)
  begin
    case (wdptr & size) is 
      when "00000" =>
        bytes <= 1;
        byteLanes <= "10000000";
      when "00001" =>
        bytes <= 1;
        byteLanes <= "01000000";
 
      when "00010" =>
        bytes <= 1;
        byteLanes <= "00100000";
      when "00011" =>
        bytes <= 1;
        byteLanes <= "00010000";
 
      when "10000" =>
        bytes <= 1;
        byteLanes <= "00001000";
      when "10001" =>
        bytes <= 1;
        byteLanes <= "00000100";
 
      when "10010" =>
        bytes <= 1;
        byteLanes <= "00000010";
      when "10011" =>
        bytes <= 1;
        byteLanes <= "00000001";
 
      when "00100" =>
        bytes <= 2;
        byteLanes <= "11000000";
      when "00101" =>
        bytes <= 3;
        byteLanes <= "11100000";
 
      when "00110" =>
        bytes <= 2;
        byteLanes <= "00110000";
      when "00111" =>
        bytes <= 5;
        byteLanes <= "11111000";
 
      when "10100" =>
        bytes <= 2;
        byteLanes <= "00001100";
      when "10101" =>
        bytes <= 3;
        byteLanes <= "00000111";
 
      when "10110" =>
        bytes <= 2;
        byteLanes <= "00000011";
      when "10111" =>
        bytes <= 5;
        byteLanes <= "00011111";
 
      when "01000" =>
        bytes <= 4;
        byteLanes <= "11110000";
      when "11000" =>
        bytes <= 4;
        byteLanes <= "00001111";
 
      when "01001" =>
        bytes <= 6;
        byteLanes <= "11111100";
      when "11001" =>
        bytes <= 6;
        byteLanes <= "00111111";
 
      when "01010" =>
        bytes <= 7;
        byteLanes <= "11111110";
      when "11010" =>
        bytes <= 7;
        byteLanes <= "01111111";
 
      when "01011" =>
        bytes <= 8;
        byteLanes <= "11111111";
      when "11011" =>
        bytes <= 16;
        byteLanes <= "11111111";
 
      when "01100" =>
        bytes <= 32;
        byteLanes <= "11111111";
      when "11100" =>
        bytes <= 64;
        byteLanes <= "11111111";
 
      when "01101" =>
        bytes <= 96;
        byteLanes <= "11111111";
      when "11101" =>
        bytes <= 128;
        byteLanes <= "11111111";
 
      when "01110" =>
        bytes <= 160;
        byteLanes <= "11111111";
      when "11110" =>
        bytes <= 192;
        byteLanes <= "11111111";
 
      when "01111" =>
        bytes <= 224;
        byteLanes <= "11111111";
      when "11111" =>
        bytes <= 256;
        byteLanes <= "11111111";
 
    end case;
  end process;
 
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.