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

Subversion Repositories rio

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /rio/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/bench/vhdl/TestRioSwitch.vhd
0,0 → 1,1265
-------------------------------------------------------------------------------
--
-- RapidIO IP Library Core
--
-- This file is part of the RapidIO IP library project
-- http://www.opencores.org/cores/rio/
--
-- Description
-- Contains automatic simulation test code to verify a RioSwitch implementation.
--
-- To Do:
-- -
--
-- 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
--
-------------------------------------------------------------------------------
 
 
-------------------------------------------------------------------------------
-- TestRioSwitch.
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
library std;
use std.textio.all;
use work.rio_common.all;
 
 
-------------------------------------------------------------------------------
-- Entity for TestRioSwitch.
-------------------------------------------------------------------------------
entity TestRioSwitch is
end entity;
 
 
-------------------------------------------------------------------------------
-- Architecture for TestRioSwitch.
-------------------------------------------------------------------------------
architecture TestRioSwitchImpl of TestRioSwitch is
component RioSwitch is
generic(
SWITCH_PORTS : natural range 3 to 255 := 4;
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;
writeFrameFull_i : in Array1(SWITCH_PORTS-1 downto 0);
writeFrame_o : out Array1(SWITCH_PORTS-1 downto 0);
writeFrameAbort_o : out Array1(SWITCH_PORTS-1 downto 0);
writeContent_o : out Array1(SWITCH_PORTS-1 downto 0);
writeContentData_o : out Array32(SWITCH_PORTS-1 downto 0);
 
readFrameEmpty_i : in Array1(SWITCH_PORTS-1 downto 0);
readFrame_o : out Array1(SWITCH_PORTS-1 downto 0);
readFrameRestart_o : out Array1(SWITCH_PORTS-1 downto 0);
readFrameAborted_i : in Array1(SWITCH_PORTS-1 downto 0);
readContentEmpty_i : in Array1(SWITCH_PORTS-1 downto 0);
readContent_o : out Array1(SWITCH_PORTS-1 downto 0);
readContentEnd_i : in Array1(SWITCH_PORTS-1 downto 0);
readContentData_i : in Array32(SWITCH_PORTS-1 downto 0);
portLinkTimeout_o : out std_logic_vector(23 downto 0);
 
linkInitialized_i : in Array1(SWITCH_PORTS-1 downto 0);
outputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0);
inputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0);
localAckIdWrite_o : out Array1(SWITCH_PORTS-1 downto 0);
clrOutstandingAckId_o : out Array1(SWITCH_PORTS-1 downto 0);
inboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0);
outstandingAckId_o : out Array5(SWITCH_PORTS-1 downto 0);
outboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0);
inboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0);
outstandingAckId_i : in Array5(SWITCH_PORTS-1 downto 0);
outboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0);
configStb_o : out std_logic;
configWe_o : out std_logic;
configAddr_o : out std_logic_vector(23 downto 0);
configData_o : out std_logic_vector(31 downto 0);
configData_i : in std_logic_vector(31 downto 0));
end component;
 
component TestPort is
port(
clk : in std_logic;
areset_n : in std_logic;
 
frameValid_i : in std_logic;
frameWrite_i : in RioFrame;
frameComplete_o : out std_logic;
frameExpected_i : in std_logic;
frameRead_i : in RioFrame;
frameReceived_o : out std_logic;
 
readFrameEmpty_o : out std_logic;
readFrame_i : in std_logic;
readFrameRestart_i : in std_logic;
readFrameAborted_o : out std_logic;
readContentEmpty_o : out std_logic;
readContent_i : in std_logic;
readContentEnd_o : out std_logic;
readContentData_o : out std_logic_vector(31 downto 0);
writeFrameFull_o : out std_logic;
writeFrame_i : in std_logic;
writeFrameAbort_i : in std_logic;
writeContent_i : in std_logic;
writeContentData_i : in std_logic_vector(31 downto 0));
end component;
 
constant PORTS : natural := 7;
constant SWITCH_IDENTITY : std_logic_vector(15 downto 0) := x"0123";
constant SWITCH_VENDOR_IDENTITY : std_logic_vector(15 downto 0) := x"4567";
constant SWITCH_REV : std_logic_vector(31 downto 0) := x"89abcdef";
constant SWITCH_ASSY_IDENTITY : std_logic_vector(15 downto 0) := x"0011";
constant SWITCH_ASSY_VENDOR_IDENTITY : std_logic_vector(15 downto 0) := x"2233";
constant SWITCH_ASSY_REV : std_logic_vector(15 downto 0) := x"4455";
signal clk : std_logic;
signal areset_n : std_logic;
 
signal frameValid : Array1(PORTS-1 downto 0);
signal frameWrite : RioFrameArray(PORTS-1 downto 0);
signal frameComplete : Array1(PORTS-1 downto 0);
signal frameExpected : Array1(PORTS-1 downto 0);
signal frameRead : RioFrameArray(PORTS-1 downto 0);
signal frameReceived : Array1(PORTS-1 downto 0);
signal writeFrameFull : Array1(PORTS-1 downto 0);
signal writeFrame : Array1(PORTS-1 downto 0);
signal writeFrameAbort : Array1(PORTS-1 downto 0);
signal writeContent : Array1(PORTS-1 downto 0);
signal writeContentData : Array32(PORTS-1 downto 0);
 
signal readFrameEmpty : Array1(PORTS-1 downto 0);
signal readFrame : Array1(PORTS-1 downto 0);
signal readFrameRestart : Array1(PORTS-1 downto 0);
signal readFrameAborted : Array1(PORTS-1 downto 0);
signal readContentEmpty : Array1(PORTS-1 downto 0);
signal readContent : Array1(PORTS-1 downto 0);
signal readContentEnd : Array1(PORTS-1 downto 0);
signal readContentData : Array32(PORTS-1 downto 0);
signal portLinkTimeout : std_logic_vector(23 downto 0);
signal linkInitialized : Array1(PORTS-1 downto 0);
signal outputPortEnable : Array1(PORTS-1 downto 0);
signal inputPortEnable : Array1(PORTS-1 downto 0);
signal localAckIdWrite : Array1(PORTS-1 downto 0);
signal clrOutstandingAckId : Array1(PORTS-1 downto 0);
signal inboundAckIdWrite : Array5(PORTS-1 downto 0);
signal outstandingAckIdWrite : Array5(PORTS-1 downto 0);
signal outboundAckIdWrite : Array5(PORTS-1 downto 0);
signal inboundAckIdRead : Array5(PORTS-1 downto 0);
signal outstandingAckIdRead : Array5(PORTS-1 downto 0);
signal outboundAckIdRead : Array5(PORTS-1 downto 0);
signal configStb, configStbExpected : std_logic;
signal configWe, configWeExpected : std_logic;
signal configAddr, configAddrExpected : std_logic_vector(23 downto 0);
signal configDataWrite, configDataWriteExpected : std_logic_vector(31 downto 0);
signal configDataRead, configDataReadExpected : std_logic_vector(31 downto 0);
begin
-----------------------------------------------------------------------------
-- Clock generation.
-----------------------------------------------------------------------------
ClockGenerator: process
begin
clk <= '0';
wait for 20 ns;
clk <= '1';
wait for 20 ns;
end process;
 
 
-----------------------------------------------------------------------------
-- Serial port emulator.
-----------------------------------------------------------------------------
TestDriver: process
 
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
procedure SendFrame(constant portIndex : natural range 0 to 7;
constant frame : RioFrame) is
begin
frameValid(portIndex) <= '1';
frameWrite(portIndex) <= frame;
wait until frameComplete(portIndex) = '1';
frameValid(portIndex) <= '0';
end procedure;
 
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
procedure ReceiveFrame(constant portIndex : natural range 0 to 7;
constant frame : RioFrame) is
begin
frameExpected(portIndex) <= '1';
frameRead(portIndex) <= frame;
wait until frameReceived(portIndex) = '1';
frameExpected(portIndex) <= '0';
end procedure;
 
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
procedure ReadConfig32(constant portIndex : natural range 0 to 7;
constant destinationId : std_logic_vector(15 downto 0);
constant sourceId : std_logic_vector(15 downto 0);
constant hop : std_logic_vector(7 downto 0);
constant tid : std_logic_vector(7 downto 0);
constant address : std_logic_vector(23 downto 0);
constant data : std_logic_vector(31 downto 0)) is
variable maintData : DoubleWordArray(0 to 7);
begin
SendFrame(portIndex, RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00",
tt=>"01", ftype=>FTYPE_MAINTENANCE_CLASS,
sourceId=>sourceId, destId=>destinationId,
payload=>RioMaintenance(transaction=>"0000",
size=>"1000",
tid=>tid,
hopCount=>hop,
configOffset=>address(23 downto 3),
wdptr=>address(2),
dataLength=>0,
data=>maintData)));
if (address(2) = '0') then
maintData(0) := data & x"00000000";
else
maintData(0) := x"00000000" & data ;
end if;
ReceiveFrame(portIndex, RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00",
tt=>"01", ftype=>FTYPE_MAINTENANCE_CLASS,
sourceId=>destinationId, destId=>sourceId,
payload=>RioMaintenance(transaction=>"0010",
size=>"0000",
tid=>tid,
hopCount=>x"ff",
configOffset=>"000000000000000000000",
wdptr=>'0',
dataLength=>1,
data=>maintData)));
end procedure;
 
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
procedure WriteConfig32(constant portIndex : natural range 0 to 7;
constant destinationId : std_logic_vector(15 downto 0);
constant sourceId : std_logic_vector(15 downto 0);
constant hop : std_logic_vector(7 downto 0);
constant tid : std_logic_vector(7 downto 0);
constant address : std_logic_vector(23 downto 0);
constant data : std_logic_vector(31 downto 0)) is
variable maintData : DoubleWordArray(0 to 7);
begin
if (address(2) = '0') then
maintData(0) := data & x"00000000";
else
maintData(0) := x"00000000" & data ;
end if;
 
SendFrame(portIndex, RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00",
tt=>"01", ftype=>FTYPE_MAINTENANCE_CLASS,
sourceId=>sourceId, destId=>destinationId,
payload=>RioMaintenance(transaction=>"0001",
size=>"1000",
tid=>tid,
hopCount=>hop,
configOffset=>address(23 downto 3),
wdptr=>address(2),
dataLength=>1,
data=>maintData)));
ReceiveFrame(portIndex, RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00",
tt=>"01", ftype=>FTYPE_MAINTENANCE_CLASS,
sourceId=>destinationId, destId=>sourceId,
payload=>RioMaintenance(transaction=>"0011",
size=>"0000",
tid=>tid,
hopCount=>x"ff",
configOffset=>"000000000000000000000",
wdptr=>'0',
dataLength=>0,
data=>maintData)));
end procedure;
 
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
procedure RouteFrame(constant sourcePortIndex : natural range 0 to 7;
constant destinationPortIndex : natural range 0 to 7;
constant sourceId : std_logic_vector(15 downto 0);
constant destinationId : std_logic_vector(15 downto 0);
constant payload : RioPayload) is
variable frame : RioFrame;
begin
frame := RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00",
tt=>"01", ftype=>"0000",
sourceId=>sourceId, destId=>destinationId,
payload=>payload);
frameExpected(destinationPortIndex) <= '1';
frameRead(destinationPortIndex) <= frame;
 
frameValid(sourcePortIndex) <= '1';
frameWrite(sourcePortIndex) <= frame;
wait until frameComplete(sourcePortIndex) = '1';
frameValid(sourcePortIndex) <= '0';
wait until frameReceived(destinationPortIndex) = '1';
frameExpected(destinationPortIndex) <= '0';
end procedure;
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
procedure SendFrame(constant portIndex : natural range 0 to 7;
constant sourceId : std_logic_vector(15 downto 0);
constant destinationId : std_logic_vector(15 downto 0);
constant payload : RioPayload) is
variable frame : RioFrame;
begin
frame := RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00",
tt=>"01", ftype=>"0000",
sourceId=>sourceId, destId=>destinationId,
payload=>payload);
frameValid(portIndex) <= '1';
frameWrite(portIndex) <= frame;
end procedure;
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
procedure ReceiveFrame(constant portIndex : natural range 0 to 7;
constant sourceId : std_logic_vector(15 downto 0);
constant destinationId : std_logic_vector(15 downto 0);
constant payload : RioPayload) is
variable frame : RioFrame;
begin
frame := RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00",
tt=>"01", ftype=>"0000",
sourceId=>sourceId, destId=>destinationId,
payload=>payload);
frameExpected(portIndex) <= '1';
frameRead(portIndex) <= frame;
end procedure;
-- These variabels are needed for the random number generation.
variable seed1 : positive := 1;
variable seed2: positive := 1;
 
variable data : DoubleWordArray(0 to 31);
variable randomPayload : RioPayload;
variable randomPayload1 : RioPayload;
variable randomPayload2 : RioPayload;
variable frame : RioFrameArray(0 to PORTS-1);
begin
areset_n <= '0';
 
linkInitialized <= (others=>'0');
for portIndex in 0 to PORTS-1 loop
frameValid(portIndex) <= '0';
frameExpected(portIndex) <= '0';
localAckIdWrite(portIndex) <= '0';
clrOutstandingAckId(portIndex) <= '0';
inboundAckIdWrite(portIndex) <= (others=>'0');
outstandingAckIdWrite(portIndex) <= (others=>'0');
outboundAckIdWrite(portIndex) <= (others=>'0');
end loop;
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
areset_n <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("TG_RioSwitch");
PrintS("-----------------------------------------------------------------");
PrintS("TG_RioSwitch-TC1");
PrintS("Description: Test switch maintenance accesses on different ports.");
PrintS("Requirement: XXXXX");
PrintS("-----------------------------------------------------------------");
PrintS("Step 1:");
PrintS("Action: Send maintenance read request packets to read switch identity.");
PrintS("Result: The switch should answer with its configured identitiy.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step1");
---------------------------------------------------------------------------
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000000", data=>(SWITCH_IDENTITY & SWITCH_VENDOR_IDENTITY));
ReadConfig32(portIndex=>1, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"01", address=>x"000004", data=>SWITCH_REV);
ReadConfig32(portIndex=>2, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"02", address=>x"000008", data=>(SWITCH_ASSY_IDENTITY & SWITCH_ASSY_VENDOR_IDENTITY));
ReadConfig32(portIndex=>3, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"03", address=>x"00000c", data=>(SWITCH_ASSY_REV & x"0100"));
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 2:");
PrintS("Action: Check the switch Processing Element Features.");
PrintS("Result: The expected switch features should be returned. ");
PrintS(" Switch with extended features pointer valid. Common ");
PrintS(" transport large system support and standard route table ");
PrintS(" configuration support.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step2");
---------------------------------------------------------------------------
 
ReadConfig32(portIndex=>4, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"04", address=>x"000010", data=>x"10000118");
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 3:");
PrintS("Action: Check the switch port information.");
PrintS("Result: The expected port and number of ports should be returned.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step3");
---------------------------------------------------------------------------
 
ReadConfig32(portIndex=>5, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"05", address=>x"000014", data=>x"00000705");
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 4:");
PrintS("Action: Check the switch number of supported routes.");
PrintS("Result: The expected number of supported routes should be returned.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step4");
---------------------------------------------------------------------------
 
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000034", data=>x"00000800");
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 5:");
PrintS("Action: Test host base device id lock by reading it, then hold it ");
PrintS(" and try to grab it from another address.");
PrintS("Result: The value should follow the specification.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step5");
---------------------------------------------------------------------------
 
-- Check that the lock is released.
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"0000ffff");
 
-- Try to accuire the lock.
WriteConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000002");
 
-- Check that the lock has been accuired.
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000002");
 
-- Try to accuire the lock from another source.
WriteConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000003");
 
-- Check that the lock refuses the new access.
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000002");
 
-- Release the lock.
WriteConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000002");
 
-- Check that the lock is released.
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"0000ffff");
-- Check that the lock can be accuired from another source once unlocked.
WriteConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000003");
-- Check that the lock is released.
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000003");
-- Release the lock again.
WriteConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"00000003");
-- Check that the lock is released.
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"00", address=>x"000068", data=>x"0000ffff");
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 6");
PrintS("Action: Check the component tag register.");
PrintS("Result: The written value in the component tag should be saved.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step6");
---------------------------------------------------------------------------
 
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00006c", data=>x"00000000");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00006c", data=>x"ffffffff");
 
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00006c", data=>x"ffffffff");
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 7");
PrintS("Action: Read and write to the port link timeout.");
PrintS("Result: Check that the portLinkTimeout output from the switch changes.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step7");
---------------------------------------------------------------------------
 
assert portLinkTimeout = x"ffffff" report "Unexpected portLinkTimeout." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000120", data=>x"ffffff00");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000120", data=>x"00000100");
 
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000120", data=>x"00000100");
 
assert portLinkTimeout = x"000001" report "Unexpected portLinkTimeout." severity error;
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 8");
PrintS("Action: Read from the port general control.");
PrintS("Result: Check the discovered bit.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step8");
---------------------------------------------------------------------------
 
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00013c", data=>x"00000000");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00013c", data=>x"20000000");
 
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00013c", data=>x"20000000");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00013c", data=>x"00000000");
 
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00013c", data=>x"00000000");
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 9");
PrintS("Action: Read from the port N error and status.");
PrintS("Result: Check the port ok and port uninitialized bits.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step9");
---------------------------------------------------------------------------
 
linkInitialized(0) <= '0';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000158", data=>x"00000001");
linkInitialized(0) <= '1';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000158", data=>x"00000002");
 
linkInitialized(1) <= '0';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000178", data=>x"00000001");
linkInitialized(1) <= '1';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000178", data=>x"00000002");
 
linkInitialized(2) <= '0';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000198", data=>x"00000001");
linkInitialized(2) <= '1';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000198", data=>x"00000002");
 
linkInitialized(3) <= '0';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001b8", data=>x"00000001");
linkInitialized(3) <= '1';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001b8", data=>x"00000002");
 
linkInitialized(4) <= '0';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001d8", data=>x"00000001");
linkInitialized(4) <= '1';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001d8", data=>x"00000002");
 
linkInitialized(5) <= '0';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001f8", data=>x"00000001");
linkInitialized(5) <= '1';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001f8", data=>x"00000002");
 
linkInitialized(6) <= '0';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000218", data=>x"00000001");
linkInitialized(6) <= '1';
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"000218", data=>x"00000002");
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 10");
PrintS("Action: Read and write to/from the port N control.");
PrintS("Result: Check the output/input port enable.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step10");
---------------------------------------------------------------------------
 
assert outputPortEnable(0) = '0' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(0) = '0' report "Unexpected inputPortEnable." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00015c", data=>x"00000001");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00015c", data=>x"00600001");
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00015c", data=>x"00600001");
 
assert outputPortEnable(0) = '1' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(0) = '1' report "Unexpected inputPortEnable." severity error;
 
---------------------------------------------------------------------------
assert outputPortEnable(1) = '0' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(1) = '0' report "Unexpected inputPortEnable." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00017c", data=>x"00000001");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00017c", data=>x"00600001");
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00017c", data=>x"00600001");
 
assert outputPortEnable(1) = '1' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(1) = '1' report "Unexpected inputPortEnable." severity error;
 
---------------------------------------------------------------------------
assert outputPortEnable(2) = '0' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(2) = '0' report "Unexpected inputPortEnable." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00019c", data=>x"00000001");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00019c", data=>x"00600001");
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00019c", data=>x"00600001");
 
assert outputPortEnable(2) = '1' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(2) = '1' report "Unexpected inputPortEnable." severity error;
 
---------------------------------------------------------------------------
assert outputPortEnable(3) = '0' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(3) = '0' report "Unexpected inputPortEnable." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001bc", data=>x"00000001");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001bc", data=>x"00600001");
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001bc", data=>x"00600001");
 
assert outputPortEnable(3) = '1' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(3) = '1' report "Unexpected inputPortEnable." severity error;
 
---------------------------------------------------------------------------
assert outputPortEnable(4) = '0' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(4) = '0' report "Unexpected inputPortEnable." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001dc", data=>x"00000001");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001dc", data=>x"00600001");
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001dc", data=>x"00600001");
 
assert outputPortEnable(4) = '1' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(4) = '1' report "Unexpected inputPortEnable." severity error;
 
---------------------------------------------------------------------------
assert outputPortEnable(5) = '0' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(5) = '0' report "Unexpected inputPortEnable." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001fc", data=>x"00000001");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001fc", data=>x"00600001");
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"0001fc", data=>x"00600001");
 
assert outputPortEnable(5) = '1' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(5) = '1' report "Unexpected inputPortEnable." severity error;
 
---------------------------------------------------------------------------
assert outputPortEnable(6) = '0' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(6) = '0' report "Unexpected inputPortEnable." severity error;
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00021c", data=>x"00000001");
 
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00021c", data=>x"00600001");
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"00021c", data=>x"00600001");
 
assert outputPortEnable(6) = '1' report "Unexpected outputPortEnable." severity error;
assert inputPortEnable(6) = '1' report "Unexpected inputPortEnable." severity error;
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 11");
PrintS("Action: Read and write to/from the implementation defined space.");
PrintS("Result: Check the accesses on the external configuration port.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC1-Step11");
---------------------------------------------------------------------------
 
configStbExpected <= '1';
configWeExpected <= '0';
configAddrExpected <= x"010000";
configDataReadExpected <= x"deadbeef";
ReadConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"010000", data=>x"deadbeef");
 
configStbExpected <= '1';
configWeExpected <= '1';
configAddrExpected <= x"010004";
configDataWriteExpected <= x"c0debabe";
WriteConfig32(portIndex=>6, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"06", address=>x"010004", data=>x"c0debabe");
 
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("TG_RioSwitch-TC2");
PrintS("Description: Test the configuration of the routing table and the ");
PrintS(" routing of packets.");
PrintS("Requirement: XXXXX");
PrintS("-----------------------------------------------------------------");
PrintS("Step 1:");
PrintS("Action: Configure the routing table for address 0->port 1.");
PrintS("Result: A packet to address 0 should be forwarded to port 1.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC2-Step1");
---------------------------------------------------------------------------
 
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"07", address=>x"000070", data=>x"00000000");
WriteConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"08", address=>x"000074", data=>x"00000001");
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"09", address=>x"000074", data=>x"00000001");
 
-- Send a frame from a port and check if it is correctly routed.
randomPayload.length := 3;
CreateRandomPayload(randomPayload.data, seed1, seed2);
RouteFrame(sourcePortIndex=>0, destinationPortIndex=>1,
sourceId=>x"ffff", destinationId=>x"0000", payload=>randomPayload);
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 2:");
PrintS("Action: Test the configuration of the default route->port 6.");
PrintS("Result: An unknown address should be routed to port 6.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC2-Step2");
---------------------------------------------------------------------------
 
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"0a", address=>x"000078", data=>x"00000000");
WriteConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"0b", address=>x"000078", data=>x"00000006");
ReadConfig32(portIndex=>0, destinationId=>x"0000", sourceId=>x"0002", hop=>x"00",
tid=>x"0c", address=>x"000078", data=>x"00000006");
-- Send a frame from a port and check if it is correctly routed.
randomPayload.length := 4;
CreateRandomPayload(randomPayload.data, seed1, seed2);
RouteFrame(sourcePortIndex=>1, destinationPortIndex=>6,
sourceId=>x"0000", destinationId=>x"ffff", payload=>randomPayload);
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("TG_RioSwitch-TC3");
PrintS("Description: Test the routing of normal packets.");
PrintS("Requirement: XXXXX");
PrintS("-----------------------------------------------------------------");
PrintS("Step 1:");
PrintS("Action: Send two packets but not the same time.");
PrintS("Result: Both packets should be received at the expected ports.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC3-Step1");
---------------------------------------------------------------------------
 
-- Frame on port 0 to port 1.
randomPayload.length := 3;
CreateRandomPayload(randomPayload.data, seed1, seed2);
SendFrame(portIndex=>0,
sourceId=>x"ffff", destinationId=>x"0000", payload=>randomPayload);
ReceiveFrame(portIndex=>1,
sourceId=>x"ffff", destinationId=>x"0000", payload=>randomPayload);
 
-- Frame on port 1 to port 6.
randomPayload.length := 4;
CreateRandomPayload(randomPayload.data, seed1, seed2);
SendFrame(portIndex=>1,
sourceId=>x"0000", destinationId=>x"ffff", payload=>randomPayload);
ReceiveFrame(portIndex=>6,
sourceId=>x"0000", destinationId=>x"ffff", payload=>randomPayload);
 
wait until frameComplete(1) = '1';
frameValid(1) <= '0';
wait until frameReceived(6) = '1';
frameExpected(6) <= '0';
 
wait until frameComplete(0) = '1';
frameValid(0) <= '0';
wait until frameReceived(1) = '1';
frameExpected(1) <= '0';
---------------------------------------------------------------------------
PrintS("-----------------------------------------------------------------");
PrintS("Step 2:");
PrintS("Action: Send two packets to the same port with is full and one to");
PrintS(" another that is also full. Then receive the packets one at");
PrintS(" a time.");
PrintS("Result: The packet to the port that is ready should go though.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC3-Step2");
---------------------------------------------------------------------------
 
-- Frame on port 0 to port 1.
randomPayload.length := 5;
CreateRandomPayload(randomPayload.data, seed1, seed2);
SendFrame(portIndex=>0,
sourceId=>x"ffff", destinationId=>x"0000", payload=>randomPayload);
 
-- Frame on port 1 to port 6.
randomPayload1.length := 6;
CreateRandomPayload(randomPayload1.data, seed1, seed2);
SendFrame(portIndex=>1,
sourceId=>x"0000", destinationId=>x"ffff", payload=>randomPayload1);
 
-- Frame on port 2 to port 6.
randomPayload2.length := 7;
CreateRandomPayload(randomPayload2.data, seed1, seed2);
SendFrame(portIndex=>2,
sourceId=>x"0000", destinationId=>x"ffff", payload=>randomPayload2);
 
wait for 10 us;
 
ReceiveFrame(portIndex=>1,
sourceId=>x"ffff", destinationId=>x"0000", payload=>randomPayload);
wait until frameComplete(0) = '1';
frameValid(0) <= '0';
wait until frameReceived(1) = '1';
frameExpected(1) <= '0';
wait for 10 us;
ReceiveFrame(portIndex=>6,
sourceId=>x"0000", destinationId=>x"ffff", payload=>randomPayload1);
wait until frameComplete(1) = '1';
frameValid(1) <= '0';
wait until frameReceived(6) = '1';
frameExpected(6) <= '0';
wait for 10 us;
ReceiveFrame(portIndex=>6,
sourceId=>x"0000", destinationId=>x"ffff", payload=>randomPayload2);
wait until frameComplete(2) = '1';
frameValid(2) <= '0';
wait until frameReceived(6) = '1';
frameExpected(6) <= '0';
---------------------------------------------------------------------------
-- Test completed.
---------------------------------------------------------------------------
wait for 10 us;
 
assert readContentEmpty = "1111111"
report "Pending frames exist." severity error;
 
TestEnd;
end process;
 
-----------------------------------------------------------------------------
-- Instantiate a process receiving the configuration accesses to the
-- implementation defined space.
-----------------------------------------------------------------------------
process
begin
loop
wait until configStb = '1' and clk'event and clk = '1';
assert configStb = configStbExpected report "Unexpected configStb." severity error;
assert configWe = configWeExpected report "Unexpected configWe." severity error;
assert configAddr = configAddrExpected report "Unexpected configAddr." severity error;
if (configWe = '1') then
assert configDataWrite = configDataWriteExpected report "Unexpected configDataWrite." severity error;
else
configDataRead <= configDataReadExpected;
end if;
end loop;
end process;
-----------------------------------------------------------------------------
-- Instantiate the test port array.
-----------------------------------------------------------------------------
TestPortGeneration: for portIndex in 0 to PORTS-1 generate
TestPortInst: TestPort
port map(
clk=>clk, areset_n=>areset_n,
frameValid_i=>frameValid(portIndex),
frameWrite_i=>frameWrite(portIndex),
frameComplete_o=>frameComplete(portIndex),
frameExpected_i=>frameExpected(portIndex),
frameRead_i=>frameRead(portIndex),
frameReceived_o=>frameReceived(portIndex),
readFrameEmpty_o=>readFrameEmpty(portIndex),
readFrame_i=>readFrame(portIndex),
readFrameRestart_i=>readFrameRestart(portIndex),
readFrameAborted_o=>readFrameAborted(portIndex),
readContentEmpty_o=>readContentEmpty(portIndex),
readContent_i=>readContent(portIndex),
readContentEnd_o=>readContentEnd(portIndex),
readContentData_o=>readContentData(portIndex),
writeFrameFull_o=>writeFrameFull(portIndex),
writeFrame_i=>writeFrame(portIndex),
writeFrameAbort_i=>writeFrameAbort(portIndex),
writeContent_i=>writeContent(portIndex),
writeContentData_i=>writeContentData(portIndex));
end generate;
 
-----------------------------------------------------------------------------
-- Instantiate the switch.
-----------------------------------------------------------------------------
 
TestSwitch: RioSwitch
generic map(
SWITCH_PORTS=>7,
DEVICE_IDENTITY=>SWITCH_IDENTITY,
DEVICE_VENDOR_IDENTITY=>SWITCH_VENDOR_IDENTITY,
DEVICE_REV=>SWITCH_REV,
ASSY_IDENTITY=>SWITCH_ASSY_IDENTITY,
ASSY_VENDOR_IDENTITY=>SWITCH_ASSY_VENDOR_IDENTITY,
ASSY_REV=>SWITCH_ASSY_REV)
port map(
clk=>clk, areset_n=>areset_n,
writeFrameFull_i=>writeFrameFull,
writeFrame_o=>writeFrame, writeFrameAbort_o=>writeFrameAbort,
writeContent_o=>writeContent, writeContentData_o=>writeContentData,
readFrameEmpty_i=>readFrameEmpty,
readFrame_o=>readFrame, readFrameRestart_o=>readFrameRestart,
readFrameAborted_i=>readFrameAborted,
readContentEmpty_i=>readContentEmpty,
readContent_o=>readContent, readContentEnd_i=>readContentEnd,
readContentData_i=>readContentData,
portLinkTimeout_o=>portLinkTimeout,
linkInitialized_i=>linkInitialized,
outputPortEnable_o=>outputPortEnable, inputPortEnable_o=>inputPortEnable,
localAckIdWrite_o=>localAckIdWrite,
clrOutstandingAckId_o=>clrOutstandingAckId,
inboundAckId_o=>inboundAckIdWrite,
outstandingAckId_o=>outstandingAckIdWrite,
outboundAckId_o=>outboundAckIdWrite,
inboundAckId_i=>inboundAckIdRead,
outstandingAckId_i=>outstandingAckIdRead,
outboundAckId_i=>outboundAckIdRead,
configStb_o=>configStb, configWe_o=>configWe, configAddr_o=>configAddr,
configData_o=>configDataWrite, configData_i=>configDataRead);
end architecture;
 
 
 
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------
-- REMARK: Add support for testing partially complete frames, cut-through-routing...
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library std;
use std.textio.all;
use work.rio_common.all;
 
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------
entity TestPort is
port(
clk : in std_logic;
areset_n : in std_logic;
 
frameValid_i : in std_logic;
frameWrite_i : in RioFrame;
frameComplete_o : out std_logic;
frameExpected_i : in std_logic;
frameRead_i : in RioFrame;
frameReceived_o : out std_logic;
 
readFrameEmpty_o : out std_logic;
readFrame_i : in std_logic;
readFrameRestart_i : in std_logic;
readFrameAborted_o : out std_logic;
readContentEmpty_o : out std_logic;
readContent_i : in std_logic;
readContentEnd_o : out std_logic;
readContentData_o : out std_logic_vector(31 downto 0);
writeFrameFull_o : out std_logic;
writeFrame_i : in std_logic;
writeFrameAbort_i : in std_logic;
writeContent_i : in std_logic;
writeContentData_i : in std_logic_vector(31 downto 0));
end entity;
 
 
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------
architecture TestPortImpl of TestPort is
begin
-----------------------------------------------------------------------------
--
-----------------------------------------------------------------------------
FrameReader: process
type StateType is (STATE_IDLE, STATE_WRITE);
variable state : StateType;
variable frameIndex : natural range 0 to 69;
begin
writeFrameFull_o <= '1';
frameReceived_o <= '0';
wait until areset_n = '1';
 
state := STATE_IDLE;
 
loop
wait until clk'event and clk = '1';
case state is
when STATE_IDLE =>
frameReceived_o <= '0';
if (frameExpected_i = '1') then
writeFrameFull_o <= '0';
state := STATE_WRITE;
frameIndex := 0;
else
writeFrameFull_o <= '1';
end if;
assert writeFrame_i = '0' report "Unexpected frame." severity error;
assert writeFrameAbort_i = '0' report "Unexpected frame abort." severity error;
assert writeContent_i = '0' report "Unexpected data." severity error;
when STATE_WRITE =>
if (writeContent_i = '1') then
-- Writing content.
if (frameIndex < frameRead_i.length) then
assert writeContentData_i = frameRead_i.payload(frameIndex)
report "Unexpected frame content received:" &
" index=" & integer'image(frameIndex) &
" expected=" & integer'image(to_integer(unsigned(frameRead_i.payload(frameIndex)))) &
" got=" & integer'image(to_integer(unsigned(writeContentData_i)))
severity error;
frameIndex := frameIndex + 1;
else
report "Unexpected frame content received:" &
" index=" & integer'image(frameIndex) &
" expected=" & integer'image(to_integer(unsigned(frameRead_i.payload(frameIndex)))) &
" got=" & integer'image(to_integer(unsigned(writeContentData_i)))
severity error;
frameIndex := frameIndex + 1;
end if;
else
-- Not writing any content.
end if;
if (writeFrame_i = '1') then
-- Writing a complete frame.
assert frameIndex = frameRead_i.length report "Unexpected frame length received." severity error;
state := STATE_IDLE;
frameReceived_o <= '1';
writeFrameFull_o <= '1';
else
-- Not writing any frame.
end if;
 
if (writeFrameAbort_i = '1') then
-- The frame should be aborted.
frameIndex := 0;
else
-- Not aborting any frame.
end if;
end case;
end loop;
end process;
 
-----------------------------------------------------------------------------
--
-----------------------------------------------------------------------------
-- REMARK: add support for these signals...
-- readFrameEmpty_i : in std_logic;
-- readFrameAborted_i : in std_logic;
FrameSender: process
type StateType is (STATE_IDLE, STATE_READ);
variable state : StateType;
variable frameIndex : natural range 0 to 69;
begin
readFrameEmpty_o <= '1';
readFrameAborted_o <= '0';
readContentEmpty_o <= '1';
readContentEnd_o <= '1';
readContentData_o <= (others => 'U');
frameComplete_o <= '0';
wait until areset_n = '1';
 
state := STATE_IDLE;
 
loop
wait until clk'event and clk = '1';
case state is
 
when STATE_IDLE =>
frameComplete_o <= '0';
if (frameValid_i = '1') then
state := STATE_READ;
frameIndex := 0;
readContentEmpty_o <= '0';
readFrameEmpty_o <= '0';
else
readContentEmpty_o <= '1';
end if;
when STATE_READ =>
if (readFrameRestart_i = '1') then
readContentEnd_o <= '0';
frameIndex := 0;
else
-- Not restarting a frame.
end if;
if (readContent_i = '1') then
if (frameIndex < frameWrite_i.length) then
readContentData_o <= frameWrite_i.payload(frameIndex);
readContentEnd_o <= '0';
frameIndex := frameIndex + 1;
elsif (frameIndex = frameWrite_i.length) then
readContentEnd_o <= '1';
else
report "Reading empty frame." severity error;
end if;
else
-- Not reading data.
end if;
 
if (readFrame_i = '1') then
state := STATE_IDLE;
assert frameIndex = frameWrite_i.length report "Unread frame data discarded." severity error;
frameComplete_o <= '1';
readFrameEmpty_o <= '1';
readContentEmpty_o <= '1';
readContentData_o <= (others => 'U');
else
-- Not reading a frame.
end if;
 
end case;
end loop;
end process;
 
end architecture;
bench/vhdl/TestRioSwitch.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/vhdl/RioCommon.vhd =================================================================== --- rtl/vhdl/RioCommon.vhd (nonexistent) +++ rtl/vhdl/RioCommon.vhd (revision 2) @@ -0,0 +1,1078 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- Contains commonly used types, functions, procedures and entities used in +-- the RapidIO IP library project. +-- +-- To Do: +-- - +-- +-- 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 +-- +------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- RioCommon library. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; +use std.textio.all; + + +------------------------------------------------------------------------------- +-- RioCommon package description. +------------------------------------------------------------------------------- +package rio_common is + ----------------------------------------------------------------------------- + -- Commonly used types. + ----------------------------------------------------------------------------- + type Array1 is array (natural range <>) of + std_logic; + type Array2 is array (natural range <>) of + std_logic_vector(1 downto 0); + type Array3 is array (natural range <>) of + std_logic_vector(2 downto 0); + type Array4 is array (natural range <>) of + std_logic_vector(3 downto 0); + type Array5 is array (natural range <>) of + std_logic_vector(4 downto 0); + type Array8 is array (natural range <>) of + std_logic_vector(7 downto 0); + type Array9 is array (natural range <>) of + std_logic_vector(8 downto 0); + type Array10 is array (natural range <>) of + std_logic_vector(9 downto 0); + type Array16 is array (natural range <>) of + std_logic_vector(15 downto 0); + type Array32 is array (natural range <>) of + std_logic_vector(31 downto 0); + type Array34 is array (natural range <>) of + std_logic_vector(33 downto 0); + + ----------------------------------------------------------------------------- + -- Commonly used constants. + ----------------------------------------------------------------------------- + + -- Symbol types between the serial and the PCS layer. + constant SYMBOL_IDLE : std_logic_vector(1 downto 0) := "00"; + constant SYMBOL_CONTROL : std_logic_vector(1 downto 0) := "01"; + constant SYMBOL_ERROR : std_logic_vector(1 downto 0) := "10"; + constant SYMBOL_DATA : std_logic_vector(1 downto 0) := "11"; + + -- STYPE0 constants. + constant STYPE0_PACKET_ACCEPTED : std_logic_vector(2 downto 0) := "000"; + constant STYPE0_PACKET_RETRY : std_logic_vector(2 downto 0) := "001"; + constant STYPE0_PACKET_NOT_ACCEPTED : std_logic_vector(2 downto 0) := "010"; + constant STYPE0_RESERVED : std_logic_vector(2 downto 0) := "011"; + constant STYPE0_STATUS : std_logic_vector(2 downto 0) := "100"; + constant STYPE0_VC_STATUS : std_logic_vector(2 downto 0) := "101"; + constant STYPE0_LINK_RESPONSE : std_logic_vector(2 downto 0) := "110"; + constant STYPE0_IMPLEMENTATION_DEFINED : std_logic_vector(2 downto 0) := "111"; + + -- STYPE1 constants. + constant STYPE1_START_OF_PACKET : std_logic_vector(2 downto 0) := "000"; + constant STYPE1_STOMP : std_logic_vector(2 downto 0) := "001"; + constant STYPE1_END_OF_PACKET : std_logic_vector(2 downto 0) := "010"; + constant STYPE1_RESTART_FROM_RETRY : std_logic_vector(2 downto 0) := "011"; + constant STYPE1_LINK_REQUEST : std_logic_vector(2 downto 0) := "100"; + constant STYPE1_MULTICAST_EVENT : std_logic_vector(2 downto 0) := "101"; + constant STYPE1_RESERVED : std_logic_vector(2 downto 0) := "110"; + constant STYPE1_NOP : std_logic_vector(2 downto 0) := "111"; + + -- FTYPE constants. + constant FTYPE_REQUEST_CLASS : std_logic_vector(3 downto 0) := "0010"; + constant FTYPE_WRITE_CLASS : std_logic_vector(3 downto 0) := "0101"; + constant FTYPE_STREAMING_WRITE_CLASS : std_logic_vector(3 downto 0) := "0110"; + constant FTYPE_MAINTENANCE_CLASS : std_logic_vector(3 downto 0) := "1000"; + constant FTYPE_RESPONSE_CLASS : std_logic_vector(3 downto 0) := "1101"; + constant FTYPE_DOORBELL_CLASS : std_logic_vector(3 downto 0) := "1010"; + constant FTYPE_MESSAGE_CLASS : std_logic_vector(3 downto 0) := "0010"; + + -- TTYPE Constants + constant TTYPE_MAINTENANCE_READ_REQUEST : std_logic_vector(3 downto 0) := "0000"; + constant TTYPE_MAINTENANCE_WRITE_REQUEST : std_logic_vector(3 downto 0) := "0001"; + constant TTYPE_MAINTENANCE_READ_RESPONSE : std_logic_vector(3 downto 0) := "0010"; + constant TTYPE_MAINTENANCE_WRITE_RESPONSE : std_logic_vector(3 downto 0) := "0011"; + constant TTYPE_NREAD_TRANSACTION : std_logic_vector(3 downto 0) := "0100"; + constant TTYPE_NWRITE_TRANSACTION : std_logic_vector(3 downto 0) := "0100"; + + constant LINK_REQUEST_CMD_RESET_DEVICE : std_logic_vector(2 downto 0) := "011"; + constant LINK_REQUEST_CMD_INPUT_STATUS : std_logic_vector(2 downto 0) := "100"; + + constant PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID : std_logic_vector(4 downto 0) := "00001"; + constant PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC : std_logic_vector(4 downto 0) := "00010"; + constant PACKET_NOT_ACCEPTED_CAUSE_NON_MAINTENANCE_STOPPED : std_logic_vector(4 downto 0) := "00011"; + constant PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC : std_logic_vector(4 downto 0) := "00100"; + constant PACKET_NOT_ACCEPTED_CAUSE_INVALID_CHARACTER : std_logic_vector(4 downto 0) := "00101"; + constant PACKET_NOT_ACCEPTED_CAUSE_NO_RESOURCES : std_logic_vector(4 downto 0) := "00110"; + constant PACKET_NOT_ACCEPTED_CAUSE_LOSS_DESCRAMBLER : std_logic_vector(4 downto 0) := "00111"; + constant PACKET_NOT_ACCEPTED_CAUSE_GENERAL_ERROR : std_logic_vector(4 downto 0) := "11111"; + + ----------------------------------------------------------------------------- + -- Types used in simulations. + ----------------------------------------------------------------------------- + type ByteArray is array (natural range <>) of + std_logic_vector(7 downto 0); + type HalfwordArray is array (natural range <>) of + std_logic_vector(15 downto 0); + type WordArray is array (natural range <>) of + std_logic_vector(31 downto 0); + type DoublewordArray is array (natural range <>) of + std_logic_vector(63 downto 0); + + -- Type defining a RapidIO frame. + type RioFrame is record + length : natural range 0 to 69; + payload : WordArray(0 to 68); + end record; + type RioFrameArray is array (natural range <>) of RioFrame; + + -- Type defining a RapidIO payload. + type RioPayload is record + length : natural range 0 to 133; + data : HalfwordArray(0 to 132); + end record; + + ----------------------------------------------------------------------------- + -- Crc5 calculation function. + -- ITU, polynom=0x15. + ----------------------------------------------------------------------------- + function Crc5(constant data : in std_logic_vector(18 downto 0); + constant crc : in std_logic_vector(4 downto 0)) + return std_logic_vector; + + --------------------------------------------------------------------------- + -- Create a RapidIO physical layer control symbol. + --------------------------------------------------------------------------- + function RioControlSymbolCreate( + constant stype0 : in std_logic_vector(2 downto 0); + constant parameter0 : in std_logic_vector(4 downto 0); + constant parameter1 : in std_logic_vector(4 downto 0); + constant stype1 : in std_logic_vector(2 downto 0); + constant cmd : in std_logic_vector(2 downto 0)) + return std_logic_vector; + + ----------------------------------------------------------------------------- + -- Crc16 calculation function. + -- CITT, polynom=0x1021. + ----------------------------------------------------------------------------- + function Crc16(constant data : in std_logic_vector(15 downto 0); + constant crc : in std_logic_vector(15 downto 0)) + return std_logic_vector; + + --------------------------------------------------------------------------- + -- Create a randomly initialized data array. + --------------------------------------------------------------------------- + procedure CreateRandomPayload( + variable payload : out HalfwordArray(0 to 132); + variable seed1 : inout positive; + variable seed2 : inout positive); + procedure CreateRandomPayload( + variable payload : out DoublewordArray(0 to 31); + variable seed1 : inout positive; + variable seed2 : inout positive); + + --------------------------------------------------------------------------- + -- Create a generic RapidIO frame. + --------------------------------------------------------------------------- + function RioFrameCreate( + constant ackId : in std_logic_vector(4 downto 0); + constant vc : in std_logic; + constant crf : in std_logic; + constant prio : in std_logic_vector(1 downto 0); + constant tt : in std_logic_vector(1 downto 0); + constant ftype : in std_logic_vector(3 downto 0); + constant sourceId : in std_logic_vector(15 downto 0); + constant destId : in std_logic_vector(15 downto 0); + constant payload : in RioPayload) + return RioFrame; + + --------------------------------------------------------------------------- + -- Create a NWRITE RapidIO frame. + --------------------------------------------------------------------------- + function RioNwrite( + constant wrsize : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant address : in std_logic_vector(28 downto 0); + constant wdptr : in std_logic; + constant xamsbs : in std_logic_vector(1 downto 0); + constant dataLength : in natural range 1 to 32; + constant data : in DoublewordArray(0 to 31)) + return RioPayload; + + --------------------------------------------------------------------------- + -- Create a NREAD RapidIO frame. + --------------------------------------------------------------------------- + function RioNread( + constant rdsize : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant address : in std_logic_vector(28 downto 0); + constant wdptr : in std_logic; + constant xamsbs : in std_logic_vector(1 downto 0)) + return RioPayload; + + --------------------------------------------------------------------------- + -- Create a RESPONSE RapidIO frame. + --------------------------------------------------------------------------- + function RioResponse( + constant status : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant dataLength : in natural range 0 to 32; + constant data : in DoublewordArray(0 to 31)) + return RioPayload; + + --------------------------------------------------------------------------- + -- Create a Maintenance RapidIO frame. + --------------------------------------------------------------------------- + function RioMaintenance( + constant transaction : in std_logic_vector(3 downto 0); + constant size : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant hopCount : in std_logic_vector(7 downto 0); + constant configOffset : in std_logic_vector(20 downto 0); + constant wdptr : in std_logic; + constant dataLength : in natural range 0 to 8; + constant data : in DoublewordArray(0 to 7)) + return RioPayload; + + ----------------------------------------------------------------------------- + -- Function to convert a std_logic_vector to a string. + ----------------------------------------------------------------------------- + function byteToString(constant byte : std_logic_vector(7 downto 0)) + return string; + + --------------------------------------------------------------------------- + -- Procedure to print to report file and output + --------------------------------------------------------------------------- + procedure PrintR( constant str : string ); + + --------------------------------------------------------------------------- + -- Procedure to print to spec file + --------------------------------------------------------------------------- + procedure PrintS( constant str : string ); + + --------------------------------------------------------------------------- + -- Procedure to Assert Expression + --------------------------------------------------------------------------- + procedure AssertE( constant exp: boolean; constant str : string ); + + --------------------------------------------------------------------------- + -- Procedure to Print Error + --------------------------------------------------------------------------- + procedure PrintE( constant str : string ); + + --------------------------------------------------------------------------- + -- Procedure to end a test. + --------------------------------------------------------------------------- + procedure TestEnd; + +end package; + +------------------------------------------------------------------------------- +-- RioCommon package body description. +------------------------------------------------------------------------------- +package body rio_common is + ----------------------------------------------------------------------------- + -- Crc5 calculation function. + -- ITU, polynom=0x15. + ----------------------------------------------------------------------------- + function Crc5(constant data : in std_logic_vector(18 downto 0); + constant crc : in std_logic_vector(4 downto 0)) + return std_logic_vector is + type crcTableType is array (0 to 31) of std_logic_vector(7 downto 0); + constant crcTable : crcTableType := ( + x"00", x"15", x"1f", x"0a", x"0b", x"1e", x"14", x"01", + x"16", x"03", x"09", x"1c", x"1d", x"08", x"02", x"17", + x"19", x"0c", x"06", x"13", x"12", x"07", x"0d", x"18", + x"0f", x"1a", x"10", x"05", x"04", x"11", x"1b", x"0e" ); + variable index : natural range 0 to 31; + variable result : std_logic_vector(4 downto 0); + begin + result := crc; + index := to_integer(unsigned(data(18 downto 14) xor result)); + result := crcTable(index)(4 downto 0); + index := to_integer(unsigned(data(13 downto 9) xor result)); + result := crcTable(index)(4 downto 0); + index := to_integer(unsigned(data(8 downto 4) xor result)); + result := crcTable(index)(4 downto 0); + index := to_integer(unsigned((data(3 downto 0) & '0') xor result)); + return crcTable(index)(4 downto 0); + end Crc5; + + --------------------------------------------------------------------------- + -- Create a RapidIO physical layer control symbol. + --------------------------------------------------------------------------- + function RioControlSymbolCreate( + constant stype0 : in std_logic_vector(2 downto 0); + constant parameter0 : in std_logic_vector(4 downto 0); + constant parameter1 : in std_logic_vector(4 downto 0); + constant stype1 : in std_logic_vector(2 downto 0); + constant cmd : in std_logic_vector(2 downto 0)) + return std_logic_vector is + variable returnValue : std_logic_vector(31 downto 0); + variable symbolData : std_logic_vector(18 downto 0); + begin + symbolData(18 downto 16) := stype0; + symbolData(15 downto 11) := parameter0; + symbolData(10 downto 6) := parameter1; + symbolData(5 downto 3) := stype1; + symbolData(2 downto 0) := cmd; + + returnValue(31 downto 13) := symbolData; + returnValue(12 downto 8) := Crc5(symbolData, "11111"); + returnValue(7 downto 0) := x"00"; + + return returnValue; + end function; + + ----------------------------------------------------------------------------- + -- Crc16 calculation function. + -- CITT, polynom=0x1021. + ----------------------------------------------------------------------------- + function Crc16(constant data : in std_logic_vector(15 downto 0); + constant crc : in std_logic_vector(15 downto 0)) + return std_logic_vector is + type crcTableType is array (0 to 255) of std_logic_vector(15 downto 0); + constant crcTable : crcTableType := ( + x"0000", x"1021", x"2042", x"3063", x"4084", x"50a5", x"60c6", x"70e7", + x"8108", x"9129", x"a14a", x"b16b", x"c18c", x"d1ad", x"e1ce", x"f1ef", + x"1231", x"0210", x"3273", x"2252", x"52b5", x"4294", x"72f7", x"62d6", + x"9339", x"8318", x"b37b", x"a35a", x"d3bd", x"c39c", x"f3ff", x"e3de", + x"2462", x"3443", x"0420", x"1401", x"64e6", x"74c7", x"44a4", x"5485", + x"a56a", x"b54b", x"8528", x"9509", x"e5ee", x"f5cf", x"c5ac", x"d58d", + x"3653", x"2672", x"1611", x"0630", x"76d7", x"66f6", x"5695", x"46b4", + x"b75b", x"a77a", x"9719", x"8738", x"f7df", x"e7fe", x"d79d", x"c7bc", + x"48c4", x"58e5", x"6886", x"78a7", x"0840", x"1861", x"2802", x"3823", + x"c9cc", x"d9ed", x"e98e", x"f9af", x"8948", x"9969", x"a90a", x"b92b", + x"5af5", x"4ad4", x"7ab7", x"6a96", x"1a71", x"0a50", x"3a33", x"2a12", + x"dbfd", x"cbdc", x"fbbf", x"eb9e", x"9b79", x"8b58", x"bb3b", x"ab1a", + x"6ca6", x"7c87", x"4ce4", x"5cc5", x"2c22", x"3c03", x"0c60", x"1c41", + x"edae", x"fd8f", x"cdec", x"ddcd", x"ad2a", x"bd0b", x"8d68", x"9d49", + x"7e97", x"6eb6", x"5ed5", x"4ef4", x"3e13", x"2e32", x"1e51", x"0e70", + x"ff9f", x"efbe", x"dfdd", x"cffc", x"bf1b", x"af3a", x"9f59", x"8f78", + x"9188", x"81a9", x"b1ca", x"a1eb", x"d10c", x"c12d", x"f14e", x"e16f", + x"1080", x"00a1", x"30c2", x"20e3", x"5004", x"4025", x"7046", x"6067", + x"83b9", x"9398", x"a3fb", x"b3da", x"c33d", x"d31c", x"e37f", x"f35e", + x"02b1", x"1290", x"22f3", x"32d2", x"4235", x"5214", x"6277", x"7256", + x"b5ea", x"a5cb", x"95a8", x"8589", x"f56e", x"e54f", x"d52c", x"c50d", + x"34e2", x"24c3", x"14a0", x"0481", x"7466", x"6447", x"5424", x"4405", + x"a7db", x"b7fa", x"8799", x"97b8", x"e75f", x"f77e", x"c71d", x"d73c", + x"26d3", x"36f2", x"0691", x"16b0", x"6657", x"7676", x"4615", x"5634", + x"d94c", x"c96d", x"f90e", x"e92f", x"99c8", x"89e9", x"b98a", x"a9ab", + x"5844", x"4865", x"7806", x"6827", x"18c0", x"08e1", x"3882", x"28a3", + x"cb7d", x"db5c", x"eb3f", x"fb1e", x"8bf9", x"9bd8", x"abbb", x"bb9a", + x"4a75", x"5a54", x"6a37", x"7a16", x"0af1", x"1ad0", x"2ab3", x"3a92", + x"fd2e", x"ed0f", x"dd6c", x"cd4d", x"bdaa", x"ad8b", x"9de8", x"8dc9", + x"7c26", x"6c07", x"5c64", x"4c45", x"3ca2", x"2c83", x"1ce0", x"0cc1", + x"ef1f", x"ff3e", x"cf5d", x"df7c", x"af9b", x"bfba", x"8fd9", x"9ff8", + x"6e17", x"7e36", x"4e55", x"5e74", x"2e93", x"3eb2", x"0ed1", x"1ef0" ); + variable index : natural range 0 to 255; + variable result : std_logic_vector(15 downto 0); + begin + result := crc; + index := to_integer(unsigned(data(15 downto 8) xor result(15 downto 8))); + result := crcTable(index) xor (result(7 downto 0) & x"00"); + index := to_integer(unsigned(data(7 downto 0) xor result(15 downto 8))); + result := crcTable(index) xor (result(7 downto 0) & x"00"); + return result; + end Crc16; + + --------------------------------------------------------------------------- + -- Create a randomly initialized data array. + --------------------------------------------------------------------------- + procedure CreateRandomPayload( + variable payload : out HalfwordArray(0 to 132); + variable seed1 : inout positive; + variable seed2 : inout positive) is + variable rand: real; + variable int_rand: integer; + variable stim: std_logic_vector(7 downto 0); + begin + for i in payload'range loop + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(7 downto 0) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(15 downto 8) := std_logic_vector(to_unsigned(int_rand, 8)); + end loop; + end procedure; + + procedure CreateRandomPayload( + variable payload : out DoublewordArray(0 to 31); + variable seed1 : inout positive; + variable seed2 : inout positive) is + variable rand: real; + variable int_rand: integer; + variable stim: std_logic_vector(7 downto 0); + begin + for i in payload'range loop + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(7 downto 0) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(15 downto 8) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(23 downto 16) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(31 downto 24) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(39 downto 32) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(47 downto 40) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(55 downto 48) := std_logic_vector(to_unsigned(int_rand, 8)); + uniform(seed1, seed2, rand); + int_rand := integer(trunc(rand*256.0)); + payload(i)(63 downto 56) := std_logic_vector(to_unsigned(int_rand, 8)); + end loop; + end procedure; + --------------------------------------------------------------------------- + -- Create a generic RapidIO frame. + --------------------------------------------------------------------------- + function RioFrameCreate( + constant ackId : in std_logic_vector(4 downto 0); + constant vc : in std_logic; + constant crf : in std_logic; + constant prio : in std_logic_vector(1 downto 0); + constant tt : in std_logic_vector(1 downto 0); + constant ftype : in std_logic_vector(3 downto 0); + constant sourceId : in std_logic_vector(15 downto 0); + constant destId : in std_logic_vector(15 downto 0); + constant payload : in RioPayload) return RioFrame is + variable frame : RioFrame; + variable result : HalfwordArray(0 to 137); + variable crc : std_logic_vector(15 downto 0) := x"ffff"; + begin + -- Add the header and addresses. + result(0) := ackId & "0" & vc & crf & prio & tt & ftype; + result(1) := destId; + result(2) := sourceId; + + -- Update the calculated CRC with the header contents. + crc := Crc16("00000" & result(0)(10 downto 0), crc); + crc := Crc16(result(1), crc); + crc := Crc16(result(2), crc); + + -- Check if a single CRC should be added or two. + if (payload.length <= 37) then + -- Single CRC. + for i in 0 to payload.length-1 loop + result(i+3) := payload.data(i); + crc := Crc16(payload.data(i), crc); + end loop; + result(payload.length+3) := crc; + + -- Check if paddning is needed to make the payload even 32-bit. + if ((payload.length mod 2) = 1) then + result(payload.length+4) := x"0000"; + frame.length := (payload.length+5) / 2; + else + frame.length := (payload.length+4) / 2; + end if; + else + -- Double CRC. + for i in 0 to 36 loop + result(i+3) := payload.data(i); + crc := Crc16(payload.data(i), crc); + end loop; + + -- Add in-the-middle crc. + result(40) := crc; + crc := Crc16(crc, crc); + + for i in 37 to payload.length-1 loop + result(i+4) := payload.data(i); + crc := Crc16(payload.data(i), crc); + end loop; + result(payload.length+4) := crc; + + -- Check if paddning is needed to make the payload even 32-bit. + if ((payload.length mod 2) = 0) then + result(payload.length+5) := x"0000"; + frame.length := (payload.length+6) / 2; + else + frame.length := (payload.length+5) / 2; + end if; + end if; + + -- Update the result length. + for i in 0 to frame.length-1 loop + frame.payload(i) := result(2*i) & result(2*i+1); + end loop; + + return frame; + end function; + + ----------------------------------------------------------------------------- + -- + ----------------------------------------------------------------------------- + function RioNwrite( + constant wrsize : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant address : in std_logic_vector(28 downto 0); + constant wdptr : in std_logic; + constant xamsbs : in std_logic_vector(1 downto 0); + constant dataLength : in natural range 1 to 32; + constant data : in DoublewordArray(0 to 31)) + return RioPayload is + variable payload : RioPayload; + begin + payload.data(0)(15 downto 12) := "0100"; + payload.data(0)(11 downto 8) := wrsize; + payload.data(0)(7 downto 0) := tid; + + payload.data(1) := address(28 downto 13); + + payload.data(2)(15 downto 3) := address(12 downto 0); + payload.data(2)(2) := wdptr; + payload.data(2)(1 downto 0) := xamsbs; + + for i in 0 to dataLength-1 loop + payload.data(3+4*i) := data(i)(63 downto 48); + payload.data(4+4*i) := data(i)(47 downto 32); + payload.data(5+4*i) := data(i)(31 downto 16); + payload.data(6+4*i) := data(i)(15 downto 0); + end loop; + + payload.length := 3 + 4*dataLength; + + return payload; + end function; + + ----------------------------------------------------------------------------- + -- + ----------------------------------------------------------------------------- + function RioNread( + constant rdsize : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant address : in std_logic_vector(28 downto 0); + constant wdptr : in std_logic; + constant xamsbs : in std_logic_vector(1 downto 0)) + return RioPayload is + variable payload : RioPayload; + begin + payload.data(0)(15 downto 12) := "0100"; + payload.data(0)(11 downto 8) := rdsize; + payload.data(0)(7 downto 0) := tid; + + payload.data(1) := address(28 downto 13); + + payload.data(2)(15 downto 3) := address(12 downto 0); + payload.data(2)(2) := wdptr; + payload.data(2)(1 downto 0) := xamsbs; + + payload.length := 3; + + return payload; + end function; + + --------------------------------------------------------------------------- + -- Create a RESPONSE RapidIO frame. + --------------------------------------------------------------------------- + function RioResponse( + constant status : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant dataLength : in natural range 0 to 32; + constant data : in DoublewordArray(0 to 31)) + return RioPayload is + variable payload : RioPayload; + begin + payload.data(0)(11 downto 8) := status; + payload.data(0)(7 downto 0) := tid; + + if (dataLength = 0) then + payload.data(0)(15 downto 12) := "0000"; + payload.length := 1; + else + payload.data(0)(15 downto 12) := "1000"; + + for i in 0 to dataLength-1 loop + payload.data(1+4*i) := data(i)(63 downto 48); + payload.data(2+4*i) := data(i)(47 downto 32); + payload.data(3+4*i) := data(i)(31 downto 16); + payload.data(4+4*i) := data(i)(15 downto 0); + end loop; + + payload.length := 1 + 4*dataLength; + end if; + + return payload; + end function; + + --------------------------------------------------------------------------- + -- Create a Maintenance RapidIO frame. + --------------------------------------------------------------------------- + function RioMaintenance( + constant transaction : in std_logic_vector(3 downto 0); + constant size : in std_logic_vector(3 downto 0); + constant tid : in std_logic_vector(7 downto 0); + constant hopCount : in std_logic_vector(7 downto 0); + constant configOffset : in std_logic_vector(20 downto 0); + constant wdptr : in std_logic; + constant dataLength : in natural range 0 to 8; + constant data : in DoublewordArray(0 to 7)) + return RioPayload is + variable payload : RioPayload; + begin + payload.data(0)(15 downto 12) := transaction; + payload.data(0)(11 downto 8) := size; + payload.data(0)(7 downto 0) := tid; + + payload.data(1)(15 downto 8) := hopCount; + payload.data(1)(7 downto 0) := configOffset(20 downto 13); + + payload.data(2)(15 downto 3) := configOffset(12 downto 0); + payload.data(2)(2) := wdptr; + payload.data(2)(1 downto 0) := "00"; + + if (dataLength = 0) then + payload.length := 3; + else + for i in 0 to dataLength-1 loop + payload.data(3+4*i) := data(i)(63 downto 48); + payload.data(4+4*i) := data(i)(47 downto 32); + payload.data(5+4*i) := data(i)(31 downto 16); + payload.data(6+4*i) := data(i)(15 downto 0); + end loop; + + payload.length := 3 + 4*dataLength; + end if; + + return payload; + end function; + + ----------------------------------------------------------------------------- + -- Function to convert a std_logic_vector to a string. + ----------------------------------------------------------------------------- + function byteToString(constant byte : std_logic_vector(7 downto 0)) + return string is + constant table : string(1 to 16) := "0123456789abcdef"; + variable returnValue : string(1 to 2); + begin + returnValue(1) := table(to_integer(unsigned(byte(7 downto 4))) + 1); + returnValue(2) := table(to_integer(unsigned(byte(3 downto 0))) + 1); + return returnValue; + end function; + + --------------------------------------------------------------------------- + -- Procedure to print test report + --------------------------------------------------------------------------- + procedure PrintR( constant str : string ) is + file reportFile : text; + variable reportLine, outputLine : line; + variable fStatus: FILE_OPEN_STATUS; + begin + --Write report note to wave/transcript window + report str severity NOTE; + end PrintR; + + --------------------------------------------------------------------------- + -- Procedure to print test spec + --------------------------------------------------------------------------- + procedure PrintS( constant str : string ) is + file specFile : text; + variable specLine, outputLine : line; + variable fStatus: FILE_OPEN_STATUS; + begin + --Write to spec file + file_open(fStatus, specFile, "testspec.txt", append_mode); + write(specLine, string'(str)); + writeline (specFile, specLine); + file_close(specFile); + end PrintS; + + --------------------------------------------------------------------------- + -- Procedure to Assert Expression + --------------------------------------------------------------------------- + procedure AssertE( constant exp: boolean; constant str : string ) is + file reportFile : text; + variable reportLine, outputLine : line; + variable fStatus: FILE_OPEN_STATUS; + begin + if (not exp) then + --Write to STD_OUTPUT + report(str) severity error; + else + PrintR("Status: Passed"); + PrintS("Status: Passed"); + end if; + end AssertE; + + --------------------------------------------------------------------------- + -- Procedure to Print Error + --------------------------------------------------------------------------- + procedure PrintE( constant str : string ) is + file reportFile : text; + variable reportLine, outputLine : line; + variable fStatus: FILE_OPEN_STATUS; + begin + --Write to STD_OUTPUT + report str severity error; + end PrintE; + + --------------------------------------------------------------------------- + -- Procedure to end a test. + --------------------------------------------------------------------------- + procedure TestEnd is + begin + assert false report "Test complete." severity failure; + wait; + end TestEnd; + +end rio_common; + + + +------------------------------------------------------------------------------- +-- Crc16CITT +-- A CRC-16 calculator following the implementation proposed in the 2.2 +-- standard. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; + + +------------------------------------------------------------------------------- +-- Entity for Crc16CITT. +------------------------------------------------------------------------------- +entity 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 entity; + + +------------------------------------------------------------------------------- +-- Architecture for Crc16CITT. +------------------------------------------------------------------------------- +architecture Crc16Impl of Crc16CITT is + signal d : std_logic_vector(0 to 15); + signal c : std_logic_vector(0 to 15); + signal e : std_logic_vector(0 to 15); + signal cc : std_logic_vector(0 to 15); +begin + + -- Reverse the bit vector indexes to make them the same as in the standard. + d(15) <= d_i(0); d(14) <= d_i(1); d(13) <= d_i(2); d(12) <= d_i(3); + d(11) <= d_i(4); d(10) <= d_i(5); d(9) <= d_i(6); d(8) <= d_i(7); + d(7) <= d_i(8); d(6) <= d_i(9); d(5) <= d_i(10); d(4) <= d_i(11); + d(3) <= d_i(12); d(2) <= d_i(13); d(1) <= d_i(14); d(0) <= d_i(15); + + -- Reverse the bit vector indexes to make them the same as in the standard. + c(15) <= crc_i(0); c(14) <= crc_i(1); c(13) <= crc_i(2); c(12) <= crc_i(3); + c(11) <= crc_i(4); c(10) <= crc_i(5); c(9) <= crc_i(6); c(8) <= crc_i(7); + c(7) <= crc_i(8); c(6) <= crc_i(9); c(5) <= crc_i(10); c(4) <= crc_i(11); + c(3) <= crc_i(12); c(2) <= crc_i(13); c(1) <= crc_i(14); c(0) <= crc_i(15); + + -- Calculate the resulting crc. + e <= c xor d; + cc(0) <= e(4) xor e(5) xor e(8) xor e(12); + cc(1) <= e(5) xor e(6) xor e(9) xor e(13); + cc(2) <= e(6) xor e(7) xor e(10) xor e(14); + cc(3) <= e(0) xor e(7) xor e(8) xor e(11) xor e(15); + cc(4) <= e(0) xor e(1) xor e(4) xor e(5) xor e(9); + cc(5) <= e(1) xor e(2) xor e(5) xor e(6) xor e(10); + cc(6) <= e(0) xor e(2) xor e(3) xor e(6) xor e(7) xor e(11); + cc(7) <= e(0) xor e(1) xor e(3) xor e(4) xor e(7) xor e(8) xor e(12); + cc(8) <= e(0) xor e(1) xor e(2) xor e(4) xor e(5) xor e(8) xor e(9) xor e(13); + cc(9) <= e(1) xor e(2) xor e(3) xor e(5) xor e(6) xor e(9) xor e(10) xor e(14); + cc(10) <= e(2) xor e(3) xor e(4) xor e(6) xor e(7) xor e(10) xor e(11) xor e(15); + cc(11) <= e(0) xor e(3) xor e(7) xor e(11); + cc(12) <= e(0) xor e(1) xor e(4) xor e(8) xor e(12); + cc(13) <= e(1) xor e(2) xor e(5) xor e(9) xor e(13); + cc(14) <= e(2) xor e(3) xor e(6) xor e(10) xor e(14); + cc(15) <= e(3) xor e(4) xor e(7) xor e(11) xor e(15); + + -- Reverse the bit vector indexes to make them the same as in the standard. + crc_o(15) <= cc(0); crc_o(14) <= cc(1); crc_o(13) <= cc(2); crc_o(12) <= cc(3); + crc_o(11) <= cc(4); crc_o(10) <= cc(5); crc_o(9) <= cc(6); crc_o(8) <= cc(7); + crc_o(7) <= cc(8); crc_o(6) <= cc(9); crc_o(5) <= cc(10); crc_o(4) <= cc(11); + crc_o(3) <= cc(12); crc_o(2) <= cc(13); crc_o(1) <= cc(14); crc_o(0) <= cc(15); + +end architecture; + + + +------------------------------------------------------------------------------- +-- MemoryDualPort +-- Generic synchronous memory with one read/write port and one read port. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +------------------------------------------------------------------------------- +-- Entity for MemoryDualPort. +------------------------------------------------------------------------------- +entity MemoryDualPort is + generic( + ADDRESS_WIDTH : natural := 1; + DATA_WIDTH : natural := 1); + port( + clkA_i : in std_logic; + enableA_i : in std_logic; + writeEnableA_i : in std_logic; + addressA_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataA_i : in std_logic_vector(DATA_WIDTH-1 downto 0); + dataA_o : out std_logic_vector(DATA_WIDTH-1 downto 0); + + clkB_i : in std_logic; + enableB_i : in std_logic; + addressB_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataB_o : out std_logic_vector(DATA_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for MemoryDualPort. +------------------------------------------------------------------------------- +architecture MemoryDualPortImpl of MemoryDualPort is + type MemoryType is array (natural range <>) of + std_logic_vector(DATA_WIDTH-1 downto 0); + + signal memory : MemoryType(0 to (2**ADDRESS_WIDTH)-1); + +begin + process(clkA_i) + begin + if (clkA_i'event and clkA_i = '1') then + if (enableA_i = '1') then + if (writeEnableA_i = '1') then + memory(to_integer(unsigned(addressA_i))) <= dataA_i; + end if; + + dataA_o <= memory(to_integer(unsigned(addressA_i))); + end if; + end if; + end process; + + process(clkB_i) + begin + if (clkB_i'event and clkB_i = '1') then + if (enableB_i = '1') then + dataB_o <= memory(to_integer(unsigned(addressB_i))); + end if; + end if; + end process; + +end architecture; + + + +------------------------------------------------------------------------------- +-- MemorySimpleDualPort +-- Generic synchronous memory with one write port and one read port. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +------------------------------------------------------------------------------- +-- Entity for MemorySimpleDualPort. +------------------------------------------------------------------------------- +entity MemorySimpleDualPort is + generic( + ADDRESS_WIDTH : natural := 1; + DATA_WIDTH : natural := 1); + port( + clkA_i : in std_logic; + enableA_i : in std_logic; + addressA_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataA_i : in std_logic_vector(DATA_WIDTH-1 downto 0); + + clkB_i : in std_logic; + enableB_i : in std_logic; + addressB_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataB_o : out std_logic_vector(DATA_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for MemorySimpleDualPort. +------------------------------------------------------------------------------- +architecture MemorySimpleDualPortImpl of MemorySimpleDualPort is + type MemoryType is array (natural range <>) of + std_logic_vector(DATA_WIDTH-1 downto 0); + + signal memory : MemoryType(0 to (2**ADDRESS_WIDTH)-1); + +begin + process(clkA_i) + begin + if (clkA_i'event and clkA_i = '1') then + if (enableA_i = '1') then + memory(to_integer(unsigned(addressA_i))) <= dataA_i; + end if; + end if; + end process; + + process(clkB_i) + begin + if (clkB_i'event and clkB_i = '1') then + if (enableB_i = '1') then + dataB_o <= memory(to_integer(unsigned(addressB_i))); + end if; + end if; + end process; + +end architecture; + + + +------------------------------------------------------------------------------- +-- MemorySinglePort +-- Generic synchronous memory with one read/write port. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +------------------------------------------------------------------------------- +-- Entity for MemorySinglePort. +------------------------------------------------------------------------------- +entity 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 entity; + + +------------------------------------------------------------------------------- +-- Architecture for MemorySinglePort. +------------------------------------------------------------------------------- +architecture MemorySinglePortImpl of MemorySinglePort is + type MemoryType is array (natural range <>) of + std_logic_vector(DATA_WIDTH-1 downto 0); + + signal memory : MemoryType(0 to (2**ADDRESS_WIDTH)-1); + +begin + process(clk_i) + begin + if (clk_i'event and clk_i = '1') then + if (enable_i = '1') then + if (writeEnable_i = '1') then + memory(to_integer(unsigned(address_i))) <= data_i; + end if; + + data_o <= memory(to_integer(unsigned(address_i))); + end if; + end if; + end process; + +end architecture; + + + + +------------------------------------------------------------------------------- +-- MemorySimpleDualPortAsync +-- Generic memory with one synchronous write port and one asynchronous read port. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +------------------------------------------------------------------------------- +-- Entity for MemorySimpleDualPortAsync. +------------------------------------------------------------------------------- +entity MemorySimpleDualPortAsync is + generic( + ADDRESS_WIDTH : natural := 1; + DATA_WIDTH : natural := 1; + INIT_VALUE : std_logic := 'U'); + port( + clkA_i : in std_logic; + enableA_i : in std_logic; + addressA_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataA_i : in std_logic_vector(DATA_WIDTH-1 downto 0); + + addressB_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataB_o : out std_logic_vector(DATA_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for MemorySimpleDualPortAsync. +------------------------------------------------------------------------------- +architecture MemorySimpleDualPortAsyncImpl of MemorySimpleDualPortAsync is + type MemoryType is array (natural range <>) of + std_logic_vector(DATA_WIDTH-1 downto 0); + + signal memory : MemoryType(0 to (2**ADDRESS_WIDTH)-1) := (others=>(others=>INIT_VALUE)); + +begin + process(clkA_i) + begin + if (clkA_i'event and clkA_i = '1') then + if (enableA_i = '1') then + memory(to_integer(unsigned(addressA_i))) <= dataA_i; + end if; + end if; + end process; + + dataB_o <= memory(to_integer(unsigned(addressB_i))); + +end architecture; + + + + +
rtl/vhdl/RioCommon.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/vhdl/RioSwitch.vhd =================================================================== --- rtl/vhdl/RioSwitch.vhd (nonexistent) +++ rtl/vhdl/RioSwitch.vhd (revision 2) @@ -0,0 +1,2510 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- Containing RapidIO packet switching functionality contained in the top +-- entity RioSwitch. +-- +-- To Do: +-- - +-- +-- 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 +-- +------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- RioSwitch +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + +------------------------------------------------------------------------------- +-- Entity for RioSwitch. +------------------------------------------------------------------------------- +entity RioSwitch is + generic( + SWITCH_PORTS : natural range 3 to 255 := 4; + 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; + + writeFrameFull_i : in Array1(SWITCH_PORTS-1 downto 0); + writeFrame_o : out Array1(SWITCH_PORTS-1 downto 0); + writeFrameAbort_o : out Array1(SWITCH_PORTS-1 downto 0); + writeContent_o : out Array1(SWITCH_PORTS-1 downto 0); + writeContentData_o : out Array32(SWITCH_PORTS-1 downto 0); + + readFrameEmpty_i : in Array1(SWITCH_PORTS-1 downto 0); + readFrame_o : out Array1(SWITCH_PORTS-1 downto 0); + readFrameRestart_o : out Array1(SWITCH_PORTS-1 downto 0); + readFrameAborted_i : in Array1(SWITCH_PORTS-1 downto 0); + readContentEmpty_i : in Array1(SWITCH_PORTS-1 downto 0); + readContent_o : out Array1(SWITCH_PORTS-1 downto 0); + readContentEnd_i : in Array1(SWITCH_PORTS-1 downto 0); + readContentData_i : in Array32(SWITCH_PORTS-1 downto 0); + + portLinkTimeout_o : out std_logic_vector(23 downto 0); + + linkInitialized_i : in Array1(SWITCH_PORTS-1 downto 0); + outputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0); + inputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0); + + localAckIdWrite_o : out Array1(SWITCH_PORTS-1 downto 0); + clrOutstandingAckId_o : out Array1(SWITCH_PORTS-1 downto 0); + inboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + outstandingAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + outboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + inboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + outstandingAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + outboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + + configStb_o : out std_logic; + configWe_o : out std_logic; + configAddr_o : out std_logic_vector(23 downto 0); + configData_o : out std_logic_vector(31 downto 0); + configData_i : in std_logic_vector(31 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioSwitch. +------------------------------------------------------------------------------- +architecture RioSwitchImpl of RioSwitch is + + component RouteTableInterconnect is + generic( + WIDTH : natural range 1 to 256 := 8); + port( + clk : in std_logic; + areset_n : in std_logic; + + stb_i : in Array1(WIDTH-1 downto 0); + addr_i : in Array16(WIDTH-1 downto 0); + dataM_o : out Array8(WIDTH-1 downto 0); + ack_o : out Array1(WIDTH-1 downto 0); + + stb_o : out std_logic; + addr_o : out std_logic_vector(15 downto 0); + dataS_i : in std_logic_vector(7 downto 0); + ack_i : in std_logic); + end component; + + component SwitchPortInterconnect is + generic( + WIDTH : natural range 1 to 256 := 8); + port( + clk : in std_logic; + areset_n : in std_logic; + + masterCyc_i : in Array1(WIDTH-1 downto 0); + masterStb_i : in Array1(WIDTH-1 downto 0); + masterWe_i : in Array1(WIDTH-1 downto 0); + masterAddr_i : in Array10(WIDTH-1 downto 0); + masterData_i : in Array32(WIDTH-1 downto 0); + masterData_o : out Array1(WIDTH-1 downto 0); + masterAck_o : out Array1(WIDTH-1 downto 0); + + slaveCyc_o : out Array1(WIDTH-1 downto 0); + slaveStb_o : out Array1(WIDTH-1 downto 0); + slaveWe_o : out Array1(WIDTH-1 downto 0); + slaveAddr_o : out Array10(WIDTH-1 downto 0); + slaveData_o : out Array32(WIDTH-1 downto 0); + slaveData_i : in Array1(WIDTH-1 downto 0); + slaveAck_i : in Array1(WIDTH-1 downto 0)); + end component; + + component SwitchPortMaintenance is + generic( + SWITCH_PORTS : natural range 0 to 255; + 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; + + lookupStb_i : in std_logic; + lookupAddr_i : in std_logic_vector(15 downto 0); + lookupData_o : out std_logic_vector(7 downto 0); + lookupAck_o : out std_logic; + + masterCyc_o : out std_logic; + masterStb_o : out std_logic; + masterWe_o : out std_logic; + masterAddr_o : out std_logic_vector(9 downto 0); + masterData_o : out std_logic_vector(31 downto 0); + masterData_i : in std_logic; + masterAck_i : in std_logic; + + slaveCyc_i : in std_logic; + slaveStb_i : in std_logic; + slaveWe_i : in std_logic; + slaveAddr_i : in std_logic_vector(9 downto 0); + slaveData_i : in std_logic_vector(31 downto 0); + slaveData_o : out std_logic; + slaveAck_o : out std_logic; + + lookupStb_o : out std_logic; + lookupAddr_o : out std_logic_vector(15 downto 0); + lookupData_i : in std_logic_vector(7 downto 0); + lookupAck_i : in std_logic; + + portLinkTimeout_o : out std_logic_vector(23 downto 0); + + linkInitialized_i : in Array1(SWITCH_PORTS-1 downto 0); + outputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0); + inputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0); + localAckIdWrite_o : out Array1(SWITCH_PORTS-1 downto 0); + clrOutstandingAckId_o : out Array1(SWITCH_PORTS-1 downto 0); + inboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + outstandingAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + outboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + inboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + outstandingAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + outboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + + configStb_o : out std_logic; + configWe_o : out std_logic; + configAddr_o : out std_logic_vector(23 downto 0); + configData_o : out std_logic_vector(31 downto 0); + configData_i : in std_logic_vector(31 downto 0)); + end component; + + component SwitchPort is + generic( + PORT_INDEX : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + masterCyc_o : out std_logic; + masterStb_o : out std_logic; + masterWe_o : out std_logic; + masterAddr_o : out std_logic_vector(9 downto 0); + masterData_o : out std_logic_vector(31 downto 0); + masterData_i : in std_logic; + masterAck_i : in std_logic; + + slaveCyc_i : in std_logic; + slaveStb_i : in std_logic; + slaveWe_i : in std_logic; + slaveAddr_i : in std_logic_vector(9 downto 0); + slaveData_i : in std_logic_vector(31 downto 0); + slaveData_o : out std_logic; + slaveAck_o : out std_logic; + + lookupStb_o : out std_logic; + lookupAddr_o : out std_logic_vector(15 downto 0); + lookupData_i : in std_logic_vector(7 downto 0); + lookupAck_i : in std_logic; + + readFrameEmpty_i : in std_logic; + readFrame_o : out std_logic; + readFrameRestart_o : out std_logic; + readFrameAborted_i : in std_logic; + readContentEmpty_i : in 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)); + end component; + + signal masterLookupStb : Array1(SWITCH_PORTS downto 0); + signal masterLookupAddr : Array16(SWITCH_PORTS downto 0); + signal masterLookupData : Array8(SWITCH_PORTS downto 0); + signal masterLookupAck : Array1(SWITCH_PORTS downto 0); + + signal slaveLookupStb : std_logic; + signal slaveLookupAddr : std_logic_vector(15 downto 0); + signal slaveLookupData : std_logic_vector(7 downto 0); + signal slaveLookupAck : std_logic; + + signal masterCyc : Array1(SWITCH_PORTS downto 0); + signal masterStb : Array1(SWITCH_PORTS downto 0); + signal masterWe : Array1(SWITCH_PORTS downto 0); + signal masterAddr : Array10(SWITCH_PORTS downto 0); + signal masterDataWrite : Array32(SWITCH_PORTS downto 0); + signal masterDataRead : Array1(SWITCH_PORTS downto 0); + signal masterAck : Array1(SWITCH_PORTS downto 0); + + signal slaveCyc : Array1(SWITCH_PORTS downto 0); + signal slaveStb : Array1(SWITCH_PORTS downto 0); + signal slaveWe : Array1(SWITCH_PORTS downto 0); + signal slaveAddr : Array10(SWITCH_PORTS downto 0); + signal slaveDataWrite : Array32(SWITCH_PORTS downto 0); + signal slaveDataRead : Array1(SWITCH_PORTS downto 0); + signal slaveAck : Array1(SWITCH_PORTS downto 0); + +begin + + ----------------------------------------------------------------------------- + -- The routing table interconnect. + ----------------------------------------------------------------------------- + RouteInterconnect: RouteTableInterconnect + generic map( + WIDTH=>SWITCH_PORTS+1) + port map( + clk=>clk, areset_n=>areset_n, + stb_i=>masterLookupStb, addr_i=>masterLookupAddr, + dataM_o=>masterLookupData, ack_o=>masterLookupAck, + stb_o=>slaveLookupStb, addr_o=>slaveLookupAddr, + dataS_i=>slaveLookupData, ack_i=>slaveLookupAck); + + ----------------------------------------------------------------------------- + -- The port interconnect. + ----------------------------------------------------------------------------- + PortInterconnect: SwitchPortInterconnect + generic map( + WIDTH=>SWITCH_PORTS+1) + port map( + clk=>clk, areset_n=>areset_n, + masterCyc_i=>masterCyc, masterStb_i=>masterStb, masterWe_i=>masterWe, masterAddr_i=>masterAddr, + masterData_i=>masterDataWrite, masterData_o=>masterDataRead, masterAck_o=>masterAck, + slaveCyc_o=>slaveCyc, slaveStb_o=>slaveStb, slaveWe_o=>slaveWe, slaveAddr_o=>slaveAddr, + slaveData_o=>slaveDataWrite, slaveData_i=>slaveDataRead, slaveAck_i=>slaveAck); + + ----------------------------------------------------------------------------- + -- Data relaying port instantiation. + ----------------------------------------------------------------------------- + PortGeneration: for portIndex in 0 to SWITCH_PORTS-1 generate + PortInst: SwitchPort + generic map( + PORT_INDEX=>portIndex) + port map( + clk=>clk, areset_n=>areset_n, + masterCyc_o=>masterCyc(portIndex), masterStb_o=>masterStb(portIndex), + masterWe_o=>masterWe(portIndex), masterAddr_o=>masterAddr(portIndex), + masterData_o=>masterDataWrite(portIndex), + masterData_i=>masterDataRead(portIndex), masterAck_i=>masterAck(portIndex), + slaveCyc_i=>slaveCyc(portIndex), slaveStb_i=>slaveStb(portIndex), + slaveWe_i=>slaveWe(portIndex), slaveAddr_i=>slaveAddr(portIndex), + slaveData_i=>slaveDataWrite(portIndex), + slaveData_o=>slaveDataRead(portIndex), slaveAck_o=>slaveAck(portIndex), + lookupStb_o=>masterLookupStb(portIndex), + lookupAddr_o=>masterLookupAddr(portIndex), + lookupData_i=>masterLookupData(portIndex), lookupAck_i=>masterLookupAck(portIndex), + readFrameEmpty_i=>readFrameEmpty_i(portIndex), readFrame_o=>readFrame_o(portIndex), + readFrameRestart_o=>readFrameRestart_o(portIndex), + readFrameAborted_i=>readFrameAborted_i(portIndex), + readContentEmpty_i=>readContentEmpty_i(portIndex), readContent_o=>readContent_o(portIndex), + readContentEnd_i=>readContentEnd_i(portIndex), readContentData_i=>readContentData_i(portIndex), + writeFrameFull_i=>writeFrameFull_i(portIndex), writeFrame_o=>writeFrame_o(portIndex), + writeFrameAbort_o=>writeFrameAbort_o(portIndex), writeContent_o=>writeContent_o(portIndex), + writeContentData_o=>writeContentData_o(portIndex)); + end generate; + + ----------------------------------------------------------------------------- + -- Maintenance port instantiation. + ----------------------------------------------------------------------------- + MaintenancePort: SwitchPortMaintenance + generic map( + SWITCH_PORTS=>SWITCH_PORTS, + DEVICE_IDENTITY=>DEVICE_IDENTITY, + DEVICE_VENDOR_IDENTITY=>DEVICE_VENDOR_IDENTITY, + DEVICE_REV=>DEVICE_REV, + ASSY_IDENTITY=>ASSY_IDENTITY, + ASSY_VENDOR_IDENTITY=>ASSY_VENDOR_IDENTITY, + ASSY_REV=>ASSY_REV) + port map( + clk=>clk, areset_n=>areset_n, + lookupStb_i=>slaveLookupStb, lookupAddr_i=>slaveLookupAddr, + lookupData_o=>slaveLookupData, lookupAck_o=>slaveLookupAck, + masterCyc_o=>masterCyc(SWITCH_PORTS), masterStb_o=>masterStb(SWITCH_PORTS), + masterWe_o=>masterWe(SWITCH_PORTS), masterAddr_o=>masterAddr(SWITCH_PORTS), + masterData_o=>masterDataWrite(SWITCH_PORTS), + masterData_i=>masterDataRead(SWITCH_PORTS), masterAck_i=>masterAck(SWITCH_PORTS), + slaveCyc_i=>slaveCyc(SWITCH_PORTS), slaveStb_i=>slaveStb(SWITCH_PORTS), + slaveWe_i=>slaveWe(SWITCH_PORTS), slaveAddr_i=>slaveAddr(SWITCH_PORTS), + slaveData_i=>slaveDataWrite(SWITCH_PORTS), + slaveData_o=>slaveDataRead(SWITCH_PORTS), slaveAck_o=>slaveAck(SWITCH_PORTS), + lookupStb_o=>masterLookupStb(SWITCH_PORTS), + lookupAddr_o=>masterLookupAddr(SWITCH_PORTS), + lookupData_i=>masterLookupData(SWITCH_PORTS), lookupAck_i=>masterLookupAck(SWITCH_PORTS), + portLinkTimeout_o=>portLinkTimeout_o, + linkInitialized_i=>linkInitialized_i, + outputPortEnable_o=>outputPortEnable_o, inputPortEnable_o=>inputPortEnable_o, + localAckIdWrite_o=>localAckIdWrite_o, clrOutstandingAckId_o=>clrOutstandingAckId_o, + inboundAckId_o=>inboundAckId_o, outstandingAckId_o=>outstandingAckId_o, + outboundAckId_o=>outboundAckId_o, inboundAckId_i=>inboundAckId_i, + outstandingAckId_i=>outstandingAckId_i, outboundAckId_i=>outboundAckId_i, + configStb_o=>configStb_o, configWe_o=>configWe_o, configAddr_o=>configAddr_o, + configData_o=>configData_o, configData_i=>configData_i); + +end architecture; + + + +------------------------------------------------------------------------------- +-- SwitchPort +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for SwitchPort. +------------------------------------------------------------------------------- +entity SwitchPort is + generic( + PORT_INDEX : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + -- Master port signals. + -- Write frames to other ports. + masterCyc_o : out std_logic; + masterStb_o : out std_logic; + masterWe_o : out std_logic; + masterAddr_o : out std_logic_vector(9 downto 0); + masterData_o : out std_logic_vector(31 downto 0); + masterData_i : in std_logic; + masterAck_i : in std_logic; + + -- Slave port signals. + -- Receives frames from other ports. + slaveCyc_i : in std_logic; + slaveStb_i : in std_logic; + slaveWe_i : in std_logic; + slaveAddr_i : in std_logic_vector(9 downto 0); + slaveData_i : in std_logic_vector(31 downto 0); + slaveData_o : out std_logic; + slaveAck_o : out std_logic; + + -- Address-lookup interface. + lookupStb_o : out std_logic; + lookupAddr_o : out std_logic_vector(15 downto 0); + lookupData_i : in std_logic_vector(7 downto 0); + lookupAck_i : in std_logic; + + -- Physical port frame buffer interface. + readFrameEmpty_i : in std_logic; + readFrame_o : out std_logic; + readFrameRestart_o : out std_logic; + readFrameAborted_i : in std_logic; + readContentEmpty_i : in 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)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for SwitchPort. +------------------------------------------------------------------------------- +architecture SwitchPortImpl of SwitchPort is + + type MasterStateType is (STATE_IDLE, + STATE_WAIT_HEADER_0, STATE_READ_HEADER_0, + STATE_READ_PORT_LOOKUP, + STATE_READ_TARGET_PORT, + STATE_WAIT_TARGET_PORT, + STATE_WAIT_TARGET_WRITE, + STATE_WAIT_COMPLETE); + signal masterState : MasterStateType; + + type SlaveStateType is (STATE_IDLE, STATE_SEND_ACK); + signal slaveState : SlaveStateType; + + alias ftype : std_logic_vector(3 downto 0) is readContentData_i(19 downto 16); + alias tt : std_logic_vector(1 downto 0) is readContentData_i(21 downto 20); + +begin + + ----------------------------------------------------------------------------- + -- Master interface process. + ----------------------------------------------------------------------------- + Master: process(clk, areset_n) + begin + if (areset_n = '0') then + masterState <= STATE_IDLE; + + lookupStb_o <= '0'; + lookupAddr_o <= (others => '0'); + + masterCyc_o <= '0'; + masterStb_o <= '0'; + masterWe_o <= '0'; + masterAddr_o <= (others => '0'); + masterData_o <= (others => '0'); + + readContent_o <= '0'; + readFrame_o <= '0'; + readFrameRestart_o <= '0'; + elsif (clk'event and clk = '1') then + readContent_o <= '0'; + readFrame_o <= '0'; + readFrameRestart_o <= '0'; + + -- REMARK: Add support for aborted frames... + case masterState is + + when STATE_IDLE => + --------------------------------------------------------------------- + -- Wait for a new packet or content of a new packet. + --------------------------------------------------------------------- + + -- Reset bus signals. + masterCyc_o <= '0'; + masterStb_o <= '0'; + + -- Wait for frame content to be available. + -- Use different signals to trigger the forwarding of packets depending + -- on the switch philosofy. + if (readFrameEmpty_i = '0') then + readContent_o <= '1'; + masterState <= STATE_WAIT_HEADER_0; + end if; + + when STATE_WAIT_HEADER_0 => + --------------------------------------------------------------------- + -- Wait for the frame buffer output to be updated. + --------------------------------------------------------------------- + + -- Wait for frame buffer output to be updated. + masterState <= STATE_READ_HEADER_0; + + when STATE_READ_HEADER_0 => + --------------------------------------------------------------------- + -- Check the FTYPE and forward it to the maintenance port if it is a + -- maintenance packet. Otherwise, initiate an address lookup and wait + -- for the result. + --------------------------------------------------------------------- + + -- Check if the frame has ended. + if (readContentEnd_i = '0') then + -- The frame has not ended. + -- This word contains the header and the source id. + + -- Read the tt-field to check the source and destination id size. + if (tt = "01") then + -- This frame contains 16-bit addresses. + + -- Read the new content. + readContent_o <= '1'; + + -- Save the content of the header and destination. + masterData_o <= readContentData_i; + + -- Check if this is a maintenance frame. + if (ftype = FTYPE_MAINTENANCE_CLASS) then + -- This is a maintenance frame. + + -- Always route these frames to the maintenance module in the + -- switch by setting the MSB bit of the port address. + masterAddr_o <= '1' & std_logic_vector(to_unsigned(PORT_INDEX, 8)) & '0'; + + -- Start an access to the maintenance port. + masterState <= STATE_READ_TARGET_PORT; + else + -- This is not a maintenance frame. + + -- Lookup the destination address and proceed to wait for the + -- result. + lookupStb_o <= '1'; + lookupAddr_o <= readContentData_i(15 downto 0); + + -- Wait for the port lookup to return a result. + masterState <= STATE_READ_PORT_LOOKUP; + end if; + else + -- Unsupported tt-value, discard the frame. + readFrame_o <= '1'; + masterState <= STATE_IDLE; + end if; + else + -- End of frame. + -- The frame is too short to contain a valid frame. Discard it. + readFrame_o <= '1'; + masterState <= STATE_IDLE; + end if; + + when STATE_READ_PORT_LOOKUP => + --------------------------------------------------------------------- + -- Wait for the address lookup to be complete. + --------------------------------------------------------------------- + + -- Wait for the routing table to complete the request. + if (lookupAck_i = '1') then + -- The address lookup is complete. + + -- Terminate the lookup cycle. + lookupStb_o <= '0'; + + -- Proceed to read the target port. + masterAddr_o <= '0' & lookupData_i & '0'; + masterState <= STATE_READ_TARGET_PORT; + else + -- Wait until the address lookup is complete. + -- REMARK: Timeout here??? + end if; + + when STATE_READ_TARGET_PORT => + --------------------------------------------------------------------- + -- Initiate an access to the target port. + --------------------------------------------------------------------- + + -- Read the status of the target port using the result from the + -- lookup in the routing table. + masterCyc_o <= '1'; + masterStb_o <= '1'; + masterWe_o <= '0'; + masterState <= STATE_WAIT_TARGET_PORT; + + when STATE_WAIT_TARGET_PORT => + --------------------------------------------------------------------- + -- Wait to get access to the target port. When the port is ready + -- check if it is ready to accept a new frame. If it cannot accept a + -- new frame, terminate the access and go back and start a new one. + -- This is to free the interconnect to let other ports access it if + -- it is a shared bus. If the port is ready, initiate a write access + -- to the selected port. + --------------------------------------------------------------------- + + -- Wait for the target port to complete the request. + if (masterAck_i = '1') then + -- Target port has completed the request. + + -- Check the status of the target port. + if (masterData_i = '0') then + -- The target port has empty buffers to receive the frame. + + -- Hold the bus with cyc until the cycle is complete. + -- Write the first word of the frame to the target port. + -- The masterData_o has already been assigned. + masterCyc_o <= '1'; + masterStb_o <= '1'; + masterWe_o <= '1'; + masterAddr_o(0) <= '1'; + + -- Change state to transfer the frame. + masterState <= STATE_WAIT_TARGET_WRITE; + else + -- The target port has no empty buffer to receive the frame. + -- Terminate the cycle and retry later. + masterCyc_o <= '0'; + masterStb_o <= '0'; + masterState <= STATE_READ_TARGET_PORT; + end if; + else + -- Target port has not completed the request. + -- Dont to anything. + end if; + + when STATE_WAIT_TARGET_WRITE => + --------------------------------------------------------------------- + -- Wait for the write access to complete. When complete, write the + -- next content and update the content to the next. If the frame does + -- not have any more data ready, terminate the access but keep the + -- cycle active and proceed to wait for new data. + --------------------------------------------------------------------- + + -- Wait for the target port to complete the request. + -- REMARK: Remove the ack-condition, we know that the write takes one + -- cycle... + if (masterAck_i = '1') then + -- The target port is ready. + + -- Check if the frame has ended. + if (readContentEnd_i = '0') then + -- The frame has not ended. + + -- There are more data to transfer. + masterData_o <= readContentData_i; + readContent_o <= '1'; + else + -- There are no more data to transfer. + + -- Update to the next frame. + readFrame_o <= '1'; + + -- Tell the target port that the frame is complete. + masterWe_o <= '1'; + masterAddr_o(0) <= '0'; + masterData_o <= x"00000001"; + + -- Change state to wait for the target port to finalize the write + -- of the full frame. + masterState <= STATE_WAIT_COMPLETE; + end if; + else + -- Wait for the target port to reply. + -- Dont do anything. + end if; + + when STATE_WAIT_COMPLETE => + --------------------------------------------------------------------- + -- Wait for the target port to signal that the frame has been + -- completed. + --------------------------------------------------------------------- + + -- Wait for the target port to complete the final request. + if (masterAck_i = '1') then + -- The target port has finalized the write of the frame. + + -- Reset master bus signals. + masterCyc_o <= '0'; + masterStb_o <= '0'; + masterState <= STATE_IDLE; + else + -- Wait for the target port to reply. + -- REMARK: Timeout here??? + end if; + + when others => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + end case; + end if; + end process; + + + ----------------------------------------------------------------------------- + -- Slave interface process. + ----------------------------------------------------------------------------- + -- Addr | Read | Write + -- 0 | full | abort & complete + -- 1 | full | frameData + writeContentData_o <= slaveData_i; + Slave: process(clk, areset_n) + begin + if (areset_n = '0') then + slaveState <= STATE_IDLE; + + slaveData_o <= '0'; + + writeFrame_o <= '0'; + writeFrameAbort_o <= '0'; + writeContent_o <= '0'; + elsif (clk'event and clk = '1') then + writeFrame_o <= '0'; + writeFrameAbort_o <= '0'; + writeContent_o <= '0'; + + case slaveState is + + when STATE_IDLE => + --------------------------------------------------------------------- + -- Wait for an access from a master. + --------------------------------------------------------------------- + + -- Check if any cycle is active. + if ((slaveCyc_i = '1') and (slaveStb_i = '1')) then + -- Cycle is active. + + -- Check if the cycle is accessing the status- or data address. + if (slaveAddr_i(0) = '0') then + -- Accessing port status address. + + -- Check if writing. + if (slaveWe_i = '1') then + -- Writing the status address. + -- Update the buffering output signals according to the input + -- data. + writeFrame_o <= slaveData_i(0); + writeFrameAbort_o <= slaveData_i(1); + else + -- Reading the status address. + slaveData_o <= writeFrameFull_i; + end if; + else + -- Accessing port data address. + + -- Check if writing. + if (slaveWe_i = '1') then + -- Write frame content into the frame buffer. + writeContent_o <= '1'; + else + slaveData_o <= writeFrameFull_i; + end if; + end if; + + -- Change state to send an ack to the master. + slaveState <= STATE_SEND_ACK; + end if; + + when STATE_SEND_ACK => + --------------------------------------------------------------------- + -- Wait for acknowledge to be received by the master. + --------------------------------------------------------------------- + + -- Go back to the idle state and wait for a new cycle. + slaveState <= STATE_IDLE; + + when others => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + null; + + end case; + end if; + end process; + + -- Assign the acknowledge depending on the current slave state. + slaveAck_o <= '1' when (slaveState = STATE_SEND_ACK) else '0'; + +end architecture; + + + +------------------------------------------------------------------------------- +-- SwitchPortMaintenance +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for SwitchPortMaintenance. +------------------------------------------------------------------------------- +entity SwitchPortMaintenance is + generic( + SWITCH_PORTS : natural range 0 to 255; + 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; + + -- Routing table port lookup signals. + lookupStb_i : in std_logic; + lookupAddr_i : in std_logic_vector(15 downto 0); + lookupData_o : out std_logic_vector(7 downto 0); + lookupAck_o : out std_logic; + + -- Master port signals. + -- Write frames to other ports. + masterCyc_o : out std_logic; + masterStb_o : out std_logic; + masterWe_o : out std_logic; + masterAddr_o : out std_logic_vector(9 downto 0); + masterData_o : out std_logic_vector(31 downto 0); + masterData_i : in std_logic; + masterAck_i : in std_logic; + + -- Slave port signals. + -- Receives frames from other ports. + slaveCyc_i : in std_logic; + slaveStb_i : in std_logic; + slaveWe_i : in std_logic; + slaveAddr_i : in std_logic_vector(9 downto 0); + slaveData_i : in std_logic_vector(31 downto 0); + slaveData_o : out std_logic; + slaveAck_o : out std_logic; + + -- Address-lookup interface. + lookupStb_o : out std_logic; + lookupAddr_o : out std_logic_vector(15 downto 0); + lookupData_i : in std_logic_vector(7 downto 0); + lookupAck_i : in std_logic; + + -- Port common access interface. + portLinkTimeout_o : out std_logic_vector(23 downto 0); + + -- Port specific access interface. + linkInitialized_i : in Array1(SWITCH_PORTS-1 downto 0); + outputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0); + inputPortEnable_o : out Array1(SWITCH_PORTS-1 downto 0); + localAckIdWrite_o : out Array1(SWITCH_PORTS-1 downto 0); + clrOutstandingAckId_o : out Array1(SWITCH_PORTS-1 downto 0); + inboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + outstandingAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + outboundAckId_o : out Array5(SWITCH_PORTS-1 downto 0); + inboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + outstandingAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + outboundAckId_i : in Array5(SWITCH_PORTS-1 downto 0); + + -- Configuration space for implementation-defined space. + configStb_o : out std_logic; + configWe_o : out std_logic; + configAddr_o : out std_logic_vector(23 downto 0); + configData_o : out std_logic_vector(31 downto 0); + configData_i : in std_logic_vector(31 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for SwitchPort. +------------------------------------------------------------------------------- +architecture SwitchPortMaintenanceImpl of SwitchPortMaintenance is + + component MemoryDualPort is + generic( + ADDRESS_WIDTH : natural := 1; + DATA_WIDTH : natural := 1); + port( + clkA_i : in std_logic; + enableA_i : in std_logic; + writeEnableA_i : in std_logic; + addressA_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataA_i : in std_logic_vector(DATA_WIDTH-1 downto 0); + dataA_o : out std_logic_vector(DATA_WIDTH-1 downto 0); + + clkB_i : in std_logic; + enableB_i : in std_logic; + addressB_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0); + dataB_o : out std_logic_vector(DATA_WIDTH-1 downto 0)); + end component; + + 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; + + 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; + + type MasterStateType is (STATE_IDLE, + STATE_CHECK_FRAME, + STATE_RELAY_READ_RESPONSE, + STATE_RELAY_WRITE_RESPONSE, + STATE_SEND_READ_REQUEST, + STATE_SEND_WRITE_REQUEST, + STATE_SEND_READ_RESPONSE, + STATE_SEND_WRITE_RESPONSE, + STATE_START_PORT_LOOKUP, + STATE_READ_PORT_LOOKUP, + STATE_READ_TARGET_PORT, + STATE_WAIT_TARGET_PORT, + STATE_WAIT_TARGET_WRITE, + STATE_WAIT_COMPLETE, + STATE_WAIT_SLAVE); + signal masterState : MasterStateType; + + signal crc16Data : std_logic_vector(31 downto 0); + signal crc16Current : std_logic_vector(15 downto 0); + signal crc16Temp : std_logic_vector(15 downto 0); + signal crc16Next : std_logic_vector(15 downto 0); + + signal configEnable : std_logic; + signal configWrite : std_logic; + signal configAddress : std_logic_vector(23 downto 0); + signal configDataWrite : std_logic_vector(31 downto 0); + signal configDataRead, configDataReadInternal : std_logic_vector(31 downto 0); + + signal outboundFrameEnable : std_logic; + signal outboundFrameWrite : std_logic; + signal outboundFrameAddress : std_logic_vector(2 downto 0); + signal outboundFrameDataWrite : std_logic_vector(31 downto 0); + signal outboundFrameDataRead : std_logic_vector(31 downto 0); + signal outboundFrameLength : std_logic_vector(2 downto 0); + + type SlaveStateType is (STATE_READY, + STATE_BUSY); + signal slaveState : SlaveStateType; + signal slaveAck : std_logic; + + signal inboundFrameReady : std_logic; + signal inboundFramePort : std_logic_vector(7 downto 0); + signal inboundFrameLength : natural range 0 to 7; + signal inboundFrameComplete : std_logic; + + signal vc : std_logic; + signal crf : std_logic; + signal prio : std_logic_vector(1 downto 0); + signal tt : std_logic_vector(1 downto 0); + signal ftype : std_logic_vector(3 downto 0); + signal destinationId : std_logic_vector(15 downto 0); + signal sourceId : std_logic_vector(15 downto 0); + signal transaction : std_logic_vector(3 downto 0); + signal size : std_logic_vector(3 downto 0); + signal srcTid : std_logic_vector(7 downto 0); + signal hopCount : std_logic_vector(7 downto 0); + signal configOffset : std_logic_vector(20 downto 0); + signal wdptr : std_logic; + signal content : std_logic_vector(63 downto 0); + + ----------------------------------------------------------------------------- + -- Route table access signals. + ----------------------------------------------------------------------------- + + signal address0 : std_logic_vector(7 downto 0); + signal address1 : std_logic_vector(7 downto 0); + signal address2 : std_logic_vector(7 downto 0); + signal address3 : std_logic_vector(7 downto 0); + + signal lookupEnable : std_logic; + signal lookupAddress : std_logic_vector(10 downto 0); + signal lookupData : std_logic_vector(7 downto 0); + signal lookupAck : std_logic; + + signal routeTableEnable : std_logic; + signal routeTableWrite : std_logic; + signal routeTableAddress : std_logic_vector(10 downto 0); + signal routeTablePortWrite : std_logic_vector(7 downto 0); + signal routeTablePortRead : std_logic_vector(7 downto 0); + + signal routeTablePortDefault : std_logic_vector(7 downto 0); + + ----------------------------------------------------------------------------- + -- Configuration space signals. + ----------------------------------------------------------------------------- + + signal discovered : std_logic; + + signal hostBaseDeviceIdLocked : std_logic; + signal hostBaseDeviceId : std_logic_vector(15 downto 0); + signal componentTag : std_logic_vector(31 downto 0); + + signal portLinkTimeout : std_logic_vector(23 downto 0); + + signal outputPortEnable : Array1(SWITCH_PORTS-1 downto 0); + signal inputPortEnable : Array1(SWITCH_PORTS-1 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Memory to contain the outbound frame. + ----------------------------------------------------------------------------- + + OutboundFrameMemory: MemorySinglePort + generic map( + ADDRESS_WIDTH=>3, DATA_WIDTH=>32) + port map( + clk_i=>clk, + enable_i=>outboundFrameEnable, writeEnable_i=>outboundFrameWrite, + address_i=>outboundFrameAddress, + data_i=>outboundFrameDataWrite, data_o=>outboundFrameDataRead); + + ----------------------------------------------------------------------------- + -- CRC generation for outbound frames. + ----------------------------------------------------------------------------- + + crc16Data <= outboundFrameDataWrite; + + -- REMARK: Insert FFs here to make the critical path shorter... + Crc16High: Crc16CITT + port map( + d_i=>crc16Data(31 downto 16), crc_i=>crc16Current, crc_o=>crc16Temp); + Crc16Low: Crc16CITT + port map( + d_i=>crc16Data(15 downto 0), crc_i=>crc16Temp, crc_o=>crc16Next); + + ----------------------------------------------------------------------------- + -- Master interface process. + ----------------------------------------------------------------------------- + Master: process(clk, areset_n) + begin + if (areset_n = '0') then + masterState <= STATE_IDLE; + + lookupStb_o <= '0'; + lookupAddr_o <= (others => '0'); + + masterCyc_o <= '0'; + masterStb_o <= '0'; + masterWe_o <= '0'; + masterAddr_o <= (others => '0'); + masterData_o <= (others => '0'); + + configEnable <= '0'; + configWrite <= '0'; + configAddress <= (others => '0'); + configDataWrite <= (others => '0'); + + outboundFrameEnable <= '0'; + outboundFrameWrite <= '0'; + outboundFrameAddress <= (others=>'0'); + outboundFrameDataWrite <= (others=>'0'); + outboundFrameLength <= (others=>'0'); + + inboundFrameComplete <= '0'; + elsif (clk'event and clk = '1') then + configEnable <= '0'; + configWrite <= '0'; + inboundFrameComplete <= '0'; + + case masterState is + + when STATE_IDLE => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Wait for a full frame to be available. + if (inboundFrameReady = '1') then + if (inboundFrameLength > 3) then + masterState <= STATE_CHECK_FRAME; + else + -- Frame is too short. + -- REMARK: Discard the frame. + end if; + end if; + + when STATE_CHECK_FRAME => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Check if the frame has 16-bit addresses and is a maintenance frame. + if (tt = "01") and (ftype = FTYPE_MAINTENANCE_CLASS) then + -- Maintenance class frame and 16-bit addresses. + + -- Check the frame type. + case transaction is + + when "0000" => + --------------------------------------------------------------- + -- Maintenance read request. + --------------------------------------------------------------- + + -- Check if the frame is for us. + if (hopCount = x"00") then + -- This frame is for us. + configEnable <= '1'; + configWrite <= '0'; + configAddress <= configOffset & wdptr & "00"; + + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= (others=>'0'); + outboundFrameDataWrite <= "000000" & vc & crf & prio & tt & ftype & sourceId; + crc16Current <= x"ffff"; + + masterState <= STATE_SEND_READ_RESPONSE; + else + -- This frame is not for us. + -- Decrement hop_count and relay. + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= (others=>'0'); + outboundFrameDataWrite <= "000000" & vc & crf & prio & tt & ftype & destinationId; + crc16Current <= x"ffff"; + + masterState <= STATE_SEND_READ_REQUEST; + end if; + + when "0001" => + --------------------------------------------------------------- + -- Maintenance write request. + --------------------------------------------------------------- + + -- Check if the frame is for us. + if (hopCount = x"00") then + -- This frame is for us. + configEnable <= '1'; + configWrite <= '1'; + configAddress <= configOffset & wdptr & "00"; + + if (wdptr = '0') then + configDataWrite <= content(63 downto 32); + else + configDataWrite <= content(31 downto 0); + end if; + + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= (others=>'0'); + outboundFrameDataWrite <= "000000" & vc & crf & prio & tt & ftype & sourceId; + crc16Current <= x"ffff"; + + masterState <= STATE_SEND_WRITE_RESPONSE; + else + -- This frame is not for us. + -- Decrement hop_count and relay. + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= (others=>'0'); + outboundFrameDataWrite <= "000000" & vc & crf & prio & tt & ftype & destinationId; + crc16Current <= x"ffff"; + + masterState <= STATE_SEND_WRITE_REQUEST; + end if; + + when "0010" => + --------------------------------------------------------------- + -- Maintenance read response frame. + --------------------------------------------------------------- + + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= (others=>'0'); + outboundFrameDataWrite <= "000000" & vc & crf & prio & tt & ftype & destinationId; + crc16Current <= x"ffff"; + + -- Relay frame. + masterState <= STATE_RELAY_READ_RESPONSE; + + when "0011" => + --------------------------------------------------------------- + -- Maintenance write response frame. + --------------------------------------------------------------- + + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= (others=>'0'); + outboundFrameDataWrite <= "000000" & vc & crf & prio & tt & ftype & destinationId; + crc16Current <= x"ffff"; + + -- Relay frame. + masterState <= STATE_RELAY_WRITE_RESPONSE; + + when "0100" => + --------------------------------------------------------------- + -- Maintenance port write frame. + --------------------------------------------------------------- + + -- REMARK: Support these??? + + when others => + --------------------------------------------------------------- + -- Unsupported frame type. + --------------------------------------------------------------- + + -- REMARK: Support these??? + end case; + else + -- Non-maintenance class frame or unsupported address type. + -- REMARK: These should not end up here... discard them??? + end if; + + when STATE_RELAY_READ_RESPONSE => + --------------------------------------------------------------------- + -- A maintenance response has been received. It should be relayed as + -- is using the destinationId. + --------------------------------------------------------------------- + + case to_integer(unsigned(outboundFrameAddress)) is + when 0 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= sourceId & transaction & size & srcTid; + crc16Current <= crc16Next; + when 1 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= hopCount & configOffset & wdptr & "00"; + crc16Current <= crc16Next; + when 2 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= content(63 downto 32); + crc16Current <= crc16Next; + when 3 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= content(31 downto 0); + crc16Current <= crc16Next; + when 4 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite(31 downto 16) <= crc16Next; + outboundFrameDataWrite(15 downto 0) <= x"0000"; + when others => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '0'; + outboundFrameAddress <= (others=>'0'); + outboundFrameLength <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + masterState <= STATE_START_PORT_LOOKUP; + end case; + + when STATE_RELAY_WRITE_RESPONSE => + --------------------------------------------------------------------- + -- A maintenance response has been received. It should be relayed as + -- is using the destinationId. + --------------------------------------------------------------------- + + case to_integer(unsigned(outboundFrameAddress)) is + when 0 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= sourceId & transaction & size & srcTid; + crc16Current <= crc16Next; + when 1 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= hopCount & configOffset & wdptr & "00"; + crc16Current <= crc16Next; + when 2 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite(31 downto 16) <= crc16Next; + outboundFrameDataWrite(15 downto 0) <= x"0000"; + when others => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '0'; + outboundFrameAddress <= (others=>'0'); + outboundFrameLength <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + masterState <= STATE_START_PORT_LOOKUP; + end case; + + when STATE_SEND_READ_REQUEST => + --------------------------------------------------------------------- + -- A read request has been received but the hopcount is larger than + -- zero. Decrement the hopcount, recalculate the crc and relay the + -- frame using the destinationId. + --------------------------------------------------------------------- + + case to_integer(unsigned(outboundFrameAddress)) is + when 0 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= sourceId & transaction & size & srcTid; + crc16Current <= crc16Next; + when 1 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= std_logic_vector(unsigned(hopCount) - 1) & configOffset & wdptr & "00"; + crc16Current <= crc16Next; + when 2 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite(31 downto 16) <= crc16Next; + outboundFrameDataWrite(15 downto 0) <= x"0000"; + when others => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '0'; + outboundFrameAddress <= (others=>'0'); + outboundFrameLength <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + masterState <= STATE_START_PORT_LOOKUP; + end case; + + when STATE_SEND_WRITE_REQUEST => + --------------------------------------------------------------------- + -- A write request has been received but the hopcount is larger than + -- zero. Decrement the hopcount, recalculate the crc and relay the + -- frame using the destinationId. + --------------------------------------------------------------------- + + case to_integer(unsigned(outboundFrameAddress)) is + when 0 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= sourceId & transaction & size & srcTid; + crc16Current <= crc16Next; + when 1 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= std_logic_vector(unsigned(hopCount) - 1) & configOffset & wdptr & "00"; + crc16Current <= crc16Next; + when 2 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= content(63 downto 32); + crc16Current <= crc16Next; + when 3 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= content(31 downto 0); + crc16Current <= crc16Next; + when 4 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite(31 downto 16) <= crc16Next; + outboundFrameDataWrite(15 downto 0) <= x"0000"; + when others => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '0'; + outboundFrameAddress <= (others=>'0'); + outboundFrameLength <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + masterState <= STATE_START_PORT_LOOKUP; + end case; + + when STATE_SEND_READ_RESPONSE => + --------------------------------------------------------------------- + -- A read request has been received with a hopcount that are zero. + -- Create a read response, calculate crc and write it to the port it + -- came from. + --------------------------------------------------------------------- + + case to_integer(unsigned(outboundFrameAddress)) is + when 0 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= destinationId & "0010" & "0000" & srcTid; + crc16Current <= crc16Next; + when 1 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= x"ff" & x"000000"; + crc16Current <= crc16Next; + when 2 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + if (wdptr = '1') then + outboundFrameDataWrite <= (others => '0'); + else + outboundFrameDataWrite <= configDataRead(31 downto 0); + end if; + crc16Current <= crc16Next; + when 3 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + if (wdptr = '1') then + outboundFrameDataWrite <= configDataRead(31 downto 0); + else + outboundFrameDataWrite <= (others => '0'); + end if; + crc16Current <= crc16Next; + when 4 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite(31 downto 16) <= crc16Next; + outboundFrameDataWrite(15 downto 0) <= x"0000"; + when others => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '0'; + outboundFrameAddress <= (others=>'0'); + outboundFrameLength <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + masterAddr_o <= '0' & inboundFramePort & '0'; + masterState <= STATE_READ_TARGET_PORT; + end case; + + when STATE_SEND_WRITE_RESPONSE => + --------------------------------------------------------------------- + -- A write request has been received with a hopcount that are zero. + -- Create a write response, calculate crc and write it to the port it + -- came from. + --------------------------------------------------------------------- + + case to_integer(unsigned(outboundFrameAddress)) is + when 0 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= destinationId & "0011" & "0000" & srcTid; + crc16Current <= crc16Next; + when 1 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite <= x"ff" & x"000000"; + crc16Current <= crc16Next; + when 2 => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '1'; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + outboundFrameDataWrite(31 downto 16) <= crc16Next; + outboundFrameDataWrite(15 downto 0) <= x"0000"; + when others => + outboundFrameEnable <= '1'; + outboundFrameWrite <= '0'; + outboundFrameAddress <= (others=>'0'); + outboundFrameLength <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + masterAddr_o <= '0' & inboundFramePort & '0'; + masterState <= STATE_READ_TARGET_PORT; + end case; + + when STATE_START_PORT_LOOKUP => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Initiate a port-lookup of the destination address. + lookupStb_o <= '1'; + lookupAddr_o <= destinationId; + masterState <= STATE_READ_PORT_LOOKUP; + + when STATE_READ_PORT_LOOKUP => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Wait for the routing table to complete the request. + if (lookupAck_i = '1') then + -- The address lookup is complete. + + -- Terminate the lookup cycle. + lookupStb_o <= '0'; + + -- Wait for the target port to reply. + masterAddr_o <= '0' & lookupData_i & '0'; + masterState <= STATE_READ_TARGET_PORT; + else + -- Wait until the address lookup is complete. + -- REMARK: Timeout here??? + end if; + + when STATE_READ_TARGET_PORT => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Read the status of the target port using the result from the + -- lookup in the routing table. + masterCyc_o <= '1'; + masterStb_o <= '1'; + masterWe_o <= '0'; + masterState <= STATE_WAIT_TARGET_PORT; + + when STATE_WAIT_TARGET_PORT => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Wait for the target port to complete the request. + if (masterAck_i = '1') then + if (masterData_i = '0') then + -- The target port has empty buffers to receive the frame. + + -- Write the first word of the frame to the target port. + -- The masterData_o has already been assigned. + masterCyc_o <= '1'; + masterStb_o <= '1'; + masterWe_o <= '1'; + masterAddr_o(0) <= '1'; + + -- Read the first word in the frame and update the frame address. + masterData_o <= outboundFrameDataRead; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + + -- Change state to transfer the frame. + masterState <= STATE_WAIT_TARGET_WRITE; + else + -- The target port has no empty buffer to receive the frame. + -- Terminate the cycle and retry later. + masterCyc_o <= '0'; + masterStb_o <= '0'; + masterState <= STATE_READ_TARGET_PORT; + end if; + else + -- Wait for the target port to reply. + -- REMARK: Timeout here??? + end if; + + when STATE_WAIT_TARGET_WRITE => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Wait for the target port to complete the request. + if (masterAck_i = '1') then + -- The target port is ready. + + -- Check if the frame has ended. + if (outboundFrameLength /= outboundFrameAddress) then + -- The frame has not ended. + + -- There are more data to transfer. + masterData_o <= outboundFrameDataRead; + outboundFrameAddress <= std_logic_vector(unsigned(outboundFrameAddress) + 1); + else + -- There are no more data to transfer. + + -- Tell the target port that the frame is complete. + masterWe_o <= '1'; + masterAddr_o(0) <= '0'; + masterData_o <= x"00000001"; + outboundFrameAddress <= (others=>'0'); + + -- Change state to wait for the target port to finalize the write + -- of the full frame. + masterState <= STATE_WAIT_COMPLETE; + end if; + else + -- Wait for the target port to reply. + -- REMARK: Timeout here??? + end if; + + when STATE_WAIT_COMPLETE => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + + -- Wait for the target port to complete the final request. + if (masterAck_i = '1') then + -- The target port has finalized the write of the frame. + masterCyc_o <= '0'; + masterStb_o <= '0'; + masterState <= STATE_WAIT_SLAVE; + + -- Indicate the frame has been read. + inboundFrameComplete <= '1'; + else + -- Wait for the target port to reply. + -- REMARK: Timeout here??? + end if; + + when STATE_WAIT_SLAVE => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + masterState <= STATE_IDLE; + + when others => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + end case; + end if; + end process; + + + ----------------------------------------------------------------------------- + -- Slave interface process. + ----------------------------------------------------------------------------- + -- Addr | Read | Write + -- 0 | full | abort & complete + -- 1 | full | frameData + Slave: process(clk, areset_n) + begin + if (areset_n = '0') then + slaveState <= STATE_READY; + slaveData_o <= '0'; + slaveAck <= '0'; + + vc <= '0'; + crf <= '0'; + prio <= (others=>'0'); + tt <= (others=>'0'); + ftype <= (others=>'0'); + destinationId <= (others=>'0'); + sourceId <= (others=>'0'); + transaction <= (others=>'0'); + size <= (others=>'0'); + srcTid <= (others=>'0'); + hopCount <= (others=>'0'); + configOffset <= (others=>'0'); + wdptr <= '0'; + content <= (others=>'0'); + + inboundFrameReady <= '0'; + inboundFramePort <= (others => '0'); + inboundFrameLength <= 0; + elsif (clk'event and clk = '1') then + slaveAck <= '0'; + + case slaveState is + when STATE_READY => + --------------------------------------------------------------------- + -- Ready to receive a new frame. + --------------------------------------------------------------------- + + -- Check if any cycle is active. + if ((slaveCyc_i = '1') and (slaveStb_i = '1') and (slaveAck = '0')) then + -- Cycle is active. + + -- Check if writing. + if (slaveWe_i = '1') then + -- Writing request. + + -- Check if the cycle is accessing the status- or data address. + if (slaveAddr_i(0) = '0') then + -- Writing to port status address. + + if (slaveData_i(0) = '1') and (slaveData_i(1) = '0') then + -- A frame has been written. + + -- Indicate the frame is ready for processing. + -- The slave address contains the number of the accessing port. + inboundFrameReady <= '1'; + inboundFramePort <= slaveAddr_i(8 downto 1); + + -- Change state until the frame has been processed. + slaveState <= STATE_BUSY; + else + -- The frame has been aborted. + -- Reset the received frame length. + inboundFrameLength <= 0; + end if; + else + -- Write frame content into the frame buffer. + + -- Check which frame index that is written. + case inboundFrameLength is + when 0 => + vc <= slaveData_i(25); + crf <= slaveData_i(24); + prio <= slaveData_i(23 downto 22); + tt <= slaveData_i(21 downto 20); + ftype <= slaveData_i(19 downto 16); + destinationId <= slaveData_i(15 downto 0); + inboundFrameLength <= inboundFrameLength + 1; + when 1 => + sourceId <= slaveData_i(31 downto 16); + transaction <= slaveData_i(15 downto 12); + size <= slaveData_i(11 downto 8); + srcTid <= slaveData_i(7 downto 0); + inboundFrameLength <= inboundFrameLength + 1; + when 2 => + hopCount <= slaveData_i(31 downto 24); + configOffset <= slaveData_i(23 downto 3); + wdptr <= slaveData_i(2); + inboundFrameLength <= inboundFrameLength + 1; + when 3 => + -- Note that crc will be assigned here if there are no + -- content in the frame. + content(63 downto 32) <= slaveData_i; + inboundFrameLength <= inboundFrameLength + 1; + when 4 => + content(31 downto 0) <= slaveData_i; + inboundFrameLength <= inboundFrameLength + 1; + when others => + -- Dont support longer frames. + -- REMARK: Add support for longer frames??? Especially + -- received frames that only should be routed... + end case; + end if; + + -- Send acknowledge. + slaveAck <= '1'; + else + -- Reading request. + + -- Reading the status address. + -- Always indicate that we are ready to accept a new frame. + slaveData_o <= '0'; + + -- Send acknowledge. + slaveAck <= '1'; + end if; + else + -- No cycle is active. + end if; + + when STATE_BUSY => + --------------------------------------------------------------------- + -- Waiting for a received frame to be processed. + --------------------------------------------------------------------- + + -- Check if any cycle is active. + if ((slaveCyc_i = '1') and (slaveStb_i = '1') and (slaveAck = '0')) then + -- Cycle is active. + + -- Check if writing. + if (slaveWe_i = '1') then + -- Writing. + -- Dont do anything. + + -- Send acknowledge. + slaveAck <= '1'; + else + -- Read port data address. + + -- Reading the status address. + -- Always indicate that we are busy. + slaveData_o <= '1'; + + -- Send acknowledge. + slaveAck <= '1'; + end if; + else + -- No cycle is active. + -- Dont do anything. + end if; + + -- Check if the master process has processed the received frame. + if (inboundFrameComplete = '1') then + -- The master has processed the frame. + inboundFrameReady <= '0'; + inboundFrameLength <= 0; + slaveState <= STATE_READY; + else + -- The master is not ready yet. + -- Dont do anything. + end if; + + when others => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + null; + + end case; + end if; + end process; + + slaveAck_o <= slaveAck; + + ----------------------------------------------------------------------------- + -- Logic implementing the routing table access. + ----------------------------------------------------------------------------- + + -- Lookup interface port memory signals. + lookupEnable <= '1' when (lookupStb_i = '1') and (lookupAddr_i(15 downto 11) = "00000") else '0'; + lookupAddress <= lookupAddr_i(10 downto 0); + lookupData_o <= lookupData when (lookupEnable = '1') else routeTablePortDefault; + lookupAck_o <= lookupAck; + LookupProcess: process(clk, areset_n) + begin + if (areset_n = '0') then + lookupAck <= '0'; + elsif (clk'event and clk = '1') then + if ((lookupStb_i = '1') and (lookupAck = '0')) then + lookupAck <= '1'; + else + lookupAck <= '0'; + end if; + end if; + end process; + + -- Dual port memory containing the routing table. + RoutingTable: MemoryDualPort + generic map( + ADDRESS_WIDTH=>11, DATA_WIDTH=>8) + port map( + clkA_i=>clk, enableA_i=>routeTableEnable, writeEnableA_i=>routeTableWrite, + addressA_i=>routeTableAddress, + dataA_i=>routeTablePortWrite, dataA_o=>routeTablePortRead, + clkB_i=>clk, enableB_i=>lookupEnable, + addressB_i=>lookupAddress, dataB_o=>lookupData); + + ----------------------------------------------------------------------------- + -- Configuration memory. + ----------------------------------------------------------------------------- + + portLinkTimeout_o <= portLinkTimeout; + outputPortEnable_o <= outputPortEnable; + inputPortEnable_o <= inputPortEnable; + + configStb_o <= '1' when ((configEnable = '1') and (configAddress(23 downto 16) /= x"00")) else '0'; + configWe_o <= configWrite; + configAddr_o <= configAddress; + configData_o <= configDataWrite; + configDataRead <= configData_i when (configAddress(23 downto 16) /= x"00") else + configDataReadInternal; + + ConfigMemory: process(areset_n, clk) + begin + if (areset_n = '0') then + configDataReadInternal <= (others => '0'); + + routeTableEnable <= '1'; + routeTableWrite <= '0'; + routeTableAddress <= (others => '0'); + routeTablePortWrite <= (others => '0'); + routeTablePortDefault <= (others => '0'); + + discovered <= '0'; + + hostBaseDeviceIdLocked <= '0'; + hostBaseDeviceId <= (others => '1'); + componentTag <= (others => '0'); + + portLinkTimeout <= (others => '1'); + + -- REMARK: These should be set to zero when a port gets initialized... + outputPortEnable <= (others => '0'); + inputPortEnable <= (others => '0'); + + localAckIdWrite_o <= (others => '0'); + elsif (clk'event and clk = '1') then + routeTableWrite <= '0'; + localAckIdWrite_o <= (others => '0'); + + if (configEnable = '1') then + -- Check if the access is into implementation defined space or if the + -- access should be handled here. + if (configAddress(23 downto 16) /= x"00") then + -- Accessing implementation defined space. + -- Make an external access and return the resonse. + configDataReadInternal <= (others=>'0'); + else + -- Access should be handled here. + + case (configAddress) is + when x"000000" => + ----------------------------------------------------------------- + -- Device Identity CAR. Read-only. + ----------------------------------------------------------------- + + configDataReadInternal(31 downto 16) <= DEVICE_IDENTITY; + configDataReadInternal(15 downto 0) <= DEVICE_VENDOR_IDENTITY; + + when x"000004" => + ----------------------------------------------------------------- + -- Device Information CAR. Read-only. + ----------------------------------------------------------------- + + configDataReadInternal(31 downto 0) <= DEVICE_REV; + + when x"000008" => + ----------------------------------------------------------------- + -- Assembly Identity CAR. Read-only. + ----------------------------------------------------------------- + + configDataReadInternal(31 downto 16) <= ASSY_IDENTITY; + configDataReadInternal(15 downto 0) <= ASSY_VENDOR_IDENTITY; + + when x"00000c" => + ----------------------------------------------------------------- + -- Assembly Informaiton CAR. Read-only. + ----------------------------------------------------------------- + + configDataReadInternal(31 downto 16) <= ASSY_REV; + configDataReadInternal(15 downto 0) <= x"0100"; + + when x"000010" => + ----------------------------------------------------------------- + -- Processing Element Features CAR. Read-only. + ----------------------------------------------------------------- + + -- Bridge. + configDataReadInternal(31) <= '0'; + + -- Memory. + configDataReadInternal(30) <= '0'; + + -- Processor. + configDataReadInternal(29) <= '0'; + + -- Switch. + configDataReadInternal(28) <= '1'; + + -- Reserved. + configDataReadInternal(27 downto 10) <= (others => '0'); + + -- Extended route table configuration support. + configDataReadInternal(9) <= '0'; + + -- Standard route table configuration support. + configDataReadInternal(8) <= '1'; + + -- Reserved. + configDataReadInternal(7 downto 5) <= (others => '0'); + + -- Common transport large system support. + configDataReadInternal(4) <= '1'; + + -- Extended features. + configDataReadInternal(3) <= '1'; + + -- Extended addressing support. + -- Not a processing element. + configDataReadInternal(2 downto 0) <= "000"; + + when x"000014" => + ----------------------------------------------------------------- + -- Switch Port Information CAR. Read-only. + ----------------------------------------------------------------- + + -- Reserved. + configDataReadInternal(31 downto 16) <= (others => '0'); + + -- PortTotal. + configDataReadInternal(15 downto 8) <= + std_logic_vector(to_unsigned(SWITCH_PORTS, 8)); + + -- PortNumber. + configDataReadInternal(7 downto 0) <= inboundFramePort; + + when x"000034" => + ----------------------------------------------------------------- + -- Switch Route Table Destination ID Limit CAR. + ----------------------------------------------------------------- + + -- Max_destId. + -- Support 2048 addresses. + configDataReadInternal(15 downto 0) <= x"0800"; + + when x"000068" => + ----------------------------------------------------------------- + -- Host Base Device ID Lock CSR. + ----------------------------------------------------------------- + + if (configWrite = '1') then + -- 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 <= configDataWrite(15 downto 0); + else + -- The field has been written. + -- Check if the written data is the same as the stored. + if (hostBaseDeviceId = configDataWrite(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; + + configDataReadInternal(31 downto 16) <= (others => '0'); + configDataReadInternal(15 downto 0) <= hostBaseDeviceId; + + when x"00006c" => + ----------------------------------------------------------------- + -- Component TAG CSR. + ----------------------------------------------------------------- + + if (configWrite = '1') then + componentTag <= configDataWrite; + end if; + + configDataReadInternal <= componentTag; + + when x"000070" => + ----------------------------------------------------------------- + -- Standard Route Configuration Destination ID Select CSR. + ----------------------------------------------------------------- + + if (configWrite = '1') then + -- Write the address to access the routing table. + routeTableAddress <= configDataWrite(10 downto 0); + end if; + + configDataReadInternal(31 downto 11) <= (others => '0'); + configDataReadInternal(10 downto 0) <= routeTableAddress; + + when x"000074" => + ----------------------------------------------------------------- + -- Standard Route Configuration Port Select CSR. + ----------------------------------------------------------------- + + if (configWrite = '1') then + -- Write the port information for the address selected by the + -- above register. + routeTableWrite <= '1'; + routeTablePortWrite <= configDataWrite(7 downto 0); + end if; + + configDataReadInternal(31 downto 8) <= (others => '0'); + configDataReadInternal(7 downto 0) <= routeTablePortRead; + + when x"000078" => + ----------------------------------------------------------------- + -- Standard Route Default Port CSR. + ----------------------------------------------------------------- + + if (configWrite = '1') then + -- Write the default route device id. + routeTablePortDefault <= configDataWrite(7 downto 0); + end if; + + configDataReadInternal(31 downto 8) <= (others => '0'); + configDataReadInternal(7 downto 0) <= routeTablePortDefault; + + when x"000100" => + ----------------------------------------------------------------- + -- Extended features. LP-Serial Register Block Header. + ----------------------------------------------------------------- + + -- One feature only, 0x0003=Generic End Point Free Device. + configDataReadInternal(31 downto 16) <= x"0000"; + configDataReadInternal(15 downto 0) <= x"0003"; + + when x"000120" => + ----------------------------------------------------------------- + -- Port Link Timeout Control CSR. + ----------------------------------------------------------------- + + if (configWrite = '1') then + portLinkTimeout <= configDataWrite(31 downto 8); + end if; + + configDataReadInternal(31 downto 8) <= portLinkTimeout; + configDataReadInternal(7 downto 0) <= x"00"; + + when x"00013c" => + ----------------------------------------------------------------- + -- Port General Control CSR. + ----------------------------------------------------------------- + + if (configWrite = '1') then + discovered <= configDataWrite(29); + end if; + + configDataReadInternal(31 downto 30) <= "00"; + configDataReadInternal(29) <= discovered; + configDataReadInternal(28 downto 0) <= (others => '0'); + + when others => + ----------------------------------------------------------------- + -- Other port specific registers. + ----------------------------------------------------------------- + + -- Make sure the output is always set to something. + configDataReadInternal <= (others=>'0'); + + -- Iterate through all active ports. + for portIndex in 0 to SWITCH_PORTS-1 loop + + if(unsigned(configAddress) = (x"000148" + (x"000020"*portIndex))) then + ----------------------------------------------------------------- + -- Port N Local ackID CSR. + ----------------------------------------------------------------- + if (configWrite = '1') then + localAckIdWrite_o(portIndex) <= '1'; + clrOutstandingAckId_o(portIndex) <= configDataWrite(31); + inboundAckId_o(portIndex) <= configDataWrite(28 downto 24); + outstandingAckId_o(portIndex) <= configDataWrite(12 downto 8); + outboundAckId_o(portIndex) <= configDataWrite(4 downto 0); + end if; + configDataReadInternal(31 downto 29) <= (others => '0'); + configDataReadInternal(28 downto 24) <= inboundAckId_i(portIndex); + configDataReadInternal(23 downto 13) <= (others => '0'); + configDataReadInternal(12 downto 8) <= outstandingAckId_i(portIndex); + configDataReadInternal(7 downto 5) <= (others => '0'); + configDataReadInternal(4 downto 0) <= outboundAckId_i(portIndex); + + elsif(unsigned(configAddress) = (x"000154" + (x"000020"*portIndex))) then + ----------------------------------------------------------------- + -- Port N Control 2 CSR. + ----------------------------------------------------------------- + configDataReadInternal <= (others => '0'); + + elsif(unsigned(configAddress) = (x"000158" + (x"000020"*portIndex))) then + ----------------------------------------------------------------- + -- Port N Error and Status CSR. + ----------------------------------------------------------------- + -- Idle Sequence 2 Support. + configDataReadInternal(31) <= '0'; + + -- Idle Sequence 2 Enable. + configDataReadInternal(30) <= '0'; + + -- Idle Sequence. + configDataReadInternal(29) <= '0'; + + -- Reserved. + configDataReadInternal(28) <= '0'; + + -- Flow Control Mode. + configDataReadInternal(27) <= '0'; + + -- Reserved. + configDataReadInternal(26 downto 21) <= (others => '0'); + + -- Output retry-encountered. + configDataReadInternal(20) <= '0'; + + -- Output retried. + configDataReadInternal(19) <= '0'; + + -- Output retried-stopped. + configDataReadInternal(18) <= '0'; + + -- Output error-encountered. + configDataReadInternal(17) <= '0'; + + -- Output error-stopped. + configDataReadInternal(16) <= '0'; + + -- Reserved. + configDataReadInternal(15 downto 11) <= (others => '0'); + + -- Input retry-stopped. + configDataReadInternal(10) <= '0'; + + -- Input error-encountered. + configDataReadInternal(9) <= '0'; + + -- Input error-stopped. + configDataReadInternal(8) <= '0'; + + -- Reserved. + configDataReadInternal(7 downto 5) <= (others => '0'); + + -- Port-write pending. + configDataReadInternal(4) <= '0'; + + -- Port unavailable. + configDataReadInternal(3) <= '0'; + + -- Port error. + configDataReadInternal(2) <= '0'; + + -- Port OK. + configDataReadInternal(1) <= linkInitialized_i(portIndex); + + -- Port uninitialized. + configDataReadInternal(0) <= not linkInitialized_i(portIndex); + + elsif(unsigned(configAddress) = (x"00015c" + (x"000020"*portIndex))) then + ----------------------------------------------------------------- + -- Port N Control CSR. + ----------------------------------------------------------------- + + -- Port Width Support. + configDataReadInternal(31 downto 30) <= (others=>'0'); + + -- Initialized Port Width. + configDataReadInternal(29 downto 27) <= (others=>'0'); + + -- Port Width Override. + configDataReadInternal(26 downto 24) <= (others=>'0'); + + -- Port disable. + configDataReadInternal(23) <= '0'; + + -- Output Port Enable. + if (configWrite = '1') then + outputPortEnable(portIndex) <= configDataWrite(22); + end if; + configDataReadInternal(22) <= outputPortEnable(portIndex); + + -- Input Port Enable. + if (configWrite = '1') then + inputPortEnable(portIndex) <= configDataWrite(21); + end if; + configDataReadInternal(21) <= inputPortEnable(portIndex); + + -- Error Checking Disabled. + configDataReadInternal(20) <= '0'; + + -- Multicast-event Participant. + configDataReadInternal(19) <= '0'; + + -- Reserved. + configDataReadInternal(18) <= '0'; + + -- Enumeration Boundry. + configDataReadInternal(17) <= '0'; + + -- Reserved. + configDataReadInternal(16) <= '0'; + + -- Extended Port Width Override. + configDataReadInternal(15 downto 14) <= (others=>'0'); + + -- Extended Port Width Support. + configDataReadInternal(13 downto 12) <= (others=>'0'); + + -- Implementation defined. + configDataReadInternal(11 downto 4) <= (others=>'0'); + + -- Reserved. + configDataReadInternal(3 downto 1) <= (others=>'0'); + + -- Port Type. + configDataReadInternal(0) <= '1'; + end if; + end loop; + + end case; + end if; + else + -- Config memory not enabled. + 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 RouteTableInterconnect is + generic( + WIDTH : natural range 1 to 256 := 8); + port( + clk : in std_logic; + areset_n : in std_logic; + + stb_i : in Array1(WIDTH-1 downto 0); + addr_i : in Array16(WIDTH-1 downto 0); + dataM_o : out Array8(WIDTH-1 downto 0); + ack_o : out Array1(WIDTH-1 downto 0); + + stb_o : out std_logic; + addr_o : out std_logic_vector(15 downto 0); + dataS_i : in std_logic_vector(7 downto 0); + ack_i : in std_logic); +end entity; + + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- +architecture RouteTableInterconnectImpl of RouteTableInterconnect is + signal activeCycle : std_logic; + signal selectedMaster : natural range 0 to WIDTH-1; +begin + + ----------------------------------------------------------------------------- + -- Arbitration. + ----------------------------------------------------------------------------- + Arbiter: process(areset_n, clk) + begin + if (areset_n = '0') then + activeCycle <= '0'; + selectedMaster <= 0; + elsif (clk'event and clk = '1') then + if (activeCycle = '0') then + for i in 0 to WIDTH-1 loop + if (stb_i(i) = '1') then + activeCycle <= '1'; + selectedMaster <= i; + end if; + end loop; + else + if (stb_i(selectedMaster) = '0') then + activeCycle <= '0'; + end if; + end if; + end if; + end process; + + ----------------------------------------------------------------------------- + -- Interconnection. + ----------------------------------------------------------------------------- + stb_o <= stb_i(selectedMaster); + addr_o <= addr_i(selectedMaster); + + Interconnect: for i in 0 to WIDTH-1 generate + dataM_o(i) <= dataS_i; + ack_o(i) <= ack_i when (selectedMaster = i) else '0'; + end generate; + +end architecture; + + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- +entity SwitchPortInterconnect is + generic( + WIDTH : natural range 1 to 256 := 8); + port( + clk : in std_logic; + areset_n : in std_logic; + + masterCyc_i : in Array1(WIDTH-1 downto 0); + masterStb_i : in Array1(WIDTH-1 downto 0); + masterWe_i : in Array1(WIDTH-1 downto 0); + masterAddr_i : in Array10(WIDTH-1 downto 0); + masterData_i : in Array32(WIDTH-1 downto 0); + masterData_o : out Array1(WIDTH-1 downto 0); + masterAck_o : out Array1(WIDTH-1 downto 0); + + slaveCyc_o : out Array1(WIDTH-1 downto 0); + slaveStb_o : out Array1(WIDTH-1 downto 0); + slaveWe_o : out Array1(WIDTH-1 downto 0); + slaveAddr_o : out Array10(WIDTH-1 downto 0); + slaveData_o : out Array32(WIDTH-1 downto 0); + slaveData_i : in Array1(WIDTH-1 downto 0); + slaveAck_i : in Array1(WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- +architecture SwitchPortInterconnectImpl of SwitchPortInterconnect is + --component ChipscopeIcon1 is + -- port ( + -- CONTROL0 : inout STD_LOGIC_VECTOR ( 35 downto 0 ) + -- ); + --end component; + --component ChipscopeIlaWb is + -- port ( + -- CLK : in STD_LOGIC := 'X'; + -- TRIG0 : in STD_LOGIC_VECTOR ( 46 downto 0); + -- CONTROL : inout STD_LOGIC_VECTOR ( 35 downto 0 ) + -- ); + --end component; + --signal control : std_logic_vector(35 downto 0); + --signal trig : std_logic_vector(46 downto 0); + + signal activeCycle : std_logic; + signal selectedMaster : natural range 0 to WIDTH-1; + signal selectedSlave : natural range 0 to WIDTH-1; + +begin + + ----------------------------------------------------------------------------- + -- Arbitration process. + ----------------------------------------------------------------------------- + + RoundRobinArbiter: process(areset_n, clk) + variable index : natural range 0 to WIDTH-1; + begin + if (areset_n = '0') then + activeCycle <= '0'; + selectedMaster <= 0; + elsif (clk'event and clk = '1') then + -- Check if a cycle is ongoing. + if (activeCycle = '0') then + -- No ongoing cycles. + + -- Iterate through all ports and check if any new cycle has started. + for i in 0 to WIDTH-1 loop + if ((selectedMaster+i) >= WIDTH) then + index := (selectedMaster+i) - WIDTH; + else + index := (selectedMaster+i); + end if; + + if (masterCyc_i(index) = '1') then + activeCycle <= '1'; + selectedMaster <= index; + end if; + end loop; + else + -- Ongoing cycle. + + -- Check if the cycle has ended. + if (masterCyc_i(selectedMaster) = '0') then + -- Cycle has ended. + activeCycle <= '0'; + + -- Check if a new cycle has started from another master. + -- Start to check from the one that ended its cycle, this way, the + -- ports will be scheduled like round-robin. + for i in 0 to WIDTH-1 loop + if ((selectedMaster+i) >= WIDTH) then + index := (selectedMaster+i) - WIDTH; + else + index := (selectedMaster+i); + end if; + + if (masterCyc_i(index) = '1') then + activeCycle <= '1'; + selectedMaster <= index; + end if; + end loop; + end if; + end if; + end if; + end process; + + ----------------------------------------------------------------------------- + -- Address decoding. + ----------------------------------------------------------------------------- + + -- Select the last port when the top bit is set. + -- The last port must be the maintenance slave port. + selectedSlave <= WIDTH-1 when masterAddr_i(selectedMaster)(9) = '1' else + to_integer(unsigned(masterAddr_i(selectedMaster)(8 downto 1))); + + ----------------------------------------------------------------------------- + -- Interconnection matrix. + ----------------------------------------------------------------------------- + Interconnect: for i in 0 to WIDTH-1 generate + slaveCyc_o(i) <= masterCyc_i(selectedMaster) when (selectedSlave = i) else '0'; + slaveStb_o(i) <= masterStb_i(selectedMaster) when (selectedSlave = i) else '0'; + slaveWe_o(i) <= masterWe_i(selectedMaster); + slaveAddr_o(i) <= masterAddr_i(selectedMaster); + slaveData_o(i) <= masterData_i(selectedMaster); + masterData_o(i) <= slaveData_i(selectedSlave); + masterAck_o(i) <= slaveAck_i(selectedSlave) when (selectedMaster = i) else '0'; + end generate; + + ----------------------------------------------------------------------------- + -- Chipscope debugging probe. + ----------------------------------------------------------------------------- + --trig <= masterCyc_i(selectedMaster) & masterStb_i(selectedMaster) & + -- masterWe_i(selectedMaster) & masterAddr_i(selectedMaster) & + -- masterData_i(selectedMaster) & slaveData_i(selectedSlave) & + -- slaveAck_i(selectedSlave); + --ChipscopeIconInst: ChipscopeIcon1 + -- port map(CONTROL0=>control); + --ChipscopeIlaInst: ChipscopeIlaWb + -- port map(CLK=>clk, TRIG0=>trig, CONTROL=>control); + +end architecture; + + +
rtl/vhdl/RioSwitch.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property

powered by: WebSVN 2.1.0

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