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

Subversion Repositories rio

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /rio/tags
    from Rev 23 to Rev 29
    Reverse comparison

Rev 23 → Rev 29

/1.0.1/bench/vhdl/TestRioSwitch.vhd
0,0 → 1,1266
-------------------------------------------------------------------------------
--
-- 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);
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;
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 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
 
---------------------------------------------------------------------------
-- Place a new ingress frame on a port.
---------------------------------------------------------------------------
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 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;
---------------------------------------------------------------------------
-- Expect a new egress frame on a port.
---------------------------------------------------------------------------
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 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;
---------------------------------------------------------------------------
-- Read a configuration-space register.
---------------------------------------------------------------------------
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;
 
---------------------------------------------------------------------------
-- Write a configuration-space register.
---------------------------------------------------------------------------
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;
 
---------------------------------------------------------------------------
-- Set a route table entry.
---------------------------------------------------------------------------
procedure RouteSet(constant deviceId : std_logic_vector(15 downto 0);
constant portIndex : std_logic_vector(7 downto 0)) is
variable frame : RioFrame;
begin
WriteConfig32(portIndex=>0, destinationId=>x"ffff", sourceId=>x"ffff", hop=>x"00",
tid=>x"de", address=>x"000070", data=>(x"0000" & deviceId));
WriteConfig32(portIndex=>0, destinationId=>x"ffff", sourceId=>x"ffff", hop=>x"00",
tid=>x"ad", address=>x"000074", data=>(x"000000" & portIndex));
end procedure;
---------------------------------------------------------------------------
-- Set the default route table entry.
---------------------------------------------------------------------------
procedure RouteSetDefault(constant portIndex : std_logic_vector(7 downto 0)) is
variable frame : RioFrame;
begin
WriteConfig32(portIndex=>0, destinationId=>x"ffff", sourceId=>x"ffff", hop=>x"00",
tid=>x"ad", address=>x"000078", data=>(x"000000" & portIndex));
end procedure;
---------------------------------------------------------------------------
-- Send a frame on an ingress port and expect it at an egress port.
---------------------------------------------------------------------------
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;
 
---------------------------------------------------------------------------
-- Variable definitions.
---------------------------------------------------------------------------
-- 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 at the same time.");
PrintS("Result: Both packets should be received at the expected ports.");
---------------------------------------------------------------------------
PrintR("TG_RioSwitch-TC3-Step1");
---------------------------------------------------------------------------
 
-- Setup the routing table for the following steps.
RouteSet(x"0000", x"00");
RouteSet(x"0001", x"00");
RouteSet(x"0002", x"00");
RouteSet(x"0003", x"00");
RouteSet(x"0004", x"01");
RouteSet(x"0005", x"02");
RouteSet(x"0006", x"03");
RouteSetDefault(x"06");
-- Frame on port 0 to port 1.
randomPayload.length := 3;
CreateRandomPayload(randomPayload.data, seed1, seed2);
SendFrame(portIndex=>0,
sourceId=>x"ffff", destinationId=>x"0004", payload=>randomPayload);
ReceiveFrame(portIndex=>1,
sourceId=>x"ffff", destinationId=>x"0004", 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 that 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"0004", payload=>randomPayload);
 
-- Frame on port 1 to port 2.
randomPayload1.length := 6;
CreateRandomPayload(randomPayload1.data, seed1, seed2);
SendFrame(portIndex=>1,
sourceId=>x"0000", destinationId=>x"0005", payload=>randomPayload1);
 
-- Frame on port 2 to port 2.
randomPayload2.length := 7;
CreateRandomPayload(randomPayload2.data, seed1, seed2);
SendFrame(portIndex=>2,
sourceId=>x"0000", destinationId=>x"0005", payload=>randomPayload2);
 
wait for 10 us;
 
ReceiveFrame(portIndex=>1,
sourceId=>x"ffff", destinationId=>x"0004", payload=>randomPayload);
wait until frameComplete(0) = '1';
frameValid(0) <= '0';
wait until frameReceived(1) = '1';
frameExpected(1) <= '0';
wait for 10 us;
ReceiveFrame(portIndex=>2,
sourceId=>x"0000", destinationId=>x"0005", payload=>randomPayload1);
wait until frameComplete(1) = '1';
frameValid(1) <= '0';
wait until frameReceived(2) = '1';
frameExpected(2) <= '0';
wait for 10 us;
ReceiveFrame(portIndex=>2,
sourceId=>x"0000", destinationId=>x"0005", payload=>randomPayload2);
wait until frameComplete(2) = '1';
frameValid(2) <= '0';
wait until frameReceived(2) = '1';
frameExpected(2) <= '0';
---------------------------------------------------------------------------
-- Test completed.
---------------------------------------------------------------------------
wait for 10 us;
 
assert readFrameEmpty = "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),
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,
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;
 
 
 
-------------------------------------------------------------------------------
-- Switch port test stub.
-------------------------------------------------------------------------------
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 for TestPort.
-------------------------------------------------------------------------------
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;
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 for TestPort.
-------------------------------------------------------------------------------
architecture TestPortImpl of TestPort is
begin
-----------------------------------------------------------------------------
-- Egress frame receiver.
-----------------------------------------------------------------------------
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;
 
-----------------------------------------------------------------------------
-- Ingress frame sender.
-----------------------------------------------------------------------------
FrameSender: process
type StateType is (STATE_IDLE, STATE_READ);
variable state : StateType;
variable frameIndex : natural range 0 to 69;
begin
readFrameEmpty_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;
readFrameEmpty_o <= '0';
end if;
when STATE_READ =>
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';
readContentData_o <= (others => 'U');
else
-- Not reading a frame.
end if;
 
end case;
end loop;
end process;
 
end architecture;
1.0.1/bench/vhdl/TestRioSwitch.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/bench/vhdl/TestRioPcsUart.vhd =================================================================== --- 1.0.1/bench/vhdl/TestRioPcsUart.vhd (nonexistent) +++ 1.0.1/bench/vhdl/TestRioPcsUart.vhd (revision 29) @@ -0,0 +1,673 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- This file contains a testbench for RioPcsUart. +-- +-- 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 +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- TestRioPcsUart. +------------------------------------------------------------------------------- + +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 for TestRioPcsUart. +------------------------------------------------------------------------------- +entity TestRioPcsUart is +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for TestUart. +------------------------------------------------------------------------------- +architecture TestRioPcsUartImpl of TestRioPcsUart is + + component RioFifo1 is + generic( + WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + empty_o : out std_logic; + read_i : in std_logic; + data_o : out std_logic_vector(WIDTH-1 downto 0); + + full_o : out std_logic; + write_i : in std_logic; + data_i : in std_logic_vector(WIDTH-1 downto 0)); + end component; + + component RioSymbolConverter is + port( + clk : in std_logic; + areset_n : in std_logic; + + portInitialized_o : out std_logic; + outboundSymbolEmpty_i : in std_logic; + outboundSymbolRead_o : out std_logic; + outboundSymbol_i : in std_logic_vector(33 downto 0); + inboundSymbolFull_i : in std_logic; + inboundSymbolWrite_o : out std_logic; + inboundSymbol_o : out std_logic_vector(33 downto 0); + + uartEmpty_i : in std_logic; + uartRead_o : out std_logic; + uartData_i : in std_logic_vector(7 downto 0); + uartFull_i : in std_logic; + uartWrite_o : out std_logic; + uartData_o : out std_logic_vector(7 downto 0)); + end component; + + signal clk : std_logic; + signal areset_n : std_logic; + + signal portInitialized : std_logic; + + signal outboundSymbolEmpty : std_logic; + signal outboundSymbolRead : std_logic; + signal outboundSymbolReadData : std_logic_vector(33 downto 0); + signal outboundSymbolFull : std_logic; + signal outboundSymbolWrite : std_logic; + signal outboundSymbolWriteData : std_logic_vector(33 downto 0); + + signal inboundSymbolFull : std_logic; + signal inboundSymbolWrite : std_logic; + signal inboundSymbolWriteData : std_logic_vector(33 downto 0); + + signal uartInboundEmpty : std_logic; + signal uartInboundRead : std_logic; + signal uartInboundReadData : std_logic_vector(7 downto 0); + signal uartInboundFull : std_logic; + signal uartInboundWrite : std_logic; + signal uartInboundWriteData : std_logic_vector(7 downto 0); + + signal uartOutboundFull : std_logic; + signal uartOutboundWrite : std_logic; + signal uartOutboundWriteData : std_logic_vector(7 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Clock generation. + ----------------------------------------------------------------------------- + ClockGenerator: process + begin + clk <= '0'; + wait for 20 ns; + clk <= '1'; + wait for 20 ns; + end process; + + + ----------------------------------------------------------------------------- + -- Serial protocol test driver. + ----------------------------------------------------------------------------- + TestDriver: process + + --------------------------------------------------------------------------- + -- Procedure to read a symbol. + --------------------------------------------------------------------------- + procedure ReadSymbol( + constant symbolType : in std_logic_vector(1 downto 0); + constant symbolContent : in std_logic_vector(31 downto 0) := x"00000000") is + begin + inboundSymbolFull <= '0'; + wait until inboundSymbolWrite = '1' and clk'event and clk = '1'; + inboundSymbolFull <= '1'; + + assert symbolType = inboundSymbolWriteData(33 downto 32) + report "Missmatching symbol type:expected=" & + integer'image(to_integer(unsigned(symbolType))) & + " got=" & + integer'image(to_integer(unsigned(outboundSymbolWriteData(33 downto 32)))) + severity error; + + if (symbolType = SYMBOL_CONTROL) then + assert symbolContent(31 downto 8) = inboundSymbolWriteData(31 downto 8) + report "Missmatching symbol content:expected=" & + integer'image(to_integer(unsigned(symbolContent(31 downto 8)))) & + " got=" & + integer'image(to_integer(unsigned(inboundSymbolWriteData(31 downto 8)))) + severity error; + elsif (symbolType = SYMBOL_DATA) then + assert symbolContent(31 downto 0) = inboundSymbolWriteData(31 downto 0) + report "Missmatching symbol content:expected=" & + integer'image(to_integer(unsigned(symbolContent(31 downto 0)))) & + " got=" & + integer'image(to_integer(unsigned(inboundSymbolWriteData(31 downto 0)))) + severity error; + end if; + end procedure; + + --------------------------------------------------------------------------- + -- Procedure to write a symbol. + --------------------------------------------------------------------------- + procedure WriteSymbol( + constant symbolType : in std_logic_vector(1 downto 0); + constant symbolContent : in std_logic_vector(31 downto 0) := x"00000000") is + begin + wait until outboundSymbolFull = '0' and clk'event and clk = '1'; + outboundSymbolWrite <= '1'; + outboundSymbolWriteData <= symbolType & symbolContent; + wait until clk'event and clk = '1'; + outboundSymbolWrite <= '0'; + end procedure; + + --------------------------------------------------------------------------- + -- Procedure to read an octet. + --------------------------------------------------------------------------- + procedure ReadOctet( + constant octet : in std_logic_vector(7 downto 0) := x"00") is + begin + uartOutboundFull <= '0'; + wait until uartOutboundWrite = '1' and clk'event and clk = '1'; + uartOutboundFull <= '1'; + + assert uartOutboundWriteData = octet + report "Missmatching octet content:expected=" & + integer'image(to_integer(unsigned(octet))) & + " got=" & + integer'image(to_integer(unsigned(uartOutboundWriteData))) + severity error; + end procedure; + + --------------------------------------------------------------------------- + -- Procedure to send a symbol. + --------------------------------------------------------------------------- + procedure WriteOctet( + constant octet : in std_logic_vector(7 downto 0) := x"00") is + begin + wait until uartInboundFull = '0' and clk'event and clk = '1'; + uartInboundWrite <= '1'; + uartInboundWriteData <= octet; + wait until clk'event and clk = '1'; + uartInboundWrite <= '0'; + end procedure; + + --------------------------------------------------------------------------- + -- Process variables. + --------------------------------------------------------------------------- + + begin + --------------------------------------------------------------------------- + -- Test case initialization. + --------------------------------------------------------------------------- + + uartOutboundFull <= '1'; + uartInboundWrite <= '0'; + + inboundSymbolFull <= '1'; + outboundSymbolWrite <= '0'; + + -- Generate a startup reset pulse. + areset_n <= '0'; + 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_RioPcsUart"); + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPcsUart-TC1"); + PrintS("Description: Check initial silence time."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC1-Step1"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_IDLE); + + uartOutboundFull <= '0'; + for i in 0 to 4095 loop + wait until clk'event and clk = '1'; + assert uartOutboundWrite = '0' report "Sending during silence time." + severity error; + end loop; + + ReadOctet(x"7e"); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPcsUart-TC2"); + PrintS("Description: Check outbound symbol generation."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step1"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_IDLE); + ReadOctet(x"7e"); + WriteSymbol(SYMBOL_IDLE); + ReadOctet(x"7e"); + WriteSymbol(SYMBOL_IDLE); + ReadOctet(x"7e"); + + --------------------------------------------------------------------------- + PrintS("Step 2:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step2"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_CONTROL, x"123456" & "XXXXXXXX"); + ReadOctet(x"12"); + ReadOctet(x"34"); + ReadOctet(x"56"); + ReadOctet(x"7e"); + + --------------------------------------------------------------------------- + PrintS("Step 3:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step3"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_CONTROL, x"7d7d7d" & "XXXXXXXX"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7e"); + + --------------------------------------------------------------------------- + PrintS("Step 4:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step4"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_CONTROL, x"7e7e7e" & "XXXXXXXX"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7e"); + + --------------------------------------------------------------------------- + PrintS("Step 5:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step5"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_CONTROL, x"7d7f7e" & "XXXXXXXX"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7f"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7e"); + + --------------------------------------------------------------------------- + PrintS("Step 6:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step6"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_DATA, x"12345678"); + ReadOctet(x"12"); + ReadOctet(x"34"); + ReadOctet(x"56"); + ReadOctet(x"78"); + + --------------------------------------------------------------------------- + PrintS("Step 7:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step7"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_DATA, x"7d7d7d7d"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + + --------------------------------------------------------------------------- + PrintS("Step 8:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step8"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_DATA, x"7e7e7e7e"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + + --------------------------------------------------------------------------- + PrintS("Step 9:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step9"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_DATA, x"7d7f7e7f"); + ReadOctet(x"7d"); + ReadOctet(x"5d"); + ReadOctet(x"7f"); + ReadOctet(x"7d"); + ReadOctet(x"5e"); + ReadOctet(x"7f"); + + --------------------------------------------------------------------------- + PrintS("Step 10:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC2-Step10"); + --------------------------------------------------------------------------- + + WriteSymbol(SYMBOL_IDLE); + ReadOctet(x"7e"); + WriteSymbol(SYMBOL_CONTROL, x"123456" & "XXXXXXXX"); + ReadOctet(x"12"); + ReadOctet(x"34"); + ReadOctet(x"56"); + ReadOctet(x"7e"); + WriteSymbol(SYMBOL_DATA, x"789abcde"); + ReadOctet(x"78"); + ReadOctet(x"9a"); + ReadOctet(x"bc"); + ReadOctet(x"de"); + WriteSymbol(SYMBOL_CONTROL, x"123456" & "XXXXXXXX"); + ReadOctet(x"12"); + ReadOctet(x"34"); + ReadOctet(x"56"); + ReadOctet(x"7e"); + WriteSymbol(SYMBOL_DATA, x"789abcde"); + ReadOctet(x"78"); + ReadOctet(x"9a"); + ReadOctet(x"bc"); + ReadOctet(x"de"); + WriteSymbol(SYMBOL_DATA, x"789abcde"); + ReadOctet(x"78"); + ReadOctet(x"9a"); + ReadOctet(x"bc"); + ReadOctet(x"de"); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPcsUart-TC3"); + PrintS("Description: Check inbound symbol generation."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step1"); + --------------------------------------------------------------------------- + + WriteOctet(x"7e"); + WriteOctet(x"7e"); + ReadSymbol(SYMBOL_IDLE); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"12"); + WriteOctet(x"7e"); + ReadSymbol(SYMBOL_IDLE); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"34"); + WriteOctet(x"56"); + WriteOctet(x"7e"); + ReadSymbol(SYMBOL_IDLE); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"78"); + WriteOctet(x"9a"); + WriteOctet(x"bc"); + WriteOctet(x"7e"); + ReadSymbol(SYMBOL_CONTROL, x"789abc" & "XXXXXXXX"); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"7d"); + WriteOctet(x"5d"); + WriteOctet(x"7d"); + WriteOctet(x"5d"); + WriteOctet(x"7d"); + WriteOctet(x"5d"); + WriteOctet(x"7e"); + ReadSymbol(SYMBOL_CONTROL, x"7d7d7d" & "XXXXXXXX"); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"7d"); + WriteOctet(x"5e"); + WriteOctet(x"7d"); + WriteOctet(x"5e"); + WriteOctet(x"7d"); + WriteOctet(x"5e"); + WriteOctet(x"7e"); + ReadSymbol(SYMBOL_CONTROL, x"7e7e7e" & "XXXXXXXX"); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"f1"); + WriteOctet(x"11"); + WriteOctet(x"22"); + WriteOctet(x"33"); + ReadSymbol(SYMBOL_DATA, x"f1112233"); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"7e"); + ReadSymbol(SYMBOL_IDLE); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"7d"); + WriteOctet(x"5d"); + WriteOctet(x"7d"); + WriteOctet(x"5d"); + WriteOctet(x"7d"); + WriteOctet(x"5d"); + WriteOctet(x"7d"); + WriteOctet(x"5d"); + ReadSymbol(SYMBOL_DATA, x"7d7d7d7d"); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"7d"); + WriteOctet(x"5e"); + WriteOctet(x"7d"); + WriteOctet(x"5e"); + WriteOctet(x"7d"); + WriteOctet(x"5e"); + WriteOctet(x"7d"); + WriteOctet(x"5e"); + ReadSymbol(SYMBOL_DATA, x"7e7e7e7e"); + + --------------------------------------------------------------------------- + PrintS("Step :"); + PrintS("Action: ."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPcsUart-TC3-Step"); + --------------------------------------------------------------------------- + + WriteOctet(x"44"); + WriteOctet(x"55"); + WriteOctet(x"66"); + WriteOctet(x"77"); + ReadSymbol(SYMBOL_DATA, x"44556677"); + WriteOctet(x"88"); + WriteOctet(x"99"); + WriteOctet(x"aa"); + WriteOctet(x"bb"); + ReadSymbol(SYMBOL_DATA, x"8899aabb"); + + --------------------------------------------------------------------------- + -- Test completed. + --------------------------------------------------------------------------- + + TestEnd; + end process; + + + ----------------------------------------------------------------------------- + -- + ----------------------------------------------------------------------------- + + OutboundSymbolFifo: RioFifo1 + generic map(WIDTH=>34) + port map( + clk=>clk, areset_n=>areset_n, + empty_o=>outboundSymbolEmpty, read_i=>outboundSymbolRead, data_o=>outboundSymbolReadData, + full_o=>outboundSymbolFull, write_i=>outboundSymbolWrite, data_i=>outboundSymbolWriteData); + + InboundOctetFifo: RioFifo1 + generic map(WIDTH=>8) + port map( + clk=>clk, areset_n=>areset_n, + empty_o=>uartInboundEmpty, read_i=>uartInboundRead, data_o=>uartInboundReadData, + full_o=>uartInboundFull, write_i=>uartInboundWrite, data_i=>uartInboundWriteData); + + TestSymbolConverter: RioSymbolConverter + port map( + clk=>clk, areset_n=>areset_n, + portInitialized_o=>portInitialized, + outboundSymbolEmpty_i=>outboundSymbolEmpty, + outboundSymbolRead_o=>outboundSymbolRead, outboundSymbol_i=>outboundSymbolReadData, + inboundSymbolFull_i=>inboundSymbolFull, + inboundSymbolWrite_o=>inboundSymbolWrite, inboundSymbol_o=>inboundSymbolWriteData, + uartEmpty_i=>uartInboundEmpty, uartRead_o=>uartInboundRead, uartData_i=>uartInboundReadData, + uartFull_i=>uartOutboundFull, uartWrite_o=>uartOutboundWrite, uartData_o=>uartOutboundWriteData); + +end architecture;
1.0.1/bench/vhdl/TestRioPcsUart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/bench/vhdl/TestUart.vhd =================================================================== --- 1.0.1/bench/vhdl/TestUart.vhd (nonexistent) +++ 1.0.1/bench/vhdl/TestUart.vhd (revision 29) @@ -0,0 +1,228 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- Contains a testbench for the generic UART entity. +-- +-- 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 +-- +------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- TestUart. +------------------------------------------------------------------------------- + +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 for TestUart. +------------------------------------------------------------------------------- +entity TestUart is +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for TestUart. +------------------------------------------------------------------------------- +architecture TestUartImpl of TestUart is + + component Uart is + generic( + DIVISOR_WIDTH : natural; + DATA_WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0); + + serial_i : in std_logic; + serial_o : out std_logic; + + empty_o : out std_logic; + read_i : in std_logic; + data_o : out std_logic_vector(DATA_WIDTH-1 downto 0); + + full_o : out std_logic; + write_i : in std_logic; + data_i : in std_logic_vector(DATA_WIDTH-1 downto 0)); + end component; + + signal clk : std_logic; + signal areset_n : std_logic; + + signal rxSerial : std_logic; + signal txSerial : std_logic; + + signal rxEmpty : std_logic; + signal rxRead : std_logic; + signal rxData : std_logic_vector(7 downto 0); + + signal txFull : std_logic; + signal txWrite : std_logic; + signal txData : std_logic_vector(7 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 SerialSend( + constant data : in std_logic_vector(7 downto 0)) is + variable outgoing : std_logic_vector(9 downto 0); + begin + -- Create the complete transmission character. + outgoing(0) := '0'; + for i in 0 to 7 loop + outgoing(i+1) := data(i); + end loop; + outgoing(9) := '1'; + + -- Send the character. + for i in 0 to 9 loop + txSerial <= outgoing(i); + wait for 500 ns; + end loop; + end procedure; + + procedure SerialReceive( + constant data : in std_logic_vector(7 downto 0)) is + variable incomming : std_logic_vector(9 downto 0); + begin + -- Receive the character. + wait until rxSerial = '0'; + incomming(0) := '0'; + for i in 1 to 9 loop + wait for 500 ns; + incomming(i) := rxSerial; + end loop; + + -- Check if the received character is expected. + assert (incomming(0) = '0') report "Start bit." severity error; + assert (incomming(8 downto 1) = data) report "Data bit" severity error; + assert (incomming(9) = '1') report "Stop bit." severity error; + end procedure; + + begin + txSerial <= '1'; + txWrite <= '0'; + rxRead <= '0'; + areset_n <= '0'; + + 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'; + + --------------------------------------------------------------------------- + -- Send byte to uart. + --------------------------------------------------------------------------- + SerialSend(x"55"); + wait until rxEmpty = '0' and clk'event and clk = '1'; + rxRead <= '1'; + wait until clk'event and clk = '1'; + rxRead <= '0'; + wait until clk'event and clk = '1'; + assert rxData = x"55" report "rxData" severity error; + + SerialSend(x"62"); + wait until rxEmpty = '0' and clk'event and clk = '1'; + rxRead <= '1'; + wait until clk'event and clk = '1'; + rxRead <= '0'; + wait until clk'event and clk = '1'; + assert rxData = x"62" report "rxData" severity error; + + wait until txFull = '0' and clk'event and clk = '1'; + txWrite <= '1'; + txData <= x"55"; + wait until clk'event and clk = '1'; + txWrite <= '0'; + SerialReceive(x"55"); + + wait until txFull = '0' and clk'event and clk = '1'; + txWrite <= '1'; + txData <= x"62"; + wait until clk'event and clk = '1'; + txWrite <= '0'; + SerialReceive(x"62"); + + -- REMARK: Formalize the tests and write more testcases... + + --------------------------------------------------------------------------- + -- Test completed. + --------------------------------------------------------------------------- + + TestEnd; + end process; + + + ----------------------------------------------------------------------------- + -- Instantiate the uart. + ----------------------------------------------------------------------------- + + UartInst: Uart + generic map(DIVISOR_WIDTH=>4, DATA_WIDTH=>8) + port map( + clk=>clk, areset_n=>areset_n, + divisor_i=>"1011", + serial_i=>txSerial, serial_o=>rxSerial, + empty_o=>rxEmpty, read_i=>rxRead, data_o=>rxData, + full_o=>txFull, write_i=>txWrite, data_i=>txData); + +end architecture;
1.0.1/bench/vhdl/TestUart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/bench/vhdl/TestRioSerial.vhd =================================================================== --- 1.0.1/bench/vhdl/TestRioSerial.vhd (nonexistent) +++ 1.0.1/bench/vhdl/TestRioSerial.vhd (revision 29) @@ -0,0 +1,2486 @@ +------------------------------------------------------------------------------- +-- +-- 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 RioSerial 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 +-- +------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- TestRioSerial. +------------------------------------------------------------------------------- + +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 for TestRioSerial. +------------------------------------------------------------------------------- +entity TestRioSerial is +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for TestUart. +------------------------------------------------------------------------------- +architecture TestRioSerialImpl of TestRioSerial is + + component TestSwitchPort is + port( + clk : in std_logic; + areset_n : in std_logic; + + frameValid_i : in std_logic_vector(0 to 63); + frameWrite_i : in RioFrameArray(0 to 63); + 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; + + readWindowEmpty_o : out std_logic; + readWindowReset_i : in std_logic; + readWindowNext_i : in 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; + + component RioSerial is + generic( + TIMEOUT_WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + portLinkTimeout_i : in std_logic_vector(TIMEOUT_WIDTH-1 downto 0); + linkInitialized_o : out std_logic; + inputPortEnable_i : in std_logic; + outputPortEnable_i : in std_logic; + + localAckIdWrite_i : in std_logic; + clrOutstandingAckId_i : in std_logic; + inboundAckId_i : in std_logic_vector(4 downto 0); + outstandingAckId_i : in std_logic_vector(4 downto 0); + outboundAckId_i : in std_logic_vector(4 downto 0); + inboundAckId_o : out std_logic_vector(4 downto 0); + outstandingAckId_o : out std_logic_vector(4 downto 0); + outboundAckId_o : out std_logic_vector(4 downto 0); + + readFrameEmpty_i : in std_logic; + readFrame_o : out std_logic; + readFrameRestart_o : out std_logic; + readFrameAborted_i : in std_logic; + + readWindowEmpty_i : in std_logic; + readWindowReset_o : out std_logic; + readWindowNext_o : out 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); + + portInitialized_i : in std_logic; + outboundSymbolEmpty_o : out std_logic; + outboundSymbolRead_i : in std_logic; + outboundSymbol_o : out std_logic_vector(33 downto 0); + inboundSymbolFull_o : out std_logic; + inboundSymbolWrite_i : in std_logic; + inboundSymbol_i : in std_logic_vector(33 downto 0)); + end component; + + signal clk : std_logic; + signal areset_n : std_logic; + + signal uartInbound : std_logic; + signal uartOutbound : std_logic; + + signal portLinkTimeout : std_logic_vector(10 downto 0); + signal linkInitialized : std_logic; + signal inputPortEnable : std_logic; + signal outputPortEnable : std_logic; + + signal localAckIdWrite : std_logic; + signal clrOutstandingAckId : std_logic; + signal inboundAckIdWrite : std_logic_vector(4 downto 0); + signal outstandingAckIdWrite : std_logic_vector(4 downto 0); + signal outboundAckIdWrite : std_logic_vector(4 downto 0); + signal inboundAckIdRead : std_logic_vector(4 downto 0); + signal outstandingAckIdRead : std_logic_vector(4 downto 0); + signal outboundAckIdRead : std_logic_vector(4 downto 0); + + signal portInitialized : std_logic; + signal outboundSymbolEmpty : std_logic; + signal outboundSymbolRead : std_logic; + signal outboundSymbol : std_logic_vector(33 downto 0); + signal inboundSymbolFull : std_logic; + signal inboundSymbolWrite : std_logic; + signal inboundSymbol : std_logic_vector(33 downto 0); + + signal readFrameEmpty : std_logic; + signal readFrame : std_logic; + signal readFrameRestart : std_logic; + signal readFrameAborted : std_logic; + signal readWindowEmpty : std_logic; + signal readWindowReset : std_logic; + signal readWindowNext : std_logic; + signal readContentEmpty : std_logic; + signal readContent : std_logic; + signal readContentEnd : std_logic; + signal readContentData : std_logic_vector(31 downto 0); + + signal writeFrameFull : std_logic; + signal writeFrame : std_logic; + signal writeFrameAbort : std_logic; + signal writeContent : std_logic; + signal writeContentData : std_logic_vector(31 downto 0); + + signal frameValid : std_logic_vector(0 to 63); + signal frameWrite : RioFrameArray(0 to 63); + signal frameComplete : std_logic; + signal frameExpected : std_logic; + signal frameRead : RioFrame; + signal frameReceived : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Clock generation. + ----------------------------------------------------------------------------- + ClockGenerator: process + begin + clk <= '0'; + wait for 20 ns; + clk <= '1'; + wait for 20 ns; + end process; + + + ----------------------------------------------------------------------------- + -- Serial protocol test driver. + ----------------------------------------------------------------------------- + TestDriver: process + + --------------------------------------------------------------------------- + -- Procedure to receive a symbol. + --------------------------------------------------------------------------- + procedure ReceiveSymbol( + constant symbolType : in std_logic_vector(1 downto 0); + constant symbolContent : in std_logic_vector(31 downto 0) := x"00000000") is + begin + wait until outboundSymbolEmpty = '0' and clk'event and clk = '1'; + + assert symbolType = outboundSymbol(33 downto 32) + report "Missmatching symbol type:expected=" & + integer'image(to_integer(unsigned(symbolType))) & + " got=" & + integer'image(to_integer(unsigned(outboundSymbol(33 downto 32)))) + severity error; + + if ((outboundSymbol(33 downto 32) = SYMBOL_CONTROL) or + (outboundSymbol(33 downto 32) = SYMBOL_CONTROL)) then + assert symbolContent(31 downto 8) = outboundSymbol(31 downto 8) + report "Missmatching symbol content:expected=" & + integer'image(to_integer(unsigned(symbolContent(31 downto 8)))) & + " got=" & + integer'image(to_integer(unsigned(outboundSymbol(31 downto 8)))) + severity error; + elsif (outboundSymbol(33 downto 32) = SYMBOL_DATA) then + assert symbolContent(31 downto 0) = outboundSymbol(31 downto 0) + report "Missmatching symbol content:expected=" & + integer'image(to_integer(unsigned(symbolContent(31 downto 0)))) & + " got=" & + integer'image(to_integer(unsigned(outboundSymbol(31 downto 0)))) + severity error; + end if; + + outboundSymbolRead <= '1'; + wait until clk'event and clk = '1'; + outboundSymbolRead <= '0'; + end procedure; + + --------------------------------------------------------------------------- + -- Procedure to send a symbol. + --------------------------------------------------------------------------- + procedure SendSymbol( + constant symbolType : in std_logic_vector(1 downto 0); + constant symbolContent : in std_logic_vector(31 downto 0) := x"00000000") is + begin + wait until inboundSymbolFull = '0' and clk'event and clk = '1'; + + inboundSymbolWrite <= '1'; + inboundSymbol <= symbolType & symbolContent; + + wait until clk'event and clk = '1'; + inboundSymbolWrite <= '0'; + end procedure; + + --------------------------------------------------------------------------- + -- Process variables. + --------------------------------------------------------------------------- + variable seed1 : positive := 1; + variable seed2 : positive := 1; + variable payload : RioPayload; + + variable frame : RioFrame; + + begin + --------------------------------------------------------------------------- + -- Test case initialization. + --------------------------------------------------------------------------- + + frameValid <= (others=>'0'); + frameExpected <= '0'; + + portLinkTimeout <= (others=>'1'); + inputPortEnable <= '1'; + outputPortEnable <= '1'; + + portInitialized <= '0'; + outboundSymbolRead <= '0'; + inboundSymbolWrite <= '0'; + inboundSymbol <= (others => '0'); + + localAckIdWrite <= '0'; + clrOutstandingAckId <= '0'; + inboundAckIdWrite <= (others=>'0'); + outstandingAckIdWrite <= (others=>'0'); + outboundAckIdWrite <= (others=>'0'); + + -- Generate a startup reset pulse. + areset_n <= '0'; + 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_RioSerial"); + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioSerial-TC1"); + PrintS("Description: Test idle-sequence transmission at startup."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Read transmission port."); + PrintS("Result: Idle sequence symbols should be read."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC1-Step1"); + --------------------------------------------------------------------------- + + -- Make sure only idle-sequences are transmitted at startup. + for i in 0 to 1024 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioSerial-TC2"); + PrintS("Description: Test idle-sequence and status symbol transmission"); + PrintS(" when the port has been initialized."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Set port initialized and read transmission port."); + PrintS("Result: Idle sequence and status symbols should be read."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC2-Step1"); + --------------------------------------------------------------------------- + + -- Initialize the port to trigger a change of state. + portInitialized <= '1'; + + -- The transmitter should send idle sequences at startup and a status once + -- in a while. + for i in 0 to 254 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_NOP, "000")); + for i in 0 to 254 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Toggle port initialized pin and check that no status "); + PrintS(" symbols are transmitted when uninitialized."); + PrintS("Result: Only idle sequences should be read when uninitialized."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC2-Step2"); + --------------------------------------------------------------------------- + + -- Deassert the port initialized flag. + portInitialized <= '0'; + + -- Make sure only idle-sequences are transmitted at startup. + for i in 0 to 1024 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + + -- Initialize the port to trigger a change of state. + portInitialized <= '1'; + + -- The transmitter should send idle sequences at startup and a status once + -- in a while. + for i in 0 to 254 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_NOP, "000")); + for i in 0 to 254 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send one error free status symbol to trigger the "); + PrintS(" transmission of status symbols with a higher frequency."); + PrintS("Result: Idle sequence and status symbols should be read but "); + PrintS(" status symbols should be recived more often."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC2-Step3"); + --------------------------------------------------------------------------- + + -- A received error-free status triggers transmission of status symbols in + -- a more rapid past. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_NOP, "000")); + + -- The transmitter should send at least 15 additional statuses after + -- receiving an error free status. + for j in 0 to 15 loop + for i in 0 to 15 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_NOP, "000")); + end loop; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send one errornous status symbol to restart the status "); + PrintS(" counting."); + PrintS("Result: Idle sequence and status symbols should be read but "); + PrintS(" status symbols should still be received more often."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC2-Step4"); + --------------------------------------------------------------------------- + + -- REMARK: Add this... + PrintR("Not implemented."); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Send one errornous status symbol to restart the status "); + PrintS(" counting."); + PrintS("Result: Idle sequence and status symbols should be read but "); + PrintS(" status symbols should still be received more often."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC2-Step5"); + --------------------------------------------------------------------------- + + -- Make the link fully initialized by sending 7 additional statuses. + for i in 0 to 6 loop + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_NOP, "000")); + end loop; + + wait until linkInitialized = '1'; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioSerial-TC3"); + PrintS("Description: Test port reception."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send an inbound frame with pad after the CRC."); + PrintS("Result: The frame should end up in a frame buffer."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step1"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 1; + frame := RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- End the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00000", "11111", + STYPE1_NOP, "000")); + + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send an inbound frame without a pad after the CRC."); + PrintS("Result: The frame should end up in a frame buffer."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step2"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 2; + frame := RioFrameCreate(ackId=>"00001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- End the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmited frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00001", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send an inbound frame with maximum size."); + PrintS("Result: The frame should end up in a frame buffer."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step3"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 133; + frame := RioFrameCreate(ackId=>"00010", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- End the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00010", "11111", + STYPE1_NOP, "000")); + + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send two packets without end-of-packet in between."); + PrintS("Result: Both packets should be accepted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step4"); + --------------------------------------------------------------------------- + + -- Create the first frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 10; + frame := RioFrameCreate(ackId=>"00011", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Start the reception of a frame, implicitly ending the previous. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + wait until clk'event and clk = '1'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00011", "11111", + STYPE1_NOP, "000")); + + -- Create the second frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 13; + frame := RioFrameCreate(ackId=>"00100", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- End the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00100", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Start to send a packet. Abort it with stomp. Then send "); + PrintS(" another packet."); + PrintS("Result: The first packet should be discarded and the second should"); + PrintS(" be accepted. The retried packet should be acknowledged."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step5"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 7; + frame := RioFrameCreate(ackId=>"00101", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Abort the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_STOMP, "000")); + + -- Dont expect the aborted frame anymore. + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the retry was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_RETRY, "00101", "11111", + STYPE1_NOP, "000")); + + -- Acknowledge the canceled packet. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_RESTART_FROM_RETRY, "000")); + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 8; + frame := RioFrameCreate(ackId=>"00101", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Abort the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00101", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 6:"); + PrintS("Action: Start to send a packet but dont send any payload. Abort it"); + PrintS(" with stomp. Then send another packet."); + PrintS("Result: The first packet should be discarded and the second should"); + PrintS(" be accepted. The retried packet should be acknowledged."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step6"); + --------------------------------------------------------------------------- + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Abort the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_STOMP, "000")); + + -- Receive an idle symbol left in the FIFO before the retry was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_RETRY, "00110", "11111", + STYPE1_NOP, "000")); + + -- Acknowledge the canceled packet. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_RESTART_FROM_RETRY, "000")); + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 8; + frame := RioFrameCreate(ackId=>"00110", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Abort the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00110", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 7:"); + PrintS("Action: Start to send a packet with payload, then send a "); + PrintS(" link-request. Then send another packet."); + PrintS("Result: The first packet should be canceled without any "); + PrintS(" confirmation and a link-response should be returned. The"); + PrintS(" second packet should be accepted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step7"); + --------------------------------------------------------------------------- + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 9; + frame := RioFrameCreate(ackId=>"00111", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Send a link-request/input-status to abort the current packet. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- The frame should be canceled by the link-request, dont expect it anymore. + frameExpected <= '0'; + + -- Receive link-response indicating normal operation and expected ackId. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "00111", "10000", + STYPE1_NOP, "000")); + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 10; + frame := RioFrameCreate(ackId=>"00111", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Abort the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00111", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 8:"); + PrintS("Action: Start to send a packet, no payload, then send a "); + PrintS(" link-request. Then send another packet."); + PrintS("Result: The first packet should be canceled without any "); + PrintS(" confirmation and a link-response should be returned. The"); + PrintS(" second packet should be accepted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step8"); + --------------------------------------------------------------------------- + + -- Expect an empty packet to be aborted. + frameExpected <= '1'; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send a link-request/input-status to abort the current packet. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Dont expect any frames anymore. + frameExpected <= '0'; + + -- Receive link-response indicating normal operation and expected ackId. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01000", "10000", + STYPE1_NOP, "000")); + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 11; + frame := RioFrameCreate(ackId=>"01000", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Send the data symbols of the frame. + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Abort the reception of the frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Check that the frame has been received in the frame buffer. + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive an idle symbol left in the FIFO before the ack was generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01000", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 9:"); + PrintS("Action: Send a packet when no buffers is available. Reset receiver"); + PrintS(" with link-request."); + PrintS("Result: A packet-retry should be transmitted and receiver should"); + PrintS(" enter input-retry-stopped."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step9"); + --------------------------------------------------------------------------- + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 11; + frame := RioFrameCreate(ackId=>"01001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + SendSymbol(SYMBOL_DATA, frame.payload(0)); + + -- Receive notification about that the packet needs to be retried. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_RETRY, "01001", "11111", + STYPE1_NOP, "000")); + + -- Check the status of the input port and verify the input-retry-stopped state. + -- This should also set the receiver into normal operation. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_LINK_REQUEST, "100")); + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01001", "00100", + STYPE1_NOP, "000")); + + -- Check the status of the input port and verify the input-retry-stopped state. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_LINK_REQUEST, "100")); + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01001", "10000", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 10:"); + PrintS("Action: Send a packet when no buffers is available. Reset receiver"); + PrintS(" with restart-from-retry."); + PrintS("Result: A packet-retry should be transmitted and receiver should"); + PrintS(" enter input-retry-stopped."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step10"); + --------------------------------------------------------------------------- + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 11; + frame := RioFrameCreate(ackId=>"01001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + SendSymbol(SYMBOL_DATA, frame.payload(0)); + + -- Receive notification about that the packet needs to be retried. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_RETRY, "01001", "11111", + STYPE1_NOP, "000")); + + -- Acknowledge the retried packet. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_RESTART_FROM_RETRY, "000")); + + -- Check the status of the input port and verify the input-retry-stopped state. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_LINK_REQUEST, "100")); + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01001", "10000", + STYPE1_NOP, "000")); + + -- Always receive a status after a link response when leaving input-error-stopped. +-- ReceiveSymbol(SYMBOL_CONTROL, +-- RioControlSymbolCreate(STYPE0_STATUS, "01001", "11111", +-- STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 11:"); + PrintS("Action: Start a new packet when in input-retry-stopped state."); + PrintS("Result: The packet should be discarded."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step11"); + --------------------------------------------------------------------------- + + -- Create a new frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 11; + frame := RioFrameCreate(ackId=>"01001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + + -- Start the reception of a frame. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + SendSymbol(SYMBOL_DATA, frame.payload(0)); + + -- Receive notification about that the packet needs to be retried. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_RETRY, "01001", "11111", + STYPE1_NOP, "000")); + + -- Create a packet and send it. It should be discarded. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 12; + frame := RioFrameCreate(ackId=>"01001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Acknowledge the retried packet. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_RESTART_FROM_RETRY, "000")); + + -- Create a packet and send it. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 13; + frame := RioFrameCreate(ackId=>"01001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01001", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 12:"); + PrintS("Action: Send an erronous control-symbol. Then restore with"); + PrintS(" link-request."); + PrintS("Result: Receiver should enter input-error-stopped and return to"); + PrintS(" normal operation after the link-request was receiver."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step12"); + --------------------------------------------------------------------------- + + -- Create, corrupt and send a control symbol. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000") xor x"00100000"); + + -- Receive a packet-not-accepted indicating error in control-symbol crc. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_NOT_ACCEPTED, "00000", "00010", + STYPE1_NOP, "000")); + + -- Create a packet and send it. It should be discarded. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 14; + frame := RioFrameCreate(ackId=>"01010", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Make the receiver go back to normal operation by sending a link-request. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_LINK_REQUEST, "100")); + + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01010", "00101", + STYPE1_NOP, "000")); + + -- Always receive a status after a link response when leaving input-error-stopped. +-- ReceiveSymbol(SYMBOL_CONTROL, +-- RioControlSymbolCreate(STYPE0_STATUS, "01010", "11111", +-- STYPE1_NOP, "000")); + + -- Create a packet and send it. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 15; + frame := RioFrameCreate(ackId=>"01010", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01010", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 13:"); + PrintS("Action: Send an erronous packet. Then restore with link-request."); + PrintS("Result: Receiver should enter input-error-stopped and return to"); + PrintS(" normal operation after the link-request was receiver."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC3-Step13"); + --------------------------------------------------------------------------- + + -- Create a packet and send it with a bit error. It should be discarded. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 15; + frame := RioFrameCreate(ackId=>"01011", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frame.payload(0) := frame.payload(0) xor x"00000010"; + frameExpected <= '1'; + frameRead <= frame; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Receive a packet-not-accepted indicating error in control-symbol crc. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_NOT_ACCEPTED, "00000", "00100", + STYPE1_NOP, "000")); + + -- Dont expect any frame anymore. + frameExpected <= '0'; + + -- Make the receiver go back to normal operation by sending a link-request. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_LINK_REQUEST, "100")); + + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01011", "00101", + STYPE1_NOP, "000")); + + -- Send a new frame without error. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 16; + frame := RioFrameCreate(ackId=>"01011", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameExpected <= '1'; + frameRead <= frame; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + SendSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00000", "11111", + STYPE1_END_OF_PACKET, "000")); + wait until frameReceived = '1'; + frameExpected <= '0'; + + -- Receive acknowledge for the transmitted frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01011", "11111", + STYPE1_NOP, "000")); + + -- REMARK: Complete with some more error situations: invalid ackId, too + -- short packet, too long packet, etc... + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioSerial-TC4"); + PrintS("Description: Test port transmission."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send an outbound frame."); + PrintS("Result: The frame should be read from the frame buffer and "); + PrintS(" received as symbols."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step1"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 3; + frame := RioFrameCreate(ackId=>"00000", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(0) <= '1'; + frameWrite(0) <= frame; + + -- Make sure the transmitter fills in the correct ackId and dont use the + -- one in the input packet. + frameWrite(0).payload(0)(31 downto 27) <= "UUUUU"; + + -- Receive an idle symbol left in the FIFO before the start of the frame was + -- generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive the start of the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Receive the data symbols of the frame. + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Wait for the frame to complete. + wait until frameComplete = '1'; + frameValid(0) <= '0'; + + -- Receive the end of the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send acknowledge that the frame was received. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00000", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send an outbound packet with maximum length."); + PrintS("Result: The packet should be fragmented and received in symbols."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step2"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 133; + frame := RioFrameCreate(ackId=>"00001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(1) <= '1'; + frameWrite(1) <= frame; + + -- Receive an idle symbol left in the FIFO before the start of the frame was + -- generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive the start of the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Receive the data symbols of the frame. + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Wait for the frame to complete. + wait until frameComplete = '1'; + frameValid(1) <= '0'; + + -- Receive the end of the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send acknowledge that the frame was received. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00001", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send a packet and confirm it with packet-retry."); + PrintS("Result: A restart-from-retry should be transmitted and the packet"); + PrintS(" should be retransmitted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step3"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 4; + frame := RioFrameCreate(ackId=>"00010", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(2) <= '1'; + frameWrite(2) <= frame; + + -- Receive an idle symbol left in the FIFO before the start of the frame was + -- generated. + ReceiveSymbol(SYMBOL_IDLE); + + -- Receive the start of the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Receive the data symbols of the frame. + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Receive the end of the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send packet-retry that the frame should be retransmitted. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_RETRY, "00010", "11111", + STYPE1_NOP, "000")); + + -- Receive the acknowledgement for the retransmission. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_RESTART_FROM_RETRY, "000")); + + -- Receive the start of the retransmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Receive the data symbols of the retransmitted frame. + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Wait for the frame to complete. + wait until frameComplete = '1' and clk'event and clk = '1'; + frameValid(2) <= '0'; + + -- Receive the end of the retransmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send acknowledge that the frame was received. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00010", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send a packet and confirm it with packet-not-accepted. "); + PrintS("Result: A link-request should be transmitted and the packet should"); + PrintS(" be retransmitted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step4"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 5; + frame := RioFrameCreate(ackId=>"00011", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(3) <= '1'; + frameWrite(3) <= frame; + + -- Receive the start of the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Receive the data symbols of the frame. + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Receive the end of the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send packet-retry that the frame should be retransmitted. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_NOT_ACCEPTED, "00000", "11111", + STYPE1_NOP, "000")); + + -- Receive the acknowledgement for the retransmission. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "00011", "11111", + STYPE1_NOP, "000")); + + -- Receive the start of the retransmitted frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + + -- Receive the data symbols of the retransmitted frame. + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Wait for the frame to complete. + wait until frameComplete = '1'; + frameValid(3) <= '0'; + + -- Receive the end of the retransmitted frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send acknowledge that the frame was received. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00011", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Let a packet timeout expire. Then answer with link-response."); + PrintS("Result: A link-request should be transmitted and the packet should"); + PrintS(" be retransmitted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step5"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 5; + frame := RioFrameCreate(ackId=>"00100", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(4) <= '1'; + frameWrite(4) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Wait a while to let the timer expire and receive the link-request. + for i in 0 to 2048 loop + wait until clk'event and clk = '1'; + end loop; + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Send a link-response to make the transmitter to back to normal mode. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "00100", "11111", + STYPE1_NOP, "000")); + + -- Receive the retransmitted frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + -- Wait for the frame to complete. + wait until frameComplete = '1'; + frameValid(4) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send acknowledge that the frame was received. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00100", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 6:"); + PrintS("Action: Let a packet timeout expire. Then answer with link-response"); + Prints(" that indicates that the packet was received."); + PrintS("Result: A link-request should be transmitted and the packet should"); + PrintS(" not be retransmitted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step6"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 6; + frame := RioFrameCreate(ackId=>"00101", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(5) <= '1'; + frameWrite(5) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(5) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Wait a while to let the timer expire and receive the link-request. + for i in 0 to 2048 loop + wait until clk'event and clk = '1'; + end loop; + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Send a link-response that indicates that the frame was received to make + -- the transmitter to back to normal mode. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "00110", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 7:"); + PrintS("Action: Let a packet timeout expire. No more replies."); + PrintS("Result: Three link-requests should be transmitted. When the third"); + PrintS(" times out the link will be restarted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step7"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 7; + frame := RioFrameCreate(ackId=>"00110", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(6) <= '1'; + frameWrite(6) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Wait a while to let the timer expire and receive the link-request. + for i in 0 to 2048 loop + wait until clk'event and clk = '1'; + end loop; + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Wait a while to let the timer expire and receive the link-request. + for i in 0 to 2048 loop + wait until clk'event and clk = '1'; + end loop; + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Wait a while to let the timer expire and receive the link-request. + for i in 0 to 2048 loop + wait until clk'event and clk = '1'; + end loop; + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Wait a while to let the timer expire and receive the link-request. + for i in 0 to 2048 loop + wait until clk'event and clk = '1'; + end loop; + + -- Reinitialize the transmitter. + for i in 0 to 255 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_NOP, "000")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00110", "11111", + STYPE1_NOP, "000")); + for j in 0 to 14 loop + for i in 0 to 15 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_NOP, "000")); + end loop; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(6) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00110", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 8:"); + PrintS("Action: Let a packet timeout expire. Then answer with totally "); + PrintS(" unexpected ackId."); + PrintS("Result: A link request should be transmitted and the link should "); + PrintS(" be restarted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step8"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 8; + frame := RioFrameCreate(ackId=>"00111", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(7) <= '1'; + frameWrite(7) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Wait a while to let the timer expire and receive the link-request. + for i in 0 to 2048 loop + wait until clk'event and clk = '1'; + end loop; + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Send a link-response with unexpected ackId. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "10000", "11111", + STYPE1_NOP, "000")); + + -- Reinitialize the transmitter. + for i in 0 to 255 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_NOP, "000")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "00111", "11111", + STYPE1_NOP, "000")); + for j in 0 to 14 loop + for i in 0 to 15 loop + ReceiveSymbol(SYMBOL_IDLE); + end loop; + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_NOP, "000")); + end loop; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(7) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "00111", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 9:"); + PrintS("Action: Send status with unexpected ackId in normal operation."); + PrintS("Result: The transmitter should disregard the error."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step9"); + --------------------------------------------------------------------------- + + -- Send a status with unexpected ackId. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "10000", "11111", + STYPE1_NOP, "000")); + + -- Receive no change. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_IDLE); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 10:"); + PrintS("Action: Send packet-retry with unexpected ackId in normal operation."); + PrintS("Result: The transmitter should enter output-error-stopped."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step10"); + --------------------------------------------------------------------------- + + -- Send a packet-retry with unexpected ackId. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_RETRY, "10000", "11111", + STYPE1_NOP, "000")); + + -- Receive link-request. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Send a link-response with unexpected ackId. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01000", "11111", + STYPE1_NOP, "000")); + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 10; + frame := RioFrameCreate(ackId=>"01000", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(8) <= '1'; + frameWrite(8) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(8) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01000", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 11:"); + PrintS("Action: Send packet-accepted with unexpected ackId in normal "); + PrintS(" operation."); + PrintS("Result: The transmitter should enter output-error-stopped."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step11"); + --------------------------------------------------------------------------- + + -- Send a packet-accepted with unexpected ackId. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "10000", "11111", + STYPE1_NOP, "000")); + + -- Receive link-request. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Send a link-response with unexpected ackId. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01001", "11111", + STYPE1_NOP, "000")); + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 11; + frame := RioFrameCreate(ackId=>"01001", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(9) <= '1'; + frameWrite(9) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(9) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01001", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 12:"); + PrintS("Action: Send a packet and then accept it with unexpected ackId."); + PrintS("Result: The transmitter should enter output-error-stopped."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step12"); + --------------------------------------------------------------------------- + + -- Create the frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 12; + frame := RioFrameCreate(ackId=>"01010", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(10) <= '1'; + frameWrite(10) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frame.length-1 loop + ReceiveSymbol(SYMBOL_DATA, frame.payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(10) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + -- Send unexpected ackId in packet-accepted. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "10000", "11111", + STYPE1_NOP, "000")); + + -- Receive link-request. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_LINK_REQUEST, "100")); + + -- Send a link-response with expected ackId. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_LINK_RESPONSE, "01011", "11111", + STYPE1_NOP, "000")); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 13:"); + PrintS("Action: Set two valid packets."); + PrintS("Result: The two packet should be sent without waiting for "); + PrintS(" packet-accepted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step13"); + --------------------------------------------------------------------------- + + -- Create the first frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 13; + frame := RioFrameCreate(ackId=>"01011", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(11) <= '1'; + frameWrite(11) <= frame; + + -- Create the second frame. + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := 14; + frame := RioFrameCreate(ackId=>"01100", vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(12) <= '1'; + frameWrite(12) <= frame; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frameWrite(11).length-1 loop + ReceiveSymbol(SYMBOL_DATA, frameWrite(11).payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(11) <= '0'; + + -- Receive the frame. + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frameWrite(12).length-1 loop + ReceiveSymbol(SYMBOL_DATA, frameWrite(12).payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(12) <= '0'; + + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_END_OF_PACKET, "000")); + + + -- Send packet-accepted for both packets. + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01011", "11111", + STYPE1_NOP, "000")); + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01100", "11111", + STYPE1_NOP, "000")); + + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_IDLE); + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 14:"); + PrintS("Action: Set maximum number of valid packets."); + PrintS("Result: Maximum 31 packets should be sent without waiting for "); + PrintS(" packet-accepted."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-Step14"); + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + -- Create the frames. + --------------------------------------------------------------------------- + + for j in 0 to 47 loop + CreateRandomPayload(payload.data, seed1, seed2); + payload.length := j+13; + frame := RioFrameCreate(ackId=>std_logic_vector(to_unsigned((j+13) mod 32, 5)), vc=>'0', crf=>'0', prio=>"00", + tt=>"01", ftype=>"0000", + sourceId=>x"0000", destId=>x"0000", + payload=>payload); + frameValid(j+13) <= '1'; + frameWrite(j+13) <= frame; + end loop; + + --------------------------------------------------------------------------- + -- Receive the frames. + --------------------------------------------------------------------------- + + ReceiveSymbol(SYMBOL_IDLE); + + for j in 0 to 30 loop + ReceiveSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_STATUS, "01100", "11111", + STYPE1_START_OF_PACKET, "000")); + for i in 0 to frameWrite(j+13).length-1 loop + ReceiveSymbol(SYMBOL_DATA, frameWrite(j+13).payload(i)); + end loop; + + wait until frameComplete = '1'; + frameValid(j+13) <= '0'; + end loop; + + ReceiveSymbol(SYMBOL_IDLE); + ReceiveSymbol(SYMBOL_IDLE); + + + SendSymbol(SYMBOL_CONTROL, + RioControlSymbolCreate(STYPE0_PACKET_ACCEPTED, "01101", "11111", + STYPE1_NOP, "000")); + + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step X:"); + PrintS("Action: Start sending an outbound packet and while in transmission, "); + PrintS(" start and complete an inbound packet."); + PrintS("Result: The ack for the inbound packet should be inserted into the"); + PrintS(" outbound packet."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-StepX"); + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step X:"); + PrintS("Action: Send a packet but not all content is available yet."); + PrintS("Result: Idle symbols should be inserted into the packet."); + --------------------------------------------------------------------------- + PrintR("TG_RioSerial-TC4-StepX"); + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + -- REMARK: Send long frames with a CRC in the middle... + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + -- Test completed. + --------------------------------------------------------------------------- + + TestEnd; + end process; + + + ----------------------------------------------------------------------------- + -- Instantiate the uart. + ----------------------------------------------------------------------------- + + TestPort: TestSwitchPort + port map( + clk=>clk, areset_n=>areset_n, + frameValid_i=>frameValid, frameWrite_i=>frameWrite, frameComplete_o=>frameComplete, + frameExpected_i=>frameExpected, frameRead_i=>frameRead, frameReceived_o=>frameReceived, + readFrameEmpty_o=>readFrameEmpty, readFrame_i=>readFrame, + readFrameRestart_i=>readFrameRestart, readFrameAborted_o=>readFrameAborted, + readWindowEmpty_o=>readWindowEmpty, + readWindowReset_i=>readWindowReset, readWindowNext_i=>readWindowNext, + readContentEmpty_o=>readContentEmpty, readContent_i=>readContent, + readContentEnd_o=>readContentEnd, readContentData_o=>readContentData, + writeFrameFull_o=>writeFrameFull, writeFrame_i=>writeFrame, writeFrameAbort_i=>writeFrameAbort, + writeContent_i=>writeContent, writeContentData_i=>writeContentData); + + TestPhy: RioSerial + generic map( + TIMEOUT_WIDTH=>11) + port map( + clk=>clk, areset_n=>areset_n, + portLinkTimeout_i=>portLinkTimeout, + linkInitialized_o=>linkInitialized, + inputPortEnable_i=>inputPortEnable, + outputPortEnable_i=>outputPortEnable, + localAckIdWrite_i=>localAckIdWrite, + clrOutstandingAckId_i=>clrOutstandingAckId, + inboundAckId_i=>inboundAckIdWrite, + outstandingAckId_i=>outstandingAckIdWrite, + outboundAckId_i=>outboundAckIdWrite, + inboundAckId_o=>inboundAckIdRead, + outstandingAckId_o=>outstandingAckIdRead, + outboundAckId_o=>outboundAckIdRead, + readFrameEmpty_i=>readFrameEmpty, readFrame_o=>readFrame, readFrameRestart_o=>readFrameRestart, + readFrameAborted_i=>readFrameAborted, + readWindowEmpty_i=>readWindowEmpty, + readWindowReset_o=>readWindowReset, readWindowNext_o=>readWindowNext, + readContentEmpty_i=>readContentEmpty, + readContent_o=>readContent, readContentEnd_i=>readContentEnd, readContentData_i=>readContentData, + writeFrameFull_i=>writeFrameFull, writeFrame_o=>writeFrame, writeFrameAbort_o=>writeFrameAbort, + writeContent_o=>writeContent, writeContentData_o=>writeContentData, + portInitialized_i=>portInitialized, + outboundSymbolEmpty_o=>outboundSymbolEmpty, outboundSymbolRead_i=>outboundSymbolRead, + outboundSymbol_o=>outboundSymbol, + inboundSymbolFull_o=>inboundSymbolFull, inboundSymbolWrite_i=>inboundSymbolWrite, + inboundSymbol_i=>inboundSymbol); + +end architecture; + + + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- +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 TestSwitchPort is + port( + clk : in std_logic; + areset_n : in std_logic; + + frameValid_i : in std_logic_vector(0 to 63); + frameWrite_i : in RioFrameArray(0 to 63); + 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; + + readWindowEmpty_o : out std_logic; + readWindowReset_i : in std_logic; + readWindowNext_i : in 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 TestSwitchPortImpl of TestSwitchPort is +begin + + ----------------------------------------------------------------------------- + -- + ----------------------------------------------------------------------------- + FrameSender: process + variable frameIndex : natural range 0 to 70; + variable backIndex, frontIndex : natural range 0 to 63; + begin + readFrameEmpty_o <= '1'; + readFrameAborted_o <= '0'; + readWindowEmpty_o <= '1'; + readContentEmpty_o <= '1'; + readContentEnd_o <= '0'; + readContentData_o <= (others=>'U'); + frameComplete_o <= '0'; + backIndex := 0; + frontIndex := 0; + wait until areset_n = '1'; + + loop + wait until clk'event and clk = '1'; + + if (readFrame_i = '1') then + assert (frontIndex - backIndex) >= 0 report "Unexpected readFrame." severity error; + if(backIndex < 63) then + backIndex := backIndex + 1; + else + backIndex := 0; + end if; + end if; + + if (readWindowReset_i = '1') then + frameIndex := 0; + frontIndex := backIndex; + readContentEnd_o <= '0'; + readContentData_o <= (others=>'U'); + end if; + + if (readWindowNext_i = '1') then + assert frameIndex = frameWrite_i(frontIndex).length report "Did not read all frame content." severity error; + frameComplete_o <= '1'; + readContentEnd_o <= '0'; + readContentData_o <= (others=>'U'); + frameIndex := 0; + if(frontIndex < 63) then + frontIndex := frontIndex + 1; + else + frontIndex := 0; + end if; + else + frameComplete_o <= '0'; + end if; + + if (readFrameRestart_i = '1') then + frameIndex := 0; + readContentEnd_o <= '0'; + readContentData_o <= (others=>'U'); + end if; + + if (readContent_i = '1') then + assert frameValid_i(frontIndex) = '1' report "Unexpected content read." severity error; + if (frameIndex /= frameWrite_i(frontIndex).length) then + readContentEnd_o <= '0'; + readContentData_o <= frameWrite_i(frontIndex).payload(frameIndex); + frameIndex := frameIndex + 1; + else + readContentEnd_o <= '1'; + readContentData_o <= (others=>'U'); + end if; + end if; + + if(frameValid_i(frontIndex) = '1') then + readFrameEmpty_o <= '0'; + readWindowEmpty_o <= '0'; + readContentEmpty_o <= '0'; + else + readFrameEmpty_o <= '1'; + readWindowEmpty_o <= '1'; + readContentEmpty_o <= '1'; + end if; + + end loop; + end process; + + ----------------------------------------------------------------------------- + -- + ----------------------------------------------------------------------------- + FrameReader: process + type StateType is (STATE_IDLE, STATE_READ, STATE_UPDATE); + 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 + state := STATE_READ; + frameIndex := 0; + writeFrameFull_o <= '0'; + end if; + assert writeFrame_i = '0' report "Unexpected frame received." severity error; + --assert writeFrameAbort_i = '0' report "Unexpected frame aborted received." severity error; + assert writeContent_i = '0' report "Unexpected content received." severity error; + + when STATE_READ => + if (writeFrame_i = '1') then + state := STATE_UPDATE; + frameReceived_o <= '1'; + writeFrameFull_o <= '1'; + assert frameIndex = frameRead_i.length report "Did not finish the expected frame." severity error; + end if; + if (writeFrameAbort_i = '1') then + frameIndex := 0; + end if; + if (writeContent_i = '1') then + assert writeContentData_i = frameRead_i.payload(frameIndex) + report "Unexpected frame content received." severity error; + frameIndex := frameIndex + 1; + end if; + if (frameExpected_i = '0') then + state := STATE_IDLE; + end if; + + when STATE_UPDATE => + if (frameExpected_i = '0') then + state := STATE_IDLE; + end if; + + end case; + end loop; + end process; + +end architecture;
1.0.1/bench/vhdl/TestRioSerial.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/bench/vhdl/TestRioPacketBuffer.vhd =================================================================== --- 1.0.1/bench/vhdl/TestRioPacketBuffer.vhd (nonexistent) +++ 1.0.1/bench/vhdl/TestRioPacketBuffer.vhd (revision 29) @@ -0,0 +1,2247 @@ +------------------------------------------------------------------------------- +-- +-- 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 RioPacketBufferWindow +-- 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 +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- TestRioPacketBuffer. +------------------------------------------------------------------------------- + +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 TestRioPacketBuffer. +------------------------------------------------------------------------------- +entity TestRioPacketBuffer is +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for TestRioPacketBuffer. +------------------------------------------------------------------------------- +architecture TestRioPacketBufferImpl of TestRioPacketBuffer is + + component RioPacketBufferWindow is + port( + clk : in std_logic; + areset_n : in std_logic; + + inboundWriteFrameFull_o : out std_logic; + inboundWriteFrame_i : in std_logic; + inboundWriteFrameAbort_i : in std_logic; + inboundWriteContent_i : in std_logic; + inboundWriteContentData_i : in std_logic_vector(31 downto 0); + inboundReadFrameEmpty_o : out std_logic; + inboundReadFrame_i : in std_logic; + inboundReadFrameRestart_i : in std_logic; + inboundReadFrameAborted_o : out std_logic; + inboundReadContentEmpty_o : out std_logic; + inboundReadContent_i : in std_logic; + inboundReadContentEnd_o : out std_logic; + inboundReadContentData_o : out std_logic_vector(31 downto 0); + + outboundWriteFrameFull_o : out std_logic; + outboundWriteFrame_i : in std_logic; + outboundWriteFrameAbort_i : in std_logic; + outboundWriteContent_i : in std_logic; + outboundWriteContentData_i : in std_logic_vector(31 downto 0); + outboundReadFrameEmpty_o : out std_logic; + outboundReadFrame_i : in std_logic; + outboundReadFrameRestart_i : in std_logic; + outboundReadFrameAborted_o : out std_logic; + outboundReadWindowEmpty_o : out std_logic; + outboundReadWindowReset_i : in std_logic; + outboundReadWindowNext_i : in std_logic; + outboundReadContentEmpty_o : out std_logic; + outboundReadContent_i : in std_logic; + outboundReadContentEnd_o : out std_logic; + outboundReadContentData_o : out std_logic_vector(31 downto 0)); + end component; + + signal clk : std_logic; + signal areset_n : std_logic; + + signal inboundWriteFrameFull : std_logic; + signal inboundWriteFrame : std_logic; + signal inboundWriteFrameAbort : std_logic; + signal inboundWriteContent : std_logic; + signal inboundWriteContentData : std_logic_vector(31 downto 0); + signal inboundReadFrameEmpty : std_logic; + signal inboundReadFrame : std_logic; + signal inboundReadFrameRestart : std_logic; + signal inboundReadFrameAborted : std_logic; + signal inboundReadContentEmpty : std_logic; + signal inboundReadContent : std_logic; + signal inboundReadContentEnd : std_logic; + signal inboundReadContentData : std_logic_vector(31 downto 0); + + signal outboundWriteFrameFull : std_logic; + signal outboundWriteFrame : std_logic; + signal outboundWriteFrameAbort : std_logic; + signal outboundWriteContent : std_logic; + signal outboundWriteContentData : std_logic_vector(31 downto 0); + signal outboundReadFrameEmpty : std_logic; + signal outboundReadFrame : std_logic; + signal outboundReadFrameRestart : std_logic; + signal outboundReadFrameAborted : std_logic; + signal outboundReadWindowEmpty : std_logic; + signal outboundReadWindowReset : std_logic; + signal outboundReadWindowNext : std_logic; + signal outboundReadContentEmpty : std_logic; + signal outboundReadContent : std_logic; + signal outboundReadContentEnd : std_logic; + signal outboundReadContentData : 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; + + + ----------------------------------------------------------------------------- + -- Test case driver. + ----------------------------------------------------------------------------- + TestDriver: process + --------------------------------------------------------------------------- + -- Inbound procedures. + --------------------------------------------------------------------------- + + procedure SetInboundWriteContent( + constant content : in std_logic_vector(31 downto 0)) is + begin + assert inboundWriteFrameFull = '0' + report "Inbound frame cannot be accepted." severity error; + + inboundWriteContent <= '1'; + inboundWriteContentData <= content; + wait until clk'event and clk = '1'; + wait for 1 ns; + inboundWriteContent <= '0'; + inboundWriteContentData <= (others=>'U'); + end procedure; + + procedure SetInboundWriteFrame is + begin + inboundWriteFrame <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + inboundWriteFrame <= '0'; + end procedure; + + procedure SetInboundWriteFrameAbort is + begin + inboundWriteFrameAbort <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + inboundWriteFrameAbort <= '0'; + end procedure; + + procedure SetInboundReadContent( + constant content : in std_logic_vector(31 downto 0)) is + begin + inboundReadContent <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + assert (inboundReadContentData = content) + report "Unexpected content read." severity error; + assert (inboundReadContentEnd = '0') + report "Unexpected content end." severity error; + + inboundReadContent <= '0'; + end procedure; + + procedure SetInboundReadContentEnd is + begin + inboundReadContent <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + assert (inboundReadContentEnd = '1') + report "Unexpected content end." severity error; + + inboundReadContent <= '0'; + end procedure; + + procedure SetInboundReadFrame is + begin + assert inboundReadFrameEmpty = '0' + report "No pending inbound frame to be read." severity error; + + inboundReadFrame <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + inboundReadFrame <= '0'; + end procedure; + + procedure SetInboundReadFrameRestart is + begin + inboundReadFrameRestart <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + inboundReadFrameRestart <= '0'; + end procedure; + + --------------------------------------------------------------------------- + -- Outbound procedures. + --------------------------------------------------------------------------- + + procedure SetOutboundWriteContent( + constant content : in std_logic_vector(31 downto 0)) is + begin + assert outboundWriteFrameFull = '0' + report "Outbound frame cannot be accepted." severity error; + + outboundWriteContent <= '1'; + outboundWriteContentData <= content; + wait until clk'event and clk = '1'; + wait for 1 ns; + outboundWriteContent <= '0'; + outboundWriteContentData <= (others=>'U'); + end procedure; + + procedure SetOutboundWriteFrame is + begin + assert outboundWriteFrameFull = '0' + report "Outbound frame cannot be accepted." severity error; + + outboundWriteFrame <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + outboundWriteFrame <= '0'; + end procedure; + + procedure SetOutboundWriteFrameAbort is + begin + outboundWriteFrameAbort <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + outboundWriteFrameAbort <= '0'; + end procedure; + + procedure SetOutboundReadContent( + constant content : in std_logic_vector(31 downto 0)) is + begin + outboundReadContent <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + assert (outboundReadContentData = content) + report "Unexpected content read." severity error; + assert (outboundReadContentEnd = '0') + report "Unexpected content end." severity error; + + outboundReadContent <= '0'; + end procedure; + + procedure SetOutboundReadContentEnd is + begin + outboundReadContent <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + assert (outboundReadContentEnd = '1') + report "Unexpected content end." severity error; + + outboundReadContent <= '0'; + end procedure; + + procedure SetOutboundReadFrame is + begin + assert outboundReadFrameEmpty = '0' + report "No pending outbound frame to be read." severity error; + + outboundReadFrame <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + outboundReadFrame <= '0'; + end procedure; + + procedure SetOutboundReadFrameRestart is + begin + outboundReadFrameRestart <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + outboundReadFrameRestart <= '0'; + end procedure; + + procedure SetOutboundReadWindowReset is + begin + outboundReadWindowReset <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + outboundReadWindowReset <= '0'; + end procedure; + + procedure SetOutboundReadWindowNext is + begin + assert outboundReadWindowEmpty = '0' + report "No pending outbound window frame to be read." severity error; + + outboundReadWindowNext <= '1'; + wait until clk'event and clk = '1'; + wait for 1 ns; + + outboundReadWindowNext <= '0'; + end procedure; + + begin + inboundWriteFrame <= '0'; + inboundWriteFrameAbort <= '0'; + inboundWriteContent <= '0'; + inboundWriteContentData <= (others=>'U'); + inboundReadFrame <= '0'; + inboundReadFrameRestart <= '0'; + inboundReadContent <= '0'; + + outboundWriteFrame <= '0'; + outboundWriteFrameAbort <= '0'; + outboundWriteContent <= '0'; + outboundWriteContentData <= (others=>'U'); + outboundReadFrame <= '0'; + outboundReadFrameRestart <= '0'; + outboundReadWindowReset <= '0'; + outboundReadWindowNext <= '0'; + outboundReadContent <= '0'; + + areset_n <= '0'; + 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_RioPacketBuffer"); + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPacketBuffer-TC1"); + PrintS("Description: Test normal operation without using the window. Only"); + PrintS(" full frames are tested."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Complete a small frame and read it."); + PrintS("Result: The read frame should be equal to the one written."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC1-Step1"); + --------------------------------------------------------------------------- + -- REMARK: Update testcases for inbound and outbound... + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + + SetInboundWriteContent(x"deadbeef"); + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + + SetInboundWriteFrame; + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + SetInboundReadContent(x"deadbeef"); + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + SetInboundReadContentEnd; + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + SetInboundReadFrame; + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Write a rio maximum size frame and read it."); + PrintS("Result: The read frame should be equal to the one written."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC1-Step2"); + --------------------------------------------------------------------------- + + for i in 0 to 68 loop + SetInboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + end loop; + + SetInboundWriteFrame; + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + for i in 0 to 68 loop + SetInboundReadContent(std_logic_vector(to_unsigned(i, 32))); + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + end loop; + + SetInboundReadContentEnd; + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + SetInboundReadFrame; + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Fill the maximum number of small frames without filling "); + PrintS(" the memory."); + PrintS("Result: The frame buffer should accept 63 frames."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC1-Step3"); + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + -- Write maximum number of frames. + --------------------------------------------------------------------------- + + for i in 0 to 2 loop + SetInboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + end loop; + + for j in 1 to 62 loop + SetInboundWriteFrame; + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + for i in 0 to 2 loop + SetInboundWriteContent(std_logic_vector(to_unsigned(j+i, 32))); + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + end loop; + end loop; + + SetInboundWriteFrame; + assert (inboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + --------------------------------------------------------------------------- + -- Read the frames written in the above steps. + --------------------------------------------------------------------------- + + for i in 0 to 2 loop + SetInboundReadContent(std_logic_vector(to_unsigned(i, 32))); + + assert (inboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + end loop; + + SetInboundReadContentEnd; + assert (inboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + for j in 1 to 62 loop + SetInboundReadFrame; + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + for i in 0 to 2 loop + SetInboundReadContent(std_logic_vector(to_unsigned(j+i, 32))); + + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + end loop; + + SetInboundReadContentEnd; + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + end loop; + + SetInboundReadFrame; + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Fill the memory to its limit."); + PrintS("Result: The frame buffer should accept 255-69 words."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC1-Step4"); + --------------------------------------------------------------------------- + + for i in 0 to 186 loop + SetInboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + end loop; + + SetInboundWriteFrame; + assert (inboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + --------------------------------------------------------------------------- + + for i in 0 to 186 loop + SetInboundReadContent(std_logic_vector(to_unsigned(i, 32))); + + assert (inboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + end loop; + + SetInboundReadContentEnd; + assert (inboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + + SetInboundReadFrame; + assert (inboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (inboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPacketBuffer-TC2"); + PrintS("Description: Test operation when using the window."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Add one frame and update the window."); + PrintS("Result: The window empty flag and the read frame empty flag should"); + PrintS(" be updated and it should be possible to read the frame again."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC2-Step1"); + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Add two frames and test the window accesses."); + PrintS("Result: ."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC2-Step2"); + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + -- Write two frames. + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(2+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Read the frames using the window mechanism. + --------------------------------------------------------------------------- + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(2+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Reset the window and read the frames again. + --------------------------------------------------------------------------- + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(2+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Remove one frame and access the remaining frame. + --------------------------------------------------------------------------- + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(2+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Remove the remaining frame. + --------------------------------------------------------------------------- + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Add maximum number of frames and test the window accesses."); + PrintS("Result: The buffer should be full and not accept more frames."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC2-Step3"); + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Write 3*63 frames => maximum number of frames. + --------------------------------------------------------------------------- + + for i in 0 to 2 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + for j in 1 to 62 loop + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(j+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Read the whole window until it is empty. + --------------------------------------------------------------------------- + + for j in 0 to 61 loop + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(j+i, 32))); + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(62+i, 32))); + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Reset the window and remove all frames. + --------------------------------------------------------------------------- + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for j in 0 to 61 loop + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 2 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(62+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Add maximum number of words and test the window accesses."); + PrintS("Result: The content memory should be full."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC2-Step4"); + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Write 6*31+69=255 words and 7 frames => full content. + --------------------------------------------------------------------------- + + for i in 0 to 30 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + for j in 1 to 5 loop + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 30 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(j+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 68 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(1024+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Read the whole window until it is empty. + --------------------------------------------------------------------------- + + for j in 0 to 5 loop + for i in 0 to 30 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(j+i, 32))); + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + for i in 0 to 68 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(1024+i, 32))); + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Reset the window and remove all frames. + --------------------------------------------------------------------------- + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for j in 0 to 1 loop + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + for j in 2 to 5 loop + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 68 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(1024+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Add maximum number of words -1 and test the window accesses."); + PrintS("Result: The content memory should not accept more frames."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC2-Step5"); + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Write 11*17=187 (one full frame will not fit). + --------------------------------------------------------------------------- + + for i in 0 to 16 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + for j in 1 to 10 loop + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 16 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(j+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- Reset the window and remove all frames. + --------------------------------------------------------------------------- + + SetOutboundReadWindowReset; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '1') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for j in 1 to 9 loop + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 6:"); + PrintS("Action: Add two frames and start reading the second, then remove"); + PrintS(" the first."); + PrintS("Result: The readContentEnd flag should not be changed when frames"); + PrintS(" are removed."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC2-Step6"); + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + + for i in 0 to 3 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(i+1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + + for i in 0 to 3 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(2, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(3, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(4, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPacketBuffer"); + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPacketBuffer-TC3"); + PrintS("Description: Test operation when restarting and aborting frames."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Write one frame and abort it."); + PrintS("Result: The aborted frame should be discarded."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC3-Step1"); + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrameAbort; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Write one full frame then one more that is aborted."); + PrintS("Result: The first frame should remain and the aborted should be "); + PrintS(" discarded."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC3-Step2"); + --------------------------------------------------------------------------- + + for i in 0 to 3 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(2+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrameAbort; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(3+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(3+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Write one full frame then read one that is restarted."); + PrintS("Result: The content of the first frame should be read twice. "); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC3-Step3"); + --------------------------------------------------------------------------- + + for i in 0 to 3 loop + SetOutboundWriteContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrameRestart; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + for i in 0 to 3 loop + SetOutboundReadContent(std_logic_vector(to_unsigned(1+i, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + end loop; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPacketBuffer"); + PrintS("-----------------------------------------------------------------"); + PrintS("TG_RioPacketBuffer-TC4"); + PrintS("Description: Test operation when partial frames are read."); + PrintS("Requirement: XXXXX"); + PrintS("-----------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Write a one word frame and read it before it is completed."); + PrintS("Result: Empty signals should reflect the status of the frame."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC4-Step1"); + --------------------------------------------------------------------------- + + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + + SetOutboundWriteContent(std_logic_vector(to_unsigned(1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Write content to a frame and read it, then abort the frame."); + PrintS("Result: The reader should be notified about the aborted frame. The"); + PrintS(" notification should be reset when the frame has been "); + PrintS(" restarted."); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC4-Step2"); + --------------------------------------------------------------------------- + + SetOutboundWriteContent(std_logic_vector(to_unsigned(1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundWriteFrameAbort; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '1') + report "Unexpected readFrameAborted." severity error; + + SetOutboundWriteContent(std_logic_vector(to_unsigned(2, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '1') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadFrameRestart; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(2, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + --------------------------------------------------------------------------- + PrintS("-----------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Write one complete frame then abort a second."); + PrintS("Result: The reader should not notice the aborted frame. "); + --------------------------------------------------------------------------- + PrintR("TG_RioPacketBuffer-TC4-Step3"); + --------------------------------------------------------------------------- + + SetOutboundWriteContent(std_logic_vector(to_unsigned(1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadContent(std_logic_vector(to_unsigned(1, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundWriteFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundWriteContent(std_logic_vector(to_unsigned(2, 32))); + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundWriteFrameAbort; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadContentEnd; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '0') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '0') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadWindowNext; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '0') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + SetOutboundReadFrame; + assert (outboundWriteFrameFull = '0') + report "Unexpected writeFrameFull." severity error; + assert (outboundReadFrameEmpty = '1') + report "Unexpected readFrameEmpty." severity error; + assert (outboundReadWindowEmpty = '1') + report "Unexpected readWindowEmpty." severity error; + assert (outboundReadContentEmpty = '1') + report "Unexpected readContentEmpty." severity error; + assert (outboundReadFrameAborted = '0') + report "Unexpected readFrameAborted." severity error; + + --------------------------------------------------------------------------- + -- Test completed. + --------------------------------------------------------------------------- + + TestEnd; + end process; + + ----------------------------------------------------------------------------- + -- Instantiate the testobject. + ----------------------------------------------------------------------------- + + TestPacketBuffer: RioPacketBufferWindow + port map( + clk=>clk, areset_n=>areset_n, + inboundWriteFrameFull_o=>inboundWriteFrameFull, + inboundWriteFrame_i=>inboundWriteFrame, + inboundWriteFrameAbort_i=>inboundWriteFrameAbort, + inboundWriteContent_i=>inboundWriteContent, + inboundWriteContentData_i=>inboundWriteContentData, + inboundReadFrameEmpty_o=>inboundReadFrameEmpty, + inboundReadFrame_i=>inboundReadFrame, + inboundReadFrameRestart_i=>inboundReadFrameRestart, + inboundReadFrameAborted_o=>inboundReadFrameAborted, + inboundReadContentEmpty_o=>inboundReadContentEmpty, + inboundReadContent_i=>inboundReadContent, + inboundReadContentEnd_o=>inboundReadContentEnd, + inboundReadContentData_o=>inboundReadContentData, + outboundWriteFrameFull_o=>outboundWriteFrameFull, + outboundWriteFrame_i=>outboundWriteFrame, + outboundWriteFrameAbort_i=>outboundWriteFrameAbort, + outboundWriteContent_i=>outboundWriteContent, + outboundWriteContentData_i=>outboundWriteContentData, + outboundReadFrameEmpty_o=>outboundReadFrameEmpty, + outboundReadFrame_i=>outboundReadFrame, + outboundReadFrameRestart_i=>outboundReadFrameRestart, + outboundReadFrameAborted_o=>outboundReadFrameAborted, + outboundReadWindowEmpty_o=>outboundReadWindowEmpty, + outboundReadWindowReset_i=>outboundReadWindowReset, + outboundReadWindowNext_i=>outboundReadWindowNext, + outboundReadContentEmpty_o=>outboundReadContentEmpty, + outboundReadContent_i=>outboundReadContent, + outboundReadContentEnd_o=>outboundReadContentEnd, + outboundReadContentData_o=>outboundReadContentData); + +end architecture;
1.0.1/bench/vhdl/TestRioPacketBuffer.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/rtl/vhdl/RioSwitch.vhd =================================================================== --- 1.0.1/rtl/vhdl/RioSwitch.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/RioSwitch.vhd (revision 29) @@ -0,0 +1,2473 @@ +------------------------------------------------------------------------------- +-- +-- 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); + 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; + 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), + 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; + 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_ERROR, + 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'; + elsif (clk'event and clk = '1') then + readContent_o <= '0'; + readFrame_o <= '0'; + + 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_ERROR; + end if; + else + -- End of frame. + -- The frame is too short to contain a valid frame. Discard it. + readFrame_o <= '1'; + masterState <= STATE_ERROR; + end if; + + when STATE_ERROR => + --------------------------------------------------------------------- + -- Wait one tick for the packet buffer to update its outputs. Then + -- start waiting for a new packet. + --------------------------------------------------------------------- + + masterState <= STATE_IDLE; + + 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 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 (lookupAck = '0') then + if (lookupStb_i = '1') then + lookupAck <= '1'; + end if; + 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) and activeCycle; + 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 + 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 := 0; + 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 ((activeCycle = '1') and (selectedSlave = i)) else '0'; + slaveStb_o(i) <= masterStb_i(selectedMaster) when ((activeCycle = '1') and (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; + +end architecture;
1.0.1/rtl/vhdl/RioSwitch.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/rtl/vhdl/RioCommon.vhd =================================================================== --- 1.0.1/rtl/vhdl/RioCommon.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/RioCommon.vhd (revision 29) @@ -0,0 +1,1138 @@ +------------------------------------------------------------------------------- +-- +-- 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; + + + +------------------------------------------------------------------------------- +-- RioFifo1 +-- Simple fifo which is one entry deep. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; + + +------------------------------------------------------------------------------- +-- Entity for RioFifo1. +------------------------------------------------------------------------------- +entity RioFifo1 is + generic( + WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + empty_o : out std_logic; + read_i : in std_logic; + data_o : out std_logic_vector(WIDTH-1 downto 0); + + full_o : out std_logic; + write_i : in std_logic; + data_i : in std_logic_vector(WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioFifo1. +------------------------------------------------------------------------------- +architecture RioFifo1Impl of RioFifo1 is + signal empty : std_logic; + signal full : std_logic; +begin + + empty_o <= empty; + full_o <= full; + + process(areset_n, clk) + begin + if (areset_n = '0') then + empty <= '1'; + full <= '0'; + data_o <= (others => '0'); + elsif (clk'event and clk = '1') then + if (empty = '1') then + if (write_i = '1') then + empty <= '0'; + full <= '1'; + data_o <= data_i; + end if; + else + if (read_i = '1') then + empty <= '1'; + full <= '0'; + end if; + end if; + end if; + end process; + +end architecture;
1.0.1/rtl/vhdl/RioCommon.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/rtl/vhdl/RioSerial.vhd =================================================================== --- 1.0.1/rtl/vhdl/RioSerial.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/RioSerial.vhd (revision 29) @@ -0,0 +1,2428 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- Containing the transmission channel independent parts of the LP-Serial +-- Physical Layer Specification (RapidIO 2.2, part 6). +-- +-- 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 +-- +------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- RioSerial +-- +-- clk - System clock. +-- areset_n - System reset. Asynchronous, active low. +-- +-- portLinkTimeout_i - The number of ticks to wait for a packet-accepted before +-- a timeout occurrs. +-- linkInitialized_o - Indicates if a link partner is answering with valid +-- status-control-symbols. +-- inputPortEnable_i - Activate the input port for non-maintenance packets. If +-- deasserted, only non-maintenance packets are allowed. +-- outputPortEnable_i - Activate the output port for non-maintenance packets. +-- If deasserted, only non-maintenance packets are allowed. +-- +-- This interface makes it possible to read and write ackId in both outbound +-- and inbound directions. All input signals are validated by localAckIdWrite. +-- localAckIdWrite_i - Indicate if a localAckId write operation is ongoing. +-- Usually this signal is high one tick. +-- clrOutstandingAckId_i - Clear outstanding ackId, i.e. reset the transmission +-- window. The signal is only read if localAckIdWrite_i is high. +-- inboundAckId_i - The value to set the inbound ackId (the ackId that the +-- next inbound packet should have) to. This signal is only read if localAckIdWrite +-- is high. +-- outstandingAckId_i - The value to set the outstanding ackId (the ackId +-- transmitted but not acknowledged) to. This signal is only read if localAckIdWrite +-- is high. +-- outboundAckId_i - The value to set the outbound ackId (the ackId that the +-- next outbound packet will have) to. This signal is only read if localAckIdWrite +-- is high. +-- inboundAckId_o - The current inbound ackId. +-- outstandingAckId_o - The current outstanding ackId. +-- outboundAckId_o - The current outbound ackId. +-- +-- This is the interface to the packet buffering sublayer. +-- The window signals are used to send packets without removing them from the +-- memory storage. This way, many packet can be sent without awaiting +-- packet-accepted symbols and if a packet-accepted gets lost, it is possible +-- to revert and resend a packet. This is achived by reading readWindowEmpty +-- for new packet and asserting readWindowNext when a packet has been sent. +-- When the packet-accepted is received, readFrame should be asserted to remove the +-- packet from the storage. If a packet-accepted is missing, readWindowReset is +-- asserted to set the current packet to read to the one that has not received +-- a packet-accepted. +-- readFrameEmpty_i - Indicate if a packet is ready in the outbound direction. +-- Once deasserted, it is possible to read the packet content using +-- readContent_o to update readContentData and readContentEnd. +-- readFrame_o - Assert this signal for one tick to discard the oldest packet. +-- It should be used when a packet has been fully read, a linkpartner has +-- accepted it and the resources occupied by it should be returned to be +-- used for new packets. +-- readFrameRestart_o - Assert this signal to restart the reading of the +-- current packet. readContentData and readContentEnd will be reset to the +-- first content of the packet. +-- readFrameAborted_i - This signal is asserted if the current packet was +-- aborted while it was written. It is used when a transmitter starts to send a +-- packet before it has been fully received and it is cancelled before it is +-- completed. A one tick asserted readFrameRestart signal resets this signal. +-- readWindowEmpty_i - Indicate if there are more packets to send. +-- readWindowReset_o - Reset the current packet to the oldest stored in the memory. +-- readWindowNext_o - Indicate that a new packet should be read. Must only be +-- asserted if readWindowEmpty is deasserted. It should be high for one tick. +-- readContentEmpty_i - Indicate if there are any packet content to be read. +-- This signal is updated directly when packet content is written making it +-- possible to read packet content before the full packet has been written to +-- the memory storage. +-- readContent_o - Update readContentData and readContentEnd. +-- readContentEnd_i - Indicate if the end of the current packet has been +-- reached. When asserted, readContentData is not valid. +-- readContentData_i - The content of the current packet. +-- writeFrameFull_i - Indicate if the inbound packet storage is ready to accept +-- a new packet. +-- writeFrame_o - Indicate that a new complete inbound packet has been written. +-- writeFrameAbort_o - Indicate that the current packet is aborted and that all +-- data written for this packet should be discarded. +-- writeContent_o - Indicate that writeContentData is valid and should be +-- written into the packet content storage. +-- writeContentData_o - The content to write to the packet content storage. +-- +-- This is the interface to the PCS (Physical Control Sublayer). Four types of +-- symbols exist, idle, control, data and error. +-- Idle symbols are transmitted when nothing else can be transmitted. They are +-- mainly intended to enforce a timing on the transmitted symbols. This is +-- needed to be able to guarantee that a status-control-symbol is transmitted +-- at least once every 256 symbol. +-- Control symbols contain control-symbols as described by the standard. +-- Data symbols contains a 32-bit fragment of a RapidIO packet. +-- Error symbols indicate that a corrupted symbol was received. This could be +-- used by a PCS layer to indicate that a transmission error was detected and +-- that the above layers should send link-requests to ensure the synchronism +-- between the link-partners. +-- The signals in this interface are: +-- portInitialized_i - An asserted signal on this pin indicates that the PCS +-- layer has established synchronization with the link and is ready to accept +-- symbols. +-- outboundSymbolEmpty_o - An asserted signal indicates that there are no +-- outbound symbols to read. Once deasserted, outboundSymbol_o will be +-- already be valid. This signal will be updated one tick after +-- outboundSymbolRead_i has been asserted. +-- outboundSymbolRead_i - Indicate that outboundSymbol_o has been read and a +-- new value could be accepted. It should be active for one tick. +-- outboundSymbol_o - The outbound symbol. The two MSB bits are the type of the +-- symbol. +-- bit 34-33 +-- 00=IDLE, the rest of the bits are not used. +-- 01=CONTROL, the control symbols payload (24 bits) are placed in the MSB +-- part of the symbol data. +-- 10=ERROR, the rest of the bits are not used. +-- 11=DATA, all the remaining bits contain the data-symbol payload. +-- inboundSymbolFull_o - An asserted signal indicates that no more inbound +-- symbols can be accepted. +-- inboundSymbolWrite_i - Indicate that inboundSymbol_i contains valid +-- information that should be forwarded. Should be active for one tick. +-- inboundSymbol_i - The inbound symbol. See outboundSymbol_o for formating. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for RioSerial. +------------------------------------------------------------------------------- +entity RioSerial is + generic( + TIMEOUT_WIDTH : natural); + port( + -- System signals. + clk : in std_logic; + areset_n : in std_logic; + + -- Status signals for maintenance operations. + portLinkTimeout_i : in std_logic_vector(TIMEOUT_WIDTH-1 downto 0); + linkInitialized_o : out std_logic; + inputPortEnable_i : in std_logic; + outputPortEnable_i : in std_logic; + + -- Support for portLocalAckIdCSR. + localAckIdWrite_i : in std_logic; + clrOutstandingAckId_i : in std_logic; + inboundAckId_i : in std_logic_vector(4 downto 0); + outstandingAckId_i : in std_logic_vector(4 downto 0); + outboundAckId_i : in std_logic_vector(4 downto 0); + inboundAckId_o : out std_logic_vector(4 downto 0); + outstandingAckId_o : out std_logic_vector(4 downto 0); + outboundAckId_o : out std_logic_vector(4 downto 0); + + -- Outbound frame interface. + readFrameEmpty_i : in std_logic; + readFrame_o : out std_logic; + readFrameRestart_o : out std_logic; + readFrameAborted_i : in std_logic; + readWindowEmpty_i : in std_logic; + readWindowReset_o : out std_logic; + readWindowNext_o : out 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); + + -- Inbound frame interface. + 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); + + -- PCS layer signals. + portInitialized_i : in std_logic; + outboundSymbolEmpty_o : out std_logic; + outboundSymbolRead_i : in std_logic; + outboundSymbol_o : out std_logic_vector(33 downto 0); + inboundSymbolFull_o : out std_logic; + inboundSymbolWrite_i : in std_logic; + inboundSymbol_i : in std_logic_vector(33 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioSerial. +------------------------------------------------------------------------------- +architecture RioSerialImpl of RioSerial is + + component RioFifo1 is + generic( + WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + empty_o : out std_logic; + read_i : in std_logic; + data_o : out std_logic_vector(WIDTH-1 downto 0); + + full_o : out std_logic; + write_i : in std_logic; + data_i : in std_logic_vector(WIDTH-1 downto 0)); + end component; + + component RioTransmitter is + generic( + TIMEOUT_WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + portLinkTimeout_i : in std_logic_vector(TIMEOUT_WIDTH-1 downto 0); + portEnable_i : in std_logic; + + localAckIdWrite_i : in std_logic; + clrOutstandingAckId_i : in std_logic; + outstandingAckId_i : in std_logic_vector(4 downto 0); + outboundAckId_i : in std_logic_vector(4 downto 0); + outstandingAckId_o : out std_logic_vector(4 downto 0); + outboundAckId_o : out std_logic_vector(4 downto 0); + + portInitialized_i : in std_logic; + txFull_i : in std_logic; + txWrite_o : out std_logic; + txControl_o : out std_logic_vector(1 downto 0); + txData_o : out std_logic_vector(31 downto 0); + + txControlEmpty_i : in std_logic; + txControlSymbol_i : in std_logic_vector(12 downto 0); + txControlUpdate_o : out std_logic; + rxControlEmpty_i : in std_logic; + rxControlSymbol_i : in std_logic_vector(12 downto 0); + rxControlUpdate_o : out std_logic; + + linkInitialized_i : in std_logic; + linkInitialized_o : out std_logic; + ackIdStatus_i : in std_logic_vector(4 downto 0); + + readFrameEmpty_i : in std_logic; + readFrame_o : out std_logic; + readFrameRestart_o : out std_logic; + readFrameAborted_i : in std_logic; + readWindowEmpty_i : in std_logic; + readWindowReset_o : out std_logic; + readWindowNext_o : out 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)); + end component; + + component RioReceiver is + port( + clk : in std_logic; + areset_n : in std_logic; + + portEnable_i : in std_logic; + + localAckIdWrite_i : in std_logic; + inboundAckId_i : in std_logic_vector(4 downto 0); + inboundAckId_o : out std_logic_vector(4 downto 0); + + portInitialized_i : in std_logic; + rxEmpty_i : in std_logic; + rxRead_o : out std_logic; + rxControl_i : in std_logic_vector(1 downto 0); + rxData_i : in std_logic_vector(31 downto 0); + + txControlWrite_o : out std_logic; + txControlSymbol_o : out std_logic_vector(12 downto 0); + rxControlWrite_o : out std_logic; + rxControlSymbol_o : out std_logic_vector(12 downto 0); + + ackIdStatus_o : out std_logic_vector(4 downto 0); + linkInitialized_o : out std_logic; + + writeFrameFull_i : in std_logic; + writeFrame_o : out std_logic; + writeFrameAbort_o : out std_logic; + writeContent_o : out std_logic; + writeContentData_o : out std_logic_vector(31 downto 0)); + end component; + + signal linkInitializedRx : std_logic; + signal linkInitializedTx : std_logic; + signal ackIdStatus : std_logic_vector(4 downto 0); + + signal txControlWrite : std_logic; + signal txControlWriteSymbol : std_logic_vector(12 downto 0); + signal txControlReadEmpty : std_logic; + signal txControlRead : std_logic; + signal txControlReadSymbol : std_logic_vector(12 downto 0); + + signal rxControlWrite : std_logic; + signal rxControlWriteSymbol : std_logic_vector(12 downto 0); + signal rxControlReadEmpty : std_logic; + signal rxControlRead : std_logic; + signal rxControlReadSymbol : std_logic_vector(12 downto 0); + + signal outboundFull : std_logic; + signal outboundWrite : std_logic; + signal outboundControl : std_logic_vector(1 downto 0); + signal outboundData : std_logic_vector(31 downto 0); + signal outboundSymbol : std_logic_vector(33 downto 0); + + signal inboundEmpty : std_logic; + signal inboundRead : std_logic; + signal inboundControl : std_logic_vector(1 downto 0); + signal inboundData : std_logic_vector(31 downto 0); + signal inboundSymbol : std_logic_vector(33 downto 0); + +begin + + linkInitialized_o <= + '1' when ((linkInitializedRx = '1') and (linkInitializedTx = '1')) else '0'; + + ----------------------------------------------------------------------------- + -- Serial layer modules. + ----------------------------------------------------------------------------- + + Transmitter: RioTransmitter + generic map( + TIMEOUT_WIDTH=>TIMEOUT_WIDTH) + port map( + clk=>clk, areset_n=>areset_n, + portLinkTimeout_i=>portLinkTimeout_i, + portEnable_i=>outputPortEnable_i, + localAckIdWrite_i=>localAckIdWrite_i, + clrOutstandingAckId_i=>clrOutstandingAckId_i, + outstandingAckId_i=>outstandingAckId_i, + outboundAckId_i=>outboundAckId_i, + outstandingAckId_o=>outstandingAckId_o, + outboundAckId_o=>outboundAckId_o, + portInitialized_i=>portInitialized_i, + txFull_i=>outboundFull, txWrite_o=>outboundWrite, + txControl_o=>outboundControl, txData_o=>outboundData, + txControlEmpty_i=>txControlReadEmpty, txControlSymbol_i=>txControlReadSymbol, + txControlUpdate_o=>txControlRead, + rxControlEmpty_i=>rxControlReadEmpty, rxControlSymbol_i=>rxControlReadSymbol, + rxControlUpdate_o=>rxControlRead, + linkInitialized_o=>linkInitializedTx, + linkInitialized_i=>linkInitializedRx, ackIdStatus_i=>ackIdStatus, + readFrameEmpty_i=>readFrameEmpty_i, readFrame_o=>readFrame_o, + readFrameRestart_o=>readFrameRestart_o, readFrameAborted_i=>readFrameAborted_i, + readWindowEmpty_i=>readWindowEmpty_i, + readWindowReset_o=>readWindowReset_o, readWindowNext_o=>readWindowNext_o, + readContentEmpty_i=>readContentEmpty_i, readContent_o=>readContent_o, + readContentEnd_i=>readContentEnd_i, readContentData_i=>readContentData_i); + + TxSymbolFifo: RioFifo1 + generic map(WIDTH=>13) + port map( + clk=>clk, areset_n=>areset_n, + empty_o=>txControlReadEmpty, read_i=>txControlRead, data_o=>txControlReadSymbol, + full_o=>open, write_i=>txControlWrite, data_i=>txControlWriteSymbol); + + RxSymbolFifo: RioFifo1 + generic map(WIDTH=>13) + port map( + clk=>clk, areset_n=>areset_n, + empty_o=>rxControlReadEmpty, read_i=>rxControlRead, data_o=>rxControlReadSymbol, + full_o=>open, write_i=>rxControlWrite, data_i=>rxControlWriteSymbol); + + Receiver: RioReceiver + port map( + clk=>clk, areset_n=>areset_n, + portEnable_i=>inputPortEnable_i, + localAckIdWrite_i=>localAckIdWrite_i, + inboundAckId_i=>inboundAckId_i, + inboundAckId_o=>inboundAckId_o, + portInitialized_i=>portInitialized_i, + rxEmpty_i=>inboundEmpty, rxRead_o=>inboundRead, + rxControl_i=>inboundControl, rxData_i=>inboundData, + txControlWrite_o=>txControlWrite, txControlSymbol_o=>txControlWriteSymbol, + rxControlWrite_o=>rxControlWrite, rxControlSymbol_o=>rxControlWriteSymbol, + ackIdStatus_o=>ackIdStatus, + linkInitialized_o=>linkInitializedRx, + writeFrameFull_i=>writeFrameFull_i, + writeFrame_o=>writeFrame_o, writeFrameAbort_o=>writeFrameAbort_o, + writeContent_o=>writeContent_o, writeContentData_o=>writeContentData_o); + + ----------------------------------------------------------------------------- + -- PCS layer FIFO interface. + ----------------------------------------------------------------------------- + + outboundSymbol <= outboundControl & outboundData; + OutboundSymbolFifo: RioFifo1 + generic map(WIDTH=>34) + port map( + clk=>clk, areset_n=>areset_n, + empty_o=>outboundSymbolEmpty_o, read_i=>outboundSymbolRead_i, data_o=>outboundSymbol_o, + full_o=>outboundFull, write_i=>outboundWrite, data_i=>outboundSymbol); + + inboundControl <= inboundSymbol(33 downto 32); + inboundData <= inboundSymbol(31 downto 0); + InboundSymbolFifo: RioFifo1 + generic map(WIDTH=>34) + port map( + clk=>clk, areset_n=>areset_n, + empty_o=>inboundEmpty, read_i=>inboundRead, data_o=>inboundSymbol, + full_o=>inboundSymbolFull_o, write_i=>inboundSymbolWrite_i, data_i=>inboundSymbol_i); + +end architecture; + + + +------------------------------------------------------------------------------- +-- RioTransmitter +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for RioTransmitter. +------------------------------------------------------------------------------- +entity RioTransmitter is + generic( + TIMEOUT_WIDTH : natural); + port( + -- System signals. + clk : in std_logic; + areset_n : in std_logic; + + -- Status signals used for maintenance. + portLinkTimeout_i : in std_logic_vector(TIMEOUT_WIDTH-1 downto 0); + portEnable_i : in std_logic; + + -- Support for localAckIdCSR. + localAckIdWrite_i : in std_logic; + clrOutstandingAckId_i : in std_logic; + outstandingAckId_i : in std_logic_vector(4 downto 0); + outboundAckId_i : in std_logic_vector(4 downto 0); + outstandingAckId_o : out std_logic_vector(4 downto 0); + outboundAckId_o : out std_logic_vector(4 downto 0); + + -- Port output interface. + portInitialized_i : in std_logic; + txFull_i : in std_logic; + txWrite_o : out std_logic; + txControl_o : out std_logic_vector(1 downto 0); + txData_o : out std_logic_vector(31 downto 0); + + -- Control symbols aimed to the transmitter. + txControlEmpty_i : in std_logic; + txControlSymbol_i : in std_logic_vector(12 downto 0); + txControlUpdate_o : out std_logic; + + -- Control symbols from the receiver to send. + rxControlEmpty_i : in std_logic; + rxControlSymbol_i : in std_logic_vector(12 downto 0); + rxControlUpdate_o : out std_logic; + + -- Internal signalling from the receiver part. + linkInitialized_o : out std_logic; + linkInitialized_i : in std_logic; + ackIdStatus_i : in std_logic_vector(4 downto 0); + + -- Frame buffer interface. + readFrameEmpty_i : in std_logic; + readFrame_o : out std_logic; + readFrameRestart_o : out std_logic; + readFrameAborted_i : in std_logic; + readWindowEmpty_i : in std_logic; + readWindowReset_o : out std_logic; + readWindowNext_o : out 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)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioTransmitter. +------------------------------------------------------------------------------- +architecture RioTransmitterImpl of RioTransmitter is + + constant NUMBER_STATUS_TRANSMIT : natural := 15; + constant NUMBER_LINK_RESPONSE_RETRIES : natural := 2; + + component 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 component; + + component Crc5ITU is + port( + d_i : in std_logic_vector(18 downto 0); + crc_o : out std_logic_vector(4 downto 0)); + end component; + + type StateType is (STATE_UNINITIALIZED, STATE_PORT_INITIALIZED, + STATE_NORMAL, + STATE_OUTPUT_RETRY_STOPPED, + STATE_SEND_LINK_REQUEST, STATE_OUTPUT_ERROR_STOPPED, + STATE_RECOVER, STATE_FATAL_ERROR); + signal stateCurrent, stateNext : StateType; + + signal statusReceivedCurrent, statusReceivedNext : std_logic; + signal counterCurrent, counterNext : natural range 0 to 15; + signal symbolsTransmittedCurrent, symbolsTransmittedNext : natural range 0 to 255; + + type FrameStateType is (FRAME_START, FRAME_CHECK, FRAME_ACKID, FRAME_BODY, FRAME_END); + signal frameStateCurrent, frameStateNext : FrameStateType; + signal ackIdCurrent, ackIdNext : unsigned(4 downto 0) := (others=>'0'); + signal ackIdWindowCurrent, ackIdWindowNext : unsigned(4 downto 0) := (others=>'0'); + signal bufferStatusCurrent, bufferStatusNext : std_logic_vector(4 downto 0); + + signal stype0 : std_logic_vector(2 downto 0); + signal parameter0 : std_logic_vector(4 downto 0); + signal parameter1 : std_logic_vector(4 downto 0); + signal stype1 : std_logic_vector(2 downto 0); + signal cmd : std_logic_vector(2 downto 0); + + signal txControlStype0 : std_logic_vector(2 downto 0); + signal txControlParameter0 : std_logic_vector(4 downto 0); + signal txControlParameter1 : std_logic_vector(4 downto 0); + + signal rxControlStype0 : std_logic_vector(2 downto 0); + signal rxControlParameter0 : std_logic_vector(4 downto 0); + signal rxControlParameter1 : std_logic_vector(4 downto 0); + + signal symbolWrite : std_logic; + signal symbolType : std_logic_vector(1 downto 0); + signal symbolControl : std_logic_vector(31 downto 0); + signal symbolData : std_logic_vector(31 downto 0); + signal crcCalculated : std_logic_vector(4 downto 0); + + signal timeoutWrite : std_logic; + signal timeoutCounter : unsigned(TIMEOUT_WIDTH downto 0); + signal timeoutFrame : unsigned(TIMEOUT_WIDTH downto 0); + signal timeoutElapsed : unsigned(TIMEOUT_WIDTH downto 0); + signal timeoutDelta : unsigned(TIMEOUT_WIDTH downto 0); + signal timeoutExpired : std_logic; + + signal timeoutAddress : std_logic_vector(4 downto 0); + signal timeoutMemoryOut : std_logic_vector(TIMEOUT_WIDTH downto 0); + +begin + + linkInitialized_o <= '0' when ((stateCurrent = STATE_UNINITIALIZED) or + (stateCurrent = STATE_PORT_INITIALIZED)) else '1'; + + ----------------------------------------------------------------------------- + -- Assign control symbol from fifo signals. + ----------------------------------------------------------------------------- + + txControlStype0 <= txControlSymbol_i(12 downto 10); + txControlParameter0 <= txControlSymbol_i(9 downto 5); + txControlParameter1 <= txControlSymbol_i(4 downto 0); + + rxControlStype0 <= rxControlSymbol_i(12 downto 10); + rxControlParameter0 <= rxControlSymbol_i(9 downto 5); + rxControlParameter1 <= rxControlSymbol_i(4 downto 0); + + ----------------------------------------------------------------------------- + -- Outbound symbol creation logic. + ----------------------------------------------------------------------------- + + symbolControl(31 downto 29) <= stype0; + symbolControl(28 downto 24) <= parameter0; + symbolControl(23 downto 19) <= parameter1; + symbolControl(18 downto 16) <= stype1; + symbolControl(15 downto 13) <= cmd; + symbolControl(12 downto 8) <= crcCalculated; + symbolControl(7 downto 0) <= x"00"; + + Crc5Calculator: Crc5ITU + port map( + d_i=>symbolControl(31 downto 13), crc_o=>crcCalculated); + + txWrite_o <= symbolWrite; + txControl_o <= symbolType; + txData_o <= symbolControl when (symbolType = SYMBOL_CONTROL) else symbolData; + + ----------------------------------------------------------------------------- + -- Packet timeout logic. + ----------------------------------------------------------------------------- + + -- Note that the timer is one bit larger to be able to detect a timeout on a + -- free-running counter. + process(areset_n, clk) + begin + if (areset_n = '0') then + timeoutCounter <= (others=>'0'); + elsif (clk'event and clk = '1') then + timeoutCounter <= timeoutCounter + 1; + end if; + end process; + + timeoutElapsed <= timeoutCounter - timeoutFrame; + timeoutDelta <= unsigned('0' & portLinkTimeout_i) - timeoutElapsed; + timeoutExpired <= timeoutDelta(TIMEOUT_WIDTH); + + timeoutFrame <= unsigned(timeoutMemoryOut); + TimeoutMemory: MemorySimpleDualPortAsync + generic map(ADDRESS_WIDTH=>5, DATA_WIDTH=>TIMEOUT_WIDTH+1, INIT_VALUE=>'0') + port map( + clkA_i=>clk, enableA_i=>timeoutWrite, + addressA_i=>timeoutAddress, dataA_i=>std_logic_vector(timeoutCounter), + addressB_i=>std_logic_vector(ackIdCurrent), dataB_o=>timeoutMemoryOut); + + ----------------------------------------------------------------------------- + -- Main outbound symbol handler, synchronous part. + ----------------------------------------------------------------------------- + process(areset_n, clk) + begin + if (areset_n = '0') then + stateCurrent <= STATE_UNINITIALIZED; + + statusReceivedCurrent <= '0'; + counterCurrent <= 0; + symbolsTransmittedCurrent <= 0; + + frameStateCurrent <= FRAME_START; + ackIdCurrent <= (others => '0'); + ackIdWindowCurrent <= (others => '0'); + bufferStatusCurrent <= (others => '0'); + elsif (clk'event and clk = '1') then + stateCurrent <= stateNext; + + statusReceivedCurrent <= statusReceivedNext; + counterCurrent <= counterNext; + symbolsTransmittedCurrent <= symbolsTransmittedNext; + + frameStateCurrent <= frameStateNext; + ackIdCurrent <= ackIdNext; + ackIdWindowCurrent <= ackIdWindowNext; + bufferStatusCurrent <= bufferStatusNext; + end if; + end process; + + ----------------------------------------------------------------------------- + -- Main outbound symbol handler, combinatorial part. + ----------------------------------------------------------------------------- + process(stateCurrent, + statusReceivedCurrent, counterCurrent, + symbolsTransmittedCurrent, + frameStateCurrent, ackIdCurrent, ackIdWindowCurrent, bufferStatusCurrent, + txControlStype0, txControlParameter0, txControlParameter1, + rxControlStype0, rxControlParameter0, rxControlParameter1, + portEnable_i, + localAckIdWrite_i, clrOutstandingAckId_i, + outstandingAckId_i, outboundAckId_i, + txFull_i, + txControlEmpty_i, txControlSymbol_i, + rxControlEmpty_i, rxControlSymbol_i, + portInitialized_i, linkInitialized_i, ackIdStatus_i, + readFrameEmpty_i, readFrameAborted_i, + readWindowEmpty_i, + readContentEmpty_i, readContentEnd_i, readContentData_i, + timeoutExpired) + begin + stateNext <= stateCurrent; + statusReceivedNext <= statusReceivedCurrent; + counterNext <= counterCurrent; + symbolsTransmittedNext <= symbolsTransmittedCurrent; + + frameStateNext <= frameStateCurrent; + ackIdNext <= ackIdCurrent; + ackIdWindowNext <= ackIdWindowCurrent; + bufferStatusNext <= bufferStatusCurrent; + + txControlUpdate_o <= '0'; + rxControlUpdate_o <= '0'; + + readFrame_o <= '0'; + readFrameRestart_o <= '0'; + readWindowReset_o <= '0'; + readWindowNext_o <= '0'; + readContent_o <= '0'; + + symbolWrite <= '0'; + symbolType <= (others=>'U'); + stype0 <= (others=>'U'); + parameter0 <= (others=>'U'); + parameter1 <= (others=>'U'); + stype1 <= (others=>'U'); + cmd <= (others=>'U'); + symbolData <= (others=>'U'); + + timeoutWrite <= '0'; + timeoutAddress <= (others=>'U'); + + outstandingAckId_o <= std_logic_vector(ackIdCurrent); + outboundAckId_o <= std_logic_vector(ackIdWindowCurrent); + + -- Check if a localAckIdWrite is active. + if (localAckIdWrite_i = '1') then + -- A localAckIdWrite is active. + + -- Check if all outstanding packets should be discarded. + if (clrOutstandingAckId_i = '1') then + -- Delete all outbound packets. + -- REMARK: Remove all packets in another way... what if uninitialized??? + stateNext <= STATE_RECOVER; + end if; + + -- Set ackIds. + ackIdNext <= unsigned(outstandingAckId_i); + ackIdWindowNext <= unsigned(outboundAckId_i); + else + -- A localAckIdWrite is not active. + + -- Act on the current state. + case (stateCurrent) is + + when STATE_UNINITIALIZED => + ----------------------------------------------------------------------- + -- This state is entered at startup. A port that is not initialized + -- should only transmit idle sequences. + ----------------------------------------------------------------------- + + -- Check if the port is initialized. + if (portInitialized_i = '0') then + -- Port not initialized. + + -- Check if any new symbols from the link partner has been received. + if (txControlEmpty_i = '0') then + -- New symbols have been received. + -- Discard all new symbols in this state. + txControlUpdate_o <= '1'; + else + -- No new symbols from the link partner. + -- Dont do anything. + end if; + + -- Check if any new symbols should be transmitted to the link partner. + if (rxControlEmpty_i = '0') then + -- New symbols should be transmitted. + -- Do not forward any symbols in this state. + rxControlUpdate_o <= '1'; + else + -- No new symbols to transmit. + -- Dont do anything. + end if; + + -- Check if a new symbol should be transmitted. + if (txFull_i = '0') then + -- A new symbol should be transmitted. + + -- Send idle sequence. + symbolWrite <= '1'; + symbolType <= SYMBOL_IDLE; + else + -- The outbound fifo is full. + -- Dont do anything. + end if; + + -- Check if a new full packet is ready. + if (readFrameEmpty_i = '0') then + -- A new full packet is ready. + -- It is not possible to send the packet now. If the packet is not + -- discarded it might congest the full system if the link does not + -- go initialized. To avoid a congested switch, the packet is + -- discarded and will have to be resent by the source when the link + -- is up and running. + readFrame_o <= '1'; + else + -- No new full packets are ready. + -- Dont do anything. + end if; + else + -- Port is initialized. + + -- Go to the initialized state and reset the counters. + statusReceivedNext <= '0'; + counterNext <= NUMBER_STATUS_TRANSMIT; + symbolsTransmittedNext <= 0; + stateNext <= STATE_PORT_INITIALIZED; + end if; + + when STATE_PORT_INITIALIZED => + ----------------------------------------------------------------------- + -- The specification requires a status control symbol being sent at + -- least every 1024 code word until an error-free status has been + -- received. This implies that at most 256 idle sequences should be + -- sent in between status control symbols. Once an error-free status has + -- been received, status symbols may be sent more rapidly. At least 15 + -- statuses has to be transmitted once an error-free status has been + -- received. + --------------------------------------------------------------------- + + -- Check if the port is initialized. + if (portInitialized_i = '1') then + -- Port is initialized. + + -- Check if we are ready to change state to linkInitialized. + if ((linkInitialized_i = '1') and (counterCurrent = 0)) then + -- Receiver has received enough error free status symbols and we have + -- transmitted enough. + + -- Initialize framing before entering the normal state. + ackIdWindowNext <= ackIdCurrent; + frameStateNext <= FRAME_START; + readWindowReset_o <= '1'; + + -- Considder the link initialized. + stateNext <= STATE_NORMAL; + else + -- Not ready to change state to linkInitialized. + -- Dont do anything. + end if; + + -- Check if any new symbols from the link partner has been received. + if (txControlEmpty_i = '0') then + -- New symbols have been received. + + -- Check if the new symbol is a status. + if (txControlStype0 = STYPE0_STATUS) then + -- A new status control symbol has been received. + statusReceivedNext <= '1'; + + -- Set the ackId and the linkpartner buffer status to what is indicated + -- in the received control symbol. + ackIdNext <= unsigned(txControlParameter0); + bufferStatusNext <= txControlParameter1; + else + -- Did not receive a status control symbol. + -- Discard it. + end if; + + -- Update to the next control symbol received by the receiver. + txControlUpdate_o <= '1'; + else + -- No new symbols from the link partner. + -- Dont do anything. + end if; + + -- Check if any new symbols should be transmitted to the link partner. + if (rxControlEmpty_i = '0') then + -- New symbols should be transmitted. + -- Do not forward any symbols in this state. + rxControlUpdate_o <= '1'; + else + -- No new symbols to transmit. + -- Dont do anything. + end if; + + -- Check if a new symbol may be transmitted. + if (txFull_i = '0') then + -- A new symbol can be transmitted. + + -- Check if idle sequence or a status symbol should be transmitted. + if (((statusReceivedCurrent = '0') and (symbolsTransmittedCurrent = 255)) or + ((statusReceivedCurrent = '1') and (symbolsTransmittedCurrent > 15))) then + -- A status symbol should be transmitted. + + -- Send a status control symbol to the link partner. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= STYPE0_STATUS; + parameter0 <= ackIdStatus_i; + parameter1 <= "11111"; + stype1 <= STYPE1_NOP; + cmd <= "000"; + + -- Reset idle sequence transmission counter. + symbolsTransmittedNext <= 0; + + -- Check if the number of transmitted statuses should be updated. + if (statusReceivedCurrent = '1') and (counterCurrent /= 0) then + counterNext <= counterCurrent - 1; + end if; + else + -- A idle sequence should be transmitted. + symbolWrite <= '1'; + symbolType <= SYMBOL_IDLE; + + -- Increment the idle sequence transmission counter. + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + end if; + else + -- Cannot send a new symbol. + -- Dont do anything. + end if; + else + -- Go back to the uninitialized state. + stateNext <= STATE_UNINITIALIZED; + end if; + + when STATE_NORMAL => + ------------------------------------------------------------------- + -- This state is the normal state. It relays frames and handle flow + -- control. + ------------------------------------------------------------------- + + -- Check that both the port and link is initialized. + if (portInitialized_i = '1') and (linkInitialized_i = '1') then + -- The port and link is initialized. + + -- Check if any control symbol has been received from the link + -- partner. + if (txControlEmpty_i = '0') then + -- A control symbol has been received. + + -- Check the received control symbol. + case txControlStype0 is + + when STYPE0_STATUS => + -- Save the number of buffers in the link partner. + bufferStatusNext <= txControlParameter1; + + when STYPE0_PACKET_ACCEPTED => + -- The link partner is accepting a frame. + + -- Save the number of buffers in the link partner. + bufferStatusNext <= txControlParameter1; + + -- Check if expecting this type of reply and that the ackId is + -- expected. + if ((ackIdCurrent /= ackIdWindowCurrent) and + (ackIdCurrent = unsigned(txControlParameter0))) then + -- The packet-accepted is expected and the ackId is the expected. + -- The frame has been accepted by the link partner. + + -- Update to a new buffer and increment the ackId. + readFrame_o <= '1'; + ackIdNext <= ackIdCurrent + 1; + else + -- Unexpected packet-accepted or packet-accepted for + -- unexpected ackId. + counterNext <= NUMBER_LINK_RESPONSE_RETRIES; + stateNext <= STATE_SEND_LINK_REQUEST; + end if; + + when STYPE0_PACKET_RETRY => + -- The link partner has asked for a frame retransmission. + + -- Save the number of buffers in the link partner. + bufferStatusNext <= txControlParameter1; + + -- Check if the ackId is the one expected. + if (ackIdCurrent = unsigned(txControlParameter0)) then + -- The ackId to retry is expected. + -- Go to the output-retry-stopped state. + stateNext <= STATE_OUTPUT_RETRY_STOPPED; + else + -- Unexpected ackId to retry. + counterNext <= NUMBER_LINK_RESPONSE_RETRIES; + stateNext <= STATE_SEND_LINK_REQUEST; + end if; + + when STYPE0_PACKET_NOT_ACCEPTED => + -- Packet was rejected by the link-partner. + -- REMARK: Indicate that this has happened to the outside... + counterNext <= NUMBER_LINK_RESPONSE_RETRIES; + stateNext <= STATE_SEND_LINK_REQUEST; + + when STYPE0_LINK_RESPONSE => + -- Dont expect or need a link-response in this state. + -- Discard it. + + when STYPE0_VC_STATUS => + -- Not supported. + -- Discard it. + + when STYPE0_RESERVED => + -- Not supported. + -- Discard it. + + when STYPE0_IMPLEMENTATION_DEFINED => + -- Not supported. + -- Discard it. + + when others => + null; + end case; + + -- Indicate the control symbol has been processed. + txControlUpdate_o <= '1'; + else + -- No control symbol has been received. + + -- Check if the oldest frame timeout has expired. + if ((ackIdCurrent /= ackIdWindowCurrent) and + (timeoutExpired = '1')) then + -- There has been a timeout on a transmitted frame. + + -- Send link-request. + counterNext <= NUMBER_LINK_RESPONSE_RETRIES; + stateNext <= STATE_SEND_LINK_REQUEST; + else + -- There has been no timeout. + + -- Check if the outbound fifo needs new data. + if (txFull_i = '0') then + -- There is room available in the outbound FIFO. + + -- Check if there are any events from the receiver. + if (rxControlEmpty_i = '0') then + -- A symbol from the receiver should be transmitted. + + -- Send the receiver symbol and a NOP. + -- REMARK: Combine this symbol with an STYPE1 to more effectivly + -- utilize the link. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= rxControlStype0; + parameter0 <= rxControlParameter0; + parameter1 <= rxControlParameter1; + stype1 <= STYPE1_NOP; + cmd <= "000"; + + -- Remove the symbol from the fifo. + rxControlUpdate_o <= '1'; + + -- Check if the transmitted symbol contains status about + -- available buffers. + if ((rxControlStype0 = STYPE0_PACKET_ACCEPTED) or + (rxControlStype0 = STYPE0_PACKET_RETRY)) then + -- A symbol containing the bufferStatus has been sent. + symbolsTransmittedNext <= 0; + else + -- A symbol not containing the bufferStatus has been sent. + -- REMARK: symbolsTransmitted might overflow... + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + end if; + else + -- No events from the receiver. + + -- Check if a status symbol must be sent. + if (symbolsTransmittedCurrent = 255) then + -- A status symbol must be sent. + + -- Reset the number of transmitted symbols between statuses. + symbolsTransmittedNext <= 0; + + -- Send status. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= STYPE0_STATUS; + parameter0 <= ackIdStatus_i; + parameter1 <= "11111"; + stype1 <= STYPE1_NOP; + cmd <= "000"; + else + -- A status symbol does not have to be sent. + + -- Check if a frame transfer is in progress. + case frameStateCurrent is + + when FRAME_START => + --------------------------------------------------------------- + -- No frame has been started. + --------------------------------------------------------------- + + -- Wait for a new frame to arrive from the frame buffer, + -- for new buffers to be available at the link-partner + -- and also check that a maximum 31 frames are outstanding. + if ((readWindowEmpty_i = '0') and (bufferStatusCurrent /= "00000") and + ((ackIdWindowCurrent - ackIdCurrent) /= 31)) then + -- New data is available for transmission and there + -- is room to receive it at the other side. + + -- Indicate that a control symbol has been sent to start the + -- transmission of the frame. + frameStateNext <= FRAME_CHECK; + + -- Update the output from the frame buffer to contain the + -- data when it is read later. + readContent_o <= '1'; + else + -- There are no frame data to send or the link partner has + -- no available buffers. + + -- Send idle-sequence. + symbolWrite <= '1'; + symbolType <= SYMBOL_IDLE; + + -- A symbol not containing the buffer status has been sent. + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + end if; + + when FRAME_CHECK => + ------------------------------------------------------- + -- Check if we are allowed to transmit this packet. + ------------------------------------------------------- + + -- Check if this packet is allowed to be transmitted. + if ((portEnable_i = '1') or (readContentData_i(19 downto 16) = FTYPE_MAINTENANCE_CLASS)) then + -- The packet may be transmitted. + + -- Indicate that a control symbol has been sent to start the + -- transmission of the frame. + frameStateNext <= FRAME_ACKID; + + -- Send a control symbol to start the packet and a status to complete + -- the symbol. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= STYPE0_STATUS; + parameter0 <= ackIdStatus_i; + parameter1 <= "11111"; + stype1 <= STYPE1_START_OF_PACKET; + cmd <= "000"; + + -- A symbol containing the bufferStatus has been sent. + symbolsTransmittedNext <= 0; + else + -- The packet should be discarded. + + -- Check that there are no outstanding packets that + -- has not been acknowledged. + if(ackIdWindowCurrent /= ackIdCurrent) then + -- There are packets that has not been acknowledged. + + -- Send idle-sequence. + symbolWrite <= '1'; + symbolType <= SYMBOL_IDLE; + + -- A symbol not containing the buffer status has been sent. + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + else + -- No unacknowledged packets. + -- It is now safe to remove the unallowed frame. + readFrame_o <= '1'; + + -- Go back and send a new frame. + frameStateNext <= FRAME_START; + end if; + end if; + + when FRAME_ACKID => + --------------------------------------------------------------- + -- Send the first packet content containing our current + -- ackId. + --------------------------------------------------------------- + + -- Write a new data symbol and fill in our ackId on the + -- packet. + symbolWrite <= '1'; + symbolType <= SYMBOL_DATA; + symbolData <= std_logic_vector(ackIdWindowCurrent) & "0" & readContentData_i(25 downto 0); + + -- Continue to send the rest of the body of the packet. + readContent_o <= '1'; + frameStateNext <= FRAME_BODY; + + -- A symbol not containing the buffer status has been sent. + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + + when FRAME_BODY => + --------------------------------------------------------------- + -- The frame has not been fully sent. + -- Send a data symbol. + --------------------------------------------------------------- + -- REMARK: Add support for partial frames... + + -- Check if the frame is ending. + if (readContentEnd_i = '0') then + -- The frame is not ending. + + -- Write a new data symbol. + symbolWrite <= '1'; + symbolType <= SYMBOL_DATA; + symbolData <= readContentData_i; + + -- Continue to send the rest of the body of the packet. + readContent_o <= '1'; + + -- A symbol not containing the buffer status has been sent. + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + else + -- The frame is ending. + + -- Update the window to the next frame. + -- It takes one tick for the output from the frame + -- buffer to get updated. + readWindowNext_o <= '1'; + + -- Proceed to check if there is another frame to start + -- with directly. + frameStateNext <= FRAME_END; + end if; + + when FRAME_END => + --------------------------------------------------------------- + -- A frame has ended and the window has been updated. + -- Check if the next symbol should end the frame or if a + -- new one should be started. + --------------------------------------------------------------- + + -- Check if there is a new frame pending. + if (readWindowEmpty_i = '1') then + -- No new frame is pending. + + -- Send a control symbol to end the packet. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= STYPE0_STATUS; + parameter0 <= ackIdStatus_i; + parameter1 <= "11111"; + stype1 <= STYPE1_END_OF_PACKET; + cmd <= "000"; + + -- A symbol containing the bufferStatus has been sent. + symbolsTransmittedNext <= 0; + end if; + + -- Update the window ackId. + ackIdWindowNext <= ackIdWindowCurrent + 1; + + -- Start timeout supervision for transmitted frame. + timeoutWrite <= '1'; + timeoutAddress <= std_logic_vector(ackIdWindowCurrent); + + -- Start a new frame the next time. + frameStateNext <= FRAME_START; + + when others => + --------------------------------------------------------------- + -- + --------------------------------------------------------------- + null; + + end case; + end if; + end if; + else + -- Wait for new storage in the transmission FIFO to become + -- available. + -- Dont do anything. + end if; + end if; + end if; + else + -- The port or the link has become uninitialized. + -- Go back to the uninitialized state. + stateNext <= STATE_UNINITIALIZED; + end if; + + when STATE_OUTPUT_RETRY_STOPPED => + ----------------------------------------------------------------------- + -- This is the output-retry-stopped state described in 5.9.1.5. + ----------------------------------------------------------------------- + + -- Check if the outbound fifo needs new data. + if (txFull_i = '0') then + -- There is room available in the outbound FIFO. + + -- Send a restart-from-retry control symbol to acknowledge the restart + -- of the frame. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= STYPE0_STATUS; + parameter0 <= ackIdStatus_i; + parameter1 <= "11111"; + stype1 <= STYPE1_RESTART_FROM_RETRY; + cmd <= "000"; + + -- Make sure there wont be any timeout before the frame is + -- starting to be retransmitted. + timeoutWrite <= '1'; + timeoutAddress <= std_logic_vector(ackIdCurrent); + + -- Restart the frame transmission. + ackIdWindowNext <= ackIdCurrent; + frameStateNext <= FRAME_START; + readWindowReset_o <= '1'; + + -- Proceed back to the normal state. + stateNext <= STATE_NORMAL; + + -- A symbol containing the bufferStatus has been sent. + symbolsTransmittedNext <= 0; + end if; + + when STATE_SEND_LINK_REQUEST => + ----------------------------------------------------------------------- + -- Send a link-request symbol when the transmission fifo is ready. Then + -- always proceed to the output-error-state. + ----------------------------------------------------------------------- + + -- Check if the outbound fifo needs new data. + if (txFull_i = '0') then + -- There is room available in the outbound FIFO. + + -- Send a link-request symbol. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= STYPE0_STATUS; + parameter0 <= ackIdStatus_i; + parameter1 <= "11111"; + stype1 <= STYPE1_LINK_REQUEST; + cmd <= LINK_REQUEST_CMD_INPUT_STATUS; + + -- Write the current timer value. + timeoutWrite <= '1'; + timeoutAddress <= std_logic_vector(ackIdCurrent); + + -- Proceed to the output-error-stopped state. + stateNext <= STATE_OUTPUT_ERROR_STOPPED; + + -- A symbol containing the bufferStatus has been sent. + symbolsTransmittedNext <= 0; + end if; + + when STATE_OUTPUT_ERROR_STOPPED => + ------------------------------------------------------------------- + -- This state is the error stopped state described in 5.13.2.7. + ------------------------------------------------------------------- + + -- Check that both the port and link is initialized. + if (portInitialized_i = '1') and (linkInitialized_i = '1') then + -- The port and link is initialized. + + -- Check if any control symbol has been received from the link + -- partner. + if (txControlEmpty_i = '0') then + -- A control symbol has been received. + + -- Check the received control symbol. + case txControlStype0 is + + when STYPE0_PACKET_ACCEPTED => + -- Wait for a link-response. + -- Discard these. + + when STYPE0_PACKET_RETRY => + -- Wait for a link-response. + -- Discard these. + + when STYPE0_PACKET_NOT_ACCEPTED => + -- Wait for a link-response. + -- Discard these. + + when STYPE0_STATUS => + -- Wait for a link-response. + -- Discard these. + + when STYPE0_LINK_RESPONSE => + -- Check if the link partner return value is acceptable. + if ((unsigned(txControlParameter0) - ackIdCurrent) <= + (ackIdWindowCurrent - ackIdCurrent)) then + -- Recoverable error. + -- Use the received ackId and recover by removing packets + -- that were received by the link-partner. + ackIdWindowNext <= unsigned(txControlParameter0); + stateNext <= STATE_RECOVER; + else + -- Totally out of sync. + stateNext <= STATE_FATAL_ERROR; + end if; + + when STYPE0_VC_STATUS => + -- Not supported. + + when STYPE0_RESERVED => + -- Not supported. + + when STYPE0_IMPLEMENTATION_DEFINED => + -- Not supported. + + when others => + null; + end case; + + -- Indicate the control symbol has been processed. + txControlUpdate_o <= '1'; + else + -- No control symbol has been received. + + -- Check if the timeout for a link-response has expired. + if (timeoutExpired = '1') then + -- There was no reply on the link-request. + + -- Count the number of retransmissions and abort if + -- no reply has been received for too many times. + if (counterCurrent /= 0) then + -- Not sent link-request too many times. + + -- Send another link-request. + counterNext <= counterCurrent - 1; + stateNext <= STATE_SEND_LINK_REQUEST; + else + -- No response for too many times. + stateNext <= STATE_FATAL_ERROR; + end if; + else + -- There has been no timeout. + + -- Check if the outbound fifo needs new data. + if (txFull_i = '0') then + -- There is room available in the outbound FIFO. + + -- Check if there are any events from the receiver. + if (rxControlEmpty_i = '0') then + -- A symbol from the receiver should be transmitted. + + -- Send the receiver symbol and a NOP. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= rxControlStype0; + parameter0 <= rxControlParameter0; + parameter1 <= rxControlParameter1; + stype1 <= STYPE1_NOP; + cmd <= "000"; + + -- Remove the symbol from the fifo. + rxControlUpdate_o <= '1'; + + -- Check if the transmitted symbol contains status about + -- available buffers. + -- The receiver never send any status so that does not have + -- to be checked. + if ((rxControlStype0 = STYPE0_PACKET_ACCEPTED) or + (rxControlStype0 = STYPE0_PACKET_RETRY)) then + -- A symbol containing the bufferStatus has been sent. + symbolsTransmittedNext <= 0; + else + -- A symbol not containing the buffer status has been sent. + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + end if; + else + -- No events from the receiver. + -- There are no frame data to send or the link partner has + -- no available buffers. + + -- Check if a status symbol must be sent. + if (symbolsTransmittedCurrent = 255) then + -- A status symbol must be sent. + + -- Reset the number of transmitted symbols between statuses. + symbolsTransmittedNext <= 0; + + -- Send status. + symbolWrite <= '1'; + symbolType <= SYMBOL_CONTROL; + stype0 <= STYPE0_STATUS; + parameter0 <= ackIdStatus_i; + parameter1 <= "11111"; + stype1 <= STYPE1_NOP; + cmd <= "000"; + else + -- A status symbol does not have to be sent. + + -- Send idle-sequence. + symbolWrite <= '1'; + symbolType <= SYMBOL_IDLE; + + -- A symbol not containing the buffer status has been sent. + symbolsTransmittedNext <= symbolsTransmittedCurrent + 1; + end if; + end if; + else + -- Wait for new storage in the transmission FIFO to become + -- available. + -- Dont do anything. + end if; + end if; + end if; + else + -- The port or the link has become uninitialized. + -- Go back to the uninitialized state. + stateNext <= STATE_UNINITIALIZED; + end if; + + when STATE_RECOVER => + ----------------------------------------------------------------------- + -- A recoverable error condition has occurred. + -- When this state is entered, ackIdWindow should contain the ackId to + -- proceed with. + ----------------------------------------------------------------------- + + -- Check if the expected ackId has incremented enough. + if (ackIdCurrent /= ackIdWindowCurrent) then + -- Remove this frame. It has been received by the link-partner. + readFrame_o <= '1'; + ackIdNext <= ackIdCurrent + 1; + else + -- Keep this frame. + -- Restart the window and the frame transmission. + frameStateNext <= FRAME_START; + readWindowReset_o <= '1'; + stateNext <= STATE_NORMAL; + end if; + + when STATE_FATAL_ERROR => + ----------------------------------------------------------------------- + -- A fatal error condition has occurred. + ----------------------------------------------------------------------- + + -- Reset the window and resynchronize the link. + -- REMARK: Count these situations... + -- REMARK: Do something else here??? + readWindowReset_o <= '1'; + stateNext <= STATE_UNINITIALIZED; + + when others => + ------------------------------------------------------------------- + -- + ------------------------------------------------------------------- + null; + end case; + 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 RioReceiver is + port( + clk : in std_logic; + areset_n : in std_logic; + + -- Status signals used for maintenance. + portEnable_i : in std_logic; + + -- Support for localAckIdCSR. + localAckIdWrite_i : in std_logic; + inboundAckId_i : in std_logic_vector(4 downto 0); + inboundAckId_o : out std_logic_vector(4 downto 0); + + -- Port input interface. + portInitialized_i : in std_logic; + rxEmpty_i : in std_logic; + rxRead_o : out std_logic; + rxControl_i : in std_logic_vector(1 downto 0); + rxData_i : in std_logic_vector(31 downto 0); + + -- Receiver has received a control symbol containing: + -- packet-accepted, packet-retry, packet-not-accepted, + -- status, VC_status, link-response + txControlWrite_o : out std_logic; + txControlSymbol_o : out std_logic_vector(12 downto 0); + + -- Reciever wants to signal the link partner: + -- a new frame has been accepted => packet-accepted(rxAckId, bufferStatus) + -- a frame needs to be retransmitted due to buffering => + -- packet-retry(rxAckId, bufferStatus) + -- a frame is rejected due to errors => packet-not-accepted + -- a link-request should be answered => link-response + rxControlWrite_o : out std_logic; + rxControlSymbol_o : out std_logic_vector(12 downto 0); + + -- Status signals used internally. + ackIdStatus_o : out std_logic_vector(4 downto 0); + linkInitialized_o : out std_logic; + + -- Frame buffering interface. + 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 RioReceiverImpl of RioReceiver is + + component Crc5ITU is + port( + d_i : in std_logic_vector(18 downto 0); + crc_o : out std_logic_vector(4 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 StateType is (STATE_UNINITIALIZED, STATE_PORT_INITIALIZED, + STATE_NORMAL, + STATE_INPUT_RETRY_STOPPED, STATE_INPUT_ERROR_STOPPED); + signal state : StateType; + + signal statusCounter : natural range 0 to 8; + + signal ackId : unsigned(4 downto 0); + signal frameIndex : natural range 0 to 70; + + signal stype0 : std_logic_vector(2 downto 0); + signal parameter0 : std_logic_vector(4 downto 0); + signal parameter1 : std_logic_vector(4 downto 0); + signal stype1 : std_logic_vector(2 downto 0); + signal cmd : std_logic_vector(2 downto 0); + + signal crc5 : std_logic_vector(4 downto 0); + signal crc5Calculated : std_logic_vector(4 downto 0); + + signal crc16Valid : std_logic; + 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 rxRead : std_logic; + +begin + + linkInitialized_o <= '0' when ((state = STATE_UNINITIALIZED) or + (state = STATE_PORT_INITIALIZED)) else '1'; + ackIdStatus_o <= std_logic_vector(ackId); + + ----------------------------------------------------------------------------- + -- Get the entries in a control symbol. + ----------------------------------------------------------------------------- + + stype0 <= rxData_i(31 downto 29); + parameter0 <= rxData_i(28 downto 24); + parameter1 <= rxData_i(23 downto 19); + stype1 <= rxData_i(18 downto 16); + cmd <= rxData_i(15 downto 13); + crc5 <= rxData_i(12 downto 8); + + ----------------------------------------------------------------------------- + -- Entity for CRC-5 calculation on control symbols according to the standard. + ----------------------------------------------------------------------------- + + Crc5Calculator: Crc5ITU + port map( + d_i=>rxData_i(31 downto 13), crc_o=>crc5Calculated); + + ----------------------------------------------------------------------------- + -- Entities for CRC-16 calculation on 32-bit data in frames according to the + -- standard. + ----------------------------------------------------------------------------- + + -- If the CRC is correct, there is either zero in crc16Next if no pad exists + -- or zero in crc16Temp and crc16Data(15 downto 0). This means that crc16Next + -- will always be zero here if the CRC is correct. + crc16Valid <= '1' when (crc16Next = x"0000") else '0'; + + 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); + + ----------------------------------------------------------------------------- + -- Main inbound symbol handler. + ----------------------------------------------------------------------------- + rxRead_o <= rxRead; + inboundAckId_o <= std_logic_vector(ackId); + process(areset_n, clk) + begin + if (areset_n = '0') then + state <= STATE_UNINITIALIZED; + + rxRead <= '0'; + txControlWrite_o <= '0'; + txControlSymbol_o <= (others => '0'); + rxControlWrite_o <= '0'; + rxControlSymbol_o <= (others => '0'); + + writeFrame_o <= '0'; + writeFrameAbort_o <= '0'; + writeContent_o <= '0'; + writeContentData_o <= (others => '0'); + + -- REMARK: Use frameIndex instead of this... + statusCounter <= 0; + + frameIndex <= 0; + ackId <= (others => '0'); + + crc16Current <= (others => '0'); + crc16Data <= (others => '0'); + elsif (clk'event and clk = '1') then + rxRead <= '0'; + + txControlWrite_o <= '0'; + rxControlWrite_o <= '0'; + + writeFrame_o <= '0'; + writeFrameAbort_o <= '0'; + writeContent_o <= '0'; + + -- Check if a locakAckIdWrite is active. + if (localAckIdWrite_i = '1') then + -- A localAckIdWrite is active. + -- Set ackId. + ackId <= unsigned(inboundAckId_i); + else + -- A localAckIdWrite is not active. + + -- Act on the current state. + case state is + + when STATE_UNINITIALIZED => + ----------------------------------------------------------------------- + -- This state is entered at startup. A port that is not initialized + -- should discard all received symbols. + ----------------------------------------------------------------------- + + -- Check if the port is initialized. + if (portInitialized_i = '0') then + -- Port not initialized. + + -- Check if a new symbol is ready to be read. + if (rxRead = '0') and (rxEmpty_i = '0') then + -- New symbol ready. + -- Discard all received symbols in this state. + rxRead <= '1'; + else + -- No new symbol ready to be read. + -- Dont do anything. + end if; + else + -- Port is initialized. + + -- Go to the initialized state and reset the counters. + state <= STATE_PORT_INITIALIZED; + statusCounter <= 0; + end if; + + when STATE_PORT_INITIALIZED => + --------------------------------------------------------------------- + -- The port has been initialized and status control symbols are being + -- received on the link to check if it is working. Count the number + -- of error-free status symbols and considder the link initialized + -- when enough of them has been received. Frames are not allowed + -- here. + --------------------------------------------------------------------- + + -- Check if the port is initialized. + if (portInitialized_i = '1') then + -- Port is initialized. + + -- Check if a new symbol is ready to be read. + if (rxRead = '0') and (rxEmpty_i = '0') then + -- There is a new symbol to read. + + -- Check the type of symbol. + if (rxControl_i = SYMBOL_CONTROL) then + -- This is a control symbol that is not a packet delimiter. + + -- Check if the control symbol has a valid checksum. + if (crc5Calculated = crc5) then + -- The control symbol has a valid checksum. + + -- Forward the stype0 part of the symbol to the transmitter. + txControlWrite_o <= '1'; + txControlSymbol_o <= stype0 & parameter0 & parameter1; + + -- Check the stype0 part if we should count the number of + -- error-free status symbols. + if (stype0 = STYPE0_STATUS) then + -- The symbol is a status. + + -- Check if enough status symbols have been received. + if (statusCounter = 7) then + -- Enough status symbols have been received. + + -- Reset all packets. + frameIndex <= 0; + writeFrameAbort_o <= '1'; + + -- Set the link as initialized. + state <= STATE_NORMAL; + else + -- Increase the number of error-free status symbols that + -- has been received. + statusCounter <= statusCounter + 1; + end if; + else + -- The symbol is not a status. + -- Dont do anything. + end if; + else + -- A control symbol with CRC5 error was recevied. + statusCounter <= 0; + end if; + else + -- Symbol that is not allowed in this state have been received. + -- Discard it. + end if; + + -- Update to the next symbol. + rxRead <= '1'; + else + -- No new symbol ready to be read. + -- Dont do anything. + end if; + else + -- Go back to the uninitialized state. + state <= STATE_UNINITIALIZED; + end if; + + when STATE_NORMAL => + --------------------------------------------------------------------- + -- The port has been initialized and enough error free status symbols + -- have been received. Forward data frames to the frame buffer + -- interface. This is the normal operational state. + --------------------------------------------------------------------- + + -- Check that the port is initialized. + if (portInitialized_i = '1') then + -- The port and link is initialized. + + -- Check if a new symbol is ready to be read. + if (rxRead = '0') and (rxEmpty_i = '0') then + -- There is a new symbol to read. + + -- Check the type of symbol. + if (rxControl_i = SYMBOL_CONTROL) then + -- This is a control symbol with or without a packet delimiter. + + -- Check if the control symbol has a valid CRC-5. + if (crc5Calculated = crc5) then + -- The control symbol is correct. + + -- Forward the stype0 part of the symbol to the transmitter. + txControlWrite_o <= '1'; + txControlSymbol_o <= stype0 & parameter0 & parameter1; + + -- Check the stype1 part. + case stype1 is + + when STYPE1_START_OF_PACKET => + ------------------------------------------------------------- + -- Start the reception of a new frame or end a currently + -- ongoing frame. + ------------------------------------------------------------- + + -- Check if a frame has already been started. + if (frameIndex /= 0) then + -- A frame is already started. + -- Complete the last frame and start to ackumulate a new one + -- and update the ackId. + + -- Check the CRC-16 and the length of the received frame. + if (crc16Valid = '1') and (frameIndex > 3) then + -- The CRC-16 is ok. + + -- Reset the frame index to indicate the frame is started. + frameIndex <= 1; + + -- Update the frame buffer to indicate that the frame has + -- been completly received. + writeFrame_o <= '1'; + + -- Update ackId. + ackId <= ackId + 1; + + -- Send packet-accepted. + -- The buffer status is appended by the transmitter + -- when sent to get the latest number. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_ACCEPTED & std_logic_vector(ackId) & "11111"; + else + -- The CRC-16 is not ok. + + -- Make the transmitter send a packet-not-accepted to indicate + -- that the received packet contained a CRC error. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_NOT_ACCEPTED & + "00000" & + PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC; + state <= STATE_INPUT_ERROR_STOPPED; + end if; + else + -- No frame has been started. + + -- Reset the frame index to indicate the frame is started. + frameIndex <= 1; + end if; + + when STYPE1_END_OF_PACKET => + ------------------------------------------------------------- + -- End the reception of an old frame. + ------------------------------------------------------------- + + -- Check the CRC-16 and the length of the received frame. + if (crc16Valid = '1') and (frameIndex > 3) then + -- The CRC-16 is ok. + + -- Reset frame reception to indicate that no frame is ongoing. + frameIndex <= 0; + + -- Update the frame buffer to indicate that the frame has + -- been completly received. + writeFrame_o <= '1'; + + -- Update ackId. + ackId <= ackId + 1; + + -- Send packet-accepted. + -- The buffer status is appended by the transmitter + -- when sent to get the latest number. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_ACCEPTED & std_logic_vector(ackId) & "11111"; + else + -- The CRC-16 is not ok. + + -- Make the transmitter send a packet-not-accepted to indicate + -- that the received packet contained a CRC error. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_NOT_ACCEPTED & + "00000" & + PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC; + state <= STATE_INPUT_ERROR_STOPPED; + end if; + + when STYPE1_STOMP => + ------------------------------------------------------------- + -- Restart the reception of an old frame. + ------------------------------------------------------------- + -- See 5.10 in the standard. + + -- Make the transmitter send a packet-retry to indicate + -- that the packet cannot be accepted. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_RETRY & std_logic_vector(ackId) & "11111"; + + -- Enter the input retry-stopped state. + state <= STATE_INPUT_RETRY_STOPPED; + + when STYPE1_RESTART_FROM_RETRY => + ------------------------------------------------------------- + -- The receiver indicates a restart from a retry sent + -- from us. + ------------------------------------------------------------- + -- See 5.10 in the standard. + -- Protocol error, this symbol should not be received here since + -- we should have been in input-retry-stopped. + + -- Send a packet-not-accepted to indicate that a protocol + -- error has occurred. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_NOT_ACCEPTED & + "00000" & + PACKET_NOT_ACCEPTED_CAUSE_GENERAL_ERROR; + state <= STATE_INPUT_ERROR_STOPPED; + + when STYPE1_LINK_REQUEST => + ------------------------------------------------------------- + -- Reply to a LINK-REQUEST. + ------------------------------------------------------------- + + -- Check the command part. + if (cmd = "100") then + -- Return input port status command. + -- This functions as a link-request(restart-from-error) + -- control symbol under error situations. + + -- Send a link response containing an ok reply. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_LINK_RESPONSE & std_logic_vector(ackId) & "10000"; + elsif (cmd = "011") then + -- Reset device command. + -- Discard this. + else + -- Unsupported command. + -- Discard this. + end if; + + -- Abort the frame and reset frame reception. + frameIndex <= 0; + writeFrameAbort_o <= '1'; + + when STYPE1_MULTICAST_EVENT => + ------------------------------------------------------------- + -- Multicast symbol. + ------------------------------------------------------------- + -- Discard the symbol. + + when STYPE1_RESERVED => + ------------------------------------------------------------- + -- Reserved. + ------------------------------------------------------------- + -- Not supported, dont do anything. + + when STYPE1_NOP => + ------------------------------------------------------------- + -- NOP, no operation. + ------------------------------------------------------------- + -- Dont do anything. + + when others => + ------------------------------------------------------------- + -- + ------------------------------------------------------------- + -- NOP, no operation, dont do anything. + null; + + end case; + else + -- The control symbol contains a crc error. + + -- Send a packet-not-accepted to indicate that a corrupted + -- control-symbol has been received and change state. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_NOT_ACCEPTED & + "00000" & + PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC; + state <= STATE_INPUT_ERROR_STOPPED; + end if; + elsif (rxControl_i = SYMBOL_DATA) then + -- This is a data symbol. + -- REMARK: Add check for in-the-middle-crc here... + + -- Check if a frame has been started. + -- Index=0 not started + -- index=1 started and expecting to receive the first data. + -- index=others, the index of the received data. + if (frameIndex /= 0) and (frameIndex /= 70) then + -- A frame has been started and is not too long. + + -- Check if the ackId is correct. + if (((frameIndex = 1) and (unsigned(rxData_i(31 downto 27)) = ackId)) or + (frameIndex /= 1)) then + -- This is the first data symbol containing the ackId which + -- is matching or receiving the rest of the frame. + + -- Check if the packet ftype is allowed. + -- If the portEnable is deasserted only maintenance + -- packets are allowed. + if (((frameIndex = 1) and + ((portEnable_i = '1') or (rxData_i(19 downto 16) = FTYPE_MAINTENANCE_CLASS))) or + (frameIndex /= 1)) then + -- The packet is allowed. + + -- Check if there is buffers available to store the new packet. + if(writeFrameFull_i = '0') then + -- There is buffering space available to store the new data. + + -- Write the data to the frame FIFO. + writeContent_o <= '1'; + writeContentData_o <= rxData_i; + + -- Increment the number of received data symbols. + frameIndex <= frameIndex + 1; + + -- Update the saved crc result with the output from the CRC calculation. + if (frameIndex = 1) then + -- Note that the ackId should not be included when the CRC + -- is calculated. + crc16Data <= "000000" & rxData_i(25 downto 0); + crc16Current <= (others => '1'); + else + crc16Data <= rxData_i; + crc16Current <= crc16Next; + end if; + else + -- The packet buffer is full. + -- Let the link-partner resend the packet. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_RETRY & std_logic_vector(ackId) & "11111"; + state <= STATE_INPUT_RETRY_STOPPED; + end if; + else + -- The non-maintenance packets are not allowed. + -- Send packet-not-accepted. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= + STYPE0_PACKET_NOT_ACCEPTED & "00000" & PACKET_NOT_ACCEPTED_CAUSE_NON_MAINTENANCE_STOPPED; + state <= STATE_INPUT_ERROR_STOPPED; + end if; + else + -- The ackId is unexpected. + -- Send packet-not-accepted. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= + STYPE0_PACKET_NOT_ACCEPTED & "00000" & PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID; + state <= STATE_INPUT_ERROR_STOPPED; + end if; + else + -- A frame has not been started or is too long. + -- Send packet-not-accepted. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_NOT_ACCEPTED & "00000" & PACKET_NOT_ACCEPTED_CAUSE_GENERAL_ERROR; + state <= STATE_INPUT_ERROR_STOPPED; + end if; + else + -- Idle sequence received. + -- Discard these. + end if; + + -- Update to the next symbol. + rxRead <= '1'; + else + -- No new symbol received. + -- Dont do anything. + end if; + else + -- The port has become uninitialized. + -- Go back to the uninitialized state. + state <= STATE_UNINITIALIZED; + end if; + + when STATE_INPUT_RETRY_STOPPED => + --------------------------------------------------------------------- + -- This state is entered when a frame could not be accepted. All + -- symbols except restart-from-retry and link-request are discarded. + -- A restart-from-retry triggers a state change into the normal + -- link-initialized state. + --------------------------------------------------------------------- + + -- Check that the port is initialized. + if (portInitialized_i = '1') then + -- The port and link is initialized. + + -- Check if a new symbol is ready to be read. + if (rxRead = '0') and (rxEmpty_i = '0') then + -- There is a new symbol to read. + + -- Check the type of symbol. + if (rxControl_i = SYMBOL_CONTROL) then + -- This is a control symbol with or without a packet delimiter. + + -- Check if the control symbol has a valid CRC-5. + if (crc5Calculated = crc5) then + -- The control symbol is correct. + + -- Forward the stype0 part of the symbol to the transmitter. + txControlWrite_o <= '1'; + txControlSymbol_o <= stype0 & parameter0 & parameter1; + + -- Check the stype1 part. + case stype1 is + + when STYPE1_RESTART_FROM_RETRY => + ------------------------------------------------------------- + -- The receiver indicates a restart from a retry sent + -- from us. + ------------------------------------------------------------- + + -- Abort the frame and reset frame reception. + frameIndex <= 0; + writeFrameAbort_o <= '1'; + + -- Go back to the normal operational state. + state <= STATE_NORMAL; + + when STYPE1_LINK_REQUEST => + ------------------------------------------------------------- + -- Received a link-request. + ------------------------------------------------------------- + + -- Check the command part. + if (cmd = "100") then + -- Return input port status command. + -- This functions as a link-request(restart-from-error) + -- control symbol under error situations. + + -- Send a link response containing an ok reply. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_LINK_RESPONSE & std_logic_vector(ackId) & "00100"; + elsif (cmd = "011") then + -- Reset device command. + -- Discard this. + else + -- Unsupported command. + -- Discard this. + end if; + + -- Abort the frame and reset frame reception. + frameIndex <= 0; + writeFrameAbort_o <= '1'; + + -- Go back to the normal operational state. + state <= STATE_NORMAL; + + when others => + ------------------------------------------------------------- + -- + ------------------------------------------------------------- + -- Discard other control symbols. + null; + + end case; + else + -- The control symbol contains a crc error. + + -- Send a packet-not-accepted to indicate that a corrupted + -- control-symbol has been received and change state. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_PACKET_NOT_ACCEPTED & + "00000" & + PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC; + state <= STATE_INPUT_ERROR_STOPPED; + end if; + elsif (rxControl_i = SYMBOL_DATA) then + -- This is a data symbol. + -- Discard all data symbols in this state. + else + -- Idle sequence received. + -- Discard other symbols. + end if; + + -- Update to the next symbol. + rxRead <= '1'; + else + -- No new symbol received. + -- Dont do anything. + end if; + else + -- The port has become uninitialized. + -- Go back to the uninitialized state. + state <= STATE_UNINITIALIZED; + end if; + + when STATE_INPUT_ERROR_STOPPED => + --------------------------------------------------------------------- + -- This state is entered when an error situation has occurred. When in this + -- state, all symbols should be discarded until a link-request-symbols has + -- been received. See section 5.13.2.6 in part 6 of the standard. + -- Note that it is only the input side of the port that are affected, not the + -- output side. Packets may still be transmitted and acknowledges should be + -- accepted. + --------------------------------------------------------------------- + + -- Check that the port is initialized. + if (portInitialized_i = '1') then + -- The port and link is initialized. + + -- Check if a new symbol is ready to be read. + if (rxRead = '0') and (rxEmpty_i = '0') then + -- There is a new symbol to read. + + -- Check the type of symbol. + if (rxControl_i = SYMBOL_CONTROL) then + -- This is a control symbol with or without a packet delimiter. + + -- Check if the control symbol has a valid CRC-5. + if (crc5Calculated = crc5) then + -- The control symbol is correct. + + -- Forward the stype0 part of the symbol to the transmitter. + txControlWrite_o <= '1'; + txControlSymbol_o <= stype0 & parameter0 & parameter1; + + -- Check the stype1 part. + case stype1 is + + when STYPE1_LINK_REQUEST => + ------------------------------------------------------------- + -- Received a link-request. + ------------------------------------------------------------- + + -- Check the command part. + -- REMARK: Should also send a status-control-symbol + -- directly following this symbol... + if (cmd = "100") then + -- Return input port status command. + -- This functions as a link-request(restart-from-error) + -- control symbol under error situations. + + -- Send a link response containing an ok reply. + rxControlWrite_o <= '1'; + rxControlSymbol_o <= STYPE0_LINK_RESPONSE & std_logic_vector(ackId) & "00101"; + elsif (cmd = "011") then + -- Reset device command. + -- Discard this. + else + -- Unsupported command. + -- Discard this. + end if; + + -- Abort the frame and reset frame reception. + frameIndex <= 0; + writeFrameAbort_o <= '1'; + + -- Go back to the normal operational state. + state <= STATE_NORMAL; + + when others => + ------------------------------------------------------------- + -- + ------------------------------------------------------------- + -- Discard other control symbols. + null; + + end case; + else + -- The control symbol contains a crc error. + -- Error is ignored in this state. + end if; + else + -- Other symbol received. + -- All other symbols are discarded in this state. + end if; + + -- Update to the next symbol. + rxRead <= '1'; + else + -- No new symbol received. + -- Dont do anything. + end if; + else + -- The port has become uninitialized. + -- Go back to the uninitialized state. + state <= STATE_UNINITIALIZED; + end if; + + when others => + --------------------------------------------------------------------- + -- + --------------------------------------------------------------------- + null; + end case; + end if; + end if; + end process; + +end architecture; + + + +------------------------------------------------------------------------------- +-- A CRC-5 calculator following the implementation proposed in the 2.2 +-- standard. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; + + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- +entity Crc5ITU is + port( + d_i : in std_logic_vector(18 downto 0); + crc_o : out std_logic_vector(4 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- +architecture Crc5Impl of Crc5ITU is + signal d : std_logic_vector(0 to 18); + signal c : std_logic_vector(0 to 4); + +begin + -- Reverse the bit vector indexes to make them the same as in the standard. + d(18) <= d_i(0); d(17) <= d_i(1); d(16) <= d_i(2); d(15) <= d_i(3); + d(14) <= d_i(4); d(13) <= d_i(5); d(12) <= d_i(6); d(11) <= d_i(7); + d(10) <= d_i(8); d(9) <= d_i(9); d(8) <= d_i(10); d(7) <= d_i(11); + d(6) <= d_i(12); d(5) <= d_i(13); d(4) <= d_i(14); d(3) <= d_i(15); + d(2) <= d_i(16); d(1) <= d_i(17); d(0) <= d_i(18); + + -- Calculate the resulting crc. + c(0) <= d(18) xor d(16) xor d(15) xor d(12) xor + d(10) xor d(5) xor d(4) xor d(3) xor + d(1) xor d(0); + c(1) <= (not d(18)) xor d(17) xor d(15) xor d(13) xor + d(12) xor d(11) xor d(10) xor d(6) xor + d(3) xor d(2) xor d(0); + c(2) <= (not d(18)) xor d(16) xor d(14) xor d(13) xor + d(12) xor d(11) xor d(7) xor d(4) xor + d(3) xor d(1); + c(3) <= (not d(18)) xor d(17) xor d(16) xor d(14) xor + d(13) xor d(10) xor d(8) xor d(3) xor + d(2) xor d(1); + c(4) <= d(18) xor d(17) xor d(15) xor d(14) xor + d(11) xor d(9) xor d(4) xor d(3) xor + d(2) xor d(0); + + -- Reverse the bit vector indexes to make them the same as in the standard. + crc_o(4) <= c(0); crc_o(3) <= c(1); crc_o(2) <= c(2); crc_o(1) <= c(3); + crc_o(0) <= c(4); +end architecture;
1.0.1/rtl/vhdl/RioSerial.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/rtl/vhdl/RioPacketBuffer.vhd =================================================================== --- 1.0.1/rtl/vhdl/RioPacketBuffer.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/RioPacketBuffer.vhd (revision 29) @@ -0,0 +1,873 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- Containing RapidIO packet buffering functionallity. Two different entities +-- are implemented, one with transmission window support and one without. +-- +-- 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 +-- +------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- RioPacketBuffer +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for RioPacketBuffer. +-- +-- Generic variables +-- ----------------- +-- SIZE_ADDRESS_WIDTH - The number of frames in powers of two. +-- CONTENT_ADDRESS_WIDTH - The total number of entries in the memory that can +-- be used to store packet data. +-- CONTENT_WIDTH - The width of the data to store as packet content in the memory. +-- MAX_PACKET_SIZE - The number of entries that must be available for a new +-- complete full sized packet to be received. This option is present to ensure +-- that it is always possible to move a packet to the storage without being +-- surprised that the storage is suddenly empty. +------------------------------------------------------------------------------- +entity RioPacketBuffer is + generic( + SIZE_ADDRESS_WIDTH : natural := 6; + CONTENT_ADDRESS_WIDTH : natural := 8; + CONTENT_WIDTH : natural := 32; + MAX_PACKET_SIZE : natural := 69); + port( + clk : in std_logic; + areset_n : in std_logic; + + inboundWriteFrameFull_o : out std_logic; + inboundWriteFrame_i : in std_logic; + inboundWriteFrameAbort_i : in std_logic; + inboundWriteContent_i : in std_logic; + inboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0); + inboundReadFrameEmpty_o : out std_logic; + inboundReadFrame_i : in std_logic; + inboundReadFrameRestart_i : in std_logic; + inboundReadFrameAborted_o : out std_logic; + inboundReadFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0); + inboundReadContentEmpty_o : out std_logic; + inboundReadContent_i : in std_logic; + inboundReadContentEnd_o : out std_logic; + inboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0); + + outboundWriteFrameFull_o : out std_logic; + outboundWriteFrame_i : in std_logic; + outboundWriteFrameAbort_i : in std_logic; + outboundWriteContent_i : in std_logic; + outboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0); + outboundReadFrameEmpty_o : out std_logic; + outboundReadFrame_i : in std_logic; + outboundReadFrameRestart_i : in std_logic; + outboundReadFrameAborted_o : out std_logic; + outboundReadFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0); + outboundReadContentEmpty_o : out std_logic; + outboundReadContent_i : in std_logic; + outboundReadContentEnd_o : out std_logic; + outboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioPacketBuffer. +------------------------------------------------------------------------------- +architecture RioPacketBufferImpl of RioPacketBuffer is + + component PacketBufferContinous is + generic( + SIZE_ADDRESS_WIDTH : natural; + CONTENT_ADDRESS_WIDTH : natural; + CONTENT_WIDTH : natural; + MAX_PACKET_SIZE : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + 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(CONTENT_WIDTH-1 downto 0); + + readFrameEmpty_o : out std_logic; + readFrame_i : in std_logic; + readFrameRestart_i : in std_logic; + readFrameAborted_o : out std_logic; + readFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0); + readContentEmpty_o : out std_logic; + readContent_i : in std_logic; + readContentEnd_o : out std_logic; + readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0)); + end component; + +begin + + ----------------------------------------------------------------------------- + -- Outbound frame buffers. + ----------------------------------------------------------------------------- + OutboundPacketBuffer: PacketBufferContinous + generic map( + SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH, + CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, + CONTENT_WIDTH=>CONTENT_WIDTH, + MAX_PACKET_SIZE=>MAX_PACKET_SIZE) + port map( + clk=>clk, + areset_n=>areset_n, + writeFrameFull_o=>outboundWriteFrameFull_o, + writeFrame_i=>outboundWriteFrame_i, writeFrameAbort_i=>outboundWriteFrameAbort_i, + writeContent_i=>outboundWriteContent_i, writeContentData_i=>outboundWriteContentData_i, + + readFrameEmpty_o=>outboundReadFrameEmpty_o, + readFrame_i=>outboundReadFrame_i, readFrameRestart_i=>outboundReadFrameRestart_i, + readFrameAborted_o=>outboundReadFrameAborted_o, + readFrameSize_o=>outboundReadFrameSize_o, + readContentEmpty_o=>outboundReadContentEmpty_o, + readContent_i=>outboundReadContent_i, readContentEnd_o=>outboundReadContentEnd_o, + readContentData_o=>outboundReadContentData_o); + + ----------------------------------------------------------------------------- + -- Inbound frame buffers. + ----------------------------------------------------------------------------- + InboundPacketBuffer: PacketBufferContinous + generic map( + SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH, + CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, + CONTENT_WIDTH=>CONTENT_WIDTH, + MAX_PACKET_SIZE=>MAX_PACKET_SIZE) + port map( + clk=>clk, + areset_n=>areset_n, + writeFrameFull_o=>inboundWriteFrameFull_o, + writeFrame_i=>inboundWriteFrame_i, writeFrameAbort_i=>inboundWriteFrameAbort_i, + writeContent_i=>inboundWriteContent_i, writeContentData_i=>inboundWriteContentData_i, + + readFrameEmpty_o=>inboundReadFrameEmpty_o, + readFrame_i=>inboundReadFrame_i, readFrameRestart_i=>inboundReadFrameRestart_i, + readFrameAborted_o=>inboundReadFrameAborted_o, + readFrameSize_o=>inboundReadFrameSize_o, + readContentEmpty_o=>inboundReadContentEmpty_o, + readContent_i=>inboundReadContent_i, readContentEnd_o=>inboundReadContentEnd_o, + readContentData_o=>inboundReadContentData_o); + +end architecture; + + + + +------------------------------------------------------------------------------- +-- RioPacketBufferWindow +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for RioPacketBufferWindow. +------------------------------------------------------------------------------- +entity RioPacketBufferWindow is + generic( + SIZE_ADDRESS_WIDTH : natural := 6; + CONTENT_ADDRESS_WIDTH : natural := 8; + CONTENT_WIDTH : natural := 32; + MAX_PACKET_SIZE : natural := 69); + port( + clk : in std_logic; + areset_n : in std_logic; + + inboundWriteFrameFull_o : out std_logic; + inboundWriteFrame_i : in std_logic; + inboundWriteFrameAbort_i : in std_logic; + inboundWriteContent_i : in std_logic; + inboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0); + inboundReadFrameEmpty_o : out std_logic; + inboundReadFrame_i : in std_logic; + inboundReadFrameRestart_i : in std_logic; + inboundReadFrameAborted_o : out std_logic; + inboundReadContentEmpty_o : out std_logic; + inboundReadContent_i : in std_logic; + inboundReadContentEnd_o : out std_logic; + inboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0); + + outboundWriteFrameFull_o : out std_logic; + outboundWriteFrame_i : in std_logic; + outboundWriteFrameAbort_i : in std_logic; + outboundWriteContent_i : in std_logic; + outboundWriteContentData_i : in std_logic_vector(CONTENT_WIDTH-1 downto 0); + outboundReadFrameEmpty_o : out std_logic; + outboundReadFrame_i : in std_logic; + outboundReadFrameRestart_i : in std_logic; + outboundReadFrameAborted_o : out std_logic; + outboundReadWindowEmpty_o : out std_logic; + outboundReadWindowReset_i : in std_logic; + outboundReadWindowNext_i : in std_logic; + outboundReadContentEmpty_o : out std_logic; + outboundReadContent_i : in std_logic; + outboundReadContentEnd_o : out std_logic; + outboundReadContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioPacketBufferWindow. +------------------------------------------------------------------------------- +architecture RioPacketBufferWindowImpl of RioPacketBufferWindow is + + component PacketBufferContinous is + generic( + SIZE_ADDRESS_WIDTH : natural; + CONTENT_ADDRESS_WIDTH : natural; + CONTENT_WIDTH : natural; + MAX_PACKET_SIZE : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + 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(CONTENT_WIDTH-1 downto 0); + + readFrameEmpty_o : out std_logic; + readFrame_i : in std_logic; + readFrameRestart_i : in std_logic; + readFrameAborted_o : out std_logic; + readFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0); + + readContentEmpty_o : out std_logic; + readContent_i : in std_logic; + readContentEnd_o : out std_logic; + readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0)); + end component; + + component PacketBufferContinousWindow is + generic( + SIZE_ADDRESS_WIDTH : natural; + CONTENT_ADDRESS_WIDTH : natural; + CONTENT_WIDTH : natural; + MAX_PACKET_SIZE : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + 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(CONTENT_WIDTH-1 downto 0); + + readFrameEmpty_o : out std_logic; + readFrame_i : in std_logic; + readFrameRestart_i : in std_logic; + readFrameAborted_o : out std_logic; + + readWindowEmpty_o : out std_logic; + readWindowReset_i : in std_logic; + readWindowNext_i : in std_logic; + + readContentEmpty_o : out std_logic; + readContent_i : in std_logic; + readContentEnd_o : out std_logic; + readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0)); + end component; + +begin + + ----------------------------------------------------------------------------- + -- Outbound frame buffers. + ----------------------------------------------------------------------------- + OutboundPacketBuffer: PacketBufferContinousWindow + generic map( + SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH, + CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, + CONTENT_WIDTH=>CONTENT_WIDTH, + MAX_PACKET_SIZE=>MAX_PACKET_SIZE) + port map( + clk=>clk, + areset_n=>areset_n, + writeFrameFull_o=>outboundWriteFrameFull_o, + writeFrame_i=>outboundWriteFrame_i, writeFrameAbort_i=>outboundWriteFrameAbort_i, + writeContent_i=>outboundWriteContent_i, writeContentData_i=>outboundWriteContentData_i, + + readFrameEmpty_o=>outboundReadFrameEmpty_o, + readFrame_i=>outboundReadFrame_i, readFrameRestart_i=>outboundReadFrameRestart_i, + readFrameAborted_o=>outboundReadFrameAborted_o, + readWindowEmpty_o=>outboundReadWindowEmpty_o, + readWindowReset_i=>outboundReadWindowReset_i, + readWindowNext_i=>outboundReadWindowNext_i, + readContentEmpty_o=>outboundReadContentEmpty_o, + readContent_i=>outboundReadContent_i, readContentEnd_o=>outboundReadContentEnd_o, + readContentData_o=>outboundReadContentData_o); + + ----------------------------------------------------------------------------- + -- Inbound frame buffers. + ----------------------------------------------------------------------------- + InboundPacketBuffer: PacketBufferContinous + generic map( + SIZE_ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH, + CONTENT_ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, + CONTENT_WIDTH=>CONTENT_WIDTH, + MAX_PACKET_SIZE=>MAX_PACKET_SIZE) + port map( + clk=>clk, + areset_n=>areset_n, + writeFrameFull_o=>inboundWriteFrameFull_o, + writeFrame_i=>inboundWriteFrame_i, writeFrameAbort_i=>inboundWriteFrameAbort_i, + writeContent_i=>inboundWriteContent_i, writeContentData_i=>inboundWriteContentData_i, + + readFrameEmpty_o=>inboundReadFrameEmpty_o, + readFrame_i=>inboundReadFrame_i, readFrameRestart_i=>inboundReadFrameRestart_i, + readFrameAborted_o=>inboundReadFrameAborted_o, + readFrameSize_o=>open, + readContentEmpty_o=>inboundReadContentEmpty_o, + readContent_i=>inboundReadContent_i, readContentEnd_o=>inboundReadContentEnd_o, + readContentData_o=>inboundReadContentData_o); + +end architecture; + + + + +------------------------------------------------------------------------------- +-- PacketBufferContinous +-- This component stores data in chuncks and stores the size of them. The full +-- memory can be used, except for one word, or a specified (using generic) +-- maximum number of frames. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +------------------------------------------------------------------------------- +-- Entity for PacketBufferContinous. +------------------------------------------------------------------------------- +entity PacketBufferContinous is + generic( + SIZE_ADDRESS_WIDTH : natural; + CONTENT_ADDRESS_WIDTH : natural; + CONTENT_WIDTH : natural; + MAX_PACKET_SIZE : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + 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(CONTENT_WIDTH-1 downto 0); + + readFrameEmpty_o : out std_logic; + readFrame_i : in std_logic; + readFrameRestart_i : in std_logic; + readFrameAborted_o : out std_logic; + readFrameSize_o : out std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0); + + readContentEmpty_o : out std_logic; + readContent_i : in std_logic; + readContentEnd_o : out std_logic; + readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for PacketBufferContinous. +------------------------------------------------------------------------------- +architecture PacketBufferContinousImpl of PacketBufferContinous is + + component MemorySimpleDualPortAsync 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); + + 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 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 component; + + -- The number of available word positions left in the memory. + signal available : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The position to place new frames. + signal backIndex, backIndexNext : unsigned(SIZE_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The position to remove old frames. + signal frontIndex, frontIndexNext : unsigned(SIZE_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The size of the current frame. + signal readFrameEnd_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The start of unread content. + signal memoryStart_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The current reading position. + signal memoryRead_p, memoryReadNext_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The end of unread content. + signal memoryEnd_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The current writing position. + signal memoryWrite_p, memoryWriteNext_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- Memory output signal containing the position of a frame. + signal framePositionReadData : std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); +begin + + ----------------------------------------------------------------------------- + -- Internal signal assignments. + ----------------------------------------------------------------------------- + + available <= not (memoryEnd_p - memoryStart_p); + + backIndexNext <= backIndex + 1; + frontIndexNext <= frontIndex + 1; + + memoryWriteNext_p <= memoryWrite_p + 1; + memoryReadNext_p <= memoryRead_p + 1; + + ----------------------------------------------------------------------------- + -- Writer logic. + ----------------------------------------------------------------------------- + + writeFrameFull_o <= '1' when ((backIndexNext = frontIndex) or + (available < MAX_PACKET_SIZE)) else '0'; + + Writer: process(clk, areset_n) + begin + if (areset_n = '0') then + backIndex <= (others=>'0'); + + memoryEnd_p <= (others=>'0'); + memoryWrite_p <= (others=>'0'); + elsif (clk'event and clk = '1') then + + if (writeFrameAbort_i = '1') then + memoryWrite_p <= memoryEnd_p; + elsif (writeContent_i = '1') then + memoryWrite_p <= memoryWriteNext_p; + end if; + + if(writeFrame_i = '1') then + memoryEnd_p <= memoryWrite_p; + backIndex <= backIndexNext; + end if; + + end if; + end process; + + ----------------------------------------------------------------------------- + -- Frame cancellation logic. + ----------------------------------------------------------------------------- + + process(clk, areset_n) + begin + if (areset_n = '0') then + readFrameAborted_o <= '0'; + elsif (clk'event and clk = '1') then + + if ((frontIndex = backIndex) and + ((writeFrameAbort_i = '1') and (readFrameRestart_i = '0'))) then + readFrameAborted_o <= '1'; + elsif ((writeFrameAbort_i = '0') and (readFrameRestart_i = '1')) then + readFrameAborted_o <= '0'; + end if; + + end if; + end process; + + ----------------------------------------------------------------------------- + -- Reader logic. + ----------------------------------------------------------------------------- + + readFrameEmpty_o <= '1' when (frontIndex = backIndex) else '0'; + readContentEmpty_o <= '1' when ((frontIndex = backIndex) and + (memoryWrite_p = memoryRead_p)) else '0'; + readFrameSize_o <= std_logic_vector(readFrameEnd_p - memoryStart_p); + + Reader: process(clk, areset_n) + begin + if (areset_n = '0') then + frontIndex <= (others=>'0'); + + memoryStart_p <= (others=>'0'); + memoryRead_p <= (others=>'0'); + + readContentEnd_o <= '0'; + elsif (clk'event and clk = '1') then + + -- REMARK: Break apart into registers to avoid priority ladder??? + if(readFrameRestart_i = '1') then + memoryRead_p <= memoryStart_p; + elsif(readContent_i = '1') then + if(memoryRead_p = readFrameEnd_p) then + readContentEnd_o <= '1'; + else + readContentEnd_o <= '0'; + memoryRead_p <= memoryReadNext_p; + end if; + elsif(readFrame_i = '1') then + memoryStart_p <= readFrameEnd_p; + frontIndex <= frontIndexNext; + memoryRead_p <= readFrameEnd_p; + end if; + + end if; + end process; + + ----------------------------------------------------------------------------- + -- Frame positioning memory signals. + ----------------------------------------------------------------------------- + + readFrameEnd_p <= unsigned(framePositionReadData); + + -- Memory to keep frame starting/ending positions in. + FramePosition: MemorySimpleDualPortAsync + generic map(ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH, DATA_WIDTH=>CONTENT_ADDRESS_WIDTH) + port map( + clkA_i=>clk, enableA_i=>writeFrame_i, + addressA_i=>std_logic_vector(backIndex), dataA_i=>std_logic_vector(memoryWrite_p), + addressB_i=>std_logic_vector(frontIndex), dataB_o=>framePositionReadData); + + ----------------------------------------------------------------------------- + -- Frame content memory signals. + ----------------------------------------------------------------------------- + + -- Memory to keep frame content in. + -- REMARK: Use paritybits here as well to make sure the frame data does not + -- become corrupt??? + FrameContent: MemorySimpleDualPort + generic map(ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, DATA_WIDTH=>CONTENT_WIDTH) + port map( + clkA_i=>clk, enableA_i=>writeContent_i, + addressA_i=>std_logic_vector(memoryWrite_p), dataA_i=>writeContentData_i, + clkB_i=>clk, enableB_i=>readContent_i, + addressB_i=>std_logic_vector(memoryRead_p), dataB_o=>readContentData_o); + +end architecture; + + + +------------------------------------------------------------------------------- +-- PacketBufferContinousWindow +-- This component stores data in chuncks and stores the size of them. The full +-- memory can be used, except for one word, or a specified (using generic) +-- maximum number of frames. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +------------------------------------------------------------------------------- +-- Entity for PacketBufferContinousWindow. +------------------------------------------------------------------------------- +entity PacketBufferContinousWindow is + generic( + SIZE_ADDRESS_WIDTH : natural; + CONTENT_ADDRESS_WIDTH : natural; + CONTENT_WIDTH : natural; + MAX_PACKET_SIZE : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + 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(CONTENT_WIDTH-1 downto 0); + + readFrameEmpty_o : out std_logic; + readFrame_i : in std_logic; + readFrameRestart_i : in std_logic; + readFrameAborted_o : out std_logic; + + readWindowEmpty_o : out std_logic; + readWindowReset_i : in std_logic; + readWindowNext_i : in std_logic; + + readContentEmpty_o : out std_logic; + readContent_i : in std_logic; + readContentEnd_o : out std_logic; + readContentData_o : out std_logic_vector(CONTENT_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for PacketBufferContinousWindow. +------------------------------------------------------------------------------- +architecture PacketBufferContinousWindowImpl of PacketBufferContinousWindow is + + component MemorySimpleDualPortAsync 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); + + 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 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 component; + + -- The number of available word positions left in the memory. + signal available : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + signal backIndex, backIndexNext : unsigned(SIZE_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + signal frontIndex, frontIndexNext : unsigned(SIZE_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + signal windowIndex, windowIndexNext : unsigned(SIZE_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The size of the current frame. + signal readFrameEnd_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The start of unread content. + signal memoryStart_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The start of unread window content. + signal memoryStartWindow_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The current reading position. + signal memoryRead_p, memoryReadNext_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The end of unread content. + signal memoryEnd_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + -- The current writing position. + signal memoryWrite_p, memoryWriteNext_p : unsigned(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + + signal framePositionReadAddress : std_logic_vector(SIZE_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); + signal framePositionReadData : std_logic_vector(CONTENT_ADDRESS_WIDTH-1 downto 0) := (others=>'0'); +begin + + ----------------------------------------------------------------------------- + -- Internal signal assignments. + ----------------------------------------------------------------------------- + + available <= not (memoryEnd_p - memoryStart_p); + + backIndexNext <= backIndex + 1; + frontIndexNext <= frontIndex + 1; + windowIndexNext <= windowIndex + 1; + + memoryWriteNext_p <= memoryWrite_p + 1; + memoryReadNext_p <= memoryRead_p + 1; + + ----------------------------------------------------------------------------- + -- Writer logic. + ----------------------------------------------------------------------------- + + writeFrameFull_o <= '1' when ((backIndexNext = frontIndex) or + (available < MAX_PACKET_SIZE)) else '0'; + + Writer: process(clk, areset_n) + begin + if (areset_n = '0') then + backIndex <= (others=>'0'); + + memoryEnd_p <= (others=>'0'); + memoryWrite_p <= (others=>'0'); + elsif (clk'event and clk = '1') then + + if (writeFrameAbort_i = '1') then + memoryWrite_p <= memoryEnd_p; + elsif (writeContent_i = '1') then + memoryWrite_p <= memoryWriteNext_p; + end if; + + if(writeFrame_i = '1') then + memoryEnd_p <= memoryWrite_p; + backIndex <= backIndexNext; + end if; + + end if; + end process; + + ----------------------------------------------------------------------------- + -- Frame cancellation logic. + ----------------------------------------------------------------------------- + + process(clk, areset_n) + begin + if (areset_n = '0') then + readFrameAborted_o <= '0'; + elsif (clk'event and clk = '1') then + + if ((windowIndex = backIndex) and + ((writeFrameAbort_i = '1') and (readFrameRestart_i = '0'))) then + readFrameAborted_o <= '1'; + elsif ((writeFrameAbort_i = '0') and (readFrameRestart_i = '1')) then + readFrameAborted_o <= '0'; + end if; + + end if; + end process; + + ----------------------------------------------------------------------------- + -- Reader logic. + ----------------------------------------------------------------------------- + + readFrameEmpty_o <= '1' when (frontIndex = backIndex) else '0'; + readWindowEmpty_o <= '1' when (windowIndex = backIndex) else '0'; + readContentEmpty_o <= '1' when ((windowIndex = backIndex) and + (memoryWrite_p = memoryRead_p)) else '0'; + + Reader: process(clk, areset_n) + begin + if (areset_n = '0') then + frontIndex <= (others=>'0'); + windowIndex <= (others=>'0'); + + memoryStart_p <= (others=>'0'); + memoryStartWindow_p <= (others=>'0'); + memoryRead_p <= (others=>'0'); + + readContentEnd_o <= '0'; + elsif (clk'event and clk = '1') then + + -- REMARK: Break apart into registers to avoid priority ladder??? + if(readFrameRestart_i = '1') then + memoryRead_p <= memoryStartWindow_p; + elsif(readContent_i = '1') then + if(memoryRead_p = readFrameEnd_p) then + readContentEnd_o <= '1'; + else + readContentEnd_o <= '0'; + memoryRead_p <= memoryReadNext_p; + end if; + elsif(readFrame_i = '1') then + memoryStart_p <= readFrameEnd_p; + frontIndex <= frontIndexNext; + elsif(readWindowReset_i = '1') then + memoryStartWindow_p <= memoryStart_p; + windowIndex <= frontIndex; + memoryRead_p <= memoryStart_p; + elsif(readWindowNext_i = '1') then + memoryStartWindow_p <= readFrameEnd_p; + windowIndex <= windowIndexNext; + memoryRead_p <= readFrameEnd_p; + end if; + + end if; + end process; + + ----------------------------------------------------------------------------- + -- Frame positioning memory signals. + ----------------------------------------------------------------------------- + + -- Assign the address from both frontIndex and windowIndex to be able to + -- share the memory between the two different types of accesses. This assumes + -- that the window is not accessed at the same time as the other signal. + framePositionReadAddress <= std_logic_vector(frontIndex) when (readFrame_i = '1') else + std_logic_vector(windowIndex); + readFrameEnd_p <= unsigned(framePositionReadData); + + -- Memory to keep frame starting/ending positions in. + FramePosition: MemorySimpleDualPortAsync + generic map(ADDRESS_WIDTH=>SIZE_ADDRESS_WIDTH, DATA_WIDTH=>CONTENT_ADDRESS_WIDTH) + port map( + clkA_i=>clk, enableA_i=>writeFrame_i, + addressA_i=>std_logic_vector(backIndex), dataA_i=>std_logic_vector(memoryWrite_p), + addressB_i=>framePositionReadAddress, dataB_o=>framePositionReadData); + + ----------------------------------------------------------------------------- + -- Frame content memory signals. + ----------------------------------------------------------------------------- + + -- Memory to keep frame content in. + -- REMARK: Use paritybits here as well to make sure the frame data does not + -- become corrupt??? + FrameContent: MemorySimpleDualPort + generic map(ADDRESS_WIDTH=>CONTENT_ADDRESS_WIDTH, DATA_WIDTH=>CONTENT_WIDTH) + port map( + clkA_i=>clk, enableA_i=>writeContent_i, + addressA_i=>std_logic_vector(memoryWrite_p), dataA_i=>writeContentData_i, + clkB_i=>clk, enableB_i=>readContent_i, + addressB_i=>std_logic_vector(memoryRead_p), dataB_o=>readContentData_o); + +end architecture;
1.0.1/rtl/vhdl/RioPacketBuffer.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/rtl/vhdl/RioPcsUart.vhd =================================================================== --- 1.0.1/rtl/vhdl/RioPcsUart.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/RioPcsUart.vhd (revision 29) @@ -0,0 +1,641 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- This file contains a PCS (Physical Control Sublayer) that can transfer +-- RapidIO symbols accross a 2Mbit 8-bit UART transmission channel. +-- The coding is similar to the coding used by PPP and uses flags (0x7e) +-- and escape-sequences (0x7d) to encode special characters. +-- +-- 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 +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- RioPcsUart +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for RioPcsUart. +------------------------------------------------------------------------------- +entity RioPcsUart is + generic( + DIVISOR_WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0); + + portInitialized_o : out std_logic; + outboundSymbolEmpty_i : in std_logic; + outboundSymbolRead_o : out std_logic; + outboundSymbol_i : in std_logic_vector(33 downto 0); + inboundSymbolFull_i : in std_logic; + inboundSymbolWrite_o : out std_logic; + inboundSymbol_o : out std_logic_vector(33 downto 0); + + serial_o : out std_logic; + serial_i : in std_logic); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioPcsUart. +------------------------------------------------------------------------------- +architecture RioPcsUartImpl of RioPcsUart is + + component RioSymbolConverter is + port( + clk : in std_logic; + areset_n : in std_logic; + + portInitialized_o : out std_logic; + outboundSymbolEmpty_i : in std_logic; + outboundSymbolRead_o : out std_logic; + outboundSymbol_i : in std_logic_vector(33 downto 0); + inboundSymbolFull_i : in std_logic; + inboundSymbolWrite_o : out std_logic; + inboundSymbol_o : out std_logic_vector(33 downto 0); + + uartEmpty_i : in std_logic; + uartRead_o : out std_logic; + uartData_i : in std_logic_vector(7 downto 0); + uartFull_i : in std_logic; + uartWrite_o : out std_logic; + uartData_o : out std_logic_vector(7 downto 0)); + end component; + + component Uart is + generic( + DIVISOR_WIDTH : natural; + DATA_WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0); + + serial_i : in std_logic; + serial_o : out std_logic; + + empty_o : out std_logic; + read_i : in std_logic; + data_o : out std_logic_vector(DATA_WIDTH-1 downto 0); + + full_o : out std_logic; + write_i : in std_logic; + data_i : in std_logic_vector(DATA_WIDTH-1 downto 0)); + end component; + + signal uartEmpty : std_logic; + signal uartRead : std_logic; + signal uartReadData : std_logic_vector(7 downto 0); + signal uartFull : std_logic; + signal uartWrite : std_logic; + signal uartWriteData : std_logic_vector(7 downto 0); + +begin + + SymbolConverter: RioSymbolConverter + port map( + clk=>clk, areset_n=>areset_n, + portInitialized_o=>portInitialized_o, + outboundSymbolEmpty_i=>outboundSymbolEmpty_i, + outboundSymbolRead_o=>outboundSymbolRead_o, outboundSymbol_i=>outboundSymbol_i, + inboundSymbolFull_i=>inboundSymbolFull_i, + inboundSymbolWrite_o=>inboundSymbolWrite_o, inboundSymbol_o=>inboundSymbol_o, + uartEmpty_i=>uartEmpty, uartRead_o=>uartRead, uartData_i=>uartReadData, + uartFull_i=>uartFull, uartWrite_o=>uartWrite, uartData_o=>uartWriteData); + + UartInst: Uart + generic map(DIVISOR_WIDTH=>DIVISOR_WIDTH, DATA_WIDTH=>8) + port map( + clk=>clk, areset_n=>areset_n, + divisor_i=>divisor_i, + serial_i=>serial_i, serial_o=>serial_o, + empty_o=>uartEmpty, read_i=>uartRead, data_o=>uartReadData, + full_o=>uartFull, write_i=>uartWrite, data_i=>uartWriteData); + +end architecture; + + + +------------------------------------------------------------------------------- +-- This module encodes and decodes RapidIO symbols for transmission on a 8-bit +-- UART using HDLC-like framing (see PPP). +-- When an idle-symbol is received it will be preceeded by an idle link for a +-- few micro seconds. This idle link time is used to synchronize the receiver +-- in the link partner that needs to know when a character is starting and not. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + + +------------------------------------------------------------------------------- +-- Entity for RioSymbolConverter. +------------------------------------------------------------------------------- +entity RioSymbolConverter is + port( + clk : in std_logic; + areset_n : in std_logic; + + portInitialized_o : out std_logic; + outboundSymbolEmpty_i : in std_logic; + outboundSymbolRead_o : out std_logic; + outboundSymbol_i : in std_logic_vector(33 downto 0); + inboundSymbolFull_i : in std_logic; + inboundSymbolWrite_o : out std_logic; + inboundSymbol_o : out std_logic_vector(33 downto 0); + + uartEmpty_i : in std_logic; + uartRead_o : out std_logic; + uartData_i : in std_logic_vector(7 downto 0); + uartFull_i : in std_logic; + uartWrite_o : out std_logic; + uartData_o : out std_logic_vector(7 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for RioSymbolConverter. +------------------------------------------------------------------------------- +architecture RioSymbolConverterImpl of RioSymbolConverter is + + -- Define the flag sequence and the control escape sequence. + constant FLAG_SEQUENCE : std_logic_vector(7 downto 0) := x"7e"; + constant CONTROL_ESCAPE : std_logic_vector(7 downto 0) := x"7d"; + constant SILENCE_TIME : natural := 4095; + constant IDLE_SYMBOL_TIME : natural := 256; + constant LINK_LOST_TIME : natural := 4095; + + type TxStateType is (STATE_SILENCE, STATE_IDLE_0, STATE_IDLE_1, + STATE_BUSY_1, STATE_BUSY_2, STATE_SEND_FLAG); + signal txState : TxStateType; + signal txStateCounter : unsigned(1 downto 0); + signal outboundSymbolData : std_logic_vector(7 downto 0); + + type RxStateType is (STATE_INIT, STATE_NORMAL); + signal rxState : RxStateType; + signal rxStateCounter : unsigned(1 downto 0); + signal escapeFound : std_logic; + + signal txTimerReset : std_logic; + signal txTimerEnable : std_logic; + signal txTimerCounter : unsigned(11 downto 0); + signal silenceTxTimerDone : std_logic; + signal idleTxTimerDone : std_logic; + + signal rxTimerReset : std_logic; + signal rxTimerEnable : std_logic; + signal rxTimerCounter : unsigned(11 downto 0); + signal lostRxTimerDone : std_logic; + + signal uartWrite : std_logic; + signal uartRead : std_logic; + +begin + + -- Set the port initialized once the receiver enters its normal state. + portInitialized_o <= '1' when (rxState = STATE_NORMAL) else '0'; + + ----------------------------------------------------------------------------- + -- Timer functionallity. + ----------------------------------------------------------------------------- + + silenceTxTimerDone <= '1' when (txTimerCounter = SILENCE_TIME) else '0'; + idleTxTimerDone <= '1' when (txTimerCounter = IDLE_SYMBOL_TIME) else '0'; + + process(areset_n, clk) + begin + if (areset_n = '0') then + txTimerCounter <= (others => '0'); + elsif (clk'event and clk = '1') then + if (txTimerReset = '1') then + txTimerCounter <= (others => '0'); + elsif (txTimerEnable = '1') then + txTimerCounter <= txTimerCounter + 1; + end if; + end if; + end process; + + lostRxTimerDone <= '1' when (rxTimerCounter = LINK_LOST_TIME) else '0'; + + process(areset_n, clk) + begin + if (areset_n = '0') then + rxTimerCounter <= (others => '0'); + elsif (clk'event and clk = '1') then + if (rxTimerReset = '1') then + rxTimerCounter <= (others => '0'); + elsif (rxTimerEnable = '1') then + rxTimerCounter <= rxTimerCounter + 1; + end if; + end if; + end process; + + ----------------------------------------------------------------------------- + -- Link symbol encoder process. + ----------------------------------------------------------------------------- + outboundSymbolData <= outboundSymbol_i(31 downto 24) when txStateCounter = 0 else + outboundSymbol_i(23 downto 16) when txStateCounter = 1 else + outboundSymbol_i(15 downto 8) when txStateCounter = 2 else + outboundSymbol_i(7 downto 0); + + uartWrite_o <= uartWrite; + Outbound: process(areset_n, clk) + begin + if (areset_n = '0') then + txState <= STATE_SILENCE; + txStateCounter <= (others => '0'); + + txTimerReset <= '0'; + txTimerEnable <= '0'; + + outboundSymbolRead_o <= '0'; + + uartWrite <= '0'; + uartData_o <= (others => '0'); + elsif (clk'event and clk = '1') then + txTimerReset <= '0'; + outboundSymbolRead_o <= '0'; + uartWrite <= '0'; + + -- Check if the UART is ready for new data. + if (uartFull_i = '0') and (uartWrite = '0') then + -- The UART want new data to transmitt. + + -- Check the transmission state. + case txState is + + when STATE_SILENCE => + ------------------------------------------------------------------- + -- Wait for a while to let the linkpartner detect a link break. + ------------------------------------------------------------------- + -- Check if the silence timer has expired. + if (silenceTxTimerDone = '1') then + -- Silence timer expired. + -- Reset the timer and proceed to transmitting symbols. + txTimerReset <= '1'; + txTimerEnable <= '0'; + txState <= STATE_IDLE_0; + else + txTimerEnable <= '1'; + end if; + + when STATE_IDLE_0 => + ----------------------------------------------------------------- + -- Wait for a new symbol to be received. An idle symbol is followed + -- by a small inter-character idle time to let the receiver in the + -- link partner synchronize itself to the link. + ----------------------------------------------------------------- + + -- Reset the state counter for the symbol generation. + txStateCounter <= "00"; + + -- Check if a new symbol is available. + if (outboundSymbolEmpty_i = '0') then + -- A new symbol is available. + + -- Check if the new symbol is idle, control or data. + if (outboundSymbol_i(33 downto 32) /= SYMBOL_IDLE) then + -- Control or data symbol. + txState <= STATE_BUSY_1; + else + -- Send idle sequence. + txState <= STATE_IDLE_1; + end if; + else + -- No new symbols are ready. + -- Dont do anything. + end if; + + when STATE_IDLE_1 => + ------------------------------------------------------------------- + -- Wait until the idle timer has expired to let the link be idle in + -- between idle symbols. + ------------------------------------------------------------------- + + -- Check if the idle timer has expired. + if (idleTxTimerDone = '1') then + -- Idle timer has expired. + -- Reset the timer and disable it. + txTimerReset <= '1'; + txTimerEnable <= '0'; + + -- Write a flag to indicate idle link. + uartWrite <= '1'; + uartData_o <= FLAG_SEQUENCE; + + -- Get a new symbol. + outboundSymbolRead_o <= '1'; + txState <= STATE_IDLE_0; + else + -- Idle timer has not expired yet. + txTimerEnable <= '1'; + end if; + + when STATE_BUSY_1 => + ----------------------------------------------------------------- + -- Encode a control or data symbol. If stuffing is needed the next + -- busy state is called. + ----------------------------------------------------------------- + + -- Check if the octet is a flag or escape character. + if ((outboundSymbolData = FLAG_SEQUENCE) or + (outboundSymbolData = CONTROL_ESCAPE)) then + -- Flag or escape octet. + uartWrite <= '1'; + uartData_o <= CONTROL_ESCAPE; + txState <= STATE_BUSY_2; + else + -- Ordinary octet. + + -- Write the octet to the uart. + uartWrite <= '1'; + uartData_o <= outboundSymbolData; + + -- Update to the next octet in the symbol. + txStateCounter <= txStateCounter + 1; + + -- Check if the symbol has been sent. + if (txStateCounter = 3) then + -- Data symbol sent. + outboundSymbolRead_o <= '1'; + txState <= STATE_IDLE_0; + elsif ((txStateCounter = 2) and + (outboundSymbol_i(33 downto 32) /= SYMBOL_DATA)) then + -- Control symbol sent. + txState <= STATE_SEND_FLAG; + else + -- Symbol not completly sent. + txState <= STATE_BUSY_1; + end if; + end if; + + when STATE_BUSY_2 => + ----------------------------------------------------------------- + -- Byte stuff a flag or escape sequence found in the symbol data + -- content. + ----------------------------------------------------------------- + + -- Byte stuff the control character. + uartWrite <= '1'; + uartData_o <= outboundSymbolData xor x"20"; + + -- Update to the next symbol. + txStateCounter <= txStateCounter + 1; + + -- Check if the symbol has been sent. + if (txStateCounter = 3) then + -- Data symbol sent. + outboundSymbolRead_o <= '1'; + txState <= STATE_IDLE_0; + elsif ((txStateCounter = 2) and + (outboundSymbol_i(33 downto 32) /= SYMBOL_DATA)) then + -- Control symbol sent. + txState <= STATE_SEND_FLAG; + else + -- Symbol not completly sent. + txState <= STATE_BUSY_1; + end if; + + when STATE_SEND_FLAG => + ----------------------------------------------------------------- + -- Force a flag to be written to the link. + ----------------------------------------------------------------- + + uartWrite <= '1'; + uartData_o <= FLAG_SEQUENCE; + outboundSymbolRead_o <= '1'; + txState <= STATE_IDLE_0; + + when others => + ----------------------------------------------------------------- + -- Unknown state. + ----------------------------------------------------------------- + txState <= STATE_IDLE_0; + + end case; + else + -- The UART is busy transmitting. + -- Wait for the UART to complete. + end if; + end if; + end process; + + + ----------------------------------------------------------------------------- + -- Link symbol decoder process. + ----------------------------------------------------------------------------- + uartRead_o <= uartRead; + Inbound: process(areset_n, clk) + begin + if (areset_n = '0') then + rxState <= STATE_INIT; + rxStateCounter <= (others => '0'); + escapeFound <= '0'; + + rxTimerReset <= '0'; + rxTimerEnable <= '0'; + + inboundSymbolWrite_o <= '0'; + inboundSymbol_o <= (others => '0'); + + uartRead <= '0'; + elsif (clk'event and clk = '1') then + rxTimerReset <= '0'; + inboundSymbolWrite_o <= '0'; + uartRead <= '0'; + + case rxState is + + when STATE_INIT => + ------------------------------------------------------------------- + -- Wait for a flag to be received. + ------------------------------------------------------------------- + -- Check if any new data is ready. + if (uartRead = '0') and (uartEmpty_i = '0') then + -- New data is ready from the uart. + + -- Check if a flag has been received. + if (uartData_i = FLAG_SEQUENCE) then + -- A flag has been received. + -- Considder the port to be initialized. + rxState <= STATE_NORMAL; + rxStateCounter <= (others => '0'); + escapeFound <= '0'; + rxTimerReset <= '1'; + rxTimerEnable <= '1'; + uartRead <= '1'; + else + -- Something that is not a flag has been received. + -- Discard the data and wait for a flag. + uartRead <= '1'; + end if; + else + -- Waiting for inbound data. + -- Dont do anything. + end if; + + when STATE_NORMAL => + ------------------------------------------------------------------- + -- Parse the incoming stream and create symbols. + ------------------------------------------------------------------- + + -- Check if the link lost timer has expired. + if (lostRxTimerDone = '1') then + -- The link lost timer has expired. + -- Reset the timer, disable it and go back to the initial state. + rxTimerReset <= '1'; + rxTimerEnable <= '0'; + rxState <= STATE_INIT; + else + -- The link lost timer has not expired. + + -- Check if any new data is ready. + if (uartRead = '0') and (uartEmpty_i = '0') then + -- New data is ready from the uart. + + -- Reset the link lost timer. + rxTimerReset <= '1'; + + -- Check if a flag has been received. + if (uartData_i /= FLAG_SEQUENCE) then + -- The received octet was not a flag. + + -- Check if the octet was a contol character. + if (uartData_i /= CONTROL_ESCAPE) then + -- The octet was not a control character. + + -- Check where in a symbol the reception is. + case rxStateCounter is + + when "00" => + inboundSymbol_o(33 downto 32) <= SYMBOL_IDLE; + if (escapeFound = '0') then + inboundSymbol_o(31 downto 24) <= uartData_i; + else + inboundSymbol_o(31 downto 24) <= uartData_i xor x"20"; + end if; + rxStateCounter <= rxStateCounter + 1; + + when "01" => + inboundSymbol_o(33 downto 32) <= SYMBOL_IDLE; + if (escapeFound = '0') then + inboundSymbol_o(23 downto 16) <= uartData_i; + else + inboundSymbol_o(23 downto 16) <= uartData_i xor x"20"; + end if; + rxStateCounter <= rxStateCounter + 1; + + when "10" => + inboundSymbol_o(33 downto 32) <= SYMBOL_CONTROL; + if (escapeFound = '0') then + inboundSymbol_o(15 downto 8) <= uartData_i; + else + inboundSymbol_o(15 downto 8) <= uartData_i xor x"20"; + end if; + rxStateCounter <= rxStateCounter + 1; + + when "11" => + inboundSymbol_o(33 downto 32) <= SYMBOL_DATA; + if (escapeFound = '0') then + inboundSymbol_o(7 downto 0) <= uartData_i; + else + inboundSymbol_o(7 downto 0) <= uartData_i xor x"20"; + end if; + rxStateCounter <= rxStateCounter + 1; + inboundSymbolWrite_o <= '1'; + + when others => + rxStateCounter <= "00"; + + end case; + + -- Read the octet from the uart. + uartRead <= '1'; + escapeFound <= '0'; + else + -- Control escape received. + + -- Read the octet and indicate that an escape character has been received. + uartRead <= '1'; + escapeFound <= '1'; + end if; + else + -- Flag received. + + -- Check if there are any unsent symbols pending. + if (rxStateCounter = 0) then + -- No pending symbol. + -- Send an idle symbol. + inboundSymbolWrite_o <= '1'; + inboundSymbol_o(33 downto 32) <= SYMBOL_IDLE; + else + -- Pending symbol. + -- Send the pending symbol. + inboundSymbolWrite_o <= '1'; + end if; + + -- Read and discard the octet. + uartRead <= '1'; + rxStateCounter <= "00"; + end if; + else + -- Waiting for inbound data. + -- Dont do anything. + end if; + end if; + + when others => + ------------------------------------------------------------------- + -- Unknown state. + ------------------------------------------------------------------- + null; + + end case; + end if; + end process; + +end architecture;
1.0.1/rtl/vhdl/RioPcsUart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/rtl/vhdl/Uart.vhd =================================================================== --- 1.0.1/rtl/vhdl/Uart.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/Uart.vhd (revision 29) @@ -0,0 +1,349 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- Generic UART with FIFO interface. +-- +-- 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 +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Uart implementation. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +------------------------------------------------------------------------------- +-- Entity for Uart. +------------------------------------------------------------------------------- +entity Uart is + generic( + DIVISOR_WIDTH : natural; + DATA_WIDTH : natural); + port( + clk : in std_logic; + areset_n : in std_logic; + + divisor_i : in std_logic_vector(DIVISOR_WIDTH-1 downto 0); + + serial_i : in std_logic; + serial_o : out std_logic; + + empty_o : out std_logic; + read_i : in std_logic; + data_o : out std_logic_vector(DATA_WIDTH-1 downto 0); + + full_o : out std_logic; + write_i : in std_logic; + data_i : in std_logic_vector(DATA_WIDTH-1 downto 0)); +end entity; + + +------------------------------------------------------------------------------- +-- Architecture for Uart. +------------------------------------------------------------------------------- +architecture UartImpl of Uart is + signal bitDuration : unsigned(DIVISOR_WIDTH-1 downto 0); + signal bitSample : unsigned(DIVISOR_WIDTH-1 downto 0); + + type StateTypeRx is (STATE_INIT, STATE_IDLE, + STATE_START, STATE_DATA, STATE_STOP); + signal rxState : StateTypeRx; + signal rxShifter : std_logic_vector(DATA_WIDTH-1 downto 0); + signal rxCounter : unsigned(DIVISOR_WIDTH-1 downto 0); + signal rxBitCounter : natural range 0 to DATA_WIDTH-1; + signal rxComplete : std_logic; + signal rxData : std_logic_vector(DATA_WIDTH-1 downto 0); + + type StateTypeRxFifo is (STATE_EMPTY, STATE_WAITREAD); + signal rxFifoState : StateTypeRxFifo; + + type StateTypeTx is (STATE_IDLE, STATE_SEND); + signal txState : StateTypeTx; + signal txShifter : std_logic_vector(DATA_WIDTH downto 0); + signal txCounter : unsigned(DIVISOR_WIDTH-1 downto 0); + signal txBitCounter : natural range 0 to DATA_WIDTH+1; + +begin + + -- Setup the tick values when a bit is complete and when to sample it. + bitDuration <= unsigned(divisor_i); + bitSample <= '0' & unsigned(divisor_i(DIVISOR_WIDTH-1 downto 1)); + + ----------------------------------------------------------------------------- + -- UART receiving process. + ----------------------------------------------------------------------------- + Receiver: process(clk, areset_n) + begin + if (areset_n = '0') then + rxState <= STATE_INIT; + rxShifter <= (others => '0'); + rxBitCounter <= 0; + rxCounter <= (others => '0'); + + rxComplete <= '0'; + rxData <= (others => '0'); + elsif (clk'event and (clk = '1')) then + rxComplete <= '0'; + + case rxState is + + when STATE_INIT => + --------------------------------------------------------------------- + -- Wait for the line to become idle. + --------------------------------------------------------------------- + if (serial_i = '1') then + rxState <= STATE_IDLE; + end if; + + when STATE_IDLE => + --------------------------------------------------------------------- + -- Wait for a long enough start pulse. + --------------------------------------------------------------------- + if (serial_i = '0') then + -- The serial input is zero, indicating a start bit. + + -- Check how long it has been zero. + if (rxCounter = bitSample) then + -- It has been zero long enough. + -- Proceed to read the full start bit before starting to sample + -- the data. + rxState <= STATE_START; + else + -- Stay in this state until it has lasted long enough. + end if; + + -- Update to next sampling interval. + rxCounter <= rxCounter + 1; + else + -- The serial input is not zero. + -- Restart the sampling interval. + rxCounter <= (others => '0'); + end if; + + when STATE_START => + --------------------------------------------------------------------- + -- Wait for the startbit to end. + --------------------------------------------------------------------- + if (rxCounter = bitDuration) then + rxCounter <= (others => '0'); + rxState <= STATE_DATA; + else + rxCounter <= rxCounter + 1; + end if; + + when STATE_DATA => + --------------------------------------------------------------------- + -- Sample data bits where it's appropriate. + --------------------------------------------------------------------- + if (rxCounter = bitDuration) then + -- End of bit. + -- Check if all the data bits has been read. + if (rxBitCounter = (DATA_WIDTH-1)) then + -- All data bits read. + -- Read the stop bit. + rxState <= STATE_STOP; + rxBitCounter <= 0; + else + -- Continue to read more data bits. + rxBitCounter <= rxBitCounter + 1; + end if; + + -- Restart sampling interval. + rxCounter <= (others => '0'); + elsif (rxCounter = bitSample) then + -- Sample the bit and continue to sample until the bit ends. + rxShifter <= serial_i & rxShifter((DATA_WIDTH-1) downto 1); + rxCounter <= rxCounter + 1; + else + -- Wait for the middle or the end of the data to be reached. + rxCounter <= rxCounter + 1; + end if; + + when STATE_STOP => + --------------------------------------------------------------------- + -- Sample stop bit where it's appropriate. + --------------------------------------------------------------------- + if (rxCounter = bitSample) then + -- Sample the stop bit. + + -- Check if the stop bit is valid. + if (serial_i = '1') then + -- The stop bit is ok. + -- Forward the read data. + rxComplete <= '1'; + rxData <= rxShifter; + else + -- The stop bit is not ok. + -- Do not forward the data character. + end if; + + -- Reset sampling counter and go back to the init state. + rxState <= STATE_INIT; + rxCounter <= (others => '0'); + else + -- Wait for the middle or the end of the data to be reached. + rxCounter <= rxCounter + 1; + end if; + + when others => + --------------------------------------------------------------------- + -- Undefined state. + --------------------------------------------------------------------- + rxState <= STATE_IDLE; + rxCounter <= (others => '0'); + + end case; + end if; + end process; + + ----------------------------------------------------------------------------- + -- UART receiver fifo. + ----------------------------------------------------------------------------- + ReceiverFifo: process(clk, areset_n) + begin + if (areset_n = '0') then + empty_o <= '1'; + data_o <= (others => '0'); + rxFifoState <= STATE_EMPTY; + elsif (clk'event and (clk = '1')) then + case rxFifoState is + + when STATE_EMPTY => + -- Wait for data to be forwarded from the UART receiver. + if (rxComplete = '1') then + -- Indicate there is data to read from. + empty_o <= '0'; + data_o <= rxData; + rxFifoState <= STATE_WAITREAD; + else + -- Wait for data to be received. + end if; + + when STATE_WAITREAD => + -- Wait for the data to be read from the output port. + if (read_i = '1') then + -- The data has been read. + empty_o <= '1'; + rxFifoState <= STATE_EMPTY; + end if; + -- Check if new data has been forwarded from the UART. + if (rxComplete = '1') then + -- New data has been forwarded without the output port being read. + -- Overrun. Data has been lost. + -- REMARK: Indicate this??? + end if; + + when others => + -- Undefined state. + rxFifoState <= STATE_EMPTY; + end case; + end if; + end process; + + ----------------------------------------------------------------------------- + -- UART transmitter process. + ----------------------------------------------------------------------------- + Transmitter: process(clk, areset_n) + begin + if (areset_n = '0') then + txState <= STATE_IDLE; + txShifter <= (others => '0'); + txBitCounter <= 0; + txCounter <= (others => '0'); + + full_o <= '0'; + serial_o <= '1'; + elsif (clk'event and (clk = '1')) then + case txState is + + when STATE_IDLE => + --------------------------------------------------------------------- + -- Wait for new data to be input on the input port. + --------------------------------------------------------------------- + if (write_i = '1') then + -- New data present. + full_o <= '1'; + txShifter <= "1" & data_i; + txCounter <= (others => '0'); + txBitCounter <= 0; + txState <= STATE_SEND; + serial_o <= '0'; + end if; + + when STATE_SEND => + --------------------------------------------------------------------- + -- Wait for the bit to be completly transmitted. + --------------------------------------------------------------------- + if (txCounter = bitDuration) then + -- The bit has been sent. + + -- Check if the full character has been sent. + if (txBitCounter = (DATA_WIDTH+1)) then + -- Character has been sent. + full_o <= '0'; + txState <= STATE_IDLE; + else + -- Character has not been sent yet. + -- Send the next bit. + serial_o <= txShifter(0); + txShifter <= "0" & txShifter(DATA_WIDTH downto 1); + txBitCounter <= txBitCounter + 1; + end if; + + -- Update to the next bit. + txCounter <= (others => '0'); + else + -- Wait for the end of the bit. + txCounter <= txCounter + 1; + end if; + + when others => + --------------------------------------------------------------------- + -- Undefined state. + --------------------------------------------------------------------- + txState <= STATE_IDLE; + + end case; + end if; + end process; + +end architecture; +
1.0.1/rtl/vhdl/Uart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/rtl/vhdl/srio_pcs_struct.vhd =================================================================== --- 1.0.1/rtl/vhdl/srio_pcs_struct.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/srio_pcs_struct.vhd (revision 29) @@ -0,0 +1,2912 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- +-- File name: ccs_timer.vhd +-- Rev: 0.0 +-- Description: This entity watches the CCS (clock compensation sequence) +-- insertion according to RIO Sepec. Part-6, subchapter 4.7.1 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; +use work.rio_common.all; + +entity ccs_timer is + generic ( + TCQ : time := 100 ps + ); + port ( + rst_n : in std_logic; + UCLK : in std_logic; + + send_ccs : out std_logic; + ccs_timer_rst : in std_logic + ); +end ccs_timer; + +architecture RTL of ccs_timer is +-------------------------------------------------------------------------------------- +signal ccs_counter : std_logic_vector(11 downto 0) := (others => '0'); +constant CCS_INTERVAL : std_logic_vector(11 downto 0) := x"7FF"; -- = 4096 chars + +-------------------------------------------------------------------------------------- +begin + +-- CCS counter process +process(rst_n, UCLK) + begin + if rst_n = '0' then + ccs_counter <= CCS_INTERVAL; + send_ccs <= '0'; + elsif rising_edge(UCLK) then + if ccs_timer_rst = '0' then + if ccs_counter = CCS_INTERVAL then + send_ccs <= '1'; + else + send_ccs <= '0'; + ccs_counter <= ccs_counter + '1'; + end if; + else + send_ccs <= '0'; + ccs_counter <= (others => '0'); + end if; + end if; +end process; + +end RTL; +--------------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- +-- File name: idle_generator.vhd +-- Rev: 0.0 +-- Description: This entity generates IDLE1 sequence for SRIO PHY +-- RIO Sepec. Part-6, subchapter 4.7.2 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; +use work.rio_common.all; + +entity idle_generator is + generic ( + lfsr_init : std_logic_vector(7 downto 0) := x"01"; + TCQ : time := 100 ps + ); + port ( + UCLK : in std_logic; + rst_n : in std_logic; + + send_idle : in std_logic; + + send_K : out std_logic; + send_A : out std_logic; + send_R : out std_logic + ); +end idle_generator; + +architecture RTL of idle_generator is +------------------------------------------------------------------------------------------------------------------------------------------- +signal q_pseudo_random_number : std_logic_vector(7 downto 0) := (others => '0'); +signal pseudo_random_bit : std_logic := '0'; + +signal down_counter_load_value : std_logic_vector(4 downto 0) := (others => '0'); +signal down_counter : std_logic_vector(4 downto 0) := (others => '0'); +signal Acntr_eq_zero : std_logic := '0'; +signal send_idle_q : std_logic := '0'; +-- + +COMPONENT pseudo_random_number_generator +GENERIC ( + lfsr_init : std_logic_vector(7 downto 0) + ); +PORT( + clk : IN std_logic; + rst_n : IN std_logic; + q : OUT std_logic_vector(7 downto 0) + ); +END COMPONENT; + +------------------------------------------------------------------------------------------------------------------------------------------- +begin + +inst_prng: pseudo_random_number_generator GENERIC MAP( + lfsr_init => lfsr_init --x"01" + ) + PORT MAP( + clk => UCLK, + rst_n => rst_n, + q => q_pseudo_random_number + ); + +pseudo_random_bit <= q_pseudo_random_number(0); + +down_counter_load_value <= '1' & q_pseudo_random_number(6) & q_pseudo_random_number(4) & q_pseudo_random_number(3) & q_pseudo_random_number(1); + +-- down counter process +process(rst_n, UCLK) + begin + if rst_n = '0' then + down_counter <= (others => '0'); + elsif rising_edge(UCLK) then + if Acntr_eq_zero = '1' then + down_counter <= down_counter_load_value; + else + down_counter <= down_counter - '1'; + end if; + end if; +end process; + +Acntr_eq_zero <= '1' when down_counter = "00000" else '0'; + +-- send_idle delay process +process(rst_n, UCLK) + begin + if rst_n = '0' then + send_idle_q <= '0'; + elsif rising_edge(UCLK) then + send_idle_q <= send_idle; + end if; +end process; + +send_K <= send_idle and (not(send_idle_q) or (send_idle_q and not(Acntr_eq_zero) and pseudo_random_bit)); +send_A <= send_idle and send_idle_q and Acntr_eq_zero; +send_R <= send_idle and send_idle_q and not(Acntr_eq_zero) and not(pseudo_random_bit); + +end RTL; +------------------------------------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- +-- File name: idle_generator_dual.vhd +-- Rev: 0.0 +-- Description: This entity generates IDLE1 sequence for SRIO PHY +-- RIO Sepec. Part-6, subchapter 4.7.2 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; +use work.rio_common.all; + +entity idle_generator_dual is + generic ( + TCQ : time := 100 ps + ); + port ( + UCLK : in std_logic; + rst_n : in std_logic; + + send_idle : in std_logic_vector(1 downto 0); + + send_K : out std_logic_vector(1 downto 0); + send_A : out std_logic_vector(1 downto 0); + send_R : out std_logic_vector(1 downto 0) + ); +end idle_generator_dual; + +architecture RTL of idle_generator_dual is +------------------------------------------------------------------------------------------------------------------------------------------- + +COMPONENT idle_generator + generic ( + lfsr_init : std_logic_vector(7 downto 0); + TCQ : time + ); +PORT( + UCLK : IN std_logic; + rst_n : IN std_logic; + send_idle : IN std_logic; + send_K : OUT std_logic; + send_A : OUT std_logic; + send_R : OUT std_logic + ); +END COMPONENT; + +------------------------------------------------------------------------------------------------------------------------------------------- +begin + + Inst_idle_generator_0: idle_generator GENERIC MAP( + TCQ => 100 ps, + lfsr_init => x"0F" + ) + PORT MAP( + UCLK => UCLK, + rst_n => rst_n, + send_idle => send_idle(0), + send_K => send_K(0), + send_A => send_A(0), + send_R => send_R(0) + ); + + Inst_idle_generator_1: idle_generator GENERIC MAP( + TCQ => 100 ps, + lfsr_init => x"F0" + ) + PORT MAP( + UCLK => UCLK, + rst_n => rst_n, + send_idle => send_idle(1), + send_K => send_K(1), + send_A => send_A(1), + send_R => send_R(1) + ); + +end RTL; +------------------------------------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- +-- File name: pcs_rx_controller.vhd +-- Rev: 0.0 +-- Description: This entity controls the RX stream +-- +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; +use work.rio_common.all; + +entity pcs_rx_controller is + generic ( + TCQ : time := 100 ps + ); + port ( + rst_n : in std_logic; + rio_clk : in std_logic; -- ~150 MHz + UCLK_x2 : in std_logic; -- 312,5 MHz + UCLK : in std_logic; -- 156,25 MHz + UCLK_x2_DV2 : in std_logic; -- 312,5 MHz @ x4 mode / 78,125 @ x1 (fallback mode) + UCLK_or_DV4 : in std_logic; -- 156,25 MHz @ x4 mode / 39,0625 @ x1 (fallback mode) + -- UCLK_DV4 : in std_logic; -- 39,0625 + -- + -- Interface to the RioSerial + inboundRead_i : in std_logic; + inboundEmpty_o : out std_logic; + inboundSymbol_o : out std_logic_vector(33 downto 0); + -- + -- Interface to the GTX transceivers + RXDATA_i : in std_logic_vector(63 downto 0); -- N = 4 + RXCHARISK_i : in std_logic_vector(7 downto 0); + RXCHARISvalid_i : in std_logic_vector(7 downto 0); + -- + -- Interface to the port init + port_initalized_i : in std_logic; + mode_sel_i : in std_logic; + mode_0_lane_sel_i : in std_logic + + ); +end pcs_rx_controller; + +architecture RTL of pcs_rx_controller is + +------------------------------------------------------------------------------- +COMPONENT pcs_rx_boudary_32b_out_64b_in + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(67 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(33 DOWNTO 0); + full : OUT STD_LOGIC; + almost_full : OUT STD_LOGIC; + empty : OUT STD_LOGIC; + almost_empty : OUT STD_LOGIC; + valid : OUT STD_LOGIC + ); +END COMPONENT; +------------------------------------------------------------------------------- +signal rst : std_logic:= '0'; + +signal RXDATA_swap : std_logic_vector(63 downto 0) := (others => '0'); +signal RXCHARISK_swap : std_logic_vector(7 downto 0) := (others => '0'); +signal RXCHARISvalid_swap : std_logic_vector(7 downto 0) := (others => '0'); + +signal RXDATA_u : std_logic_vector(31 downto 0) := (others => '0'); +signal RXCHARISK_u : std_logic_vector(3 downto 0) := (others => '0'); +signal RXDATA_l : std_logic_vector(31 downto 0) := (others => '0'); +signal RXCHARISK_l : std_logic_vector(3 downto 0) := (others => '0'); +signal RXCHARISvalid_u : std_logic_vector(3 downto 0) := (others => '0'); +signal RXCHARISvalid_l : std_logic_vector(3 downto 0) := (others => '0'); + +signal inboundValid : std_logic:= '0'; +signal rx_fifo_wr_en : std_logic:= '0'; +signal rx_fifo_wr_en_q : std_logic:= '0'; +signal rx_fifo_full : std_logic:= '0'; +signal rx_fifo_almost_full : std_logic:= '0'; +signal rx_fifo_almost_empty : std_logic:= '0'; + +signal rx_fifo_data_in : std_logic_vector(67 downto 0) := (others => '0'); +signal rx_fifo_data_in_q : std_logic_vector(67 downto 0) := (others => '0'); +signal rx_fifo_data_swapped : std_logic_vector(67 downto 0) := (others => '0'); +signal rx_fifo_full_p : std_logic:= '0'; + +signal port_initalized : std_logic:= '0'; +signal mode_sel : std_logic:= '0'; +signal mode_0_lane_sel : std_logic:= '0'; + +signal port_state : std_logic_vector(2 downto 0) := (others => '0'); + +signal upper_symbol_type : std_logic_vector(1 downto 0) := (others => '0'); +signal lower_symbol_type : std_logic_vector(1 downto 0) := (others => '0'); + +signal upper_symbol_not_idle : std_logic:= '0'; +signal lower_symbol_not_idle : std_logic:= '0'; +signal upper_symbol_valid : std_logic:= '0'; +signal lower_symbol_valid : std_logic:= '0'; +signal upper_symbol_not_error : std_logic:= '0'; +signal lower_symbol_not_error : std_logic:= '0'; + +-- signal RXDATA_sr : std_logic_vector(63 downto 0) := (others => '0'); +-- signal RXCHARISK_sr : std_logic_vector(7 downto 0) := (others => '0'); +-- signal RXCHARISvalid_sr : std_logic_vector(7 downto 0) := (others => '0'); + +signal RXDATA_sr_done : std_logic_vector(63 downto 0) := (others => '0'); +signal RXCHARISK_sr_done : std_logic_vector(7 downto 0) := (others => '0'); +signal RXCHARISvalid_sr_done : std_logic_vector(7 downto 0) := (others => '0'); + +signal RXDATA_sr : std_logic_vector(71 downto 0) := (others => '0'); +signal RXCHARISK_sr : std_logic_vector(8 downto 0) := (others => '0'); +signal RXCHARISvalid_sr : std_logic_vector(8 downto 0) := (others => '0'); + +signal RXDATA_R_lane : std_logic_vector(15 downto 0) := (others => '0'); +signal RXCHARISK_R_lane : std_logic_vector(1 downto 0) := (others => '0'); +signal RXCHARISvalid_R_lane : std_logic_vector(1 downto 0) := (others => '0'); + +signal valid_byte_cntr : std_logic_vector(2 downto 0) := (others => '0'); +signal irregular_stream : std_logic:= '0'; +signal done_cntr : std_logic_vector(1 downto 0) := (others => '0'); +signal rx_done : std_logic:= '0'; + +signal u_l_switch : std_logic:= '0'; + +-- signal sr_symbol_not_idle : std_logic:= '0'; +-- signal sr_symbol_not_idle_q : std_logic:= '0'; +-- signal sr_symbol_not_error : std_logic:= '0'; +-- signal sr_symbol_not_error_q : std_logic:= '0'; +-- signal RXDATA_sr : std_logic_vector(31 downto 0) := (others => '0'); +-- signal RXCHARISK_sr : std_logic_vector(3 downto 0) := (others => '0'); +-- signal RXCHARISvalid_sr : std_logic_vector(3 downto 0) := (others => '0'); +-- signal sr_symbol_type : std_logic_vector(1 downto 0) := (others => '0'); + +signal sr_u_symbol_not_idle : std_logic:= '0'; +signal sr_u_symbol_not_idle_q : std_logic:= '0'; +signal sr_u_symbol_not_error : std_logic:= '0'; +signal sr_u_symbol_not_error_q : std_logic:= '0'; +signal RXDATA_u_sr : std_logic_vector(31 downto 0) := (others => '0'); +signal RXCHARISK_u_sr : std_logic_vector(3 downto 0) := (others => '0'); +signal RXCHARISvalid_u_sr : std_logic_vector(3 downto 0) := (others => '0'); +signal sr_u_symbol_type : std_logic_vector(1 downto 0) := (others => '0'); + +signal sr_l_symbol_not_idle : std_logic:= '0'; +signal sr_l_symbol_not_idle_q : std_logic:= '0'; +signal sr_l_symbol_not_error : std_logic:= '0'; +signal sr_l_symbol_not_error_q : std_logic:= '0'; +signal RXDATA_sr_l : std_logic_vector(31 downto 0) := (others => '0'); +signal RXCHARISK_sr_l : std_logic_vector(3 downto 0) := (others => '0'); +signal RXCHARISvalid_sr_l : std_logic_vector(3 downto 0) := (others => '0'); +signal sr_l_symbol_type : std_logic_vector(1 downto 0) := (others => '0'); + + +signal started_once : std_logic:= '0'; +signal word_switch : std_logic:= '0'; +signal shift_cntr : std_logic_vector(1 downto 0) := (others => '0'); + + +---------------------------------------------------------------------------------- +begin +rst <= not(rst_n); + +rx_boundary_fifo : pcs_rx_boudary_32b_out_64b_in -- FWFT FIFO + PORT MAP ( + rst => rst, + rd_clk => rio_clk, + rd_en => inboundRead_i, + dout => inboundSymbol_o, + valid => inboundValid, + empty => inboundEmpty_o, + almost_empty => rx_fifo_almost_empty, + + wr_clk => UCLK_or_DV4, + wr_en => rx_fifo_wr_en_q, -- rx_fifo_wr_en, -- rx_fifo_wr_en_q, -- + din => rx_fifo_data_in_q, -- rx_fifo_data_in, -- rx_fifo_data_in_q, -- + full => rx_fifo_full, -- rx_fifo_full + almost_full => rx_fifo_almost_full -- rx_fifo_full + ); + +-- Pipelining RX write +process(UCLK_or_DV4) + begin + if rising_edge(UCLK_or_DV4) then + rx_fifo_wr_en_q <= rx_fifo_wr_en; + rx_fifo_data_in_q <= rx_fifo_data_in; + end if; +end process; + + +-- rx_fifo_data_swapped <= rx_fifo_data_in(33 downto 32) +-- & rx_fifo_data_in(7 downto 0) & rx_fifo_data_in(15 downto 8) & rx_fifo_data_in(23 downto 16) & rx_fifo_data_in(31 downto 24); + +port_initalized <= port_initalized_i; +mode_sel <= mode_sel_i; +mode_0_lane_sel <= mode_0_lane_sel_i; + +port_state <= port_initalized & mode_sel & mode_0_lane_sel; + +-- RX management / FIFO write process +process(rst_n, UCLK) -- _x2 + begin + if rst_n = '0' then + + rx_fifo_wr_en <= '0'; + word_switch <= '0'; + started_once <= '0'; + rx_fifo_data_in <= (others => '0'); + -- RXDATA_sr <= (others => '0'); + -- RXCHARISK_sr <= (others => '1'); + -- RXCHARISvalid_sr <= (others => '0'); + shift_cntr <= (others => '0'); + + elsif rising_edge(UCLK) then + -- Alternative If-Else Statement + if port_initalized = '0' then -- Port has not been initialized yet + rx_fifo_wr_en <= '0'; + rx_fifo_data_in <= (others => '0'); + else -- Port has been initialized + -- if mode_sel = '1' then -- x4 mode is active + if upper_symbol_valid = '1' and lower_symbol_valid = '1' then + rx_fifo_data_in <= upper_symbol_type & RXDATA_u & lower_symbol_type & RXDATA_l; + rx_fifo_wr_en <= not(rx_fifo_almost_full); + elsif upper_symbol_valid = '1' then + rx_fifo_data_in <= upper_symbol_type & RXDATA_u & SYMBOL_IDLE & x"00000000"; + rx_fifo_wr_en <= not(rx_fifo_almost_full); + elsif lower_symbol_valid = '1' then + rx_fifo_data_in <= SYMBOL_IDLE & x"00000000" & lower_symbol_type & RXDATA_l; + rx_fifo_wr_en <= not(rx_fifo_almost_full); + else + rx_fifo_wr_en <= '0'; + end if; + -- else -- x1 fallback mode is active + -- if upper_symbol_valid = '1' and lower_symbol_valid = '1' then + -- rx_fifo_data_in <= upper_symbol_type & RXDATA_u & lower_symbol_type & RXDATA_l; + -- rx_fifo_wr_en <= not(rx_fifo_full); + -- elsif upper_symbol_valid = '1' then + -- rx_fifo_data_in <= upper_symbol_type & RXDATA_u & SYMBOL_IDLE & RXDATA_l; + -- rx_fifo_wr_en <= not(rx_fifo_full); + -- elsif lower_symbol_valid = '1' then + -- rx_fifo_data_in <= SYMBOL_IDLE & RXDATA_u & lower_symbol_type & RXDATA_l; + -- rx_fifo_wr_en <= not(rx_fifo_full); + -- else + -- rx_fifo_wr_en <= '0'; + -- end if; + -- end if; + end if; + end if; +end process; +------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- -- Pipelining RX stream +-- process(UCLK) +-- begin +-- if rising_edge(UCLK) then +-- RXDATA_swap <= RXDATA_i(15 downto 0) & RXDATA_i(31 downto 16) & RXDATA_i(47 downto 32) & RXDATA_i(63 downto 48); +-- RXCHARISK_swap <= RXCHARISK_i(1 downto 0) & RXCHARISK_i(3 downto 2) & RXCHARISK_i(5 downto 4) & RXCHARISK_i(7 downto 6); +-- RXCHARISvalid_swap <= RXCHARISvalid_i(1 downto 0) & RXCHARISvalid_i(3 downto 2) & RXCHARISvalid_i(5 downto 4) & RXCHARISvalid_i(7 downto 6); +-- end if; +-- end process; + +-- Pipelining RX stream +process(UCLK) + begin + if rising_edge(UCLK) then + + RXDATA_swap <= RXDATA_i(15 downto 0) & RXDATA_i(31 downto 16) & RXDATA_i(47 downto 32) & RXDATA_i(63 downto 48); + RXCHARISK_swap <= RXCHARISK_i(1 downto 0) & RXCHARISK_i(3 downto 2) & RXCHARISK_i(5 downto 4) & RXCHARISK_i(7 downto 6); + RXCHARISvalid_swap <= RXCHARISvalid_i(1 downto 0) & RXCHARISvalid_i(3 downto 2) & RXCHARISvalid_i(5 downto 4) & RXCHARISvalid_i(7 downto 6); + + -- if mode_sel = '1' then -- x4 mode is active + + -- else -- x1 fallback mode is active + -- + -- RXDATA_swap <= RXDATA_sr_done ; + -- RXCHARISK_swap <= RXCHARISK_sr_done ; + -- RXCHARISvalid_swap <= RXCHARISvalid_sr_done ; + -- + -- end if; + end if; +end process; +--- Lane 0 active Lane 2 active +RXDATA_R_lane <= RXDATA_i(15 downto 0) when mode_0_lane_sel = '0' else RXDATA_i(47 downto 32) ; +RXCHARISK_R_lane <= RXCHARISK_i(1 downto 0) when mode_0_lane_sel = '0' else RXCHARISK_i(5 downto 4) ; +RXCHARISvalid_R_lane <= RXCHARISvalid_i(1 downto 0) when mode_0_lane_sel = '0' else RXCHARISvalid_i(5 downto 4) ; + +-- RXDATA shifting process for x1 mode +process(UCLK) -- _x2 rst_n, + begin + -- if rst_n = '0' then + -- + -- RXDATA_sr <= (others => '0'); + -- RXCHARISK_sr <= (others => '1'); + -- RXCHARISvalid_sr <= (others => '0'); + -- valid_byte_cntr <= (others => '0'); + -- + -- RXDATA_sr_done <= (others => '0'); + -- RXCHARISK_sr_done <= (others => '1'); + -- RXCHARISvalid_sr_done <= (others => '0'); + -- + -- done_cntr <= (others => '0'); + -- rx_done <= '0'; + -- + -- els + if rising_edge(UCLK) then + + if port_initalized = '0' then -- Port has not been initialized yet + + RXDATA_sr <= (others => '0'); + RXCHARISK_sr <= (others => '1'); + RXCHARISvalid_sr <= (others => '0'); + valid_byte_cntr <= (others => '0'); + + RXDATA_sr_done <= (others => '0'); + RXCHARISK_sr_done <= (others => '1'); + RXCHARISvalid_sr_done <= (others => '0'); + + done_cntr <= (others => '0'); + rx_done <= '0'; + + else + done_cntr <= done_cntr + rx_done; + if RXCHARISvalid_R_lane(0) = '1' and (RXCHARISK_R_lane(0) = '0' or (RXCHARISK_R_lane(0) = '1' and (RXDATA_R_lane(7 downto 0) = SC or RXDATA_R_lane(7 downto 0) = PD))) then + if RXCHARISvalid_R_lane(1) = '1' and (RXCHARISK_R_lane(1) = '0' or (RXCHARISK_R_lane(1) = '1' and (RXDATA_R_lane(15 downto 8) = SC or RXDATA_R_lane(15 downto 8) = PD))) then + --- [VVVV] It may appear anytime + valid_byte_cntr <= valid_byte_cntr + "10"; + RXDATA_sr <= RXDATA_sr(55 downto 0) & RXDATA_R_lane(15 downto 0); + RXCHARISK_sr <= RXCHARISK_sr(6 downto 0) & RXCHARISK_R_lane(1 downto 0); + RXCHARISvalid_sr <= RXCHARISvalid_sr(6 downto 0) & RXCHARISvalid_R_lane(1 downto 0); + if valid_byte_cntr = "110" then + irregular_stream <= '0'; + rx_done <= '1'; + done_cntr <= (others => '0'); + RXDATA_sr_done <= RXDATA_sr(47 downto 0) & RXDATA_R_lane(15 downto 0); + RXCHARISK_sr_done <= RXCHARISK_sr(5 downto 0) & RXCHARISK_R_lane(1 downto 0); + RXCHARISvalid_sr_done <= RXCHARISvalid_sr(5 downto 0) & RXCHARISvalid_R_lane(1 downto 0); + elsif valid_byte_cntr = "111" then + irregular_stream <= '1'; + rx_done <= '1'; + done_cntr <= (others => '0'); + RXDATA_sr_done <= RXDATA_sr(55 downto 0) & RXDATA_R_lane(15 downto 8); + RXCHARISK_sr_done <= RXCHARISK_sr(6 downto 0) & RXCHARISK_R_lane(1); + RXCHARISvalid_sr_done <= RXCHARISvalid_sr(6 downto 0) & RXCHARISvalid_R_lane(1); + elsif done_cntr = "11" then + rx_done <= '0'; + RXCHARISK_sr_done <= (others => '1'); + RXCHARISvalid_sr_done <= (others => '0'); + end if; + else + --- [__VV] : It can appear only in the beginning + if valid_byte_cntr = "100" then + valid_byte_cntr <= valid_byte_cntr + '1'; + else -- either it is an irregular start or something went wrong + valid_byte_cntr <= "001"; + irregular_stream <= '1'; + end if; + RXDATA_sr <= RXDATA_sr(63 downto 0) & RXDATA_R_lane(7 downto 0); + RXCHARISK_sr <= RXCHARISK_sr(7 downto 0) & RXCHARISK_R_lane(0); + RXCHARISvalid_sr <= RXCHARISvalid_sr(7 downto 0) & RXCHARISvalid_R_lane(0); + if done_cntr = "11" then + rx_done <= '0'; + RXCHARISK_sr_done <= (others => '1'); + RXCHARISvalid_sr_done <= (others => '0'); + end if; + end if; + else + if RXCHARISvalid_R_lane(1) = '1' and (RXCHARISK_R_lane(1) = '0' or (RXCHARISK_R_lane(1) = '1' and (RXDATA_R_lane(15 downto 8) = SC or RXDATA_R_lane(15 downto 8) = PD))) then + --- [VV__] : It can appear only in the end + RXDATA_sr <= RXDATA_sr(63 downto 0) & RXDATA_R_lane(15 downto 8); + RXCHARISK_sr <= RXCHARISK_sr(7 downto 0) & RXCHARISK_R_lane(1); + RXCHARISvalid_sr <= RXCHARISvalid_sr(7 downto 0) & RXCHARISvalid_R_lane(1); + if valid_byte_cntr = "011" then + valid_byte_cntr <= valid_byte_cntr + '1'; + irregular_stream <= '0'; -- irregularity has been compensated for the first symbol + if done_cntr = "11" then + rx_done <= '0'; + RXCHARISK_sr_done <= (others => '1'); + RXCHARISvalid_sr_done <= (others => '0'); + end if; + elsif valid_byte_cntr = "111" then -- 2 symbols (2x32b) are done + valid_byte_cntr <= (others => '0'); + irregular_stream <= '0'; -- irregularity has been compensated for the second symbol + rx_done <= '1'; + done_cntr <= (others => '0'); + RXDATA_sr_done <= RXDATA_sr(55 downto 0) & RXDATA_R_lane(15 downto 8); + RXCHARISK_sr_done <= RXCHARISK_sr(6 downto 0) & RXCHARISK_R_lane(1); + RXCHARISvalid_sr_done <= RXCHARISvalid_sr(6 downto 0) & RXCHARISvalid_R_lane(1); + else -- something went wrong + valid_byte_cntr <= (others => '0'); + irregular_stream <= '0'; + if done_cntr = "11" then + rx_done <= '0'; + RXCHARISK_sr_done <= (others => '1'); + RXCHARISvalid_sr_done <= (others => '0'); + end if; + end if; + else + --- [____] + if valid_byte_cntr /= "100" then -- No IDLE allowed, unless between two symbols: Something went wrong probably + valid_byte_cntr <= "000"; + irregular_stream <= '0'; + end if; + if done_cntr = "11" then + rx_done <= '0'; + RXCHARISK_sr_done <= (others => '1'); + RXCHARISvalid_sr_done <= (others => '0'); + end if; + end if; + end if; + end if; + end if; +end process; + +RXDATA_u <= RXDATA_swap(63 downto 56) & RXDATA_swap(47 downto 40) & RXDATA_swap(31 downto 24) & RXDATA_swap(15 downto 8) when mode_sel = '1' else -- x4 mode + RXDATA_sr_done(63 downto 32); -- x1 mode +RXCHARISK_u <= RXCHARISK_swap(7) & RXCHARISK_swap(5) & RXCHARISK_swap(3) & RXCHARISK_swap(1) when mode_sel = '1' else -- x4 mode + RXCHARISK_sr_done(7 downto 4); -- x1 mode +RXCHARISvalid_u <= RXCHARISvalid_swap(7) & RXCHARISvalid_swap(5) & RXCHARISvalid_swap(3) & RXCHARISvalid_swap(1) when mode_sel = '1' else -- x4 mode + RXCHARISvalid_sr_done(7 downto 4); -- x1 mode +RXDATA_l <= RXDATA_swap(55 downto 48) & RXDATA_swap(39 downto 32) & RXDATA_swap(23 downto 16) & RXDATA_swap(7 downto 0) when mode_sel = '1' else -- x4 mode + RXDATA_sr_done(31 downto 0); -- x1 mode +RXCHARISK_l <= RXCHARISK_swap(6) & RXCHARISK_swap(4) & RXCHARISK_swap(2) & RXCHARISK_swap(0) when mode_sel = '1' else -- x4 mode + RXCHARISK_sr_done(3 downto 0); -- x1 mode +RXCHARISvalid_l <= RXCHARISvalid_swap(6) & RXCHARISvalid_swap(4) & RXCHARISvalid_swap(2) & RXCHARISvalid_swap(0) when mode_sel = '1' else -- x4 mode + RXCHARISvalid_sr_done(3 downto 0); -- x1 mode + +-- RXDATA_u <= RXDATA_swap(63 downto 56) & RXDATA_swap(47 downto 40) & RXDATA_swap(31 downto 24) & RXDATA_swap(15 downto 8); +-- RXCHARISK_u <= RXCHARISK_swap(7) & RXCHARISK_swap(5) & RXCHARISK_swap(3) & RXCHARISK_swap(1); +-- RXDATA_l <= RXDATA_swap(55 downto 48) & RXDATA_swap(39 downto 32) & RXDATA_swap(23 downto 16) & RXDATA_swap(7 downto 0); +-- RXCHARISK_l <= RXCHARISK_swap(6) & RXCHARISK_swap(4) & RXCHARISK_swap(2) & RXCHARISK_swap(0); +-- RXCHARISvalid_u <= RXCHARISvalid_swap(7) & RXCHARISvalid_swap(5) & RXCHARISvalid_swap(3) & RXCHARISvalid_swap(1); +-- RXCHARISvalid_l <= RXCHARISvalid_swap(6) & RXCHARISvalid_swap(4) & RXCHARISvalid_swap(2) & RXCHARISvalid_swap(0); + +upper_symbol_type <= SYMBOL_IDLE when RXCHARISK_u = "1111" and RXCHARISvalid_u = "1111" else + SYMBOL_CONTROL when RXCHARISK_u = "1000" and RXCHARISvalid_u = "1111" and (RXDATA_u(31 downto 24) = SC or RXDATA_u(31 downto 24) = PD) else + SYMBOL_DATA when RXCHARISK_u = "0000" and RXCHARISvalid_u = "1111" else + SYMBOL_ERROR; + +lower_symbol_type <= SYMBOL_IDLE when RXCHARISK_l = "1111" and RXCHARISvalid_l = "1111" else + SYMBOL_CONTROL when RXCHARISK_l = "1000" and RXCHARISvalid_l = "1111" and (RXDATA_l(31 downto 24) = SC or RXDATA_l(31 downto 24) = PD) else + SYMBOL_DATA when RXCHARISK_l = "0000" and RXCHARISvalid_l = "1111" else + SYMBOL_ERROR; + +-- +upper_symbol_not_idle <= '0' when upper_symbol_type = SYMBOL_IDLE else '1'; +lower_symbol_not_idle <= '0' when lower_symbol_type = SYMBOL_IDLE else '1'; +upper_symbol_not_error <= '0' when upper_symbol_type = SYMBOL_ERROR else '1'; +lower_symbol_not_error <= '0' when lower_symbol_type = SYMBOL_ERROR else '1'; + +upper_symbol_valid <= upper_symbol_not_idle and upper_symbol_not_error; +lower_symbol_valid <= lower_symbol_not_idle and lower_symbol_not_error; + + +end RTL; +--------------------------------------------------------------------------------------- +---------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- +-- File name: pcs_tx_controller.vhd +-- Rev: 0.0 +-- Description: This entity controls the TX stream +-- +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; +use work.rio_common.all; + +entity pcs_tx_controller is + generic ( + TCQ : time := 100 ps + ); + port ( + rst_n : in std_logic; + rio_clk : in std_logic; -- ~150 MHz + UCLK_x2 : in std_logic; -- 312,5 MHz + UCLK : in std_logic; -- 156,25 MHz + UCLK_x2_DV2 : in std_logic; -- 312,5 MHz @ x4 mode / 78,125 @ x1 (fallback mode) + UCLK_or_DV4 : in std_logic; -- 156,25 MHz @ x4 mode / 39,0625 @ x1 (fallback mode) + -- + -- Interface to the RioSerial + outboundWrite_i : in std_logic; + outboundFull_o : out std_logic; + outboundSymbol_i : in std_logic_vector(33 downto 0); + -- outboundSymbolEmpty_i : in std_logic; + -- outboundSymbolRead_o : out std_logic; + -- outboundSymbol_i : in std_logic_vector(33 downto 0); + -- + -- Interface to the GTX transceivers + TXDATA_o : out std_logic_vector(63 downto 0); -- N = 4 + TXCHARISK_o : out std_logic_vector(7 downto 0); + -- + -- Interface to the other blocks + send_ccs_i : in std_logic; + ccs_timer_rst_o : out std_logic; + send_idle_o : out std_logic_vector(1 downto 0); + send_K_i : in std_logic_vector(1 downto 0); + send_A_i : in std_logic_vector(1 downto 0); + send_R_i : in std_logic_vector(1 downto 0); + -- + -- Interface to the port init + TXINHIBIT_02 : in std_logic; + TXINHIBIT_others : in std_logic; + port_initalized_i : in std_logic; + mode_sel_i : in std_logic; + mode_0_lane_sel_i : in std_logic + + ); +end pcs_tx_controller; + +architecture RTL of pcs_tx_controller is + +------------------------------------------------------------------------------- +COMPONENT pcs_tx_boudary_32b_in_64b_out + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(33 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(67 DOWNTO 0); + full : OUT STD_LOGIC; + empty : OUT STD_LOGIC; + almost_empty : out STD_LOGIC; + almost_full : out STD_LOGIC; + valid : OUT STD_LOGIC + ); +END COMPONENT; +------------------------------------------------------------------------------- +-- COMPONENT pcs_tx_boudary_32b_v2 +-- PORT ( +-- rst : IN STD_LOGIC; +-- wr_clk : IN STD_LOGIC; +-- rd_clk : IN STD_LOGIC; +-- din : IN STD_LOGIC_VECTOR(33 DOWNTO 0); +-- wr_en : IN STD_LOGIC; +-- rd_en : IN STD_LOGIC; +-- dout : OUT STD_LOGIC_VECTOR(33 DOWNTO 0); +-- full : OUT STD_LOGIC; +-- empty : OUT STD_LOGIC; +-- almost_empty : OUT STD_LOGIC; +-- valid : OUT STD_LOGIC +-- ); +-- END COMPONENT; +------------------------------------------------------------------------------- +signal rst : std_logic:= '0'; +signal fragment_counter : std_logic_vector(9 downto 0) := (others => '0'); +signal outboundSymbolType : std_logic_vector(1 downto 0) := (others => '0'); +signal outboundSymbol : std_logic_vector(33 downto 0) := (others => '0'); +signal outboundSymbolRead : std_logic:= '0'; +signal non_idle : std_logic:= '0'; +signal decrement_frag_cntr : std_logic:= '0'; + +signal tx_fifo_full : std_logic:= '0'; +signal symbol_empty : std_logic:= '0'; +signal symbol_almost_empty : std_logic:= '0'; +signal symbol_read : std_logic:= '0'; +signal symbol_valid : std_logic:= '0'; +-- signal symbol : std_logic_vector(33 downto 0) := (others => '0'); +signal symbol : std_logic_vector(67 downto 0) := (others => '0'); +signal symbol_u : std_logic_vector(33 downto 0) := (others => '0'); +signal symbol_l : std_logic_vector(33 downto 0) := (others => '0'); +-- signal symbol_type : std_logic_vector(1 downto 0) := (others => '0'); +signal symbol_type : std_logic_vector(3 downto 0) := (others => '0'); +signal symbol_type_u : std_logic_vector(1 downto 0) := (others => '0'); +signal symbol_type_l : std_logic_vector(1 downto 0) := (others => '0'); + +signal TXDATA : std_logic_vector(63 downto 0); -- N = 4 +signal TXCHARISK : std_logic_vector(7 downto 0); +signal TXDATA_u : std_logic_vector(31 downto 0); +signal TXCHARISK_u : std_logic_vector(3 downto 0); +signal TXDATA_l : std_logic_vector(31 downto 0); +signal TXCHARISK_l : std_logic_vector(3 downto 0); + +signal TXDATA_u_idle : std_logic_vector(31 downto 0); +signal TXDATA_l_idle : std_logic_vector(31 downto 0); + +signal word_switch : std_logic:= '0'; +signal lane_switch : std_logic_vector(1 downto 0) := (others => '0'); +signal cycle_switch : std_logic_vector(1 downto 0) := (others => '0'); +signal read_switch : std_logic_vector(1 downto 0) := (others => '0'); + +signal send_idle_q : std_logic:= '0'; +signal send_idle_reg : std_logic_vector(1 downto 0) := (others => '0'); +signal send_idle : std_logic_vector(1 downto 0) := (others => '0'); +signal idle_char_type_0 : std_logic_vector(2 downto 0) := (others => '0'); +signal idle_char_type_1 : std_logic_vector(2 downto 0) := (others => '0'); + +signal send_ccs_cntr : std_logic_vector(1 downto 0) := (others => '0'); +signal send_K : std_logic_vector(1 downto 0) := (others => '0'); +signal send_A : std_logic_vector(1 downto 0) := (others => '0'); +signal send_R : std_logic_vector(1 downto 0) := (others => '0'); +signal send_ccs : std_logic:= '0'; +signal send_ccs_q : std_logic:= '0'; +signal do_not_interrupt : std_logic:= '0'; + +signal be_silent : std_logic:= '0'; +signal fifo_wr_selective : std_logic:= '0'; +signal fifo_wr_selective_q : std_logic:= '0'; +signal fifo_wr_always_even : std_logic:= '0'; +signal fifo_wr_odd_or_even : std_logic:= '0'; +signal fifo_wr_evenly : std_logic:= '0'; +signal outboundSymbolisData : std_logic:= '0'; +signal outboundSymbolisData_q : std_logic:= '0'; + +signal outboundSymbol_q : std_logic_vector(33 downto 0) := (others => '0'); +signal fifo_wr_evenly_q : std_logic:= '0'; +-- signal send_K_ccs : std_logic:= '0'; +-- signal send_R_ccs : std_logic:= '0'; +-- signal send_K_q : std_logic:= '0'; +-- signal send_A_q : std_logic:= '0'; +-- signal send_R_q : std_logic:= '0'; +---------------------------------------------------------------------------------- +begin +-- +rst <= not(rst_n); + +outboundSymbolType <= outboundSymbol_i(33 downto 32); +-- Filtering the ERROR symbol out +outboundSymbol <= outboundSymbol_i when (outboundSymbolType = SYMBOL_DATA or outboundSymbolType = SYMBOL_CONTROL) else + SYMBOL_IDLE & outboundSymbol_i(31 downto 0); + +fifo_wr_selective <= outboundWrite_i when (outboundSymbolType = SYMBOL_DATA or outboundSymbolType = SYMBOL_CONTROL) else '0'; + +fifo_wr_always_even <= fifo_wr_selective or (fifo_wr_selective_q and fifo_wr_odd_or_even); + +outboundSymbolisData <= '1' when outboundSymbolType = SYMBOL_DATA else '0'; + +fifo_wr_evenly <= fifo_wr_selective or (fifo_wr_selective_q and fifo_wr_odd_or_even and not(outboundSymbolisData_q)); + +-- Writing to the FIFO +process(rio_clk) + begin + if rising_edge(rio_clk) then + fifo_wr_selective_q <= fifo_wr_selective; + outboundSymbolisData_q <= outboundSymbolisData; + if fifo_wr_selective = '1' then + fifo_wr_odd_or_even <= not(fifo_wr_odd_or_even); + elsif fifo_wr_selective_q = '1' then + fifo_wr_odd_or_even <= fifo_wr_odd_or_even and outboundSymbolisData_q; -- '0'; + end if; + + outboundSymbol_q <= outboundSymbol; + fifo_wr_evenly_q <= fifo_wr_evenly; + end if; +end process; + +send_K <= send_K_i; +send_A <= send_A_i; +send_R <= send_R_i; + +-- idle_char_type <= send_K & send_A & send_R; +idle_char_type_0 <= send_K(0) & send_A(0) & send_R(0); +idle_char_type_1 <= send_K(1) & send_A(1) & send_R(1); + +be_silent <= '1' when TXINHIBIT_02 = '1' and TXINHIBIT_others = '1' else '0'; + +-- symbol_type <= symbol(33 downto 32); +symbol_type_u <= symbol_u(33 downto 32); +symbol_type_l <= symbol_l(33 downto 32); + +symbol_u <= symbol(67 downto 34); +symbol_l <= symbol(33 downto 0); + +send_idle(1) <= '1' when (send_ccs = '0') and + ((symbol_read = '1' and symbol_type_u = SYMBOL_IDLE) or + (symbol_read = '0') or + (port_initalized_i = '0')) + else + '0'; + +send_idle(0) <= '1' when (send_ccs = '0') and + ((symbol_read = '1' and symbol_type_l = SYMBOL_IDLE) or + (symbol_read = '0') or + (port_initalized_i = '0')) + else + '0'; + +send_idle_o <= send_idle; -- _reg; + +-- symbol_read <= not(symbol_empty) and not(send_ccs) and not(send_ccs_q); + +-- Pipelining +process(UCLK) -- _x2 + begin + if rising_edge(UCLK) then + send_ccs <= not(do_not_interrupt) and send_ccs_i; -- will be high only during real CCS transmission + -- send_idle_reg <= send_idle; + end if; +end process; + +-- Reading from the FIFO +process(UCLK_or_DV4) -- UCLK_x2_DV2 + begin + if rising_edge(UCLK_or_DV4) then + -- case symbol_read is + -- when '0' => + -- symbol_read <= not(symbol_empty) and not(send_ccs) and not(send_ccs_q); -- after TCQ; + -- when '1' => + -- symbol_read <= not(symbol_almost_empty); -- after TCQ; -- and not(send_ccs) and not(send_ccs_q); + -- when others => + -- symbol_read <= '0'; -- after TCQ; + -- end case; + + end if; +end process; + +tx_boundary_fifo : pcs_tx_boudary_32b_in_64b_out -- FWFT FIFO + PORT MAP ( + rst => rst, + + wr_clk => rio_clk, + wr_en => fifo_wr_evenly_q, --fifo_wr_always_even, --outboundWrite_i, + din => outboundSymbol_q, + full => open, -- outboundFull_o, + almost_full => outboundFull_o, + + rd_clk => UCLK_or_DV4, + rd_en => symbol_read, + dout => symbol, + empty => symbol_empty, + almost_empty => symbol_almost_empty, + valid => symbol_valid + ); + +-- FIFO read / TX output process +process(rst_n, UCLK) -- UCLK_x2 + begin + if rst_n = '0' then + + ccs_timer_rst_o <= '0'; + do_not_interrupt <= '0'; + TXDATA_u <= (others => '0'); + TXCHARISK_u <= (others => '0'); + TXDATA_l <= (others => '0'); + TXCHARISK_l <= (others => '0'); + cycle_switch <= (others => '0'); + read_switch <= (others => '0'); + symbol_read <= '0'; + + elsif rising_edge(UCLK) then + + if be_silent = '0' then -- Transmitters are NOT inhibitied + if send_ccs = '1' or send_ccs_q = '1' then -- Transmitting the clock compensation sequence (ccs) = |K|,|R|,|R|,|R| + symbol_read <= '0'; + if send_ccs_q = '0' then + TXDATA_u <= K_column; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= R_column; + TXCHARISK_l <= (others => '1'); + ccs_timer_rst_o <= '1'; + else + TXDATA_u <= R_column; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= R_column; + TXCHARISK_l <= (others => '1'); + end if; + else -- Transmitting the IDLE sequence or the CONTROL/DATA symbols + + read_switch <= read_switch + '1'; + if read_switch = "00" then + case symbol_read is + when '0' => + symbol_read <= not(symbol_empty); -- and not(send_ccs) and not(send_ccs_q); -- after TCQ; + do_not_interrupt <= not(symbol_empty); + when '1' => + symbol_read <= not(symbol_almost_empty); -- after TCQ; -- and not(send_ccs) and not(send_ccs_q); + do_not_interrupt <= not(symbol_almost_empty); + when others => + symbol_read <= '0'; -- after TCQ; + do_not_interrupt <= '0'; + end case; + end if; + + ccs_timer_rst_o <= '0'; + if symbol_read = '1' then -- two symbols have been read, at least one of them is non-idle, they should be forwarded in 1 or 4 cycles + case mode_sel_i is + when '1' => -- Lane stripping (x4 mode: rd_clk = UCLK) + case symbol_type_u is + when SYMBOL_DATA => + TXDATA_u <= symbol_u(31 downto 24) & symbol_u(23 downto 16) & symbol_u(15 downto 8) & symbol_u(7 downto 0); + TXCHARISK_u <= (others => '0'); + when SYMBOL_CONTROL => + TXDATA_u <= symbol_u(31 downto 24) & symbol_u(23 downto 16) & symbol_u(15 downto 8) & symbol_u(7 downto 0); + TXCHARISK_u <= "1000"; + when SYMBOL_IDLE => + TXDATA_u <= TXDATA_u_idle; + TXCHARISK_u <= (others => '1'); + when others => + -- dummy + TXDATA_u <= TXDATA_u_idle; + TXCHARISK_u <= (others => '1'); + end case; + case symbol_type_l is + when SYMBOL_DATA => + TXDATA_l <= symbol_l(31 downto 24) & symbol_l(23 downto 16) & symbol_l(15 downto 8) & symbol_l(7 downto 0); + TXCHARISK_l <= (others => '0'); + when SYMBOL_CONTROL => + TXDATA_l <= symbol_l(31 downto 24) & symbol_l(23 downto 16) & symbol_l(15 downto 8) & symbol_l(7 downto 0); + TXCHARISK_l <= "1000"; + when SYMBOL_IDLE => + TXDATA_l <= TXDATA_l_idle; + TXCHARISK_l <= (others => '1'); + when others => + -- dummy + TXDATA_l <= TXDATA_l_idle; + TXCHARISK_l <= (others => '1'); + end case; + when '0' => -- Slow motion read (x1 mode: rd_clk = UCLK_DV4) + cycle_switch <= cycle_switch + '1'; + -- Cycle | Symbol part to be sent + ---------|---------------------- + -- 00 | symbol_u(31 downto 16) + -- 01 | symbol_u(15 downto 0) + -- 10 | symbol_l(31 downto 16) + -- 11 | symbol_l(15 downto 0) + case cycle_switch(1) is + when '0' => + case cycle_switch(0) is + when '0' => -- 00 + if symbol_type_u /= SYMBOL_IDLE then + TXDATA_u <= symbol_u(31 downto 24) & symbol_u(31 downto 24) & symbol_u(31 downto 24) & symbol_u(31 downto 24); + if symbol_type_u = SYMBOL_DATA then + TXCHARISK_u <= (others => '0'); + else -- if symbol_type_u = SYMBOL_CONTROL then + TXCHARISK_u <= (others => '1'); + end if; + TXDATA_l <= symbol_u(23 downto 16) & symbol_u(23 downto 16) & symbol_u(23 downto 16) & symbol_u(23 downto 16); + TXCHARISK_l <= (others => '0'); + else -- if symbol_type_u = SYMBOL_IDLE then + TXDATA_u <= TXDATA_u_idle; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= TXDATA_l_idle; + TXCHARISK_l <= (others => '1'); + end if; + when '1' => -- 01 + if symbol_type_u /= SYMBOL_IDLE then + TXDATA_u <= symbol_u(15 downto 8) & symbol_u(15 downto 8) & symbol_u(15 downto 8) & symbol_u(15 downto 8); + TXCHARISK_u <= (others => '0'); -- This is the second part: does not matter control or data + TXDATA_l <= symbol_u(7 downto 0) & symbol_u(7 downto 0) & symbol_u(7 downto 0) & symbol_u(7 downto 0); + TXCHARISK_l <= (others => '0'); + else -- if symbol_type_u = SYMBOL_IDLE then + TXDATA_u <= TXDATA_u_idle; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= TXDATA_l_idle; + TXCHARISK_l <= (others => '1'); + end if; + when others => + -- dummy + end case; + when '1' => + case cycle_switch(0) is + when '0' => + if symbol_type_l /= SYMBOL_IDLE then + TXDATA_u <= symbol_l(31 downto 24) & symbol_l(31 downto 24) & symbol_l(31 downto 24) & symbol_l(31 downto 24); + if symbol_type_l = SYMBOL_DATA then + TXCHARISK_u <= (others => '0'); + else -- if symbol_type_l = SYMBOL_CONTROL then + TXCHARISK_u <= (others => '1'); + end if; + TXDATA_l <= symbol_l(23 downto 16) & symbol_l(23 downto 16) & symbol_l(23 downto 16) & symbol_l(23 downto 16); + TXCHARISK_l <= (others => '0'); + else -- if symbol_type_l = SYMBOL_IDLE then + TXDATA_u <= TXDATA_u_idle; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= TXDATA_l_idle; + TXCHARISK_l <= (others => '1'); + end if; + when '1' => + if symbol_type_l /= SYMBOL_IDLE then + TXDATA_u <= symbol_l(15 downto 8) & symbol_l(15 downto 8) & symbol_l(15 downto 8) & symbol_l(15 downto 8); + TXCHARISK_u <= (others => '0'); -- This is the second part: does not matter control or data + TXDATA_l <= symbol_l(7 downto 0) & symbol_l(7 downto 0) & symbol_l(7 downto 0) & symbol_l(7 downto 0); + TXCHARISK_l <= (others => '0'); + else -- if symbol_type_l = SYMBOL_IDLE then + TXDATA_u <= TXDATA_u_idle; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= TXDATA_l_idle; + TXCHARISK_l <= (others => '1'); + end if; + when others => + -- dummy + end case; + when others => + -- dummy + end case; + + when others => + -- dummy + end case; + ----------------------------------------------------------------------------- + else -- No Symbols are present at the FIFO output: Transmitting an idle sequence: |K| or |A| or |R| + TXDATA_u <= TXDATA_u_idle; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= TXDATA_l_idle; + TXCHARISK_l <= (others => '1'); + end if; + end if; + else -- Transmitters are inhibitied + TXDATA_u <= x"BCBCBCBC" ; + TXCHARISK_u <= (others => '1'); + TXDATA_l <= x"FDFDFDFD" ; + TXCHARISK_l <= (others => '1'); + end if; + end if; +end process; + +-- Combinational idle drive process +process(idle_char_type_0, idle_char_type_1) + begin + case idle_char_type_1 is + when "100" => -- |K| (~%50) + TXDATA_u_idle <= K_column; + + when "010" => -- |A| (1/16 .. 1/32) + TXDATA_u_idle <= A_column; + + when "001" => -- |R| (~%50) + TXDATA_u_idle <= R_column; + + when others => + -- dummy + TXDATA_u_idle <= K_column; + end case; + case idle_char_type_0 is + when "100" => -- |K| (~%50) + TXDATA_l_idle <= K_column; + + when "010" => -- |A| (1/16 .. 1/32) + TXDATA_l_idle <= A_column; + + when "001" => -- |R| (~%50) + TXDATA_l_idle <= R_column; + + when others => + -- dummy + TXDATA_l_idle <= R_column; + end case; +end process; + +-- TXDATA buffering by UCLK +process(UCLK) + begin + if rising_edge(UCLK) then + ------------------ + -- MUST BE SWAPPED + TXDATA_o <= TXDATA_u( 7 downto 0) & TXDATA_l( 7 downto 0) & TXDATA_u(15 downto 8) & TXDATA_l(15 downto 8) + & TXDATA_u(23 downto 16) & TXDATA_l(23 downto 16) & TXDATA_u(31 downto 24) & TXDATA_l(31 downto 24); + TXCHARISK_o <= TXCHARISK_u(0) & TXCHARISK_l(0) & TXCHARISK_u(1) & TXCHARISK_l(1) & TXCHARISK_u(2) & TXCHARISK_l(2) & TXCHARISK_u(3) & TXCHARISK_l(3); + ------------------ + end if; +end process; + +-- Delaying send_ccs +process(UCLK) + begin + if rising_edge(UCLK) then + if be_silent = '0' then + send_ccs_q <= send_ccs; --- + else + send_ccs_q <= '0'; + end if; + end if; +end process; + +end RTL; +---------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- +-- File name: port_init_fsms.vhd +-- Rev: 0.0 +-- Description: This entity does the 1x/Nx port init according to the +-- RIO Sepec. Part-6, subchapter 4.2 +-- +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; +use work.rio_common.all; +--use work.rio_common_sim.all; + +entity port_init_fsms is + generic ( + TCQ : time := 100 ps + ); + port ( + rst_n : in std_logic; + UCLK_x2 : in std_logic; + UCLK : in std_logic; + UCLK_DV4 : in std_logic; + UCLK_DV_1024 : in std_logic; + + force_reinit : in std_logic:='0'; -- force retraining + mode_sel : out std_logic; -- 0: x1 fallback mode / 1: xN Mode + mode_0_lane_sel : out std_logic; -- If mode_sel = 0 then 0: Lane 0 is active(R), 1: Lane 2 is active else don't care + port_initalized : out std_logic; -- 1: Port initialization is successfully complete + lane_sync : out std_logic_vector(N-1 downto 0); -- Lane is synchoronised + RXCHARISvalid : out std_logic_vector(N*2-1 downto 0); + + -- GTXRESET : out std_logic; + TXINHIBIT_02 : out std_logic; + TXINHIBIT_others : out std_logic; + ENCHANSYNC : out std_logic; + -- TXDATA : out std_logic_vector(N*16-1 downto 0); + -- TXCHARISK : out std_logic_vector(N*2-1 downto 0); + PLLLKDET : in std_logic; + RXDATA : in std_logic_vector(N*16-1 downto 0); + RXCHARISK : in std_logic_vector(N*2-1 downto 0); + RXCHARISCOMMA : in std_logic_vector(N*2-1 downto 0); + RXBYTEISALIGNED : in std_logic_vector(N-1 downto 0); + RXBYTEREALIGN : in std_logic_vector(N-1 downto 0); + RXELECIDLE : in std_logic_vector(N-1 downto 0); + RXDISPERR : in std_logic_vector(N*2-1 downto 0); + RXNOTINTABLE : in std_logic_vector(N*2-1 downto 0); + RXBUFERR : in std_logic; + RXBUFRST : out std_logic; + CHBONDDONE : in std_logic_vector(N-1 downto 0) + ); +end port_init_fsms; + +architecture rtl of port_init_fsms is +------------------------------------------------------------------------------------------------------------------------------------------- +-- Lane_Synchronization State Machine +type lane_sync_states is (NO_SYNC, NO_SYNC_1, NO_SYNC_2, NO_SYNC_2a, NO_SYNC_2b, NO_SYNC_3, SYNC, SYNCa, SYNCb, SYNC_1, SYNC_2, SYNC_2a, SYNC_2b, SYNC_3, SYNC_4); +type lane_sync_states_array is array (N-1 downto 0) of lane_sync_states; + +signal lane_sync_state_n : lane_sync_states_array := (others => NO_SYNC); +signal lane_sync_n : std_logic_vector(N-1 downto 0) := (others => '0'); +signal Kcounter_n : Kcounter_array_type := (others => (others => '0')); +signal Vcounter_n : Vcounter_array_type := (others => (others => '0')); +signal Icounter_n : Icounter_array_type := (others => (others => '0')); +signal code_group_valid : std_logic_vector(N*2-1 downto 0) := (others => '0'); +------------------------------------------------------------------------------------------------------------------------------------------- +-- Lane_Alignment State Machine +type lane_alignment_states is (NOT_ALIGNED, NOT_ALIGNED_1, NOT_ALIGNED_2, ALIGNED, ALIGNED_1, ALIGNED_2, ALIGNED_3); + +signal lane_alignment_state : lane_alignment_states := NOT_ALIGNED; +signal N_lanes_aligned : std_logic := '0'; +signal Acounter : std_logic_vector(2 downto 0) := (others => '0'); +signal Mcounter : Mcounter_type := (others => '0'); +signal lane_alignment_reset : std_logic := '0'; +signal N_lane_sync : std_logic := '0'; +constant N_lanes_all_high : std_logic_vector(N-1 downto 0) := (others => '1'); +constant N_lanes_all_low : std_logic_vector(N-1 downto 0) := (others => '0'); + +signal A_column_valid : std_logic := '0'; +signal align_error : std_logic := '0'; +signal A_column_valid_upper : std_logic := '0'; +signal align_error_upper : std_logic := '0'; +signal A_column_valid_lower : std_logic := '0'; +signal align_error_lower : std_logic := '0'; + +signal RXCHARIS_A_upper : std_logic_vector(N-1 downto 0) := (others => '0'); +signal RXCHARIS_A_lower : std_logic_vector(N-1 downto 0) := (others => '0'); +------------------------------------------------------------------------------------------------------------------------------------------- +-- begin --dummy +-- 1x/Nx Mode Init State Machine +type mode_init_states is (SILENT, SEEK, DISCOVERY, x1_RECOVERY, Nx_MODE, x1_MODE_LANE0, x1_MODE_LANE2); + +signal mode_init_state : mode_init_states := SILENT; +signal lanes02_drvr_oe : std_logic := '0'; +signal N_lanes_drvr_oe : std_logic := '0'; +signal Nx_mode_active : std_logic := '0'; +signal receive_lane2 : std_logic := '0'; +signal force_reinit_reg : std_logic := '0'; +signal force_reinit_clear : std_logic := '0'; + +signal silence_timer_en : std_logic := '0'; +signal silence_timer_done : std_logic := '0'; +signal silence_timer : std_logic_vector(4 downto 0) := (others => '0'); + +signal disc_tmr_en : std_logic := '0'; +signal disc_tmr_done : std_logic := '0'; +signal disc_tmr : std_logic_vector(15 downto 0) := (others => '0'); + +signal port_initalized_reg : std_logic := '0'; + +signal idle_selected : std_logic := '1'; -- Only IDLE1 is to be used +signal Nx_mode_enabled : std_logic := '1'; -- Nx mode is to be always enabled +signal force_1x_mode : std_logic := '0'; -- don't force 1x mode +signal force_laneR : std_logic := '0'; -- don't care, when force_1x_mode = 0 + +signal lane_ready_n : std_logic_vector(N-1 downto 0) := (others => '0'); +signal rcvr_trained_n : std_logic_vector(N-1 downto 0) := (others => '0'); +signal N_lanes_ready : std_logic := '0'; + +signal rxbufrst_cntr : std_logic_vector(2 downto 0) := (others => '0'); +signal rxbuferr_reg : std_logic := '0'; +------------------------------------------------------------------------------------------------------------------------------------------- +begin + +lane_sync <= lane_sync_n; +---------------------------------------------------------------- +-- Figure 4-14. Lane_Synchronization State Machine for N Lanes +GEN_LANE_SYNC_FSM: for i in 0 to N-1 generate + +code_group_valid(i*2) <= not(RXNOTINTABLE(i*2) ) and not(RXDISPERR(i*2) ); +code_group_valid(i*2+1) <= not(RXNOTINTABLE(i*2+1)) and not(RXDISPERR(i*2+1)); + +RXCHARISvalid(i*2) <= code_group_valid(i*2) ; +RXCHARISvalid(i*2+1) <= code_group_valid(i*2+1); + +process(rst_n, UCLK) -- (UCLK_x2) -- + begin + + if rst_n = '0' then + + lane_sync_state_n(i) <= NO_SYNC; + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + Vcounter_n(i) <= (others => '0'); + + elsif rising_edge(UCLK) then + + case lane_sync_state_n(i) is + when NO_SYNC => + -- change(signal_detect[n]) + if RXELECIDLE(i) = '1' then + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + Vcounter_n(i) <= (others => '0'); + -- signal_detect[n] & /COMMA/ [ KK-- ] : /K/ is being detected at the upper half + elsif (code_group_valid(i*2+1) = '1' and RXCHARISCOMMA(i*2+1) = '1') then + -- signal_detect[n] & /COMMA/ [ --KK ] : /K/ is being detected also at the lower half + if (code_group_valid(i*2) = '1' and RXCHARISCOMMA(i*2) = '1') then + lane_sync_state_n(i) <= NO_SYNC_2; + Kcounter_n(i) <= Kcounter_n(i) + "10"; + Vcounter_n(i) <= Vcounter_n(i) + "10"; + -- signal_detect[n] [ --VV ] : At the lower half: no comma, but valid + elsif (code_group_valid(i*2) = '1') then + lane_sync_state_n(i) <= NO_SYNC_2; + Kcounter_n(i) <= Kcounter_n(i) + '1'; + Vcounter_n(i) <= Vcounter_n(i) + "10"; + -- do nothing + else + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + Vcounter_n(i) <= (others => '0'); + end if; + ---------------------------------------------------------------------------------------------- + -- signal_detect[n] & /COMMA/ [ --KK ] : /K/ is being detected only at the lower half + elsif (code_group_valid(i*2) = '1' and RXCHARISCOMMA(i*2) = '1') then + lane_sync_state_n(i) <= NO_SYNC_2; + Kcounter_n(i) <= Kcounter_n(i) + '1'; + Vcounter_n(i) <= Vcounter_n(i) + '1'; + ---------------------------------------------------------------------------------------------- + -- !signal_detect[n] | !/COMMA/ + else + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + Vcounter_n(i) <= (others => '0'); + end if; + -- -- change(signal_detect[n]) + -- if RXELECIDLE(i) = '1' then + -- lane_sync_n(i) <= '0'; + -- Kcounter_n(i) <= (others => '0'); + -- Vcounter_n(i) <= (others => '0'); + -- -- signal_detect[n] & /COMMA/ [ KK-- ] : /K/ is being detected at the upper half + -- elsif (code_group_valid(i*2+1) = '1' and RXCHARISCOMMA(i*2+1) = '1') then + -- lane_sync_state_n(i) <= NO_SYNC_2a; + -- Kcounter_n(i) <= Kcounter_n(i) + '1'; + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- -- signal_detect[n] & /COMMA/ [ --KK ] : /K/ is being detected at the lower half + -- elsif (code_group_valid(i*2) = '1' and RXCHARISCOMMA(i*2) = '1') then + -- lane_sync_state_n(i) <= NO_SYNC_2b; + -- Kcounter_n(i) <= Kcounter_n(i) + '1'; + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- -- !signal_detect[n] | !/COMMA/ + -- else + -- lane_sync_n(i) <= '0'; + -- Kcounter_n(i) <= (others => '0'); + -- Vcounter_n(i) <= (others => '0'); + -- end if; + + -- when NO_SYNC_1 => + + when NO_SYNC_2 => + -- [ IIXX or XXII ] -- One of both /INVALID/ + if (code_group_valid(i*2) = '0' or code_group_valid(i*2+1) = '0') then + lane_sync_state_n(i) <= NO_SYNC; + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + Vcounter_n(i) <= (others => '0'); + -- [ KKKK ] -- Both /COMMA/ + elsif (RXCHARISCOMMA(i*2) = '1' and RXCHARISCOMMA(i*2+1) = '1') then + -- (Kcounter[n] > 126) & (Vcounter[n] > Vmin-1) + if Kcounter_n(i) >= Kmin and Vcounter_n(i) >= Vmin then + lane_sync_state_n(i) <= SYNC; + -- (Kcounter[n] < 127) | (Vcounter[n] < Vmin) + else + Kcounter_n(i) <= Kcounter_n(i) + "10"; + Vcounter_n(i) <= Vcounter_n(i) + "10"; + end if; + -- [ KKVV or VVKK ] -- One of both /COMMA/ + elsif (RXCHARISCOMMA(i*2) = '1' or RXCHARISCOMMA(i*2+1) = '1') then + -- (Kcounter[n] > 126) & (Vcounter[n] > Vmin-1) + if Kcounter_n(i) >= Kmin and Vcounter_n(i) >= Vmin then + lane_sync_state_n(i) <= SYNC; + -- (Kcounter[n] < 127) | (Vcounter[n] < Vmin) + else + Kcounter_n(i) <= Kcounter_n(i) + '1' ; + Vcounter_n(i) <= Vcounter_n(i) + "10"; + end if; + + -- [ VVVV ] -- None of both /COMMA/, but both /VALID/ + else -- if RXCHARISCOMMA(i*2) = '0') and RXCHARISCOMMA(i*2+1) = '0') then + -- (Kcounter[n] > 126) & (Vcounter[n] > Vmin-1) + if Kcounter_n(i) >= Kmin and Vcounter_n(i) >= Vmin then + lane_sync_state_n(i) <= SYNC; + -- (Kcounter[n] < 127) | (Vcounter[n] < Vmin) + else + Vcounter_n(i) <= Vcounter_n(i) + "10"; + end if; + end if; + + -- when NO_SYNC_2a => + -- -- !(/COMMA/|/INVALID/) + -- if (code_group_valid(i*2) = '1' and not(RXCHARISCOMMA(i*2) = '1')) then --RXCHARISK(i*2) = '1' and RXDATA(i*16+7 downto i*16) = x"BC")) then + -- lane_sync_state_n(i) <= NO_SYNC_2b; + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- -- /COMMA/ + -- elsif (code_group_valid(i*2) = '1' and RXCHARISCOMMA(i*2) = '1') then --RXCHARISK(i*2) = '1' and RXDATA(i*16+7 downto i*16) = x"BC") then + -- -- (Kcounter[n] > 126) & (Vcounter[n] > Vmin-1) + -- if Kcounter_n(i) >= Kmin and Vcounter_n(i) >= Vmin then + -- lane_sync_state_n(i) <= SYNCb; + -- -- (Kcounter[n] < 127) | (Vcounter[n] < Vmin) + -- else + -- lane_sync_state_n(i) <= NO_SYNC_2b; + -- Kcounter_n(i) <= Kcounter_n(i) + '1'; + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- end if; + -- -- /INVALID/ + -- elsif (code_group_valid(i*2) = '0') then + -- lane_sync_state_n(i) <= NO_SYNC; + -- lane_sync_n(i) <= '0'; + -- Kcounter_n(i) <= (others => '0'); + -- Vcounter_n(i) <= (others => '0'); + -- end if; + -- + -- when NO_SYNC_2b => + -- -- !(/COMMA/|/INVALID/) + -- if (code_group_valid(i*2+1) = '1' and not(RXCHARISCOMMA(i*2+1) = '1')) then --RXCHARISK(i*2+1) = '1' and RXDATA(i*16+15 downto i*16+8) = x"BC")) then + -- lane_sync_state_n(i) <= NO_SYNC_2a; + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- -- /COMMA/ + -- elsif (code_group_valid(i*2+1) = '1' and RXCHARISCOMMA(i*2+1) = '1') then --RXCHARISK(i*2+1) = '1' and RXDATA(i*16+15 downto i*16+8) = x"BC") then + -- -- (Kcounter[n] > 126) & (Vcounter[n] > Vmin-1) + -- if Kcounter_n(i) >= Kmin and Vcounter_n(i) >= Vmin then + -- lane_sync_state_n(i) <= SYNCa; + -- -- (Kcounter[n] < 127) | (Vcounter[n] < Vmin) + -- else + -- lane_sync_state_n(i) <= NO_SYNC_2a; + -- Kcounter_n(i) <= Kcounter_n(i) + '1'; + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- end if; + -- -- /INVALID/ + -- elsif (code_group_valid(i*2+1) = '0') then + -- lane_sync_state_n(i) <= NO_SYNC; + -- lane_sync_n(i) <= '0'; + -- Kcounter_n(i) <= (others => '0'); + -- Vcounter_n(i) <= (others => '0'); + -- end if; + + -- when NO_SYNC_3 => + + when SYNC => + -- Both /VALID/ + if (code_group_valid(i*2) = '1' and code_group_valid(i*2+1) = '1') then + lane_sync_n(i) <= '1'; + Icounter_n(i) <= (others => '0'); + -- One of both /INVALID/ + elsif (code_group_valid(i*2) = '1' or code_group_valid(i*2+1) = '1') then + Icounter_n(i) <= Icounter_n(i) + '1'; + lane_sync_state_n(i) <= SYNC_2; + -- Both /INVALID/ + else + Icounter_n(i) <= Icounter_n(i) + "10"; + lane_sync_state_n(i) <= SYNC_2; + end if; + -- + -- when SYNCa => + -- -- /INVALID/ + -- if (code_group_valid(i*2) = '0') then + -- Icounter_n(i) <= Icounter_n(i) + '1'; + -- lane_sync_state_n(i) <= SYNC_2b; + -- -- /VALID/ + -- else + -- lane_sync_state_n(i) <= SYNCb; + -- lane_sync_n(i) <= '1'; + -- Icounter_n(i) <= (others => '0'); + -- end if; + -- + -- when SYNCb => + -- -- /INVALID/ + -- if (code_group_valid(i*2+1) = '0') then + -- Icounter_n(i) <= Icounter_n(i) + '1'; + -- lane_sync_state_n(i) <= SYNC_2a; + -- -- /VALID/ + -- else + -- lane_sync_state_n(i) <= SYNCa; + -- lane_sync_n(i) <= '1'; + -- Icounter_n(i) <= (others => '0'); + -- end if; + + -- when SYNC_1 => + + when SYNC_2 => + -- Both /VALID/ + if (code_group_valid(i*2) = '1' and code_group_valid(i*2+1) = '1') then + Vcounter_n(i) <= Vcounter_n(i) + "10"; + -- (Vcounter[n] < 255) + if Vcounter_n(i) < x"FF" then + -- do nothing + lane_sync_state_n(i) <= SYNC_2; + -- (Vcounter[n] = 255) + else + Icounter_n(i) <= Icounter_n(i) - '1'; + Vcounter_n(i) <= (others => '0'); + -- (Icounter[n] > 0) + if Icounter_n(i) > Ione then + -- do nothing + lane_sync_state_n(i) <= SYNC_2; + -- (Icounter[n] = 0) + else + lane_sync_state_n(i) <= SYNC; + end if; + end if; + -- One of both /INVALID/ + elsif (code_group_valid(i*2) = '1' or code_group_valid(i*2+1) = '1') then + Icounter_n(i) <= Icounter_n(i) + '1'; + Vcounter_n(i) <= (others => '0'); + -- (Icounter[n] = Imax) + if Icounter_n(i) = Imax then + lane_sync_state_n(i) <= NO_SYNC; + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + -- (Icounter[n] < Imax) + else + -- do nothing + lane_sync_state_n(i) <= SYNC_2; + end if; + -- Both /INVALID/ + else + Icounter_n(i) <= Icounter_n(i) + "10"; + Vcounter_n(i) <= (others => '0'); + -- (Icounter[n] = Imax) + if Icounter_n(i) = Imax then + lane_sync_state_n(i) <= NO_SYNC; + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + -- (Icounter[n] < Imax) + else + -- do nothing + lane_sync_state_n(i) <= SYNC_2; + end if; + end if; + ---------------------------------------------- + + -- when SYNC_2a => + -- -- /INVALID/ + -- if (code_group_valid(i*2+1) = '0') then + -- Icounter_n(i) <= Icounter_n(i) + '1'; + -- Vcounter_n(i) <= (others => '0'); + -- -- (Icounter[n] = Imax) + -- if Icounter_n(i) = Imax then + -- lane_sync_state_n(i) <= NO_SYNC; + -- lane_sync_n(i) <= '0'; + -- Kcounter_n(i) <= (others => '0'); + -- -- (Icounter[n] < Imax) + -- else + -- lane_sync_state_n(i) <= SYNC_2b; + -- end if; + -- -- /VALID/ + -- else + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- -- (Vcounter[n] < 255) + -- if Vcounter_n(i) < x"FF" then + -- lane_sync_state_n(i) <= SYNC_2b; + -- -- (Vcounter[n] = 255) + -- else + -- Icounter_n(i) <= Icounter_n(i) - '1'; + -- Vcounter_n(i) <= (others => '0'); + -- -- (Icounter[n] > 0) + -- if Icounter_n(i) > Izero then + -- lane_sync_state_n(i) <= SYNC_2b; + -- -- (Icounter[n] = 0) + -- else + -- lane_sync_state_n(i) <= SYNCb; + -- end if; + -- end if; + -- end if; + -- + -- when SYNC_2b => + -- -- /INVALID/ + -- if (code_group_valid(i*2+1) = '0') then + -- Icounter_n(i) <= Icounter_n(i) + '1'; + -- Vcounter_n(i) <= (others => '0'); + -- -- (Icounter[n] = Imax) + -- if Icounter_n(i) = Imax then + -- lane_sync_state_n(i) <= NO_SYNC; + -- lane_sync_n(i) <= '0'; + -- Kcounter_n(i) <= (others => '0'); + -- -- (Icounter[n] < Imax) + -- else + -- lane_sync_state_n(i) <= SYNC_2a; + -- end if; + -- -- /VALID/ + -- else + -- Vcounter_n(i) <= Vcounter_n(i) + '1'; + -- -- (Vcounter[n] < 255) + -- if Vcounter_n(i) < x"FF" then + -- lane_sync_state_n(i) <= SYNC_2a; + -- -- (Vcounter[n] = 255) + -- else + -- Icounter_n(i) <= Icounter_n(i) - '1'; + -- Vcounter_n(i) <= (others => '0'); + -- -- (Icounter[n] > 0) + -- if Icounter_n(i) > Izero then + -- lane_sync_state_n(i) <= SYNC_2a; + -- -- (Icounter[n] = 0) + -- else + -- lane_sync_state_n(i) <= SYNCa; + -- end if; + -- end if; + -- end if; + + -- when SYNC_3 => + + -- when SYNC_4 => + + when others => + lane_sync_state_n(i) <= NO_SYNC; + lane_sync_n(i) <= '0'; + Kcounter_n(i) <= (others => '0'); + Vcounter_n(i) <= (others => '0'); + + end case; + end if; +end process; + +end generate GEN_LANE_SYNC_FSM; +---------------------------------------------------------------- +-- Figure 4-15. Lane_Alignment State Machine (for N lanes) + +N_lane_sync <= '1' when lane_sync_n = N_lanes_all_high else '0'; +lane_alignment_reset <= N_lane_sync and rst_n; +A_column_valid_upper <= '1' when (RXCHARIS_A_upper = N_lanes_all_high) else '0'; +A_column_valid_lower <= '1' when (RXCHARIS_A_lower = N_lanes_all_high) else '0'; +A_column_valid <= A_column_valid_upper or A_column_valid_lower; +align_error_upper <= '1' when (RXCHARIS_A_upper /= N_lanes_all_low) and (RXCHARIS_A_upper /= N_lanes_all_high) else '0'; +align_error_lower <= '1' when (RXCHARIS_A_lower /= N_lanes_all_low) and (RXCHARIS_A_lower /= N_lanes_all_high) else '0'; +align_error <= align_error_upper or align_error_lower; +GEN_CHAR_A_CHECKER: for i in 0 to N-1 generate +RXCHARIS_A_upper(i) <= '1' when (code_group_valid(i*2+1) = '1') and (RXCHARISK(i*2+1) = '1') and (RXDATA(i*16+15 downto i*16+8) = A_align) else '0'; +RXCHARIS_A_lower(i) <= '1' when (code_group_valid(i*2) = '1' ) and (RXCHARISK(i*2) = '1' ) and (RXDATA(i*16+7 downto i*16 ) = A_align) else '0'; +end generate GEN_CHAR_A_CHECKER; + +process(lane_alignment_reset, UCLK) + begin + + if lane_alignment_reset = '0' then + + lane_alignment_state <= NOT_ALIGNED; + N_lanes_aligned <= '0'; + Acounter <= (others => '0'); + -- Mcounter <= (others => '0'); + + elsif rising_edge(UCLK) then + + -- if lane_alignment_reset = '1' then + + case lane_alignment_state is + when NOT_ALIGNED => + -- N_lane_sync & ||A|| + if N_lane_sync = '1' and A_column_valid = '1' then + Acounter <= Acounter + '1'; + lane_alignment_state <= NOT_ALIGNED_2; + end if; + + -- when NOT_ALIGNED_1 => + + when NOT_ALIGNED_2 => + -- align_error + if align_error = '1' then + lane_alignment_state <= NOT_ALIGNED; + N_lanes_aligned <= '0'; + Acounter <= (others => '0'); + -- ||A|| + elsif A_column_valid = '1' then + Acounter <= Acounter + '1'; + -- Acounter = 4 + if Acounter = "100" then + lane_alignment_state <= ALIGNED; + -- Acounter < 4 + else + lane_alignment_state <= NOT_ALIGNED_2; + end if; + -- !align_error & !||A|| + else + -- Do nothing: Wait for the next column + end if; + + when ALIGNED => + N_lanes_aligned <= '1'; + Mcounter <= (others => '0'); + -- align_error + if align_error = '1' then + Acounter <= (others => '0'); + Mcounter <= Mcounter + '1'; + lane_alignment_state <= ALIGNED_2; + -- !(align_error) + else + -- Do nothing extra: Wait for the next column + end if; + + -- when ALIGNED_1 => + + when ALIGNED_2 => + -- align_error + if align_error = '1' then + Acounter <= (others => '0'); + Mcounter <= Mcounter + '1'; + -- Mcounter = Mmax + if Mcounter = Mmax then + lane_alignment_state <= NOT_ALIGNED; + N_lanes_aligned <= '0'; + -- Mcounter < Mmax + else + -- Do nothing extra: Wait for the next column + end if; + -- ||A|| + elsif A_column_valid = '1' then + Acounter <= Acounter + '1'; + -- Acounter = 4 + if Acounter = "100" then + lane_alignment_state <= ALIGNED; + -- Acounter < 4 + else + -- Do nothing extra: Wait for the next column + end if; + -- !align_error & !||A|| + else + -- Do nothing: Wait for the next column + end if; + + -- when ALIGNED_3 => + + when others => + lane_alignment_state <= NOT_ALIGNED; + N_lanes_aligned <= '0'; + Acounter <= (others => '0'); + Mcounter <= (others => '0'); + + end case; + -- else + -- lane_alignment_state <= NOT_ALIGNED; + -- N_lanes_aligned <= '0'; + -- Acounter <= (others => '0'); + -- end if; + end if; +end process; + +-- Figure 4-18. 1x/Nx_Initialization State Machine for N = 4 +TXINHIBIT_02 <= not(lanes02_drvr_oe); +TXINHIBIT_others <= not(N_lanes_drvr_oe); +rcvr_trained_n <= CHBONDDONE; -- TBD +lane_ready_n <= lane_sync_n and rcvr_trained_n; +-- lane_ready_n <= lane_sync_n; -- and rcvr_trained_n; +N_lanes_ready <= '1' when N_lanes_aligned = '1' and lane_ready_n = N_lanes_all_high else '0'; + +-- process(UCLK) +-- begin +-- if rising_edge(UCLK) then +-- mode_sel <= Nx_mode_active; +-- mode_0_lane_sel <= receive_lane2; +-- port_initalized <= port_initalized_reg; +-- end if; +-- end process; +mode_sel <= Nx_mode_active; +mode_0_lane_sel <= receive_lane2; +port_initalized <= port_initalized_reg; + +process(rst_n, UCLK) + begin + if rst_n = '0' then + + mode_init_state <= SILENT; + disc_tmr_en <= '0'; + lanes02_drvr_oe <= '0'; + N_lanes_drvr_oe <= '0'; + port_initalized_reg <= '0'; + Nx_mode_active <= '0'; + receive_lane2 <= '0'; + force_reinit_clear <= '0'; + silence_timer_en <= '0'; + idle_selected <= '1'; + + elsif rising_edge(UCLK) then + case mode_init_state is + + when SILENT => + disc_tmr_en <= '0'; + lanes02_drvr_oe <= '0'; + N_lanes_drvr_oe <= '0'; + port_initalized_reg <= '0'; + Nx_mode_active <= '0'; + receive_lane2 <= '0'; + force_reinit_clear <= '1'; -- = force_reinit <= '0'; + silence_timer_en <= '1'; + -- force_reinit + if force_reinit_reg = '1' then + mode_init_state <= SILENT; + -- silence_timer_done + elsif silence_timer_done = '1' then + mode_init_state <= SEEK; + end if; + + when SEEK => + lanes02_drvr_oe <= '1'; + silence_timer_en <= '0'; + -- (lane_sync_0 | lane_sync_2) & idle_selected + if (lane_sync_n(0) = '1' or lane_sync_n(2) = '1') and idle_selected = '1' then + mode_init_state <= DISCOVERY; + end if; + + when DISCOVERY => + port_initalized_reg <= '0'; + Nx_mode_active <= '0'; + N_lanes_drvr_oe <= Nx_mode_enabled; + disc_tmr_en <= '1'; + -- Nx_mode_enabled & N_lanes_ready + if Nx_mode_enabled = '1' and N_lanes_ready = '1' then + + mode_init_state <= Nx_MODE; + + -- lane_ready[0] & (force_1x_mode & (!force_laneR | force_laneR & disc_tmr_done & !lane_ready[2]) + -- | !force_1x_mode & disc_tmr_done & !N_lanes_ready) + elsif lane_ready_n(0) = '1' and ((force_1x_mode = '1' and (force_laneR = '0' or (force_laneR = '1' and disc_tmr_done = '1' and lane_ready_n(2) = '0'))) + or (force_1x_mode = '0' and disc_tmr_done = '1' and N_lanes_ready = '0')) then + + mode_init_state <= x1_MODE_LANE0; + + -- lane_ready[2] & (force_1x_mode & force_laneR | disc_tmr_done & !lane_ready[0] + -- & (force_1x_mode & !force_laneR | !force_1x_mode & !N_lanes_ready)) + elsif lane_ready_n(2) = '1' and ((force_1x_mode = '1' and force_laneR = '1') or + (disc_tmr_done = '1' and lane_ready_n(0) = '0' and + ((force_1x_mode = '1' and force_laneR = '0') or (force_1x_mode = '0' and N_lanes_ready = '0')))) then + + mode_init_state <= x1_MODE_LANE2; + + ---- -- !lane_sync[0] & !lane_sync[2] | disc_tmr_done & !lane_ready[0] & !lane_ready[2] + ---- elsif (lane_sync_n(0) = '0' and lane_sync_n(2) = '0') or (disc_tmr_done = '1' and lane_ready_n(0) = '0' and lane_ready_n(2) = '0') then + -- disc_tmr_done & !lane_ready[0] & !lane_ready[2] + elsif (disc_tmr_done = '1' and lane_ready_n(0) = '0' and lane_ready_n(2) = '0') then + + mode_init_state <= SILENT; + + end if; + + when Nx_MODE => + disc_tmr_en <= '0'; + port_initalized_reg <= '1'; + Nx_mode_active <= '1'; + -- !N_lanes_ready & (lane_sync[0] | lane_sync[2]) + if N_lanes_ready = '0' and (lane_sync_n(0) = '1' or lane_sync_n(2) = '1') then + mode_init_state <= DISCOVERY; + -- !N_lanes_ready & !lane_sync[0] & !lane_sync[2] + elsif N_lanes_ready = '0' and lane_sync_n(0) = '0' and lane_sync_n(2) = '0' then + mode_init_state <= SILENT; + end if; + + when x1_MODE_LANE0 => + disc_tmr_en <= '0'; + N_lanes_drvr_oe <= '0'; + port_initalized_reg <= '1'; + -- !lane_sync[0] + if lane_sync_n(0) = '0' then + mode_init_state <= SILENT; + -- !lane_ready[0] & lane_sync[0] + elsif lane_ready_n(0) = '0' and lane_sync_n(0) = '1' then + mode_init_state <= x1_RECOVERY; + end if; + + when x1_MODE_LANE2 => + disc_tmr_en <= '0'; + receive_lane2 <= '1'; + N_lanes_drvr_oe <= '0'; + port_initalized_reg <= '1'; + -- !lane_sync[2] + if lane_sync_n(2) = '0' then + mode_init_state <= SILENT; + -- !lane_ready[2] & lane_sync[2] + elsif lane_ready_n(2) = '0' and lane_sync_n(2) = '1' then + mode_init_state <= x1_RECOVERY; + end if; + + when x1_RECOVERY => + port_initalized_reg <= '0'; + disc_tmr_en <= '1'; + -- !lane_sync[0] & !lane_sync[2] & disc_tmr_done (!!!) + if lane_sync_n(0) = '0' and lane_sync_n(2) = '0' and disc_tmr_done = '1' then + + mode_init_state <= SILENT; + + -- lane_ready[0] & !receive_lane2 & !disc_tmr_done + elsif lane_sync_n(0) = '1' and receive_lane2 = '0' and disc_tmr_done = '0' then + + mode_init_state <= x1_MODE_LANE0; + + -- lane_ready[2] & receive_lane2 & !disc_tmr_done + elsif lane_sync_n(2) = '1' and receive_lane2 = '1' and disc_tmr_done = '0' then + + mode_init_state <= x1_MODE_LANE2; + + end if; + + when others => + port_initalized_reg <= '0'; + mode_init_state <= SILENT; + + end case; + + end if; + +end process; + +-- Sticky force_reinit set-reset register +process(rst_n, UCLK) + begin + if rst_n = '0' then + force_reinit_reg <= '0'; + elsif rising_edge(UCLK) then + case force_reinit_reg is + when '0' => + force_reinit_reg <= force_reinit or rxbuferr_reg; + when '1' => + -- force_reinit_reg <= not(force_reinit_clear) and not(force_reinit); + force_reinit_reg <= not(force_reinit_clear and not(force_reinit) and not(rxbuferr_reg)); + when others => + force_reinit_reg <= '0'; + end case; + end if; +end process; + +-- RXBUFRST handler +process(rst_n, UCLK) + begin + if rst_n = '0' then + rxbufrst_cntr <= (others => '0'); + rxbuferr_reg <= '0'; + RXBUFRST <= '0'; + + elsif rising_edge(UCLK) then + case rxbuferr_reg is + when '0' => + rxbuferr_reg <= RXBUFERR; + RXBUFRST <= '0'; + when '1' => + if rxbufrst_cntr = "111" then + rxbuferr_reg <= '0'; + rxbufrst_cntr <= (others => '0'); + else + RXBUFRST <= '1'; + rxbufrst_cntr <= rxbufrst_cntr + '1'; + end if; + when others => + rxbuferr_reg <= '0'; + end case; + end if; +end process; + + +-- Silence Timer Process +-- silence_timer_done: Asserted when silence_timer_en has been continuously asserted +-- for 120 +/- 40 µs and the state machine is in the SILENT state. The assertion of +-- silence_timer_done causes silence_timer_en to be de-asserted. When the state +-- machine is not in the SILENT state, silence_timer_done is de-asserted. +process(rst_n, UCLK_DV_1024) + begin + if rst_n = '0' then + silence_timer_done <= '0'; + silence_timer <= (others => '0'); + elsif rising_edge(UCLK_DV_1024) then + + case silence_timer_en is + when '0' => + silence_timer <= (others => '0'); + silence_timer_done <= '0'; + when '1' => + if silence_timer = SILENT_ENOUGH then + if mode_init_state = SILENT then + silence_timer_done <= '1'; + else + silence_timer_done <= '0'; + end if; + else + silence_timer <= silence_timer + '1'; + end if; + when others => + silence_timer <= (others => '0'); + end case; + end if; +end process; + +-- Discovery Timer Process +-- disc_tmr_done: Asserted when disc_tmr_en has been continuously asserted for 28 +/- 4 ms +-- and the state machine is in the DISCOVERY or a RECOVERY state. The assertion of +-- disc_tmr_done causes disc_tmr_en to be de-asserted. When the state machine is in +-- a state other than the DISCOVERY or a RECOVERY state, disc_tmr_done is de-asserted. +process(rst_n, UCLK_DV_1024) + begin + if rst_n = '0' then + disc_tmr_done <= '0'; + disc_tmr <= (others => '0'); + elsif rising_edge(UCLK_DV_1024) then + + case disc_tmr_en is + when '0' => + disc_tmr <= (others => '0'); + disc_tmr_done <= '0'; + when '1' => + if disc_tmr = DISCOVERY_ENDS then + if mode_init_state = DISCOVERY or mode_init_state = x1_RECOVERY then + disc_tmr_done <= '1'; + else + disc_tmr_done <= '0'; + end if; + else + disc_tmr <= disc_tmr + '1'; + end if; + when others => + disc_tmr <= (others => '0'); + end case; + end if; +end process; + +ENCHANSYNC <= '0'; + +end rtl; +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity pseudo_random_number_generator is + Generic ( + lfsr_init : std_logic_vector(7 downto 0) := x"01" + ); + Port ( + clk : in STD_LOGIC; + rst_n : in STD_LOGIC; + -- Pseudo random number + q : out STD_LOGIC_VECTOR(7 downto 0) + ); +end pseudo_random_number_generator; + +architecture Behavioral of pseudo_random_number_generator is + +signal lfsr : std_logic_vector(7 downto 0) := x"01"; +signal q0 : std_logic; + + begin + +q <= lfsr; + +-- Polynomial: x^7 + x^6 + 1 +q0 <= lfsr(7) xnor lfsr(6) xnor lfsr(0) ; + +process (clk, rst_n) begin + + if rst_n = '0' then + + lfsr <= lfsr_init; -- x"01"; --(others => '0'); + + elsif rising_edge(clk) then + + lfsr <= lfsr(6 downto 0) & q0; + + end if; + +end process; + +end Behavioral; + +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- +-- File name: serdes_wrapper_v0.vhd +-- Rev: 0.0 +-- Description: This entity instantiates 4-Lane SerDes (GTX-Quad) of Virtex-6 +-- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.rio_common.all; + +entity serdes_wrapper_v0 is + port ( + REFCLK : in std_logic; + RXUSRCLK : in std_logic; + RXUSRCLK2 : in std_logic; + TXUSRCLK : in std_logic; + TXUSRCLK2 : in std_logic; + GTXRESET : in std_logic; + RXBUFRST : in std_logic; + + -- RXN : in std_logic_vector(N-1 downto 0); + -- RXP : in std_logic_vector(N-1 downto 0); + RXN : in std_logic_vector(0 to N-1); + RXP : in std_logic_vector(0 to N-1); + TXINHIBIT_02 : in std_logic; + TXINHIBIT_others : in std_logic; + ENCHANSYNC : in std_logic; + TXDATA : in std_logic_vector(N*16-1 downto 0); + TXCHARISK : in std_logic_vector(N*2-1 downto 0); + -- TXN : out std_logic_vector(N-1 downto 0); + -- TXP : out std_logic_vector(N-1 downto 0); + TXN : out std_logic_vector(0 to N-1); + TXP : out std_logic_vector(0 to N-1); + PLLLKDET : out std_logic; + RXDATA : out std_logic_vector(N*16-1 downto 0); + RXCHARISK : out std_logic_vector(N*2-1 downto 0); + RXCHARISCOMMA : out std_logic_vector(N*2-1 downto 0); + RXBYTEISALIGNED : out std_logic_vector(N-1 downto 0); + RXBYTEREALIGN : out std_logic_vector(N-1 downto 0); + RXELECIDLE : out std_logic_vector(N-1 downto 0); + RXDISPERR : out std_logic_vector(N*2-1 downto 0); + RXNOTINTABLE : out std_logic_vector(N*2-1 downto 0); + RXBUFERR : out std_logic; + CHBONDDONE : out std_logic_vector(N-1 downto 0) + ); +end serdes_wrapper_v0; + +architecture struct of serdes_wrapper_v0 is + + COMPONENT srio_gt_wrapper_v6_4x + PORT( + REFCLK : IN std_logic; + RXUSRCLK : IN std_logic; + RXUSRCLK2 : IN std_logic; + TXUSRCLK : IN std_logic; + TXUSRCLK2 : IN std_logic; + GTXRESET : IN std_logic; + RXBUFRST : IN std_logic; + RXN0 : IN std_logic; + RXN1 : IN std_logic; + RXN2 : IN std_logic; + RXN3 : IN std_logic; + RXP0 : IN std_logic; + RXP1 : IN std_logic; + RXP2 : IN std_logic; + RXP3 : IN std_logic; + TXINHIBIT_02 : IN std_logic; + TXINHIBIT_13 : IN std_logic; + ENCHANSYNC : IN std_logic; + TXDATA0 : IN std_logic_vector(15 downto 0); + TXDATA1 : IN std_logic_vector(15 downto 0); + TXDATA2 : IN std_logic_vector(15 downto 0); + TXDATA3 : IN std_logic_vector(15 downto 0); + TXCHARISK0 : IN std_logic_vector(1 downto 0); + TXCHARISK1 : IN std_logic_vector(1 downto 0); + TXCHARISK2 : IN std_logic_vector(1 downto 0); + TXCHARISK3 : IN std_logic_vector(1 downto 0); + TXN0 : OUT std_logic; + TXN1 : OUT std_logic; + TXN2 : OUT std_logic; + TXN3 : OUT std_logic; + TXP0 : OUT std_logic; + TXP1 : OUT std_logic; + TXP2 : OUT std_logic; + TXP3 : OUT std_logic; + PLLLKDET : OUT std_logic; + RXDATA0 : OUT std_logic_vector(15 downto 0); + RXDATA1 : OUT std_logic_vector(15 downto 0); + RXDATA2 : OUT std_logic_vector(15 downto 0); + RXDATA3 : OUT std_logic_vector(15 downto 0); + RXCHARISK0 : OUT std_logic_vector(1 downto 0); + RXCHARISK1 : OUT std_logic_vector(1 downto 0); + RXCHARISK2 : OUT std_logic_vector(1 downto 0); + RXCHARISK3 : OUT std_logic_vector(1 downto 0); + RXCHARISCOMMA0 : OUT std_logic_vector(1 downto 0); + RXCHARISCOMMA1 : OUT std_logic_vector(1 downto 0); + RXCHARISCOMMA2 : OUT std_logic_vector(1 downto 0); + RXCHARISCOMMA3 : OUT std_logic_vector(1 downto 0); + RXBYTEISALIGNED: OUT std_logic_vector(3 downto 0); + RXBYTEREALIGN : OUT std_logic_vector(3 downto 0); + RXELECIDLE : OUT std_logic_vector(3 downto 0); + RXDISPERR0 : OUT std_logic_vector(1 downto 0); + RXDISPERR1 : OUT std_logic_vector(1 downto 0); + RXDISPERR2 : OUT std_logic_vector(1 downto 0); + RXDISPERR3 : OUT std_logic_vector(1 downto 0); + RXNOTINTABLE0 : OUT std_logic_vector(1 downto 0); + RXNOTINTABLE1 : OUT std_logic_vector(1 downto 0); + RXNOTINTABLE2 : OUT std_logic_vector(1 downto 0); + RXNOTINTABLE3 : OUT std_logic_vector(1 downto 0); + RXBUFERR : OUT std_logic; + CHBONDDONE0 : OUT std_logic; + CHBONDDONE1 : OUT std_logic; + CHBONDDONE2 : OUT std_logic; + CHBONDDONE3 : OUT std_logic + ); + END COMPONENT; + +begin + + Inst_srio_gt_wrapper_v6_4x: srio_gt_wrapper_v6_4x PORT MAP( + REFCLK => REFCLK , + RXUSRCLK => RXUSRCLK , + RXUSRCLK2 => RXUSRCLK2 , + TXUSRCLK => TXUSRCLK , + TXUSRCLK2 => TXUSRCLK2 , + GTXRESET => GTXRESET , + RXBUFRST => RXBUFRST , + RXN0 => RXN(0) , + RXN1 => RXN(1) , + RXN2 => RXN(2) , + RXN3 => RXN(3) , + RXP0 => RXP(0) , + RXP1 => RXP(1) , + RXP2 => RXP(2) , + RXP3 => RXP(3) , + TXINHIBIT_02 => TXINHIBIT_02 , + TXINHIBIT_13 => TXINHIBIT_others , + ENCHANSYNC => ENCHANSYNC , + TXDATA0 => TXDATA(15 downto 0) , + TXDATA1 => TXDATA(31 downto 16) , + TXDATA2 => TXDATA(47 downto 32) , + TXDATA3 => TXDATA(63 downto 48) , + TXCHARISK0 => TXCHARISK(1 downto 0) , + TXCHARISK1 => TXCHARISK(3 downto 2) , + TXCHARISK2 => TXCHARISK(5 downto 4) , + TXCHARISK3 => TXCHARISK(7 downto 6) , + TXN0 => TXN(0) , + TXN1 => TXN(1) , + TXN2 => TXN(2) , + TXN3 => TXN(3) , + TXP0 => TXP(0) , + TXP1 => TXP(1) , + TXP2 => TXP(2) , + TXP3 => TXP(3) , + PLLLKDET => PLLLKDET , + RXDATA0 => RXDATA(15 downto 0) , + RXDATA1 => RXDATA(31 downto 16) , + RXDATA2 => RXDATA(47 downto 32) , + RXDATA3 => RXDATA(63 downto 48) , + RXCHARISK0 => RXCHARISK(1 downto 0) , + RXCHARISK1 => RXCHARISK(3 downto 2) , + RXCHARISK2 => RXCHARISK(5 downto 4) , + RXCHARISK3 => RXCHARISK(7 downto 6) , + RXCHARISCOMMA0 => RXCHARISCOMMA(1 downto 0) , + RXCHARISCOMMA1 => RXCHARISCOMMA(3 downto 2) , + RXCHARISCOMMA2 => RXCHARISCOMMA(5 downto 4) , + RXCHARISCOMMA3 => RXCHARISCOMMA(7 downto 6) , + RXBYTEISALIGNED => RXBYTEISALIGNED , + RXBYTEREALIGN => RXBYTEREALIGN , + RXELECIDLE => RXELECIDLE , + RXDISPERR0 => RXDISPERR(1 downto 0) , + RXDISPERR1 => RXDISPERR(3 downto 2) , + RXDISPERR2 => RXDISPERR(5 downto 4) , + RXDISPERR3 => RXDISPERR(7 downto 6) , + RXNOTINTABLE0 => RXNOTINTABLE(1 downto 0) , + RXNOTINTABLE1 => RXNOTINTABLE(3 downto 2) , + RXNOTINTABLE2 => RXNOTINTABLE(5 downto 4) , + RXNOTINTABLE3 => RXNOTINTABLE(7 downto 6) , + RXBUFERR => RXBUFERR , + CHBONDDONE0 => CHBONDDONE(0) , + CHBONDDONE1 => CHBONDDONE(1) , + CHBONDDONE2 => CHBONDDONE(2) , + CHBONDDONE3 => CHBONDDONE(3) + ); + +end struct; +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- To Do: +-- - +-- +-- Author(s): +-- - A. Demirezen, azdem@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 +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.ALL; +use ieee.numeric_std.ALL; +library UNISIM; +use UNISIM.Vcomponents.ALL; + +entity srio_pcs_struct is + port ( CHBONDDONE : in std_logic_vector (3 downto 0); + force_reinit_i : in std_logic; + inboundRead_i : in std_logic; + outboundSymbol_i : in std_logic_vector (33 downto 0); + outboundWrite_i : in std_logic; + PLLLKDET : in std_logic; + rio_clk : in std_logic; + rst_n : in std_logic; + RXBUFERR : in std_logic; + RXBYTEISALIGNED : in std_logic_vector (3 downto 0); + RXBYTEREALIGN : in std_logic_vector (3 downto 0); + RXCAHRISCOMMA : in std_logic_vector (7 downto 0); + RXCAHRISK : in std_logic_vector (7 downto 0); + RXDATA : in std_logic_vector (63 downto 0); + RXDISPERR : in std_logic_vector (7 downto 0); + RXELECIDLE : in std_logic_vector (3 downto 0); + RXNOTINTABLE : in std_logic_vector (7 downto 0); + UCLK : in std_logic; + UCLK_DV4 : in std_logic; + UCLK_DV1024 : in std_logic; + UCLK_or_DV4 : in std_logic; + UCLK_x2 : in std_logic; + UCLK_x2_DV2 : in std_logic; + ENCHANSYNC : out std_logic; + inboundEmpty_o : out std_logic; + inboundSymbol_o : out std_logic_vector (33 downto 0); + lane_sync_o : out std_logic_vector (3 downto 0); + mode_sel_o : out std_logic; + mode_0_lane_sel_o : out std_logic; + outboundFull_o : out std_logic; + port_initialized_o : out std_logic; + RXBUFRST : out std_logic; + TXCAHRISK : out std_logic_vector (7 downto 0); + TXDATA : out std_logic_vector (63 downto 0); + TXINHIBIT_others : out std_logic; + TXINHIBIT_02 : out std_logic); +end srio_pcs_struct; + +architecture BEHAVIORAL of srio_pcs_struct is + signal ccs_timer_rst : std_logic; + signal RXCAHRISvalid : std_logic_vector (7 downto 0); + signal send_A : std_logic_vector (1 downto 0); + signal send_ccs : std_logic; + signal send_idle : std_logic_vector (1 downto 0); + signal send_K : std_logic_vector (1 downto 0); + signal send_R : std_logic_vector (1 downto 0); + signal mode_0_lane_sel_o_DUMMY : std_logic; + signal TXINHIBIT_02_DUMMY : std_logic; + signal mode_sel_o_DUMMY : std_logic; + signal port_initialized_o_DUMMY : std_logic; + signal TXINHIBIT_others_DUMMY : std_logic; + component ccs_timer + port ( rst_n : in std_logic; + ccs_timer_rst : in std_logic; + send_ccs : out std_logic; + UCLK : in std_logic); + end component; + + component idle_generator_dual + port ( UCLK : in std_logic; + rst_n : in std_logic; + send_K : out std_logic_vector (1 downto 0); + send_A : out std_logic_vector (1 downto 0); + send_R : out std_logic_vector (1 downto 0); + send_idle : in std_logic_vector (1 downto 0)); + end component; + + component port_init_fsms + port ( rst_n : in std_logic; + UCLK_x2 : in std_logic; + UCLK : in std_logic; + UCLK_DV4 : in std_logic; + UCLK_DV_1024 : in std_logic; + force_reinit : in std_logic; + PLLLKDET : in std_logic; + RXBUFERR : in std_logic; + RXDATA : in std_logic_vector (63 downto 0); + RXCHARISK : in std_logic_vector (7 downto 0); + RXCHARISCOMMA : in std_logic_vector (7 downto 0); + RXBYTEISALIGNED : in std_logic_vector (3 downto 0); + RXBYTEREALIGN : in std_logic_vector (3 downto 0); + RXELECIDLE : in std_logic_vector (3 downto 0); + RXDISPERR : in std_logic_vector (7 downto 0); + RXNOTINTABLE : in std_logic_vector (7 downto 0); + CHBONDDONE : in std_logic_vector (3 downto 0); + mode_sel : out std_logic; + port_initalized : out std_logic; + TXINHIBIT_02 : out std_logic; + TXINHIBIT_others : out std_logic; + ENCHANSYNC : out std_logic; + RXBUFRST : out std_logic; + lane_sync : out std_logic_vector (3 downto 0); + mode_0_lane_sel : out std_logic; + RXCHARISvalid : out std_logic_vector (7 downto 0)); + end component; + + component pcs_rx_controller + port ( rst_n : in std_logic; + rio_clk : in std_logic; + UCLK_x2 : in std_logic; + UCLK : in std_logic; + UCLK_x2_DV2 : in std_logic; + inboundRead_i : in std_logic; + port_initalized_i : in std_logic; + mode_sel_i : in std_logic; + mode_0_lane_sel_i : in std_logic; + RXDATA_i : in std_logic_vector (63 downto 0); + RXCHARISK_i : in std_logic_vector (7 downto 0); + RXCHARISvalid_i : in std_logic_vector (7 downto 0); + inboundEmpty_o : out std_logic; + inboundSymbol_o : out std_logic_vector (33 downto 0); + UCLK_or_DV4 : in std_logic); + end component; + + component pcs_tx_controller + port ( rst_n : in std_logic; + rio_clk : in std_logic; + UCLK_x2 : in std_logic; + UCLK : in std_logic; + UCLK_x2_DV2 : in std_logic; + UCLK_or_DV4 : in std_logic; + outboundWrite_i : in std_logic; + send_ccs_i : in std_logic; + TXINHIBIT_02 : in std_logic; + TXINHIBIT_others : in std_logic; + port_initalized_i : in std_logic; + mode_sel_i : in std_logic; + mode_0_lane_sel_i : in std_logic; + outboundSymbol_i : in std_logic_vector (33 downto 0); + send_K_i : in std_logic_vector (1 downto 0); + send_A_i : in std_logic_vector (1 downto 0); + send_R_i : in std_logic_vector (1 downto 0); + outboundFull_o : out std_logic; + ccs_timer_rst_o : out std_logic; + TXDATA_o : out std_logic_vector (63 downto 0); + TXCHARISK_o : out std_logic_vector (7 downto 0); + send_idle_o : out std_logic_vector (1 downto 0)); + end component; + +begin + mode_sel_o <= mode_sel_o_DUMMY; + mode_0_lane_sel_o <= mode_0_lane_sel_o_DUMMY; + port_initialized_o <= port_initialized_o_DUMMY; + TXINHIBIT_others <= TXINHIBIT_others_DUMMY; + TXINHIBIT_02 <= TXINHIBIT_02_DUMMY; + ccs_timer_inst : ccs_timer + port map (ccs_timer_rst=>ccs_timer_rst, + rst_n=>rst_n, + UCLK=>UCLK, + send_ccs=>send_ccs); + + dual_idle_generator : idle_generator_dual + port map (rst_n=>rst_n, + send_idle(1 downto 0)=>send_idle(1 downto 0), + UCLK=>UCLK, + send_A(1 downto 0)=>send_A(1 downto 0), + send_K(1 downto 0)=>send_K(1 downto 0), + send_R(1 downto 0)=>send_R(1 downto 0)); + + port_init_fsms_inst : port_init_fsms + port map (CHBONDDONE(3 downto 0)=>CHBONDDONE(3 downto 0), + force_reinit=>force_reinit_i, + PLLLKDET=>PLLLKDET, + rst_n=>rst_n, + RXBUFERR=>RXBUFERR, + RXBYTEISALIGNED(3 downto 0)=>RXBYTEISALIGNED(3 downto 0), + RXBYTEREALIGN(3 downto 0)=>RXBYTEREALIGN(3 downto 0), + RXCHARISCOMMA(7 downto 0)=>RXCAHRISCOMMA(7 downto 0), + RXCHARISK(7 downto 0)=>RXCAHRISK(7 downto 0), + RXDATA(63 downto 0)=>RXDATA(63 downto 0), + RXDISPERR(7 downto 0)=>RXDISPERR(7 downto 0), + RXELECIDLE(3 downto 0)=>RXELECIDLE(3 downto 0), + RXNOTINTABLE(7 downto 0)=>RXNOTINTABLE(7 downto 0), + UCLK=>UCLK, + UCLK_DV_1024=>UCLK_DV1024, + UCLK_DV4=>UCLK_DV4, + UCLK_x2=>UCLK_x2, + ENCHANSYNC=>ENCHANSYNC, + lane_sync(3 downto 0)=>lane_sync_o(3 downto 0), + mode_sel=>mode_sel_o_DUMMY, + mode_0_lane_sel=>mode_0_lane_sel_o_DUMMY, + port_initalized=>port_initialized_o_DUMMY, + RXBUFRST=>RXBUFRST, + RXCHARISvalid(7 downto 0)=>RXCAHRISvalid(7 downto 0), + TXINHIBIT_others=>TXINHIBIT_others_DUMMY, + TXINHIBIT_02=>TXINHIBIT_02_DUMMY); + + rx_controller_inst : pcs_rx_controller + port map (inboundRead_i=>inboundRead_i, + mode_sel_i=>mode_sel_o_DUMMY, + mode_0_lane_sel_i=>mode_0_lane_sel_o_DUMMY, + port_initalized_i=>port_initialized_o_DUMMY, + rio_clk=>rio_clk, + rst_n=>rst_n, + RXCHARISK_i(7 downto 0)=>RXCAHRISK(7 downto 0), + RXCHARISvalid_i(7 downto 0)=>RXCAHRISvalid(7 downto 0), + RXDATA_i(63 downto 0)=>RXDATA(63 downto 0), + UCLK=>UCLK, + UCLK_or_DV4=>UCLK_or_DV4, + UCLK_x2=>UCLK_x2, + UCLK_x2_DV2=>UCLK_x2_DV2, + inboundEmpty_o=>inboundEmpty_o, + inboundSymbol_o(33 downto 0)=>inboundSymbol_o(33 downto 0)); + + tx_controller_inst : pcs_tx_controller + port map (mode_sel_i=>mode_sel_o_DUMMY, + mode_0_lane_sel_i=>mode_0_lane_sel_o_DUMMY, + outboundSymbol_i(33 downto 0)=>outboundSymbol_i(33 downto 0), + outboundWrite_i=>outboundWrite_i, + port_initalized_i=>port_initialized_o_DUMMY, + rio_clk=>rio_clk, + rst_n=>rst_n, + send_A_i(1 downto 0)=>send_A(1 downto 0), + send_ccs_i=>send_ccs, + send_K_i(1 downto 0)=>send_K(1 downto 0), + send_R_i(1 downto 0)=>send_R(1 downto 0), + TXINHIBIT_others=>TXINHIBIT_others_DUMMY, + TXINHIBIT_02=>TXINHIBIT_02_DUMMY, + UCLK=>UCLK, + UCLK_or_DV4=>UCLK_or_DV4, + UCLK_x2=>UCLK_x2, + UCLK_x2_DV2=>UCLK_x2_DV2, + ccs_timer_rst_o=>ccs_timer_rst, + outboundFull_o=>outboundFull_o, + send_idle_o(1 downto 0)=>send_idle(1 downto 0), + TXCHARISK_o(7 downto 0)=>TXCAHRISK(7 downto 0), + TXDATA_o(63 downto 0)=>TXDATA(63 downto 0)); + +end BEHAVIORAL; + + Index: 1.0.1/rtl/vhdl/RioWbBridge.vhd =================================================================== --- 1.0.1/rtl/vhdl/RioWbBridge.vhd (nonexistent) +++ 1.0.1/rtl/vhdl/RioWbBridge.vhd (revision 29) @@ -0,0 +1,935 @@ +------------------------------------------------------------------------------- +-- +-- RapidIO IP Library Core +-- +-- This file is part of the RapidIO IP library project +-- http://www.opencores.org/cores/rio/ +-- +-- Description +-- Containing a bridge between a RapidIO network and a Wishbone bus. Packets +-- NWRITE and NREAD are currently supported. +-- +-- To Do: +-- - +-- +-- Author(s): +-- - Nader Kardouni, nader.kardouni@se.transport.bombardier.com +-- +------------------------------------------------------------------------------- +-- +-- 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 +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.numeric_std.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use work.rio_common.all; + +------------------------------------------------------------------------------- +-- entity for RioWbBridge. +------------------------------------------------------------------------------- +Entity RioWbBridge is + generic( + DEVICE_IDENTITY : std_logic_vector(15 downto 0); + DEVICE_VENDOR_IDENTITY : std_logic_vector(15 downto 0); + DEVICE_REV : std_logic_vector(31 downto 0); + ASSY_IDENTITY : std_logic_vector(15 downto 0); + ASSY_VENDOR_IDENTITY : std_logic_vector(15 downto 0); + ASSY_REV : std_logic_vector(15 downto 0); + DEFAULT_BASE_DEVICE_ID : std_logic_vector(15 downto 0) := x"ffff"); + port( + clk : in std_logic; -- Main clock 25MHz + areset_n : in std_logic; -- Asynchronous reset, active low + + readFrameEmpty_i : in std_logic; + readFrame_o : out std_logic; + readContent_o : out std_logic; + readContentEnd_i : in std_logic; + readContentData_i : in std_logic_vector(31 downto 0); + + writeFrameFull_i : in std_logic; + writeFrame_o : out std_logic; + writeFrameAbort_o : out std_logic; + writeContent_o : out std_logic; + writeContentData_o : out std_logic_vector(31 downto 0); + + -- interface to the peripherals module + wbStb_o : out std_logic; -- strob signal, active high + wbWe_o : out std_logic; -- write signal, active high + wbData_o : out std_logic_vector(7 downto 0); -- master data bus + wbAdr_o : out std_logic_vector(25 downto 0); -- master address bus + wbErr_i : in std_logic; -- error signal, high active + wbAck_i : in std_logic; -- slave acknowledge + wbData_i : in std_logic_vector(7 downto 0) -- slave data bus + ); +end; + +------------------------------------------------------------------------------- +-- Architecture for RioWbBridge. +------------------------------------------------------------------------------- +architecture rtl of RioWbBridge is + + component Crc16CITT is + port( + d_i : in std_logic_vector(15 downto 0); + crc_i : in std_logic_vector(15 downto 0); + crc_o : out std_logic_vector(15 downto 0)); + end component; + + constant RST_LVL : std_logic := '0'; + constant BERR_UNKNOWN_DATA : std_logic_vector(7 downto 0) := X"08"; -- not valid data + constant BERR_FRAME_SIZE : std_logic_vector(7 downto 0) := X"81"; -- Frame code size error + constant BERR_FRAME_CODE : std_logic_vector(7 downto 0) := X"80"; -- Frame code type error + constant BERR_NOT_RESPONSE : std_logic_vector(7 downto 0) := X"86"; -- Not response from the device + + type state_type_RioBrige is (IDLE, WAIT_HEADER_0, HEADER_0, HEADER_1, CHECK_OPERATION, + READ_ADDRESS, READ_FROM_FIFO, CHECK_ERROR, WRITE_DATA, + WRITE_TO_WB, WAIT_IDLE, SEND_DONE_0, SEND_DONE_1, + SEND_DONE_2, READ_FROM_WB, APPEND_CRC, + SEND_TO_FIFO, SEND_ERROR, SEND_FRAME, APPEND_CRC_AND_SEND, + SEND_MAINTENANCE_READ_RESPONSE_0, SEND_MAINTENANCE_READ_RESPONSE_1, + SEND_MAINTENANCE_WRITE_RESPONSE_0, SEND_MAINTENANCE_WRITE_RESPONSE_1); + signal stateRB, nextStateRB : state_type_RioBrige; + type byteArray8 is array (0 to 7) of std_logic_vector(7 downto 0); + signal dataLane : byteArray8; +-- type byteArray4 is array (0 to 3) of std_logic_vector(7 downto 0); +-- signal dataLaneS : byteArray4; + signal pos, byteOffset : integer range 0 to 7; + signal numberOfByte, byteCnt, headLen : integer range 0 to 256; + signal endianMsb, reserved, ready : std_logic; + signal start : std_logic; + signal wdptr : std_logic; + signal wbStb : std_logic; + signal xamsbs : std_logic_vector(1 downto 0); + signal ftype : std_logic_vector(3 downto 0); + signal ttype : std_logic_vector(3 downto 0); + signal size : std_logic_vector(3 downto 0); + signal tid : std_logic_vector(7 downto 0); + signal tt : std_logic_vector(1 downto 0); + signal errorCode : std_logic_vector(7 downto 0); + signal sourceId : std_logic_vector(15 downto 0); + signal destinationId : std_logic_vector(15 downto 0); + signal writeContentData : std_logic_vector(31 downto 0); + signal crc16Current, crc16Temp, crc16Next: std_logic_vector(15 downto 0); + signal tempAddr : std_logic_vector(25 downto 0); + signal timeOutCnt : std_logic_vector(14 downto 0); + + -- Configuration memory signal declaration. + 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 : std_logic_vector(31 downto 0); + signal componentTag : std_logic_vector(31 downto 0); + signal baseDeviceId : std_logic_vector(15 downto 0) := DEFAULT_BASE_DEVICE_ID; + signal hostBaseDeviceIdLocked : std_logic; + signal hostBaseDeviceId : std_logic_vector(15 downto 0) := (others => '1'); + +begin + wbStb_o <= wbStb; + writeContentData_o <= writeContentData; + + Crc16High: Crc16CITT + port map( + d_i=>writeContentData(31 downto 16), crc_i=>crc16Current, crc_o=>crc16Temp); + Crc16Low: Crc16CITT + port map( + d_i=>writeContentData(15 downto 0), crc_i=>crc16Temp, crc_o=>crc16Next); + + + + ----------------------------------------------------------------------------- + -- wbInterfaceCtrl + -- This process handle the Wishbone interface to the RioWbBridge module. + ----------------------------------------------------------------------------- + wbInterfaceCtrl: process(clk, areset_n) + variable Temp : std_logic_vector(2 downto 0); + begin + if areset_n = RST_LVL then + start <= '0'; + wdptr <= '0'; + wbStb <= '0'; + wbWe_o <= '0'; + byteCnt <= 0; + headLen <= 0; + byteOffset <= 0; + readFrame_o <= '0'; + readContent_o <= '0'; + writeFrame_o <= '0'; + writeContent_o <= '0'; + writeFrameAbort_o <= '0'; + configWrite <= '0'; + configEnable <= '0'; + ready <= '0'; + endianMsb <= '0'; + stateRB <= IDLE; + nextStateRB <= IDLE; + tt <= (others => '0'); + tid <= (others => '0'); + size <= (others => '0'); + ttype <= (others => '0'); + ftype <= (others => '0'); + xamsbs <= (others => '0'); + sourceId <= (others => '0'); + configDataWrite <= (others => '0'); + destinationId <= (others => '0'); + errorCode <= (others => '0'); + tempAddr <= (others => '0'); + wbAdr_o <= (others => '0'); + wbData_o <= (others => '0'); + writeContentData <= (others => '0'); + dataLane <= (others =>(others => '0')); +-- dataLaneS <= (others =>(others => '0')); + crc16Current <= (others => '0'); + timeOutCnt <= (others => '0'); + Temp := (others => '0'); + elsif clk'event and clk ='1' then + + case stateRB is + when IDLE => + if (readFrameEmpty_i = '0') and (writeFrameFull_i = '0') then + readContent_o <= '1'; + byteCnt <= 0; + ready <= '0'; + endianMsb <= '1'; + timeOutCnt <= (others => '0'); + crc16Current <= (others => '1'); + stateRB <= WAIT_HEADER_0; + else + start <= '0'; + readFrame_o <= '0'; + readContent_o <= '0'; + writeFrame_o <= '0'; + writeContent_o <= '0'; + writeFrameAbort_o <= '0'; + errorCode <= (others => '0'); + writeContentData <= (others => '0'); + dataLane <= (others =>(others => '0')); +-- dataLaneS <= (others =>(others => '0')); + Temp := (others => '0'); + end if; + + when WAIT_HEADER_0 => + stateRB <= HEADER_0; + + when HEADER_0 => + readContent_o <= '1'; -- read the header (frame 0) + tt <= readContentData_i(21 downto 20); + ftype <= readContentData_i(19 downto 16); + destinationId <= readContentData_i(15 downto 0); + stateRB <= HEADER_1; + + when HEADER_1 => -- read the header (frame 1) + readContent_o <= '1'; + ttype <= readContentData_i(15 downto 12); + size <= readContentData_i(11 downto 8); + tid <= readContentData_i(7 downto 0); + sourceId <= readContentData_i(31 downto 16); + stateRB <= READ_ADDRESS; + + when READ_ADDRESS => + readContent_o <= '0'; + wdptr <= readContentData_i(2); + xamsbs <= readContentData_i(1 downto 0); + tempAddr <= readContentData_i(25 downto 3) & "000"; -- Wishbone address bus is 26 bits width + configAddress <= readContentData_i(23 downto 0); -- this line is in case of maintenance pakage (config-offset(21-bits)+wdptr(1-bit)+rsv(2-bits)) + stateRB <= CHECK_ERROR; + + when CHECK_ERROR => + byteOffset <= pos; -- first byte position in the first payload + tempAddr <= tempAddr + pos; -- first address + if readContentEnd_i = '1' then -- check if data not valid i the switch buffer + wbStb <= '0'; + wbWe_o <= '0'; + byteOffset <= 0; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= BERR_UNKNOWN_DATA; -- not valid data + stateRB <= SEND_ERROR; + + -- check if error in the frame size for write pakage + elsif (reserved = '1') and (ftype = FTYPE_WRITE_CLASS) then + wbStb <= '0'; + wbWe_o <= '0'; + byteOffset <= 0; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= BERR_FRAME_SIZE; -- Frame code size error + stateRB <= SEND_ERROR; + + -- type 5 pakage formate, NWRITE transaction (write to peripherals) read payload from the buffer + elsif (ftype = FTYPE_WRITE_CLASS) and (ttype = "0100") and (tt = "01") then + readContent_o <= '1'; + stateRB <= READ_FROM_FIFO; -- read the payload + nextStateRB <= SEND_ERROR; -- this is in case not valid data in switch buffer + headLen <= 12; + + -- Type 2 pakage formate, NREAD transaction, (read from peripherals) write payload to the buffer + elsif (ftype = FTYPE_REQUEST_CLASS) and (ttype = "0100") and (tt = "01") then + writeContent_o <= '1'; -- write the header-0 of the Read Response pakage + writeContentData(15 downto 0) <= sourceId; -- write to the source address + writeContentData(19 downto 16) <= "1101"; -- Response pakage type 13, ftype Response + writeContentData(21 downto 20) <= "01"; -- tt + writeContentData(31 downto 22) <= "0000000000"; -- acckId, vc, cfr, prio + stateRB <= SEND_DONE_0; -- + headLen <= 8; + + -- Type 8 pakage formate, maintenance Read request + elsif (ftype = FTYPE_MAINTENANCE_CLASS) and (ttype = TTYPE_MAINTENANCE_READ_REQUEST) and (tt = "01") then + configWrite <= '0'; -- read config operation + configEnable <= '1'; -- enable signal to the memoryConfig process + writeContent_o <= '1'; + -- write the header-0 of the Read Response pakage + writeContentData(15 downto 0) <= sourceId; -- write to the source address, this is a response pakage + writeContentData(19 downto 16) <= FTYPE_MAINTENANCE_CLASS; -- ftype, maintenance + writeContentData(21 downto 20) <= "01"; -- tt + writeContentData(31 downto 22) <= "0000000000"; -- acckId, vc, cfr, prio + stateRB <= SEND_MAINTENANCE_READ_RESPONSE_0; + + -- Type 8 pakage formate, maintenance Write request + elsif (ftype = FTYPE_MAINTENANCE_CLASS) and (ttype = TTYPE_MAINTENANCE_WRITE_REQUEST) and (tt = "01") then + configWrite <= '1'; -- write config operation + writeContent_o <= '1'; -- write the header-0 + writeContentData(15 downto 0) <= sourceId; -- write to the source address, this is a response pakage + writeContentData(19 downto 16) <= FTYPE_MAINTENANCE_CLASS; -- ftype, maintenance + writeContentData(21 downto 20) <= "01"; -- tt + writeContentData(31 downto 22) <= "0000000000"; -- acckId, vc, cfr, prio + stateRB <= SEND_MAINTENANCE_WRITE_RESPONSE_0; + + -- Error: unexpected ftype or ttype + else + wbStb <= '0'; + wbWe_o <= '0'; + byteOffset <= 0; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= BERR_FRAME_CODE; + stateRB <= SEND_ERROR; -- next state after the dataLane is stored in the switch buffer + end if; + + when SEND_MAINTENANCE_READ_RESPONSE_0 => + byteCnt <= 0; + configEnable <= '0'; -- disable signal to the memoryConfig process + -- write the header-1 of the Read Response pakage + writeContentData(7 downto 0) <= tid; + writeContentData(11 downto 8) <= "0000"; -- size/status + writeContentData(15 downto 12) <= TTYPE_MAINTENANCE_READ_RESPONSE; -- transaction type, Maintenance Read Response + writeContentData(31 downto 16) <= baseDeviceId; -- destination address, because this is a response pakage + crc16Current <= crc16Next; -- first frame's CRC + stateRB <= SEND_MAINTENANCE_READ_RESPONSE_1; + + when SEND_MAINTENANCE_READ_RESPONSE_1 => + byteCnt <= byteCnt + 1; -- using byteCnt as a counter + if byteCnt = 0 then + writeContentData <= X"FF" & X"000000"; -- write the filed with HOP + reserved + crc16Current <= crc16Next; -- second frame's CRC + elsif byteCnt = 1 then + if configAddress(2) = '0' then -- check the wdptr bit in the config offset field + writeContentData <= configDataRead; -- write payload-0 with data if wdptr='0' + else + writeContentData <= (others => '0'); -- write zeros + end if; + crc16Current <= crc16Next; -- third frame's CRC + elsif byteCnt = 2 then + if configAddress(2) = '0' then -- check the wdptr bit in the config offset field + writeContentData <= (others => '0'); -- write zeros + else + writeContentData <= configDataRead; -- write payload-1 with data if wdptr='1' + end if; + crc16Current <= crc16Next; -- forth frame's CRC + elsif byteCnt = 3 then + writeContentData <= crc16Next & X"0000"; -- write the CRC field + else + writeContent_o <= '0'; + stateRB <= SEND_FRAME; + end if; + + when SEND_MAINTENANCE_WRITE_RESPONSE_0 => + byteCnt <= 0; + readContent_o <= '1'; -- read the config offset + if configAddress(2) = '0' then -- check the wdptr bit in the config offset field + configDataWrite <= readContentData_i; -- copy payload-0 if wdptr='0' + else + configDataWrite <= configDataWrite; -- do nothing + end if; + writeContentData(7 downto 0) <= tid; + writeContentData(11 downto 8) <= "0000"; -- size/status + writeContentData(15 downto 12) <= TTYPE_MAINTENANCE_WRITE_RESPONSE; -- transaction type, Maintenance Write Response + writeContentData(31 downto 16) <= baseDeviceId; -- destination address, because this is a response pakage + crc16Current <= crc16Next; -- first frame's CRC + stateRB <= SEND_MAINTENANCE_WRITE_RESPONSE_1; + + when SEND_MAINTENANCE_WRITE_RESPONSE_1 => + byteCnt <= byteCnt + 1; -- using byteCnt as a counter + if byteCnt = 0 then + writeContentData <= X"FF" & X"000000"; -- write the filed with HOP + reserved + crc16Current <= crc16Next; -- second frame's CRC + elsif byteCnt = 1 then + configEnable <= '1'; -- enable signal to the memoryConfig process + writeContentData <= crc16Next & X"0000"; -- write the CRC field + if configAddress(2) = '0' then -- check the wdptr bit in the config offset field + configDataWrite <= configDataWrite; -- do nothing + else + configDataWrite <= readContentData_i; -- copy payload-1 if wdptr='1' + end if; + else + configEnable <= '0'; -- disable signal to the memoryConfig process + readContent_o <= '0'; -- at this point even the frame's CRC is read from the buffer + writeContent_o <= '0'; + stateRB <= SEND_FRAME; + end if; + + when SEND_DONE_0 => + writeContent_o <= '1'; + writeContentData(7 downto 0) <= tid; + writeContentData(11 downto 8) <= "0000"; -- size/status + writeContentData(15 downto 12) <= "1000"; -- ttype + writeContentData(31 downto 16) <= baseDeviceId; + crc16Current <= crc16Next; -- first frame's CRC + stateRB <= SEND_DONE_1; + + when SEND_DONE_1 => + byteCnt <= 0; + dataLane <= (others =>(others => '0')); + writeContent_o <= '0'; -- this line is to make sure that the CRC is complete read + crc16Current <= crc16Next; -- second frame's CRC + wbAdr_o <= tempAddr; + tempAddr <= tempAddr + 1; + wbStb <= '1'; + wbWe_o <= '0'; + byteOffset <= pos; + stateRB <= READ_FROM_WB; + + when READ_FROM_WB => + if wbAck_i = '1' then + timeOutCnt <= (others => '0'); -- reset the time out conter + if wbErr_i = '0' then -- check if no error occur + if (byteCnt < numberOfByte - 1) then -- check if reach the last data byte + byteCnt <= byteCnt + 1; + if (byteCnt + headLen = 80) then -- when current position in payload is a CRC position + dataLane(0) <= crc16Current(15 downto 8); + dataLane(1) <= crc16Current(7 downto 0); + dataLane(2) <= wbData_i; + byteOffset <= 3; + elsif byteOffset < 7 then + dataLane(byteOffset) <= wbData_i; + byteOffset <= byteOffset + 1; + else -- dataLane vector is ready to send to fifo + dataLane(7) <= wbData_i; + byteOffset <= 0; -- Here, sets byteOffset for other response + stateRB <= SEND_TO_FIFO; + nextStateRB <= READ_FROM_WB; -- + end if; + else -- get last data from Wishbone + wbStb <= '0'; + byteCnt <= 0; -- Here, using byteCnt and reset it for other response + dataLane(byteOffset) <= wbData_i; + stateRB <= APPEND_CRC_AND_SEND; + if byteOffset < 7 then -- checking for CRC appending position + byteOffset <= byteOffset + 1; + else + byteOffset <= 0; + end if; + end if; + + -- when Wishbone error occur + else + wbStb <= '0'; + wbWe_o <= '0'; + byteOffset <= 0; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= wbData_i; + stateRB <= SEND_ERROR; + end if; + else -- when no acknowledge received + if timeOutCnt(13) = '1' then -- when waiting more than 1 ms for response from the device + wbStb <= '0'; + wbWe_o <= '0'; + byteOffset <= 0; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= BERR_NOT_RESPONSE; + stateRB <= SEND_ERROR; + else + timeOutCnt <= timeOutCnt + 1; + end if; + end if; + + -- appending CRC and write to the fifo when frame is shorter then 80 bytes + when APPEND_CRC_AND_SEND => + writeContent_o <= '0'; + byteCnt <= byteCnt + 1; + -- check if frame is shorter than 80 bytes + if (numberOfByte < 65) then + -- Yes, frame is shorter then 80 bytes + if byteCnt = 0 then + -- first write the current double word to the fifo + -- then put the CRC in the next double word + byteOffset <= 0; + stateRB <= SEND_TO_FIFO; + nextStateRB <= APPEND_CRC_AND_SEND; + elsif byteCnt = 1 then + -- append the CRC + writeContent_o <= '1'; + writeContentData <= crc16Current & X"0000"; + else + stateRB <= SEND_FRAME; -- store in the switch buffer + end if; + else + --No, appending CRC and write to the fifo when frame is longer then 80 bytes + if byteCnt = 0 then + -- check if the last byte was placed in the second half of the double word, + -- in that case write the first word to the fifo. + writeContentData <= dataLane(0) & dataLane(1) & dataLane(2) & dataLane(3); + elsif byteCnt = 1 then + crc16Current <= crc16Temp; -- calcylate the crc for the 16 most significant bits + elsif byteCnt = 2 then + writeContent_o <= '1'; + writeContentData <= dataLane(0) & dataLane(1) & crc16Current; + else + stateRB <= SEND_FRAME; -- store in the switch buffer + end if; + end if; + + + when SEND_TO_FIFO => + if byteOffset = 0 then -- using byteOffset as a counter + byteOffset <= 1; + writeContent_o <= '1'; + writeContentData <= dataLane(0) & dataLane(1) & dataLane(2) & dataLane(3); + elsif byteOffset = 1 then -- using byteOffset as a counter + byteOffset <= 2; + writeContent_o <= '0'; + crc16Current <= crc16Next; -- calcylate the crc + elsif byteOffset = 2 then + byteOffset <= 3; + writeContent_o <= '1'; + writeContentData <= dataLane(4) & dataLane(5) & dataLane(6) & dataLane(7); + elsif byteOffset = 3 then + crc16Current <= crc16Next; -- calcylate the crc + writeContent_o <= '0'; + byteOffset <= 0; + stateRB <= nextStateRB; + dataLane <= (others =>(others => '0')); + end if; + + when READ_FROM_FIFO => + if (endianMsb = '1') then + if (readContentEnd_i = '0') then + endianMsb <= '0'; + dataLane(0 to 3) <= (readContentData_i(31 downto 24), readContentData_i(23 downto 16), + readContentData_i(15 downto 8), readContentData_i(7 downto 0)); + else + wbStb <= '0'; + wbWe_o <= '0'; + byteOffset <= 0; + readContent_o <= '0'; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= BERR_FRAME_SIZE; + stateRB <= SEND_ERROR; +-- stateRB <= IDLE; + end if; + else + endianMsb <= '1'; + readContent_o <= '0'; + dataLane(4 to 7) <= (readContentData_i(31 downto 24), readContentData_i(23 downto 16), + readContentData_i(15 downto 8), readContentData_i(7 downto 0)); + if ready = '1' then + stateRB <= nextStateRB; + else + stateRB <= WRITE_TO_WB; + end if; + end if; + + when WRITE_TO_WB => + if wbStb = '0' then + wbStb <= '1'; + wbWe_o <= '1'; + byteCnt <= 1; + byteOffset <= byteOffset + 1; -- increase number of counted byte + tempAddr <= tempAddr + 1; -- increase the memory sddress address + wbAdr_o <= tempAddr; + wbData_o <= dataLane(byteOffset); + else + if wbAck_i = '1' then + timeOutCnt <= (others => '0'); -- reset the time out conter + if wbErr_i = '0' then -- check the peripherals error signal + if byteCnt < numberOfByte then + tempAddr <= tempAddr + 1; -- increase the memory sddress address + wbAdr_o <= tempAddr; + wbData_o <= dataLane(byteOffset); + byteCnt <= byteCnt + 1; -- increase number of counted byte + if byteOffset < 7 then + if (byteCnt + headLen = 79) then -- check for the CRC-byte position 80 in the frame + byteOffset <= byteOffset + 3; + else + byteOffset <= byteOffset + 1; + end if; + else + if (byteCnt + headLen = 79) then -- check for the CRC-byte position 80 in the frame + byteOffset <= 2; + else + byteOffset <= 0; + end if; + if byteCnt < numberOfByte - 1 then + readContent_o <= '1'; + stateRB <= READ_FROM_FIFO; + end if; + end if; + else -- no more data to send to the peripherals + wbStb <= '0'; + wbWe_o <= '0'; + ready <= '1'; + stateRB <= SEND_FRAME; + end if; + else -- if the peripheral generates an error, send an error Response + wbStb <= '0'; + wbWe_o <= '0'; + byteOffset <= 0; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= wbData_i; + stateRB <= SEND_ERROR; + end if; + else +-- if readContentEnd_i = '1' then -- when unvalid data in the switch buffer +-- wbStb <= '0'; +-- wbWe_o <= '0'; +-- readFrame_o <= '1'; +-- byteOffset <= 0; +-- writeFrameAbort_o <= '1'; -- over write the frame with an error frame +-- errorCode <= BERR_FRAME_SIZE; -- more data content is expected, Frame size error +-- stateRB <= SEND_ERROR; +-- else + if timeOutCnt(13) = '1' then -- when waiting more than 1 ms for response from the device + wbStb <= '0'; + wbWe_o <= '0'; + readFrame_o <= '1'; + byteOffset <= 0; + writeFrameAbort_o <= '1'; -- over write the frame with an error frame + errorCode <= BERR_NOT_RESPONSE; + stateRB <= SEND_ERROR; + else + timeOutCnt <= timeOutCnt + 1; + end if; +-- end if; + end if; + end if; + + when SEND_ERROR => -- Generate a Response Class, an error pakage ftype=13, ttype=8, status="1111" + readFrame_o <= '0'; + writeFrameAbort_o <= '0'; + byteOffset <= byteOffset + 1; + if byteOffset = 0 then + writeContent_o <= '1'; -- start write to the buffer + crc16Current <= (others => '1'); + writeContentData <= "00000000" & "00" & "01" & "1101" & sourceId; + elsif byteOffset = 1 then + writeContentData <= baseDeviceId & "1000" & "1111" & tid; + crc16Current <= crc16Next; -- first frame's CRC + elsif byteOffset = 2 then + writeContentData <= errorCode & x"000000"; + crc16Current <= crc16Next; -- second frame's CRC + elsif byteOffset = 3 then + writeContentData <= x"00000000"; + crc16Current <= crc16Next; -- third frame's CRC + elsif byteOffset = 4 then + writeContentData <= crc16Next & X"0000"; -- write the CRC field + else + writeContent_o <= '0'; + writeFrame_o <= '1'; + readFrame_o <= '1'; + stateRB <= WAIT_IDLE; + end if; + + when SEND_FRAME => + if (ftype = FTYPE_WRITE_CLASS) and (ttype = TTYPE_NWRITE_TRANSACTION) and (tt = "01") then -- check what type of pakage we got + readFrame_o <= '1'; + elsif (ftype = FTYPE_REQUEST_CLASS) and (ttype = TTYPE_NREAD_TRANSACTION) and (tt = "01") then -- write payload to the buffer is done + readFrame_o <= '1'; + writeFrame_o <= '1'; + else -- the operation was not valid + readFrame_o <= '1'; + writeFrame_o <= '1'; + end if; + stateRB <= WAIT_IDLE; + + when WAIT_IDLE => + readFrame_o <= '0'; + writeFrame_o <= '0'; + readContent_o <= '0'; -- this line is to make sure that the CRC is complete read + stateRB <= IDLE; + + when others => + stateRB <= IDLE; + + end case; + + end if; + + end process; + + ----------------------------------------------------------------------------- + -- Configuration memory. + ----------------------------------------------------------------------------- + memoryConfig : process(clk, areset_n) + begin + if (areset_n = '0') then + configDataRead <= (others => '0'); + baseDeviceId <= DEFAULT_BASE_DEVICE_ID; + componentTag <= (others => '0'); + hostBaseDeviceIdLocked <= '0'; + hostBaseDeviceId <= (others => '1'); + elsif (clk'event and clk = '1') then + + if (configEnable = '1') then + case (configAddress) is + when x"000000" => + -- Device Identity CAR. Read-only. + configDataRead(31 downto 16) <= DEVICE_IDENTITY; + configDataRead(15 downto 0) <= DEVICE_VENDOR_IDENTITY; + when x"000004" => + -- Device Information CAR. Read-only. + configDataRead(31 downto 0) <= DEVICE_REV; + when x"000008" => + -- Assembly Identity CAR. Read-only. + configDataRead(31 downto 16) <= ASSY_IDENTITY; + configDataRead(15 downto 0) <= ASSY_VENDOR_IDENTITY; + when x"00000c" => + -- Assembly Informaiton CAR. Read-only. + -- Extended features pointer to "0000". + configDataRead(31 downto 16) <= ASSY_REV; + configDataRead(15 downto 0) <= x"0000"; + when x"000010" => + -- Processing Element Features CAR. Read-only. + -- Bridge(31), Memory(30), Processor(29), Switch(28). + configDataRead(31) <= '1'; + configDataRead(30 downto 4) <= (others => '0'); + configDataRead(3) <= '1'; -- support 16 bits common transport large system + configDataRead(2 downto 0) <= "001"; -- support 34 bits address + when x"000018" => + -- Source Operations CAR. Read-only. + configDataRead(31 downto 0) <= (others => '0'); + when x"00001C" => + -- Destination Operations CAR. Read-only. + configDataRead(31 downto 16) <= (others => '0'); + configDataRead(15) <= '1'; + configDataRead(14) <= '1'; + configDataRead(13 downto 0) <= (others => '0'); + when x"00004C" => + -- Processing Element Logical Layer Control CSR. + configDataRead(31 downto 3) <= (others => '0'); + configDataRead(2 downto 0) <= "001"; -- support 34 bits address + when x"000060" => + -- Base Device ID CSR. + -- Only valid for end point devices. + if (configWrite = '1') then + baseDeviceId <= configDataWrite(15 downto 0); + else + configDataRead(15 downto 0) <= baseDeviceId; + end if; + 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; + else + configDataRead(31 downto 16) <= (others => '0'); + configDataRead(15 downto 0) <= hostBaseDeviceId; + end if; + when x"00006C" => + -- Component TAG CSR. + if (configWrite = '1') then + componentTag <= configDataWrite; + else + configDataRead <= componentTag; + end if; + + when others => + configDataRead <= (others => '0'); + end case; + else + -- Config memory not enabled. + end if; + end if; + end process; + + ----------------------------------------------------------------------------- + -- findInPayload + -- find out number of the bytes and first byte's position in the payload. + ----------------------------------------------------------------------------- + findInPayload: process(wdptr, size) + begin + case size is + when "0000" => + reserved <= '0'; + numberOfByte <= 1; + if wdptr = '1' then + pos <= 4; + else + pos <= 0; + end if; + when "0001" => + reserved <= '0'; + numberOfByte <= 1; + if wdptr = '1' then + pos <= 5; + else + pos <= 1; + end if; + when "0010" => + reserved <= '0'; + numberOfByte <= 1; + if wdptr = '1' then + pos <= 6; + else + pos <= 2; + end if; + when "0011" => + reserved <= '0'; + numberOfByte <= 1; + if wdptr = '1' then + pos <= 7; + else + pos <= 3; + end if; + when "0100" => + reserved <= '0'; + numberOfByte <= 2; + if wdptr = '1' then + pos <= 4; + else + pos <= 0; + end if; + when "0101" => + reserved <= '0'; + numberOfByte <= 3; + if wdptr = '1' then + pos <= 5; + else + pos <= 0; + end if; + when "0110" => + reserved <= '0'; + numberOfByte <= 2; + if wdptr = '1' then + pos <= 6; + else + pos <= 2; + end if; + when "0111" => + reserved <= '0'; + numberOfByte <= 5; + if wdptr = '1' then + pos <= 3; + else + pos <= 0; + end if; + when "1000" => + reserved <= '0'; + numberOfByte <= 4; + if wdptr = '1' then + pos <= 4; + else + pos <= 0; + end if; + when "1001" => + reserved <= '0'; + numberOfByte <= 6; + if wdptr = '1' then + pos <= 2; + else + pos <= 0; + end if; + when "1010" => + reserved <= '0'; + numberOfByte <= 7; + if wdptr = '1' then + pos <= 1; + else + pos <= 0; + end if; + when "1011" => + reserved <= '0'; + if wdptr = '1' then + numberOfByte <= 16; + else + numberOfByte <= 8; + end if; + pos <= 0; + when "1100" => + reserved <= '0'; + if wdptr = '1' then + numberOfByte <= 64; + else + numberOfByte <= 32; + end if; + pos <= 0; + when "1101" => + if wdptr = '1' then + reserved <= '0'; + numberOfByte <= 128; + else + reserved <= '1'; + numberOfByte <= 96; + end if; + pos <= 0; + when "1110" => + if wdptr = '1' then + numberOfByte <= 192; + else + numberOfByte <= 160; + end if; + reserved <= '1'; + pos <= 0; + when "1111" => + if wdptr = '1' then + reserved <= '0'; + numberOfByte <= 256; + else + reserved <= '1'; + numberOfByte <= 224; + end if; + pos <= 0; + when others => + reserved <= '1'; + numberOfByte <= 0; + pos <= 0; + end case; + end process; + +end architecture;
1.0.1/rtl/vhdl/RioWbBridge.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/sw/stack/riostack.c =================================================================== --- 1.0.1/sw/stack/riostack.c (nonexistent) +++ 1.0.1/sw/stack/riostack.c (revision 29) @@ -0,0 +1,8225 @@ +/******************************************************************************* + * + * RapidIO IP Library Core + * + * This file is part of the RapidIO IP library project + * http://www.opencores.org/cores/rio/ + * + * Description: + * This file contains a software implementation of a RapidIO stack according to + * the 2.2 version, part 6, of the standard. Only short control symbols are + * supported. + * + * Symbols are in four flavors, idle, control, data and error. They are abstract + * and should be serialized by any implementation to be sent on a transmission + * channel. Error symbols are never generated by the stack and are used if the + * symbol decoder encounters an error that the stack should be notified of. + * + * Symbols are inserted into the stack by calling RIO_portAddSymbol() and symbols to + * transmit are fetched from the stack using RIO_portGetSymbol(). These two + * functions are the low-level interface towards a physical transmission channel. + * The function RIO_portSetStatus() is used to indicate to the stack that initial + * training of the symbol codec has been completed and that the transmission port + * is ready to accept other symbols than idle. The procedure is to set the port + * status to initialized once idle symbols are successfully received. + * + * On the high-level interface are rio_sendXXX() functions used to create and + * insert packets into the outbound transmission queue. The RIO_eventPoll() + * function is used to check if any packet is available for reading in the + * inbound reception queue. These packets are then accessed using + * rio_receiveXXX() functions. + * + * ----------------- + * | OS dependent | + * | (your code) | + * ----------------- + * | + * ----------------- + * | RioStack | + * ----------------- + * | + * ----------------- + * | Symbol Codec | + * | (your code) | + * ----------------- + * | + * ----------------- + * | Port driver | + * ----------------- + * | + * ----------------- + * | Physical port | + * ----------------- + * + * The symbol codec maps a RapidIO symbol to the physical transmission media. + * + * Some typical patterns to handle this stack are: + * Initialization: + * RIO_open(...); + * RIO_portSetTimeout(...); + * ... + * + * RIO_portSetStatus(1); + * + * Bottom-half traffic handling: + * RIO_portSetTime(...); + * + * RIO_portAddSymbol(...); + * s = RIO_portGetSymbol(...); + * + * + * Receiving packets: + * switch(RIO_eventPoll(...)) + * { + * case RIO_EVENT_DOORBELL: + * RIO_receiveDoorbell(...); + * ... + * } + * RIO_packetRemove(); + * + * Transmitting packets: + * if(RIO_sendAvailable(...)) + * { + * RIO_sendDoorbell(...); + * } + * ... + * + * More details about the usage can be found in the module tests in the end of + * this file. + * + * 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 + * + *******************************************************************************/ + +/** + * \file riostack.c + */ + +/******************************************************************************* + * Includes + *******************************************************************************/ + +#include "riostack.h" + + +/*lint -e961 Allow function like macros. */ +/*lint -e621 Long identifier names allowed to increase readability. */ +/*lint -w2 */ + + +/* lint --estring(960,17.4) It is not possible to implement a rio stack without some + * pointer arithmetic */ + +/******************************************************************************* + * Local macro definitions + *******************************************************************************/ + +/* Macro to update 5-bit ackId counters. */ +#define ACKID_INC(ackId) (((ackId)+1)&0x1f) + +/* Macros to get entries from a control symbol. */ +#define STYPE0_GET(data) ((uint8_t) (((data) >> 21) & 0x00000007u)) +#define PARAMETER0_GET(data) ((uint8_t) (((data) >> 16) & 0x00000001fu)) +#define PARAMETER1_GET(data) ((uint8_t) (((data) >> 11) & 0x00000001fu)) +#define STYPE1_GET(data) ((uint8_t) (((data) >> 8) & 0x00000007u)) +#define CMD_GET(data) ((uint8_t) (((data) >> 5) & 0x00000007u)) +#define CRC5_GET(data) ((uint8_t) (((data) >> 0) & 0x0000001fu)) + +/* Macros to get entries from a packet in a buffer. */ +#define FTYPE_GET(p) (((p)[0] >> 16) & 0xf) +#define DESTID_GET(p) ((p)[0] & 0xffff) +#define SRCID_GET(p) (((p)[1] >> 16) & 0xffff) +#define TRANSACTION_GET(p) (((p)[1] >> 12) & 0xf) +#define MSGLEN_GET(p) TRANSACTION_GET(p) +#define SSIZE_GET(p) (((p)[1] >> 8) & 0xf) +#define LETTER_GET(p) (((p)[1] >> 6) & 0x3) +#define MBOX_GET(p) (((p)[1] >> 4) & 0x3) +#define MSGSEG_GET(p) ((p)[1] & 0xf) +#define XMBOX_GET(p) MSGSEG_GET(p) +#define RDSIZE_GET(p) SSIZE_GET(p) +#define WRSIZE_GET(p) SSIZE_GET(p) +#define TID_GET(p) ((p)[1] & 0xff) +#define HOP_GET(p) (((p)[2] >> 24) & 0xff) +#define CONFIG_OFFSET_GET(p) ((p)[2] & 0x00fffffcul) +#define INFO_GET(p) (((p)[2] >> 16) & 0xffff) +#define ADDRESS_GET(p) ((p)[2] & 0xfffffff8ul) +#define WDPTR_GET(p) (((p)[2] >> 2) & 0x1) +#define XAMBS_GET(p) ((p)[2] & 0x3) +#define DOUBLE_WORD_MSB_GET(p, i) (p)[3+(2*i+0)] +#define DOUBLE_WORD_LSB_GET(p, i) (p)[3+(2*i+1)] + +/* Transmitter frame states. */ +#define TX_FRAME_START ((uint8_t)0u) +#define TX_FRAME_BODY ((uint8_t)1u) + +/* Control symbol constants. */ +#define STYPE0_PACKET_ACCEPTED ((uint8_t)0x00u) +#define STYPE0_PACKET_RETRY ((uint8_t)0x01u) +#define STYPE0_PACKET_NOT_ACCEPTED ((uint8_t)0x02u) +#define STYPE0_RESERVED ((uint8_t)0x03u) +#define STYPE0_STATUS ((uint8_t)0x04u) +#define STYPE0_VC_STATUS ((uint8_t)0x05u) +#define STYPE0_LINK_RESPONSE ((uint8_t)0x06u) +#define STYPE0_IMPLEMENTATION_DEFINED ((uint8_t)0x07u) +#define STYPE1_START_OF_PACKET ((uint8_t)0x00u) +#define STYPE1_STOMP ((uint8_t)0x01u) +#define STYPE1_END_OF_PACKET ((uint8_t)0x02u) +#define STYPE1_RESTART_FROM_RETRY ((uint8_t)0x03u) +#define STYPE1_LINK_REQUEST ((uint8_t)0x04u) +#define STYPE1_MULTICAST_EVENT ((uint8_t)0x05u) +#define STYPE1_RESERVED ((uint8_t)0x06u) +#define STYPE1_NOP ((uint8_t)0x07u) + +/* Packet ftype constants. */ +#define FTYPE_REQUEST 0x2 +#define FTYPE_WRITE 0x5 +#define FTYPE_MAINTENANCE 0x8 +#define FTYPE_DOORBELL 0xa +#define FTYPE_MESSAGE 0xb +#define FTYPE_RESPONSE 0xd + +/* Transaction constants. */ +#define TRANSACTION_MAINT_READ_REQUEST 0 +#define TRANSACTION_MAINT_WRITE_REQUEST 1 +#define TRANSACTION_MAINT_READ_RESPONSE 2 +#define TRANSACTION_MAINT_WRITE_RESPONSE 3 +#define TRANSACTION_WRITE_NWRITE 4 +#define TRANSACTION_WRITE_NWRITER 5 +#define TRANSACTION_REQUEST_NREAD 4 +#define TRANSACTION_RESPONSE_NO_PAYLOAD 0 +#define TRANSACTION_RESPONSE_MESSAGE_RESPONSE 1 +#define TRANSACTION_RESPONSE_WITH_PAYLOAD 8 + +/* Maintenance transaction lengths. */ +#define MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE ((uint32_t) 4ul) +#define MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE ((uint32_t) 6ul) +#define MAINTENANCE_TRANSACTION_READ_RESPONSE_SIZE ((uint32_t) 6ul) +#define MAINTENANCE_TRANSACTION_WRITE_RESPONSE_SIZE ((uint32_t) 4ul) + +/* Constants used to forward different errors to the link partner. */ +#define PACKET_NOT_ACCEPTED_CAUSE_RESERVED 0u +#define PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID 1u +#define PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC 2u +#define PACKET_NOT_ACCEPTED_CAUSE_NON_MAINTENANCE 3u +#define PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC 4u +#define PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER 5u +#define PACKET_NOT_ACCEPTED_CAUSE_NO_RESOURCE 6u +#define PACKET_NOT_ACCEPTED_CAUSE_DESCRAMBLER 7u +#define PACKET_NOT_ACCEPTED_CAUSE_GENERAL 31u + +/* Constants used to request link-responses. */ +#define LINK_REQUEST_RESET_DEVICE 3u +#define LINK_REQUEST_INPUT_STATUS 4u + +/* Constants used to forward a port status in a link-resonse. */ +#define LINK_RESPONSE_PORT_STATUS_ERROR 2u +#define LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED 4u +#define LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED 5u +#define LINK_RESPONSE_PORT_STATUS_OK 16u + +/******************************************************************************* + * Local typedefs + *******************************************************************************/ + +/******************************************************************************* + * Global declarations + *******************************************************************************/ + +/******************************************************************************* + * Local declarations + *******************************************************************************/ + +/******************************************************************************* + * Local function prototypes + *******************************************************************************/ + +/* Helper functions for protocol events. */ +static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus); +static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus); +static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus); +static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause); +static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus); +static void handleStartOfPacket(RioStack_t *stack); +static void handleEndOfPacket(RioStack_t *stack); +static void handleLinkRequest(RioStack_t *stack, uint8_t cmd); +static void handleNewPacketStart(RioStack_t *stack); +static void handleNewPacketEnd(RioStack_t *stack); + +/* I/O logical layer maintenance packet functions. */ +static void sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset); +static void receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset); +static void sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t data); +static void receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *data); +static void sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset, const uint32_t data ); +static void receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset, uint32_t *data ); +static void sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount); +static void receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount); + +/* I/O logical layer packet functions. */ +static void sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer, + const uint8_t ack); +static uint16_t receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, const uint16_t dataLength, uint8_t *data ); +static void sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength); +static void receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, uint16_t *dataLength); +static void sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer); +static uint16_t receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + const uint32_t address, const uint16_t dataLength, uint8_t *data ); +static void sendResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t status); +static void receiveResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid); + +/* Message passing logical layer packet functions. */ +static void sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint16_t info ); +static void receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint16_t *info); +static void sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, + const uint16_t bufferSize, const uint8_t* bufferData); +static uint16_t receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox, + const uint16_t dataLength, uint8_t *data ); +static void sendMessageResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, + const uint8_t status); +static void receiveMessageResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox); + +/* Functions to help transfer data bytes to and from a packet payload. */ +static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, + const uint16_t dataSize, uint8_t *data); +static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, + const uint16_t dataSize, const uint8_t *data); + +/* Functions to help in conversions between rdsize/wrsize and size/offset. */ +static uint16_t rdsizeGet(const uint32_t address, const uint16_t size); +static uint16_t wrsizeGet(const uint32_t address, const uint16_t size); +static void rdsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size); +static void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size); + +/** + * \brief Create a control symbol. + * + * \param[in] stype0 The stype0 value. + * \param[in] parameter0 The parameter0 value. + * \param[in] parameter1 The parameter1 value. + * \param[in] stype1 The stype1 value. + * \param[in] cmd The cmd value. + * \param[out] None + * \return The control symbol that were created from the input parameters. + * + * This function creates a control symbol with the specified arguments and + * calculates a CRC-5 checksum according to the standard specification. + */ +static RioSymbol CreateControlSymbol( const uint8_t stype0, + const uint8_t parameter0, const uint8_t parameter1, + const uint8_t stype1, const uint8_t cmd); + +/** + * \brief Function to calculate ITU-CRC5, polynom=0x15. + * + * \param[in] data The data of a control symbol. + * \param[in] crc The crc to initiate the result with. + * \return A new CRC-5 value. + */ +static uint8_t Crc5( const uint32_t data, const uint8_t crc); + +/** + * \brief Function to calculate CITT-CRC16, polynom=0x1021. + * + * \param[in] data The data to calculate CRC-16 on. + * \param[in] crc The crc to initiate the result with. + * \param[out] None + * \return A new CRC-16 value. + * + * This function calculates and returns a new CRC-16 value based on + * new data and a previous CRC-16 value. + */ +static uint16_t Crc16( const uint16_t data, const uint16_t crc); + +/** + * \brief Function to calculate CITT-CRC16, polynom=0x1021. + * + * \param[in] data The data to calculate CRC-16 on. + * \param[in] crc The crc to initiate the result with. + * \param[out] None + * \return A new CRC-16 value. + * + * This function calculates and returns a new CRC-16 value based on + * new data and a previous CRC-16 value. + */ +static uint16_t Crc32( const uint32_t data, uint16_t crc); + +/** + * \brief Create a queue with a specified size and a buffer attached to it. + * + * \param[in] The number of entries in the queue. + * \param[in] A pointer to the buffer to store the content in. + * \return A queue with the specified size and where new data will be stored + * to the specified buffer. + */ +static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer); + +/** + * \brief Get number of available elements. + * + * \param[in] q The queue to operate on. + * \return The number of free packet buffers in the queue. + */ +static uint8_t QueueAvailable( const Queue_t q ); + +/** + * \brief Get if the queue is empty or not. + * + * \param[in] q The queue to operate on. + * \return Non-zero if the queue is empty. + */ +static bool_t QueueEmpty( const Queue_t q); + +/** + * \brief Get the length of a queue. + * + * \param[in] q The queue to operate on. + * \return The number of elements in the queue. + */ +static uint8_t QueueLength( const Queue_t q); + +/** + * \brief Add a new element to the queue. + * + * \param[in] q The queue to operate on. + * \return A queue with one added element. + */ +static Queue_t QueueEnqueue( Queue_t q); + +/** + * \brief Remove an element from the queue. + * + * \param[in] q The queue to operate on. + * \return A queue with on removed element. + */ +static Queue_t QueueDequeue( Queue_t q); + +/** + * \brief Check if the readout window is empty. + * + * \param[in] q The queue to operate on. + * \return If the readout window is empty. + */ +static bool_t QueueWindowEmpty( const Queue_t q); + +/** + * \brief Reset the window to none. + * + * \param[in] q The queue to operate on. + * \return The updated Queue_t structure. + */ +static Queue_t QueueWindowReset(Queue_t q); + +/** + * \brief Increase the window to the next pending element. + * + * \param[in] q The queue to operate on. + * \return The updated Queue_t structure. + */ +static Queue_t QueueWindowNext(Queue_t q); + +/** + * \brief Set actual size of the newest element. + * + * \param[in] q The queue to operate on. + * \param[in] size The size to set the newest content size to. + */ +static void QueueSetSize( Queue_t q, const uint32_t size); + +/** + * \brief Set content at a specified index in the newest element. + * + * \param[in] q The queue to operate on. + * \param[in] index posititon into the element + * \param[in] content The content to set at the specified index in the newest queue element. + */ +static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content); + +/** + * \brief Get the size of the newest element. + * + * \param[in] q The queue to operate on. + * \return The size of the currently pending element. + */ +static uint32_t QueueGetBackSize( Queue_t q); + +/** + * \brief Get a pointer to the buffer of the newest element. + * + * \param[in] q The queue to operate on. + * \return A pointer to the content. + */ +static uint32_t *QueueGetBackBuffer( Queue_t q ); + +/** + * \brief Get the size of the oldest element. + * \param[in] q The queue to operate on. + * \return The size of the element. + */ +static uint32_t QueueGetFrontSize( Queue_t q ); + +/** + * \brief Get the content of the oldest element at specified index. + * \param[in] q The queue to operate on. + * \param[in] index The index into the element to get the content from. + * \return content of element at index position. + */ +static uint32_t QueueGetFrontContent( Queue_t q, const uint32_t index); + +/** + * \brief Get a pointer to the buffer of the oldest element. + * + * \param[in] q The queue to operate on. + * \return A pointer to the content. + */ +static uint32_t *QueueGetFrontBuffer( Queue_t q ); + + + +/******************************************************************************* + * Global functions + *******************************************************************************/ + + +void RIO_open( RioStack_t *stack, const RioStackObserver_t *observer, const void *private, + const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer, + const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer, + const uint16_t configDeviceVendorId, const uint16_t configDeviceId, const uint32_t configDeviceRevisionId, + const uint16_t configAssyVendorId, const uint16_t configAssyId, const uint16_t configAssyRevisionId, + const uint16_t configBaseDeviceId ) +{ + /* Port time and timeout limit. */ + stack->portTime = 0u; + stack->portTimeout = 1000u; + + /* Setup the receiver. */ + stack->rxState = RX_STATE_UNINITIALIZED; + stack->rxCounter = 0u; + stack->rxCrc = 0xffffu; + stack->rxStatusReceived = 0u; + stack->rxAckId = 0u; + stack->rxAckIdAcked = 0u; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED; + stack->rxQueue = QueueCreate((uint8_t) (rxPacketBufferSize/RIO_BUFFER_SIZE), rxPacketBuffer); + + /* Setup the transmitter. */ + stack->txState = TX_STATE_UNINITIALIZED; + stack->txCounter = 0u; + stack->txStatusCounter = 0u; + stack->txFrameState = TX_FRAME_START; + stack->txAckId = 0u; + stack->txAckIdWindow = 0u; + stack->txQueue = QueueCreate((uint8_t) (txPacketBufferSize/RIO_BUFFER_SIZE), txPacketBuffer); + + /* Set our own device address to use in the packets. */ + stack->deviceIdentity = configDeviceId; + stack->deviceVendorIdentity = configDeviceVendorId; + stack->deviceRev = configDeviceRevisionId; + stack->assyIdentity = configAssyId; + stack->assyVendorIdentity = configAssyVendorId; + stack->assyRev = configAssyRevisionId; + stack->baseDeviceId = configBaseDeviceId; + + /* Initialize the host base lock CSR. */ + stack->hostBaseDeviceIdLock = 0xfffffffful; + stack->componentTag = 0ul; + + /* Bits that are updated by the configuration procedure. */ + stack->host = 0u; + stack->masterEnable = 0u; + stack->discovered = 0u; + + /* Setup status counters for inbound direction. */ + stack->statusInboundPacketComplete = 0ul; + stack->statusInboundPacketRetry = 0ul; + stack->statusInboundErrorControlCrc = 0ul; + stack->statusInboundErrorPacketAckId = 0ul; + stack->statusInboundErrorPacketCrc = 0ul; + stack->statusInboundErrorIllegalCharacter = 0ul; + stack->statusInboundErrorGeneral = 0ul; + stack->statusInboundErrorPacketUnsupported = 0ul; + + /* Setup status counters for outbound direction. */ + stack->statusOutboundPacketComplete = 0ul; + stack->statusOutboundPacketRetry = 0ul; + stack->statusOutboundErrorTimeout = 0ul; + stack->statusOutboundErrorPacketAccepted = 0ul; + stack->statusOutboundErrorPacketRetry = 0ul; + + /* Setup status counters for potential problems on the link-partner. */ + stack->statusPartnerLinkRequest = 0ul; + stack->statusPartnerErrorControlCrc = 0ul; + stack->statusPartnerErrorPacketAckId = 0ul; + stack->statusPartnerErrorPacketCrc = 0ul; + stack->statusPartnerErrorIllegalCharacter = 0ul; + stack->statusPartnerErrorGeneral = 0ul; + + /* Set callback structure. */ + stack->observer = observer; + + /* Set pointer to user private data. */ + stack->private = private; +} + + +/******************************************************************************************* + * Stack status functions. + * Note that status counters are access directly in the stack-structure. + *******************************************************************************************/ + +RioStatusType RIO_getStatus( RioStack_t *stack ) +{ + RioStatusType status; + + + /* Check if both receiver and transmitter is up and running. */ + if((stack->rxState == RX_STATE_LINK_INITIALIZED) && + (stack->txState == TX_STATE_LINK_INITIALIZED)) + { + /* Both receiver and transmitter is up. */ + + /* Check if it is allowed to act as a master on the bus. */ + if(stack->masterEnable) + { + /* Allowed to act as master. */ + status = RIO_STATUS_OPERATIONAL; + } + else + { + /* Not allowed to act as master. */ + /* The enumeration process has not been completed yet. */ + status = RIO_STATUS_ENUMERATION; + } + } + else + { + /* The link is not up yet. */ + status = RIO_STATUS_UNINITIALIZED; + } + + return status; +} + + +uint8_t RIO_outboundQueueLength( RioStack_t *stack ) +{ + return QueueLength(stack->txQueue); +} + + +uint8_t RIO_inboundQueueLength( RioStack_t *stack ) +{ + return QueueLength(stack->rxQueue); +} + + +/******************************************************************************************* + * Packet reception functions. + *******************************************************************************************/ + +RioEventType RIO_eventPoll( RioStack_t *stack ) +{ + RioEventType event; + uint32_t *packet; + uint32_t ftype; + uint32_t transaction; + + + /* Check if there are any new packets in the inbound queue. */ + if(!QueueEmpty(stack->rxQueue)) + { + /* There are new pending packets. */ + + /* Get the packet and its ftype. */ + packet = QueueGetFrontBuffer(stack->rxQueue); + ftype = FTYPE_GET(packet); + transaction = TRANSACTION_GET(packet); + + /* Check the type of packets, i.e. read the ftype. */ + switch(ftype) + { + case FTYPE_REQUEST: + /* Request class. */ + + /* Check transaction type. */ + switch(transaction) + { + case TRANSACTION_REQUEST_NREAD: + /* Supported NREAD request. */ + event = RIO_EVENT_NREAD; + break; + + default: + /* Unsupported request transaction. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + break; + + case FTYPE_WRITE: + /* Write class. */ + + /* Check transaction type. */ + switch(transaction) + { + case TRANSACTION_WRITE_NWRITE: + /* NWRITE transaction. */ + if(QueueGetFrontSize(stack->rxQueue) >= 6ul) + { + /* Supported NWRITE request. */ + event = RIO_EVENT_NWRITE; + } + else + { + /* Unsupported size. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + case TRANSACTION_WRITE_NWRITER: + /* NWRITE_R transaction. */ + if(QueueGetFrontSize(stack->rxQueue) >= 6ul) + { + /* Supported NWRITE_R request. */ + event = RIO_EVENT_NWRITE_R; + } + else + { + /* Unsupported size. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + default: + /* Unsupported write transaction. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + break; + + case FTYPE_MAINTENANCE: + /* Maintenance class. */ + + /* Check transaction type. */ + /* Normally, only responses could be received here unless the stack is compiled as transparent. + Maintenance requests are answered by the portAddSymbol() function. */ + switch(transaction) + { + case TRANSACTION_MAINT_READ_REQUEST: + /* Maintenance read request transaction. */ + if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE) + { + /* Supported maintenance read response. */ + event = RIO_EVENT_MAINT_READ_REQUEST; + } + else + { + /* Unsupported maintenance read request. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + case TRANSACTION_MAINT_WRITE_REQUEST: + /* Maintenance write request transaction. */ + if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE) + { + /* Supported maintenance write request. */ + event = RIO_EVENT_MAINT_WRITE_REQUEST; + } + else + { + /* Unsupported maintenance write response. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + case TRANSACTION_MAINT_READ_RESPONSE: + /* Maintenance read response transaction. */ + if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_RESPONSE_SIZE) + { + /* Supported maintenance read response. */ + event = RIO_EVENT_MAINT_READ_RESPONSE; + } + else + { + /* Unsupported maintenance read response. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + case TRANSACTION_MAINT_WRITE_RESPONSE: + /* Maintenance write response transaction. */ + if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_RESPONSE_SIZE) + { + /* Supported maintenance write response. */ + event = RIO_EVENT_MAINT_WRITE_RESPONSE; + } + else + { + /* Unsupported maintenance write response. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + default: + /* Unsupported maintenance transaction. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + break; + + case FTYPE_DOORBELL: + /* Doorbell class. */ + + /* Check size of message. */ + if(QueueGetFrontSize(stack->rxQueue) == 3ul) + { + /* Supported doorbell. */ + event = RIO_EVENT_DOORBELL; + } + else + { + /* Unsupported doorbell request. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + case FTYPE_MESSAGE: + /* Message class. */ + + /* Check msglen to see if this packet continues. */ + if(MSGLEN_GET(packet) == 0ul) + { + /* Single-packet message. */ + event = RIO_EVENT_MESSAGE; + } + else + { + /* Unsupported message type. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + } + break; + + case FTYPE_RESPONSE: + /* Response class. */ + + /* Check transaction field. */ + switch(transaction) + { + case TRANSACTION_RESPONSE_NO_PAYLOAD: + /* Response transaction without payload. */ + + /* Check status field. */ + switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul) + { + case 0x00000000: + event = RIO_EVENT_RESPONSE_DONE; + break; + case 0x00000300: + event = RIO_EVENT_RESPONSE_RETRY; + break; + case 0x00000700: + event = RIO_EVENT_RESPONSE_ERROR; + break; + default: + /* Unsupported response status. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + break; + + case TRANSACTION_RESPONSE_MESSAGE_RESPONSE: + /* Message response transaction. */ + + /* Check status field. */ + switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul) + { + case 0x00000000: + event = RIO_EVENT_MESSAGE_RESPONSE_DONE; + break; + case 0x00000300: + event = RIO_EVENT_MESSAGE_RESPONSE_RETRY; + break; + case 0x00000700: + event = RIO_EVENT_MESSAGE_RESPONSE_ERROR; + break; + default: + /* Unsupported message response status. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + break; + + case TRANSACTION_RESPONSE_WITH_PAYLOAD: + /* Response with payload transaction. */ + + /* Check status field. */ + switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul) + { + case 0x00000000: + event = RIO_EVENT_RESPONSE_DONE_PAYLOAD; + break; + case 0x00000300: + event = RIO_EVENT_RESPONSE_RETRY; + break; + case 0x00000700: + event = RIO_EVENT_RESPONSE_ERROR; + break; + default: + /* Unsupported response with payload status. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + break; + + default: + /* Unsupported response transaction. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + break; + + default: + /* Unsupported class. */ + /* REMARK: Throw these away for now. */ + stack->statusInboundErrorPacketUnsupported++; + stack->rxQueue = QueueDequeue(stack->rxQueue); + event = RIO_EVENT_NONE; + break; + } + } + else + { + /* No pending events available. */ + event = RIO_EVENT_NONE; + } + + return event; +} + + +void RIO_packetRemove( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + stack->rxQueue = QueueDequeue(stack->rxQueue); +} + + +bool_t RIO_sendAvailable( RioStack_t *stack, const uint16_t size ) +{ + /* Return if there are buffers available and if the requested size is less + than or equal to the maximum payload that fits into one packet. */ + return (bool_t) (stack->masterEnable && (size <= 256u) && (QueueAvailable(stack->txQueue) > 0u)); +} + + +uint32_t RIO_packetGet( RioStack_t *stack, uint32_t length, uint32_t *dest) +{ + uint32_t i; + uint32_t size; + uint32_t *src; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Get the size and a pointer to the raw packet. */ + size = QueueGetFrontSize(stack->rxQueue); + src = QueueGetFrontBuffer(stack->rxQueue); + + ASSERT((length >= size), "Too short destination packet."); + + /* Copy the packet to the destination packet pointer. */ + for(i = 0; i < size; i++) + { + dest[i] = src[i]; + } + + /* Remove the packet from the queue. */ + stack->rxQueue = QueueDequeue(stack->rxQueue); + + /* Return the size of the copied packet. */ + return size; +} + + +void RIO_packetSet( RioStack_t *stack, uint32_t length, uint32_t *src) +{ + uint32_t i; + uint32_t *dest; + + + ASSERT((QueueAvailable(stack->txQueue) > 0), "Writing to full transmission queue."); + ASSERT((length < RIO_PACKET_SIZE), "Writing a too large packet."); + + /* Set the size of the new packet. */ + QueueSetSize(stack->txQueue, length); + + /* Get a pointer to the destination packet in the transmission queue. */ + dest = QueueGetBackBuffer(stack->txQueue); + + /* Copy the packet into the transmission queue. */ + for(i = 0; i < length; i++) + { + dest[i] = src[i]; + } + + /* Make sure the ackId field of the copied packet is reset. */ + /* Unless this is done, the ackId field of the transmitted packet may be corrupted. */ + dest[0] &= 0x03ffffff; + + /* Enqueue the new packet. */ + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +/******************************************************************************************* + * Configuration-space access methods. + *******************************************************************************************/ + +uint32_t RIO_readConfig( RioStack_t *stack, const uint32_t offset ) +{ + uint32_t data; + + /* Check the area of the access. */ + if(offset < 0x10000ul) + { + /* Access is in not in implementation-defined space. */ + + /* Check offset and return. */ + switch(offset) + { + case DEVICE_IDENTITY_CAR: + data = (uint32_t)stack->deviceIdentity << 16; + data |= stack->deviceVendorIdentity; + break; + case DEVICE_INFORMATION_CAR: + data = stack->deviceRev; + break; + case ASSEMBLY_IDENTITY_CAR: + data = (uint32_t)stack->assyIdentity << 16; + data |= stack->assyVendorIdentity; + break; + case ASSEMBLY_INFORMATION_CAR: + data = (uint32_t)stack->assyRev << 16; + data |= EXTENDED_FEATURES_OFFSET; + break; + case PROCESSING_ELEMENT_FEATURES_CAR: + /* Indicate processor with extended features + and 34-bit address support. */ + /* Supports common transport large systems. */ + data = 0x20000019ul; + break; + case SOURCE_OPERATIONS_CAR: + /* Supporting doorbells and data messages. */ + data = 0x00000c00ul; + break; + case DESTINATION_OPERATIONS_CAR: + /* Supporting doorbells and data messages. */ + data = 0x00000c00ul; + break; + case PROCESSING_ELEMENT_LOGICAL_LAYER_CONTROL_CSR: + /* Supports 34-bit addresses. */ + data = 0x00000001ul; + break; + case BASE_DEVICE_ID_CSR: + data = stack->baseDeviceId; + break; + case HOST_BASE_DEVICE_ID_LOCK_CSR: + data = stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful; + break; + case COMPONENT_TAG_CSR: + data = stack->componentTag; + break; + case LP_SERIAL_REGISTER_BLOCK_HEADER(EXTENDED_FEATURES_OFFSET): + /* Indicate Generic end point device and no more extended features. */ + data = 0x00000001ul; + break; + case PORT_LINK_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET): + /* REMARK: Implement this... */ + data = 0x00000000ul; + break; + case PORT_RESPONSE_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET): + /* REMARK: Implement this... */ + data = 0x00000000ul; + break; + case PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET): + /* Return the host, master enable bit and the discovered bit. */ + data = ((uint32_t) stack->host) << 31; + data |= ((uint32_t) stack->masterEnable) << 30; + data |= ((uint32_t) stack->discovered) << 29; + break; + case PORT_N_LOCAL_ACKID_CSR(EXTENDED_FEATURES_OFFSET, 0u): + data = ((uint32_t) stack->rxAckId) << 24; + data |= ((uint32_t) stack->txAckId) << 8; + data |= ((uint32_t) stack->txAckIdWindow); + break; + case PORT_N_ERROR_AND_STATUS_CSR(EXTENDED_FEATURES_OFFSET, 0u): + /* Indicate the port status here. */ + if((stack->txState == TX_STATE_LINK_INITIALIZED) && + (stack->rxState == RX_STATE_LINK_INITIALIZED)) + { + /* Port ok. */ + data = 0x00000002ul; + } + else + { + /* Port not ok. */ + data = 0x00000001ul; + } + break; + default: + data = 0x00000000ul; + break; + } + } + else + { + /* Access is in implementation-defined space. */ + + /* Check if there are any registered callback. */ + if((stack->observer != NULL) && + (stack->observer->configRead != NULL)) + { + /* Call the observer callback to handle the access. */ + data = stack->observer->configRead(stack, offset - 0x00010000ul); + } + else + { + data = 0x00000000ul; + } + } + + return data; +} + + +void RIO_writeConfig( RioStack_t *stack, const uint32_t offset, const uint32_t data) +{ + /* Check the area of the access. */ + if(offset < 0x00010000ul) + { + /* Access is not in implementation-defined space. */ + + /* Check offset and execute request. */ + switch(offset) + { + case BASE_DEVICE_ID_CSR: + stack->baseDeviceId = (uint16_t) data; + break; + case HOST_BASE_DEVICE_ID_LOCK_CSR: + if (stack->hostBaseDeviceIdLock == 0xfffffffful) + { + stack->hostBaseDeviceIdLock = (uint16_t)data; + } + else + { + if ((stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful) == + (data & (uint32_t)0x0000fffful)) + { + stack->hostBaseDeviceIdLock = 0xfffffffful; + } + else + { + /* Ignore the write. */ + } + } + break; + case COMPONENT_TAG_CSR: + stack->componentTag = data; + break; + case PORT_LINK_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET): + /* REMARK: Implement this... */ + break; + case PORT_RESPONSE_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET): + /* REMARK: Implement this... */ + break; + case PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET): + /* Return host, master enable bit and discovered bit. */ + stack->host = (uint8_t)(data >> 31) & 1u; + stack->masterEnable = (uint8_t)(data >> 30) & 1u; + stack->discovered = (uint8_t)(data >> 29) & 1u; + break; + case PORT_N_LOCAL_ACKID_CSR(EXTENDED_FEATURES_OFFSET, 0u): + if(data & 0x80000000) + { + while(!QueueEmpty(stack->txQueue)) + { + stack->txQueue = QueueDequeue(stack->txQueue); + } + } + stack->rxAckId = (uint8_t) ((data >> 24) & 0x1f); + stack->txAckId = (uint8_t) ((data >> 8) & 0x1f); + stack->txAckIdWindow = (uint8_t) (data & 0x1f); + break; + default: + break; + } + } + else + { + /* Access is in implementation-defined space. */ + + /* Check if there are any registered callback. */ + if((stack->observer != NULL) && + (stack->observer->configWrite != NULL)) + { + /* Call the observer callback to handle the access. */ + stack->observer->configWrite(stack, offset - 0x00010000ul, data); + } + else + { + /* Dont do anything. */ + } + } +} + + +/******************************************************************************************* + * Logical I/O MAINTENANCE-READ functions. + *******************************************************************************************/ + +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset) +{ + sendMaintenanceReadRequest(stack, destid, srcid, tid, hopCount, offset); +} +#else +void RIO_sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset) +{ + sendMaintenanceReadRequest(stack, destid, stack->baseDeviceId, tid, hopCount, offset); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset) +{ + receiveMaintenanceReadRequest( stack, destid, srcid, tid, hopCount, offset); +} +#else +void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset) +{ + receiveMaintenanceReadRequest( stack, srcid, srcid, tid, hopCount, offset); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t data) +{ + sendMaintenanceReadResponse(stack, destid, srcid, tid, hopCount, data); +} +#else +void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount, const uint32_t data) +{ + sendMaintenanceReadResponse(stack, destid, stack->baseDeviceId, tid, hopCount, data); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *data) +{ + receiveMaintenanceReadResponse(stack, destid, srcid, tid, hopCount, data); +} +#else +void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *data) +{ + receiveMaintenanceReadResponse(stack, srcid, srcid, tid, hopCount, data); +} +#endif + +/******************************************************************************************* + * Logical I/O MAINTENANCE-WRITE functions. + *******************************************************************************************/ + +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset, const uint32_t data ) +{ + sendMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data); +} +#else +void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset, const uint32_t data ) +{ + sendMaintenanceWriteRequest(stack, destid, stack->baseDeviceId, tid, hopCount, offset, data); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset, uint32_t *data ) +{ + receiveMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data); +} +#else +void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset, uint32_t *data ) +{ + receiveMaintenanceWriteRequest(stack, srcid, srcid, tid, hopCount, offset, data); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount) +{ + sendMaintenanceWriteResponse(stack, destid, srcid, tid, hopCount); +} +#else +void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount) +{ + sendMaintenanceWriteResponse(stack, destid, stack->baseDeviceId, tid, hopCount); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount) +{ + receiveMaintenanceWriteResponse(stack, destid, srcid, tid, hopCount); +} +#else +void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount) +{ + receiveMaintenanceWriteResponse(stack, srcid, srcid, tid, hopCount); +} +#endif + +/******************************************************************************************* + * Logical I/O NWRITE/NWRITER functions. + *******************************************************************************************/ + +#ifdef RIO_TRANSPARENT +void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, + const uint32_t address, const uint16_t size, const uint8_t *data) +{ + sendNwrite(stack, destid, srcid, 0, address, size, data, 0u); +} +#else +void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, + const uint32_t address, const uint16_t size, const uint8_t *data) +{ + sendNwrite(stack, destid, stack->baseDeviceId, 0, address, size, data, 0u); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t size, const uint8_t *data) +{ + sendNwrite(stack, destid, srcid, tid, address, size, data, 1u); +} +#else +void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint32_t address, const uint16_t size, const uint8_t *data) +{ + sendNwrite(stack, destid, stack->baseDeviceId, tid, address, size, data, 1u); +} +#endif + +#ifdef RIO_TRANSPARENT +uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, const uint16_t dataLength, uint8_t *data ) +{ + return receiveNwrite(stack, destid, srcid, tid, address, dataLength, data); +} +#else +uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint32_t *address, const uint16_t dataLength, uint8_t *data ) +{ + return receiveNwrite(stack, srcid, srcid, tid, address, dataLength, data); +} +#endif + +/******************************************************************************************* + * Logical I/O NREAD functions. + *******************************************************************************************/ + +#ifdef RIO_TRANSPARENT +void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength) +{ + sendNread(stack, destid, srcid, tid, address, dataLength); +} +#else +void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength) +{ + sendNread(stack, destid, stack->baseDeviceId, tid, address, dataLength); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, uint16_t *dataLength) +{ + receiveNread( stack, destid, srcid, tid, address, dataLength); +} +#else +void RIO_receiveNread( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint32_t *address, uint16_t *dataLength) +{ + receiveNread( stack, srcid, srcid, tid, address, dataLength); +} +#endif + +/******************************************************************************************* + * Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR + * functions. + *******************************************************************************************/ + + +#ifdef RIO_TRANSPARENT +void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer) +{ + sendResponseDonePayload(stack, destid, srcid, tid, address, bufferSize, buffer); +} +#else +void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer) +{ + sendResponseDonePayload(stack, destid, stack->baseDeviceId, tid, address, bufferSize, buffer); +} +#endif + +#ifdef RIO_TRANSPARENT +uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + const uint32_t address, const uint16_t dataLength, uint8_t *data ) +{ + return receiveResponseDonePayload(stack, destid, srcid, tid, address, dataLength, data); +} +#else +uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + const uint32_t address, const uint16_t dataLength, uint8_t *data ) +{ + return receiveResponseDonePayload(stack, srcid, srcid, tid, address, dataLength, data); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid) +{ + sendResponse(stack, destid, srcid, tid, 0x0u); +} +#else +void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t tid) +{ + sendResponse(stack, destid, stack->baseDeviceId, tid, 0x0u); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid) +{ + receiveResponse(stack, destid, srcid, tid); +} +#else +void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *tid) +{ + receiveResponse(stack, srcid, srcid, tid); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid ) +{ + sendResponse(stack, destid, srcid, tid, 0x3u); +} +#else +void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t tid ) +{ + sendResponse(stack, destid, stack->baseDeviceId, tid, 0x3u); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid) +{ + receiveResponse(stack, destid, srcid, tid); +} +#else +void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *tid) +{ + receiveResponse(stack, srcid, srcid, tid); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid) +{ + sendResponse(stack, destid, srcid, tid, 0x7u); +} +#else +void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t tid) +{ + sendResponse(stack, destid, stack->baseDeviceId, tid, 0x7u); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_receiveResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid) +{ + receiveResponse(stack, destid, srcid, tid); +} +#else +void RIO_receiveResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *tid) +{ + receiveResponse(stack, srcid, srcid, tid); +} +#endif + + + +/******************************************************************************************* + * Logical message passing DOORBELL and MESSAGE functions. + *******************************************************************************************/ + +#ifdef RIO_TRANSPARENT +void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint16_t info ) +{ + sendDoorbell(stack, destid, srcid, tid, info); +} +#else +void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint16_t info ) +{ + sendDoorbell(stack, destid, stack->baseDeviceId, tid, info); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint16_t *info) +{ + receiveDoorbell(stack, destid, srcid, tid, info); +} +#else +void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint16_t *info) +{ + receiveDoorbell(stack, srcid, srcid, tid, info); +} +#endif + +#ifdef RIO_TRANSPARENT +void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, + const uint16_t bufferSize, const uint8_t* bufferData) +{ + sendMessage(stack, destid, srcid, mailbox, bufferSize, bufferData); +} +#else +void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox, + const uint16_t bufferSize, const uint8_t* bufferData) +{ + sendMessage(stack, destid, stack->baseDeviceId, mailbox, bufferSize, bufferData); +} +#endif + +#ifdef RIO_TRANSPARENT +uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox, + const uint16_t dataLength, uint8_t *data ) +{ + return receiveMessage(stack, destid, srcid, mailbox, dataLength, data); +} +#else +uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox, + const uint16_t dataLength, uint8_t *data ) +{ + return receiveMessage(stack, srcid, srcid, mailbox, dataLength, data); +} +#endif + +/******************************************************************************************* + * Logical message passing MESSAGE-RESPONSE functions. + *******************************************************************************************/ + +#ifdef RIO_TRANSPARENT +void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox) +{ + sendMessageResponse(stack, destid, srcid, mailbox, 0x0u); +} +#else +void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox) +{ + sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x0u); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox) +{ + receiveMessageResponse(stack, destid, srcid, mailbox); +} +#else +void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox) +{ + receiveMessageResponse(stack, srcid, srcid, mailbox); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox) +{ + sendMessageResponse(stack, destid, srcid, mailbox, 0x3u); +} +#else +void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox) +{ + sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x3u); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox) +{ + receiveMessageResponse(stack, destid, srcid, mailbox); +} +#else +void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox) +{ + receiveMessageResponse(stack, srcid, srcid, mailbox); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox) +{ + sendMessageResponse(stack, destid, srcid, mailbox, 0x7u); +} +#else +void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox) +{ + sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x7u); +} +#endif + + +#ifdef RIO_TRANSPARENT +void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox) +{ + receiveMessageResponse(stack, destid, srcid, mailbox); +} +#else +void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox) +{ + receiveMessageResponse(stack, srcid, srcid, mailbox); +} +#endif + + +void RIO_portSetStatus( RioStack_t *stack, const uint8_t initialized) +{ + /* REMARK: Clean the queues here as well??? */ + if (initialized) + { + stack->rxState = RX_STATE_PORT_INITIALIZED; + stack->rxCounter = 0u; + stack->rxCrc = 0xffffu; + stack->rxStatusReceived = 0; + stack->rxAckId = 0u; + stack->rxAckIdAcked = 0u; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED; + + stack->txState = TX_STATE_PORT_INITIALIZED; + stack->txCounter = 0u; + stack->txStatusCounter = 0u; + stack->txFrameState = TX_FRAME_START; + stack->txAckId = 0u; + stack->txAckIdWindow = 0u; + } + else + { + stack->rxState = RX_STATE_UNINITIALIZED; + stack->txState = TX_STATE_UNINITIALIZED; + } +} + + +void RIO_portSetTime( RioStack_t *stack, const uint32_t time) +{ + stack->portTime = time; +} + + +void RIO_portSetTimeout( RioStack_t *stack, const uint32_t time) +{ + stack->portTimeout = time; +} + + +void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s) +{ + uint8_t stype0; + uint8_t parameter0; + uint8_t parameter1; + uint8_t stype1; + + + switch(stack->rxState) + { + case RX_STATE_PORT_INITIALIZED: + /****************************************************************************** + * PORT_INITIALIZED + * This state is entered to initialize the link. Only status-control-symbols + * are accepted in this state. When 7 error-free, i.e. with CRC5 correct, status + * control symbols has been received, change state to linkInitialized. + ******************************************************************************/ + + /* Check the type of symbol. */ + if(s.type == RIO_SYMBOL_TYPE_CONTROL) + { + /* This is a control symbol. */ + + /* Check that the control symbol contains no errors. */ + if(Crc5(s.data, 0x1fu) == (s.data & 0x1ful)) + { + /* Error-free control symbol. */ + + /* Check if the symbol is a status symbol. */ + stype0 = STYPE0_GET(s.data); + if(stype0 == STYPE0_STATUS) + { + /* Status symbol received. */ + + /* Indicate an error-free status has been received. */ + stack->rxStatusReceived = 1; + + /* Check if enough status control symbols has been received. */ + if(stack->rxCounter == 7u) + { + /* Enough correct status control symbols has been received without + errors in between. */ + + /* Setup the transmitter with the content of the symbol. */ + stack->txAckId = PARAMETER0_GET(s.data); + stack->txAckIdWindow = stack->txAckId; + stack->txBufferStatus = PARAMETER1_GET(s.data); + + /* Set the transmitter in its normal operational mode. */ + stack->rxState = RX_STATE_LINK_INITIALIZED; + stack->rxCounter = 0u; + DEBUG_STATE("rx:normal"); + } + else + { + /* Count the number of consequitive error-free status control symbols + that has been received. */ + stack->rxCounter++; + } + } + else + { + /* The received symbol is not a status symbol. */ + /* Discard it. */ + } + } + else + { + /* CRC error in control symbol. */ + /* Restart counting error-free status-control-symbols. */ + stack->rxCounter = 0u; + } + } + else + { + /* Not a control symbol. */ + /* Discard the symbol. */ + } + + break; + + case RX_STATE_LINK_INITIALIZED: + /****************************************************************************** + * LINK_INITIALIZED + * The normal state. Accept packets and forward them. + ******************************************************************************/ + + /* Check the type of symbol. */ + switch(s.type) + { + case RIO_SYMBOL_TYPE_CONTROL: + /************************************************************************** + * This is a control symbol. + **************************************************************************/ + + /* Check if the CRC is correct. */ + if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful)) + { + /* The CRC is correct. */ + + /* Get the content of the control symbol. */ + stype0 = STYPE0_GET(s.data); + parameter0 = PARAMETER0_GET(s.data); + parameter1 = PARAMETER1_GET(s.data); + stype1 = STYPE1_GET(s.data); + + /********************************************************************************** + * Check the stype0 part of the symbol. + * Note that errors in this should trigger OUTPUT_ERROR_STOPPED. + **********************************************************************************/ + switch(stype0) + { + case STYPE0_STATUS: + /* A status containing the current ackId and the buffer status has been + received. */ + handleStatus(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_ACCEPTED: + /* A packet has been accepted by the link partner. */ + handlePacketAccepted(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_RETRY: + /* The link partner wants us to initiate a restart of the received ackId. */ + handlePacketRetry(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_NOT_ACCEPTED: + /* The link partner indicates that a packet has been rejected. */ + handlePacketNotAccepted(stack, parameter0, parameter1); + break; + + case STYPE0_LINK_RESPONSE: + /* The link partner has sent a response to a link-request. */ + handleLinkResponse(stack, parameter0, parameter1); + break; + + case STYPE0_VC_STATUS: + case STYPE0_RESERVED: + case STYPE0_IMPLEMENTATION_DEFINED: + default: + /* Unsupported symbol received. */ + /* Discard them. */ + break; + } + + /********************************************************************************** + * Check the stype1 part of the symbol. + * Note that errors in this should trigger INPUT_ERROR_STOPPED. + **********************************************************************************/ + switch(stype1) + { + case STYPE1_START_OF_PACKET: + /* Start of a new packet. */ + handleStartOfPacket(stack); + break; + + case STYPE1_END_OF_PACKET: + /* Ending a packet. */ + handleEndOfPacket(stack); + break; + + case STYPE1_STOMP: + /* Cancel the currently received frame. */ + stack->rxCounter = 0; + break; + + case STYPE1_RESTART_FROM_RETRY: + /* Cancel the currently received frame when in this state. */ + stack->rxCounter = 0; + break; + + case STYPE1_LINK_REQUEST: + /* A link-request has been received. */ + handleLinkRequest(stack, CMD_GET(s.data)); + break; + + case STYPE1_NOP: + /* No operation symbol. */ + /* Discard these. */ + break; + + case STYPE1_MULTICAST_EVENT: + case STYPE1_RESERVED: + default: + /* Unsupported symbol received. */ + /* Discard them. */ + break; + } + } + else + { + /* The control symbol CRC is incorrect. */ + /* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC; + stack->statusInboundErrorControlCrc++; + DEBUG_STATE("rx:error-stopped"); + } + break; + + case RIO_SYMBOL_TYPE_DATA: + /************************************************************************** + * This is a data symbol. + **************************************************************************/ + + /* Check if a packet has been started and that it is not too long. */ + if ((stack->rxCounter >= 1u) && (stack->rxCounter <= RIO_PACKET_SIZE)) + { + /* A packet has been started. */ + + /* Check if the ackId is correct on the first part of the packet. */ + if ((stack->rxCounter > 1u) || + ((stack->rxCounter == 1u) && (((uint8_t)(s.data >> 27)) == stack->rxAckId))) + { + /* The ackId is the expected one. */ + + /* Check if this is the first symbol of a packet. */ + if (stack->rxCounter == 1u) + { + /* This is the first symbol of the packet. */ + /* Start to calculate the CRC of the packet. */ + /* Note that the ackId should not be included in the CRC calculation. */ + stack->rxCrc = Crc32(s.data & (uint32_t)0x03fffffful, 0xffffu); + } + else + { + /* This is not the first symbol. */ + /* Continue to calculate the CRC of the packet. */ + stack->rxCrc = Crc32(s.data, stack->rxCrc); + } + + /* Save the new data in the packet queue and update the reception counter. */ + QueueSetContent(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul, s.data); + stack->rxCounter++; + } + else + { + DEBUG_FRAMING_RX("error=%u %u", stack->rxAckId, s.data>>27); + + /* The ackId is not correct. */ + /* Packet error. Enter input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID; + stack->statusInboundErrorPacketAckId++; + DEBUG_STATE("rx:error-stopped"); + } + } + else + { + /* No packet has been started or the packet is too long. */ + /* Packet error. Enter input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL; + stack->statusInboundErrorGeneral++; + DEBUG_STATE("rx:error-stopped"); + } + break; + + case RIO_SYMBOL_TYPE_ERROR: + /************************************************************************** + * The decoder has received a erronous symbol. + **************************************************************************/ + + /* Idle symbol error. Place the receiver in input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER; + stack->statusInboundErrorIllegalCharacter++; + DEBUG_STATE("rx:error-stopped"); + break; + + case RIO_SYMBOL_TYPE_IDLE: + default: + /************************************************************************** + * Idle symbol or unsupported symbol. + **************************************************************************/ + + /* Discard these for now. */ + break; + } + break; + + case RX_STATE_INPUT_RETRY_STOPPED: + /****************************************************************************** + * INPUT_RETRY_STOPPED + * This state is entered when no more buffers was available and a packet was + * received. When in this state, all packets should be discarded until a + * RESTART-FROM-RETRY symbol is received. See section 5.9.1.4 of the standard. + * Note that it is only the input side of the port that are affected, not the + * output side. Packets may still be transmitted and acknowledges should be + * accepted. + ******************************************************************************/ + + /* Check the type of symbol. */ + switch(s.type) + { + case RIO_SYMBOL_TYPE_CONTROL: + /* This is a control symbol. */ + + /* Check if the CRC is correct. */ + if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful)) + { + /* The CRC is correct. */ + + /* Get the content of the control symbol. */ + stype0 = STYPE0_GET(s.data); + parameter0 = PARAMETER0_GET(s.data); + parameter1 = PARAMETER1_GET(s.data); + stype1 = STYPE1_GET(s.data); + + /* Check the stype0 part of the symbol. */ + switch(stype0) + { + case STYPE0_STATUS: + /* A status containing the current ackId and the buffer status has been + received. */ + handleStatus(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_ACCEPTED: + /* A packet has been accepted by the link partner. */ + handlePacketAccepted(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_RETRY: + /* The link partner wants us to initiate a restart of the received ackId. */ + handlePacketRetry(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_NOT_ACCEPTED: + /* The link partner indicates that a packet has been rejected. */ + handlePacketNotAccepted(stack, parameter0, parameter1); + break; + + case STYPE0_LINK_RESPONSE: + /* The link partner has sent a response to a link-request. */ + handleLinkResponse(stack, parameter0, parameter1); + break; + + case STYPE0_VC_STATUS: + case STYPE0_RESERVED: + case STYPE0_IMPLEMENTATION_DEFINED: + default: + /* Unsupported symbol received. */ + /* Discard them. */ + break; + } + + /* Check the stype1 part of the symbol. */ + switch(stype1) + { + case STYPE1_START_OF_PACKET: + /* Starting new frames are ignored in this state. */ + break; + + case STYPE1_END_OF_PACKET: + /* Ending new frames are ignored in this state. */ + break; + + case STYPE1_STOMP: + /* Restarting frames are ignored in this state. */ + break; + + case STYPE1_RESTART_FROM_RETRY: + /* The link partner has confirmed our packet-retry-symbol. */ + /* Go back to the normal state and reset the frame reception. */ + stack->rxState = RX_STATE_LINK_INITIALIZED; + stack->rxCounter = 0u; + DEBUG_STATE("rx:normal(restart)"); + break; + + case STYPE1_LINK_REQUEST: + /* A link-request has been received. */ + handleLinkRequest(stack, CMD_GET(s.data)); + stack->rxState = RX_STATE_LINK_INITIALIZED; + DEBUG_STATE("rx:normal(link-req)"); + break; + + case STYPE1_NOP: + /* No operation symbol. */ + /* Discard these. */ + break; + + case STYPE1_MULTICAST_EVENT: + case STYPE1_RESERVED: + default: + /* Unsupported symbol received. */ + /* Discard them. */ + break; + } + } + else + { + /* The control symbol CRC is incorrect. */ + /* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC; + stack->statusInboundErrorControlCrc++; + DEBUG_STATE("rx:error-stopped"); + } + break; + + case RIO_SYMBOL_TYPE_ERROR: + /* Idle symbol error. Place the receiver in input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER; + stack->statusInboundErrorIllegalCharacter++; + DEBUG_STATE("rx:error-stopped"); + break; + + case RIO_SYMBOL_TYPE_DATA: + case RIO_SYMBOL_TYPE_IDLE: + default: + /* Data or idle symbol. */ + /* Discard these in this state. */ + break; + } + break; + + case RX_STATE_INPUT_ERROR_STOPPED: + /****************************************************************************** + * INPUT_ERROR_STOPPED + * This state is entered when an error situation has occurred. When in this + * state, all symbols should be discarded until a link-request-symbols has + * been received. See section 5.13.2.6 in part 6 of the standard. + * Note that it is only the input side of the port that are affected, not the + * output side. Packets may still be transmitted and acknowledges should be + * accepted. + ******************************************************************************/ + + /* Check the type of symbol. */ + switch(s.type) + { + case RIO_SYMBOL_TYPE_CONTROL: + /* This is a control symbol. */ + + /* Check if the CRC is correct. */ + if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful)) + { + /* The CRC is correct. */ + + /* Get the content of the control symbol. */ + stype0 = STYPE0_GET(s.data); + parameter0 = PARAMETER0_GET(s.data); + parameter1 = PARAMETER1_GET(s.data); + stype1 = STYPE1_GET(s.data); + + /* Check the stype0 part of the symbol. */ + switch(stype0) + { + case STYPE0_STATUS: + /* A status containing the current ackId and the buffer status has been + received. */ + handleStatus(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_ACCEPTED: + /* A packet has been accepted by the link partner. */ + handlePacketAccepted(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_RETRY: + /* The link partner wants us to initiate a restart of the received ackId. */ + handlePacketRetry(stack, parameter0, parameter1); + break; + + case STYPE0_PACKET_NOT_ACCEPTED: + /* The link partner indicates that a packet has been rejected. */ + handlePacketNotAccepted(stack, parameter0, parameter1); + break; + + case STYPE0_LINK_RESPONSE: + /* The link partner has sent a response to a link-request. */ + handleLinkResponse(stack, parameter0, parameter1); + break; + + case STYPE0_VC_STATUS: + case STYPE0_RESERVED: + case STYPE0_IMPLEMENTATION_DEFINED: + default: + /* Unsupported symbol received. */ + /* Discard them. */ + break; + } + + /* Check the stype1 part of the symbol. */ + switch(stype1) + { + case STYPE1_START_OF_PACKET: + /* Starting new frames are ignored in this state. */ + break; + + case STYPE1_END_OF_PACKET: + /* Ending new frames are ignored in this state. */ + break; + + case STYPE1_STOMP: + /* Restarting frames are ignored in this state. */ + break; + + case STYPE1_RESTART_FROM_RETRY: + /* Restart-from-retry are ignored in this state. */ + break; + + case STYPE1_LINK_REQUEST: + /* This is the symbol we have been waiting for. */ + /* Force the transmitter to send a link-response and go back into the normal + operational state. */ + /* The transmitter will always send a status as the first symbol after this. */ + handleLinkRequest(stack, CMD_GET(s.data)); + stack->rxState = RX_STATE_LINK_INITIALIZED; + DEBUG_STATE("rx:normal(link-req)"); + break; + + case STYPE1_NOP: + /* No operation symbol. */ + /* Discard these. */ + break; + + case STYPE1_MULTICAST_EVENT: + case STYPE1_RESERVED: + default: + /* Unsupported symbol received. */ + /* Discard them. */ + break; + } + } + else + { + /* The CRC is incorrect. */ + /* Discard these in this state. */ + } + break; + + case RIO_SYMBOL_TYPE_DATA: + case RIO_SYMBOL_TYPE_IDLE: + case RIO_SYMBOL_TYPE_ERROR: + default: + /* Data, idle or error symbol. */ + /* Discard these in this state. */ + break; + } + break; + + case RX_STATE_UNINITIALIZED: + default: + /****************************************************************************** + * Wait for the port to be initialized. + ******************************************************************************/ + + /* Discard all incoming symbols. */ + break; + } +} + + + +RioSymbol RIO_portGetSymbol( RioStack_t *stack ) +{ + RioSymbol s; + + + switch(stack->txState) + { + case TX_STATE_PORT_INITIALIZED: + /****************************************************************************** + * PORT_INITIALIZED + * This state is entered to initialize the link. Send status-control-symbols + * once in a while until the receiver has received enough error-free status- + * control-symbols and we have transmitted enough status-control-symbols. Once + * an error-free status-control-symbol has been received, the statuses are + * transmitted more frequently to decrease the time for the link to be + * initialized. + ******************************************************************************/ + + /* Check if an idle symbol or a status control symbol should be sent. */ + if(((stack->rxStatusReceived == 0) && (stack->txCounter == 255u)) || + ((stack->rxStatusReceived == 1) && (stack->txCounter >= 15u))) + { + /* A control symbol should be sent. */ + + /* Create a new status symbol and reset the transmission counter. */ + stack->txCounter = 0u; + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_NOP, 0u); + + /* Check if the receiver has received any error-free status and that we + have sent at least 15 status control symbols. */ + if((stack->rxStatusReceived == 1) && (stack->txStatusCounter < 15u)) + { + /* Has not sent enough status control symbols. */ + stack->txStatusCounter++; + } + else + { + /* Has sent enough status control symbols. */ + /* Dont do anything. */ + } + } + else + { + /* Idle symbol should be sent. */ + s.type = RIO_SYMBOL_TYPE_IDLE; + stack->txCounter++; + } + + /* Check if we are ready to set the transmitter in a link initialized state. */ + if ((stack->rxState == RX_STATE_LINK_INITIALIZED) && (stack->txStatusCounter == 15u)) + { + /* Ready to go to link initialized. */ + stack->txState = TX_STATE_LINK_INITIALIZED; + stack->txFrameState = TX_FRAME_START; + stack->txStatusCounter = 0u; + DEBUG_STATE("tx:normal"); + } + else + { + /* Not ready to go to link initialized. */ + /* Dont do anything. */ + } + + break; + + case TX_STATE_LINK_INITIALIZED: + /****************************************************************************** + * LINK_INITIALIZED + * The normal state. Accept packets and forward them. Send acknowledges when + * the receiver has received complete packets. + ******************************************************************************/ + + /* Check if the receiver wants to acknowledge a packet. */ + if(stack->rxAckId == stack->rxAckIdAcked) + { + /* The receiver does not want to acknowledge a packet. */ + + /* Check if there are any outstanding packets and if it has timed out. */ + if((stack->txAckId == stack->txAckIdWindow) || + ((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout)) + { + /* There are no outstanding packets or there has been no timeout. */ + + /* Check if a packet is ongoing. */ + if(stack->txFrameState == TX_FRAME_BODY) + { + /* A packet transmission is ongoing. */ + + /* Check if the packet has been completly sent. */ + if(stack->txCounter != QueueGetFrontSize(stack->txQueue)) + { + /* The packet has not been completly sent. */ + + /* Create a new data symbol to transmit. */ + s.type = RIO_SYMBOL_TYPE_DATA; + s.data = QueueGetFrontContent(stack->txQueue, (uint32_t)stack->txCounter); + + /* Check if this is the first symbol in a packet. */ + if (stack->txCounter == 0u) + { + /* Place the correct ackId in the right place. */ + s.data |= (uint32_t)stack->txAckIdWindow << 27; + } + else + { + /* Dont do anything. */ + } + + /* Update the transmission counter. */ + stack->txCounter++; + + /* A status control symbol was not sent. Update the status counter. */ + stack->txStatusCounter++; + } + else + { + /* The packet has been sent. */ + + /* Save the timeout time and update to the next ackId. */ + stack->txFrameTimeout[stack->txAckIdWindow] = stack->portTime; + stack->txAckIdWindow = ACKID_INC(stack->txAckIdWindow); + stack->txQueue = QueueWindowNext(stack->txQueue); + + /* Check if there are more packets pending to be sent. */ + /* Also check that there are buffer available at the receiver and that not too many + packets are outstanding. */ + if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) && + (((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31)) + { + /* More pending packets. */ + DEBUG_FRAMING_TX("cont=%i", stack->txAckIdWindow); + /* Create a control symbol to signal that the new packet has started. */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_START_OF_PACKET, 0u); + + /* Restart transmission counter. */ + stack->txCounter = 0; + } + else + { + /* No more pending packets. */ + DEBUG_FRAMING_TX("end=%i", stack->txAckIdWindow); + /* Create a control symbol to signal that the packet has ended. */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_END_OF_PACKET, 0u); + + /* Go back to wait for a new frame. */ + stack->txFrameState = TX_FRAME_START; + } + + /* A status control symbol has been sent. Reset the status counter. */ + stack->txStatusCounter = 0u; + } + } + else + { + /* No packet is being sent. */ + + /* Check if there are any pending packets to start sending. */ + /* Also check that there are buffer available at the receiver and that not too many + packets are outstanding. */ + if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) && + (((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31)) + { + /* There is a pending packet to send. */ + DEBUG_FRAMING_TX("start=%i", stack->txAckIdWindow); + /* Send a start-of-packet control symbol to start to send the packet. */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_START_OF_PACKET, 0u); + stack->txFrameState = TX_FRAME_BODY; + stack->txCounter = 0u; + + /* A status control symbol has been sent. Reset the status counter. */ + stack->txStatusCounter = 0u; + } + else + { + /* There are no pending packets to send. */ + + /* Check if a status control symbol must be transmitted. */ + if(stack->txStatusCounter < 255u) + { + /* Not required to send a status control symbol. */ + + /* Send an idle-symbol. */ + s.type = RIO_SYMBOL_TYPE_IDLE; + stack->txStatusCounter++; + } + else + { + /* Must send a status control symbol. */ + + /* Create a status control symbol. */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_NOP, 0u); + + /* A status control symbol has been sent. Reset the status counter. */ + stack->txStatusCounter = 0u; + } + } + } + } + else + { + /* There has been a timeout. */ + /* A packet has been sent but no packet-accepted has been received. */ + DEBUG_FRAMING_TX("timeout=%i", stack->txAckId); + /* Send link-request-symbol (input-status). */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + + /* Save the time when this was transmitted. */ + stack->txFrameTimeout[stack->txAckId] = stack->portTime; + + /* Remember that this symbol has been transmitted. */ + stack->txCounter = 1; + + /* Go into the output error stopped state. */ + stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED; + stack->statusOutboundErrorTimeout++; + DEBUG_STATE("tx:error-stopped"); + } + } + else + { + /* The receiver wants us to send an acknowledgement. */ + s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue), + STYPE1_NOP, 0u); + stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked); + + /* A status control symbol was not sent. Update the status counter. */ + stack->txStatusCounter++; + } + break; + + case TX_STATE_SEND_PACKET_RETRY: + /****************************************************************************** + * SEND_PACKET_RETRY + * This state is set by the receiver to force a packet-retry-symbol to be + * transmitted. + ******************************************************************************/ + + /* Check if the receiver wants to acknowledge a packet. */ + /* This must be done first or we will get an error for a missmatching + ackId in the link-partner. */ + if(stack->rxAckId == stack->rxAckIdAcked) + { + /* No pending acknowledge. */ + + /* Send a packet-retry symbol to tell the link partner to retry the last frame. */ + s = CreateControlSymbol(STYPE0_PACKET_RETRY, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_NOP, 0u); + + /* Proceed with normal transmission. */ + stack->txState = TX_STATE_LINK_INITIALIZED; + + /* A status control symbol was not sent. Update the status counter. */ + stack->txStatusCounter++; + } + else + { + + /* The receiver wants us to send an acknowledgement. */ + s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue), + STYPE1_NOP, 0u); + stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked); + + /* A status control symbol was not sent. Update the status counter. */ + stack->txStatusCounter++; + } + break; + + case TX_STATE_SEND_PACKET_NOT_ACCEPTED: + /****************************************************************************** + * SEND_PACKET_NOT_ACCEPTED + * This state is set by the receiver to force a packet-not-accepted-symbol to be + * transmitted. + ******************************************************************************/ + + /* Send a packet-not-accepted symbol to indicate an error on the link. */ + s = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, stack->rxErrorCause, + STYPE1_NOP, 0u); + + /* Proceed with normal transmission. */ + stack->txState = TX_STATE_LINK_INITIALIZED; + + /* A status control symbol was not sent. Update the status counter. */ + stack->txStatusCounter++; + break; + + case TX_STATE_SEND_LINK_RESPONSE: + /****************************************************************************** + * SEND_LINK_RESPONSE + * This state is set by the receiver to force a link-response-symbol to be + * transmitted. + ******************************************************************************/ + + DEBUG_FRAMING_RX("link-res:%u", stack->rxAckId); + + /* Check the state of the receiver. */ + /* REMARK: If a link-request gives this response and a link-request also makes the receiver + enter the normal operational state, none of these states except the normal state will ever + be used... */ + if((stack->rxState == RX_STATE_LINK_INITIALIZED) || (stack->rxState == RX_STATE_PORT_INITIALIZED)) + { + /* Normal state. */ + s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_OK, + STYPE1_NOP, 0u); + } + else if(stack->rxState == RX_STATE_INPUT_RETRY_STOPPED) + { + /* Input-retry-stopped state. */ + s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED, + STYPE1_NOP, 0u); + } + else if(stack->rxState == RX_STATE_INPUT_ERROR_STOPPED) + { + /* Input-error-stopped state. */ + s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED, + STYPE1_NOP, 0u); + } + else + { + /* Not in the defined states. */ + s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR, + STYPE1_NOP, 0u); + } + + /* Proceed with normal transmission. */ + stack->txState = TX_STATE_LINK_INITIALIZED; + + /* Force a status to be transmitted the next time to comply to the input-error-stopped + state rules. */ + stack->txStatusCounter = 255; + break; + + case TX_STATE_OUTPUT_RETRY_STOPPED: + /****************************************************************************** + * OUTPUT_RETRY_STOPPED + * This state is entered when the link-partner has transmitted a + * packet-retry-symbol. The packet-retry-symbol is acknowledged by sending a + * restart-from-retry-symbol. + * This state follows 5.9.1.5 in part 6. + ******************************************************************************/ + + /* Send a restart-from-retry symbol to acknowledge. */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_RESTART_FROM_RETRY, 0u); + + /* Restart the current frame and proceed with normal operation. */ + stack->txFrameState = TX_FRAME_START; + stack->txState = TX_STATE_LINK_INITIALIZED; + stack->txCounter = 0; + DEBUG_STATE("tx:normal"); + + /* Discard all packets that has not received a matching packet-accepted. */ + stack->txAckIdWindow = stack->txAckId; + stack->txQueue = QueueWindowReset(stack->txQueue); + + /* A status control symbol was sent. Reset the status counter. */ + stack->txStatusCounter = 0; + break; + + case TX_STATE_OUTPUT_ERROR_STOPPED: + /****************************************************************************** + * OUTPUT_ERROR_STOPPED + * This state is entered when the link partner has encountered any problem + * which is indicated by sending a packet-not-accepted symbol or if a packet + * timeout has expired. The error condition is acknowledged by sending a + * link-request-symbol and then wait for a link-response reply. + * This state follows 5.13.2.7 in part 6. + ******************************************************************************/ + + /* Check if a link-request-symbol has been transmitted. */ + if(stack->txCounter == 0) + { + /* A link-request-symbol has not been transmitted. */ + + /* Send link-request-symbol (input-status). */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + + /* Save the time when this was transmitted. */ + stack->txFrameTimeout[stack->txAckId] = stack->portTime; + + /* Remember that this symbol has been transmitted. */ + stack->txCounter = 1; + } + else + { + /* A link-request-symbol has been transmitted. */ + + /* Check if the link partner reply has timed out. */ + if((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout) + { + /* No timeout. */ + + /* A link-request-symbol has been transmitted. */ + /* Send only idle-symbols until the link-response is received. */ + s.type = RIO_SYMBOL_TYPE_IDLE; + } + else + { + /* Link response timeout. */ + + /* Check if the link-partner has not responded for too many times. */ + if(stack->txCounter < 5) + { + /* Not too many timeouts. */ + /* Retry and send a new link-request. */ + + /* Send link-request-symbol (input-status). */ + s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + + /* Save the time when this was transmitted. */ + stack->txFrameTimeout[stack->txAckId] = stack->portTime; + + /* Increment the number of times we have retransmitted the link-request. */ + stack->txCounter++; + } + else + { + /* The link partner has not answered for too many times. */ + /* Give up and set the state to uninitialized. */ + stack->txState = TX_STATE_UNINITIALIZED; + s.type = RIO_SYMBOL_TYPE_IDLE; + ASSERT0("No link-response received, giving up."); + } + } + } + break; + + case TX_STATE_UNINITIALIZED: + default: + /****************************************************************************** + * Wait for the port to be initialized. + ******************************************************************************/ + + /* Send only idle symbols. */ + s.type = RIO_SYMBOL_TYPE_IDLE; + break; + } + + /* Return the created symbol. */ + return s; +} + +/******************************************************************************* + * Deprecated functions + *******************************************************************************/ + +uint8_t RIO_packetTid( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue) , "Reading from empty reception queue."); + + return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 1ul) & 0xfful); +} + + +uint16_t RIO_packetDestination( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 0ul)); +} + + +uint16_t RIO_packetSource( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 1ul) >> 16); +} + + +uint8_t RIO_readMaintenanceReadRequestHop( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24); +} + +uint32_t RIO_readMaintenanceReadRequestOffset( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul); +} + +uint8_t RIO_readMaintenanceReadResponseHop( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24); +} + +uint32_t RIO_readMaintenanceReadResponse( RioStack_t *stack ) +{ + uint32_t readData; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* There is no way of knowing where the data is positioned. */ + /* Bit-or the two words together since one of the words are zero. */ + readData = QueueGetFrontContent(stack->rxQueue, 3ul); + readData |= QueueGetFrontContent(stack->rxQueue, 4ul); + return readData; +} + +uint8_t RIO_readMaintenanceWriteRequestHop( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24); +} + +uint32_t RIO_readMaintenanceWriteRequestOffset( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul); +} + +uint32_t RIO_readMaintenanceWriteRequestData( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (QueueGetFrontContent(stack->rxQueue, 3ul) | QueueGetFrontContent(stack->rxQueue, 4ul)); +} + +uint8_t RIO_readMaintenanceWriteResponseHop( RioStack_t *stack ) +{ + return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24); +} + + + +void RIO_sendNwrite8( RioStack_t *stack, const uint16_t destid, const uint32_t address, + const uint8_t data) +{ + sendNwrite(stack, destid, stack->baseDeviceId, 0, address, 1, &data, 0u); +} + + +void RIO_sendNwriteR8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, + const uint8_t data) +{ + sendNwrite(stack, destid, stack->baseDeviceId, tid, address, 1, &data, 1u); +} + + +uint32_t RIO_readNwriteAddress8( RioStack_t *stack ) +{ + uint32_t address; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Assemble the address from the wrsize field and the address itself to get a byte address. */ + address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul; + address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul; + + return address; +} + + +uint8_t RIO_readNwriteSize8( RioStack_t *stack ) +{ + uint8_t wrsize; + uint8_t n; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Get the wrsize field from the packet and check its value. */ + wrsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful); + switch(wrsize) + { + case 0: + /* Reading one byte. */ + n = 1u; + break; + case 1: + /* Reading one byte. */ + n = 1u; + break; + case 2: + /* Reading one byte. */ + n = 1u; + break; + case 3: + /* Reading one byte. */ + n = 1u; + break; + default: + /* Unsupported. */ + n = 0u; + break; + } + + return n; +} + + +uint8_t RIO_readNwritePayload8( RioStack_t *stack ) +{ + uint8_t returnValue; + uint32_t readData; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Since there is no way of knowing where the byte will be placed, + OR all bytes in the payload and return it. */ + readData = QueueGetFrontContent(stack->rxQueue, 3ul); + returnValue = (uint8_t) (readData >> 24); + returnValue |= (uint8_t) (readData >> 16); + returnValue |= (uint8_t) (readData >> 8); + returnValue |= (uint8_t) (readData); + readData = QueueGetFrontContent(stack->rxQueue, 4ul); + returnValue |= (uint8_t) (readData >> 24); + returnValue |= (uint8_t) (readData >> 16); + returnValue |= (uint8_t) (readData >> 8); + returnValue |= (uint8_t) (readData); + + return returnValue; +} + +void RIO_sendNread8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = ((uint32_t) 0x0012ul) << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) stack->baseDeviceId) << 16; + content |= ((uint32_t) 0x4ul) << 12; + content |= (address & (uint32_t)0x00000003ul) << 8; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* address(28:0)|wdptr|xamsbs(1:0) */ + /* xamsbs cannot be used if the address is a word. */ + content = address & (uint32_t)0xfffffffcul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + QueueSetContent(stack->txQueue, 3ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 4ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + + +uint32_t RIO_readNreadAddress8( RioStack_t *stack ) +{ + uint32_t address; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Assemble the address from the rdsize field and the address itself to get a byte address. */ + address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul; + address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul; + + return address; +} + + +uint8_t RIO_readNreadSize8( RioStack_t *stack ) +{ + uint8_t rdsize; + uint8_t n; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Get the rdsize field from the packet and check its value. */ + rdsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful); + switch(rdsize) + { + case 0: + /* Reading one byte. */ + n = 1u; + break; + case 1: + /* Reading one byte. */ + n = 1u; + break; + case 2: + /* Reading one byte. */ + n = 1u; + break; + case 3: + /* Reading one byte. */ + n = 1u; + break; + default: + /* Unsupported. */ + n = 0u; + break; + } + + return n; +} + + +void RIO_sendMessage8( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox, const uint16_t size, const uint8_t* data) +{ + uint32_t content; + uint16_t crc = 0xffffu; + uint32_t packetIndex; + uint32_t dataIndex; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + ASSERT((size <= 256), "Packet sizes over 256 are currently unsupported."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = ((uint32_t) 0x001bul) << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */ + content = ((uint32_t) stack->baseDeviceId) << 16; + if(size <= 8u) + { + content |= ((uint32_t) 0x09ul) << 8; + } + else if(size <= 16u) + { + content |= ((uint32_t) 0x0aul) << 8; + } + else if(size <= 32u) + { + content |= ((uint32_t) 0x0bul) << 8; + } + else if(size <= 64u) + { + content |= ((uint32_t) 0x0cul) << 8; + } + else if(size <= 128u) + { + content |= ((uint32_t) 0x0dul) << 8; + } + else + { + content |= ((uint32_t) 0x0eul) << 8; + } + content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4; + content |= ((uint32_t)mailbox) >> 4; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* double-word0...double-wordN */ + dataIndex = 0; + packetIndex = 8; + while(dataIndex < size) + { + content <<= 8; + if(packetIndex == 80) + { + content |= crc >> 8; + } + else if(packetIndex == 81) + { + content |= crc & 0xff; + } + else + { + content |= data[dataIndex++]; + } + + if((packetIndex & 0x3) == 3) + { + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, packetIndex>>2, content); + } + + packetIndex++; + } + + /* Pad the data to an even double word. */ + while((dataIndex & 0x7) != 0) + { + content <<= 8; + dataIndex++; + + if((packetIndex & 0x3) == 3) + { + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, packetIndex>>2, content); + } + + packetIndex++; + } + + /* Check where the CRC should be placed. */ + if((packetIndex & 0x3) == 0) + { + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + } + else + { + /* double-wordN-LSB|crc(15:0) */ + content &= 0x0000ffff; + crc = Crc16(content, crc); + content <<= 16; + content |= crc; + } + + /* Set the crc. */ + QueueSetContent(stack->txQueue, packetIndex>>2, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 1+(packetIndex>>2)); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + + +uint8_t RIO_readMessageMbox( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue." ); + + return (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 4) & (uint32_t)0xful); +} + + +uint16_t RIO_readMessageSize8( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (uint16_t) (4ul*(QueueGetFrontSize(stack->rxQueue) - 3ul)); +} + + +/*lint -save -e613 */ +void RIO_readMessagePayload8( RioStack_t *stack, uint8_t* buffer ) +{ + uint32_t size; + uint32_t dataIndex; + uint32_t packetIndex; + uint32_t content = 0;; + + + ASSERT((buffer != NULL), "Buffer is not allocated."); + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Move bytes from inbound packet queue into the user buffer. */ + /* Long messages contain a CRC in byte 80-81, this is removed when the buffer + is copied. */ + size = QueueGetFrontSize(stack->rxQueue); + dataIndex = 0; + packetIndex = 8; + while((packetIndex>>2) < size) + { + /* Check if a new word should be read from the inbound queue. */ + if((packetIndex & 0x3) == 0) + { + /* Get a new word. */ + content = QueueGetFrontContent(stack->rxQueue, packetIndex>>2); + } + else + { + /* Update the current word. Remove the MSB, it has already be moved + to the user buffer. */ + content <<= 8; + } + + /* Check if the current byte is CRC. */ + if((packetIndex != 80) && (packetIndex != 81)) + { + /* Not CRC. */ + /* Move the byte to the user buffer. */ + buffer[dataIndex++] = (content >> 24); + } + + /* Increment to the next position in the packet. */ + packetIndex++; + } +} +/*lint -restore */ + +uint16_t RIO_readDoorbellInfo( RioStack_t *stack ) +{ + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 16); +} + + +void RIO_sendResponseDone8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = 0x001dul << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */ + content = ((uint32_t) stack->baseDeviceId) << 16; + content |= (uint32_t)0x80ul << 8; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* double-word 0 */ + switch(address & 0x7ul) + { + case 0: + /* MSB byte. */ + content = ((uint32_t) data) << 24; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + case 1: + content = ((uint32_t) data) << 16; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + case 2: + content = ((uint32_t) data) << 8; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + case 3: + content = ((uint32_t) data); + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + case 4: + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = ((uint32_t) data) << 24; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + case 5: + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = ((uint32_t) data) << 16; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + case 6: + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = ((uint32_t) data) << 8; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + default: + /* LSB byte. */ + content = 0x00000000ul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + content = ((uint32_t) data); + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + break; + } + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + QueueSetContent(stack->txQueue, 4ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 5ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + + +uint8_t RIO_readResponseDone8( RioStack_t *stack ) +{ + uint8_t returnValue; + uint32_t readData; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Since there is no way of knowing where the byte will be placed, + OR all bytes in the reply and return it. */ + readData = QueueGetFrontContent(stack->rxQueue, 2ul); + returnValue = (uint8_t) (readData >> 24); + returnValue |= (uint8_t) (readData >> 16); + returnValue |= (uint8_t) (readData >> 8); + returnValue |= (uint8_t) (readData); + readData = QueueGetFrontContent(stack->rxQueue, 3ul); + returnValue |= (uint8_t) (readData >> 24); + returnValue |= (uint8_t) (readData >> 16); + returnValue |= (uint8_t) (readData >> 8); + returnValue |= (uint8_t) (readData); + + return returnValue; +} + + + +/******************************************************************************* + * Local functions + *******************************************************************************/ + + +static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus) +{ + /* Update the buffer status of the link partner. */ + (void) ackId; + stack->txBufferStatus = bufferStatus; +} + + +static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus) +{ + /* Check if an acknowledge is expected and that it is for a transmitted packet. */ + if((stack->txAckId != stack->txAckIdWindow) && (ackId == stack->txAckId)) + { + DEBUG_FRAMING_TX("ack=%i", ackId); + /* Acknowledge for a recently transmitted packet received. */ + /* Remove the packet from the outbound queue and restart the transmission for + a new packet. */ + stack->txQueue = QueueDequeue(stack->txQueue); + stack->txAckId = ACKID_INC(stack->txAckId); + stack->statusOutboundPacketComplete++; + } + else + { + DEBUG_FRAMING_TX("*ack=%i", ackId); + /* Acknowledge for an unexpected ackId or not waiting for an acknowledge. */ + /* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */ + stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED; + stack->txCounter = 0u; + stack->statusOutboundErrorPacketAccepted++; + DEBUG_STATE("tx:error-stopped"); + } + + /* Update the buffer status of the link partner. */ + stack->txBufferStatus = bufferStatus; +} + + +static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus) +{ + /* Check if the retried packet ackId is acceptable. */ + if(ackId == stack->txAckId) + { + DEBUG_FRAMING_TX("retry=%u", ackId); + /* The request for retry is for the current packet. */ + /* Force the transmitter to send a RESTART-FROM-RETRY symbol. */ + stack->txState = TX_STATE_OUTPUT_RETRY_STOPPED; + stack->statusOutboundPacketRetry++; + DEBUG_STATE("tx:retry-stopped"); + } + else + { + DEBUG_FRAMING_TX("*retry=%u %u", ackId, stack->txAckId); + /* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */ + stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED; + stack->txCounter = 0u; + stack->statusOutboundErrorPacketRetry++; + DEBUG_STATE("tx:error-stopped"); + } + + /* Update the buffer status of the link partner. */ + stack->txBufferStatus = bufferStatus; +} + + +static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause) +{ + (void) arbitrary; + + /* Force the transmitter to enter output-error-stopped state. */ + stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED; + stack->txCounter = 0u; + + /* Record the type of error that caused the packet to not being accepted. */ + switch(cause) + { + case PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID: + stack->statusPartnerErrorPacketAckId++; + break; + case PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC: + stack->statusPartnerErrorControlCrc++; + break; + case PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC: + stack->statusPartnerErrorPacketCrc++; + break; + case PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER: + stack->statusPartnerErrorIllegalCharacter++; + break; + default: + stack->statusPartnerErrorGeneral++; + break; + } + + DEBUG_STATE("tx:error-stopped"); +} + + +static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus) +{ + uint8_t window; + uint8_t windowReceived; + + + (void) portStatus; + + /* Check if this symbols is expected. */ + if(stack->txState == TX_STATE_OUTPUT_ERROR_STOPPED) + { + DEBUG_FRAMING_TX("link-res:%u %u %u", stack->txAckIdWindow, stack->txAckId, ackId); + + /* Calculate the number of packets that has not received an acknowledge on our side and + on the link-partner side. */ + window = (stack->txAckIdWindow - stack->txAckId) & 0x1f; + windowReceived = (ackId - stack->txAckId) & 0x1f; + + /* Check if the link-partners response is acceptable. */ + if(windowReceived <= window) + { + /* A link-response is expected. */ + DEBUG_STATE("tx:recover"); + + /* Remove entries in the queue that the link-partner has sent acknowledges for that has been lost. */ + while(stack->txAckId != ackId) + { + stack->txQueue = QueueDequeue(stack->txQueue); + stack->txAckId = ACKID_INC(stack->txAckId); + stack->statusOutboundPacketComplete++; + } + + /* Set the transmission window to the resend packets that has not been received. */ + stack->txQueue = QueueWindowReset(stack->txQueue); + stack->txAckIdWindow = ackId; + stack->txFrameState = TX_FRAME_START; + + /* Set the transmitter back into normal operation. */ + stack->txState = TX_STATE_LINK_INITIALIZED; + } + else + { + /* The link-partner response is unacceptable. */ + /* Recovery is not possible. */ + stack->txState = TX_STATE_UNINITIALIZED; + ASSERT0("Unrecoverable protocol error."); + } + } + else + { + /* Not expecting a link-response. */ + /* Just discard this symbol. */ + /* REMARK: Add status counter here??? */ + } +} + + +static void handleStartOfPacket(RioStack_t *stack) +{ + /* Check if a packet is already started. */ + if(stack->rxCounter != 0u) + { + /* Packet has already started. */ + /* This indicates an implicit end-of-packet symbol and signals the previous packet as ready. */ + DEBUG_FRAMING_RX("cont=%u", stack->rxAckId); + + /* Check the packet crc. */ + if(stack->rxCrc == 0x0000u) + { + /* The packet has a correct CRC. */ + + /* Check if the packet is long enough to contain a complete packet. */ + if(stack->rxCounter > 3u) + { + /* Packet long enough to process. */ + + /* Process the newly received packet and start a new one. */ + handleNewPacketEnd(stack); + handleNewPacketStart(stack); + } + else + { + /* The packet has a valid CRC but is too short. */ + /* Packet error. Enter input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL; + stack->statusInboundErrorGeneral++; + DEBUG_STATE("rx:error-stopped"); + } + } + else + { + /* The packet has an invalid CRC. */ + /* Packet error. Enter input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC; + stack->statusInboundErrorPacketCrc++; + DEBUG_STATE("rx:error-stopped"); + } + } + else + { + /* Packet has not already started. */ + DEBUG_FRAMING_RX("start=%u", stack->rxAckId); + handleNewPacketStart(stack); + } +} + + +static void handleEndOfPacket(RioStack_t *stack) +{ + DEBUG_FRAMING_RX("end=%u", stack->rxAckId); + + /* Check if the CRC is correct. */ + if(stack->rxCrc == 0x0000u) + { + /* The packet has a correct CRC. */ + + /* Check if the packet is long enough to contain a complete packet. */ + if(stack->rxCounter > 3u) + { + /* Packet long enough to process. */ + + /* Process the newly received packet. */ + handleNewPacketEnd(stack); + } + else + { + /* The packet has a valid CRC but is too short. */ + /* Packet error. Enter input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL; + stack->statusInboundErrorGeneral++; + DEBUG_STATE("rx:error-stopped"); + } + } + else + { + /* The packet has an invalid CRC. */ + /* Packet error. Enter input-error-stopped state. */ + stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED; + stack->rxState = RX_STATE_INPUT_ERROR_STOPPED; + stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC; + stack->statusInboundErrorPacketCrc++; + DEBUG_STATE("rx:error-stopped"); + } +} + + +static void handleNewPacketStart(RioStack_t *stack) +{ + /* Check if there are buffers available to store the new frame. */ + if (QueueAvailable(stack->rxQueue) > 0u) + { + /* There are buffers available to accept the new packet. */ + + /* Update the reception counter to indicate the frame has started. */ + stack->rxCounter = 1; + } + else + { + /* There are no buffers available. */ + /* Go to input retry stopped state. */ + DEBUG_FRAMING_RX("retry=%u", stack->rxAckId); + stack->statusInboundPacketRetry++; + stack->txState = TX_STATE_SEND_PACKET_RETRY; + stack->rxState = RX_STATE_INPUT_RETRY_STOPPED; + DEBUG_STATE("rx:retry-stopped"); + } +} + + +static void handleNewPacketEnd(RioStack_t *stack) +{ + uint32_t *packet; + uint32_t ftype; + uint32_t transaction; + + + /* Save the size of the packet. */ + QueueSetSize(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul); + + /* Get the packet and information about its type. */ + packet = QueueGetBackBuffer(stack->rxQueue); + ftype = FTYPE_GET(packet); + transaction = TRANSACTION_GET(packet); + +#ifdef RIO_TRANSPARENT + /* Always forward the packet to the top of the stack. */ + stack->rxQueue = QueueEnqueue(stack->rxQueue); +#else + /* Check if the packet should be forwarded to the top of the stack. */ + if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE) && + (ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_READ_REQUEST)) + { + /* Received maintenance read request. */ + /* Send a maintenance read response. This packet is aimed at the stack, it should + not be forwarded. */ + /* Note that only single word accesses are supported. */ + RIO_sendMaintenanceReadResponse(stack, SRCID_GET(packet),TID_GET(packet), 0xff, + RIO_readConfig(stack, CONFIG_OFFSET_GET(packet))); + } + else if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE) && + (ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_WRITE_REQUEST)) + { + /* Received maintenance write request. */ + /* Send a maintenance write response. This packet is aimed at the stack, it should + not be forwarded. */ + /* Note that only single word accesses are supported. */ + RIO_writeConfig(stack, CONFIG_OFFSET_GET(packet), + DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0)); + RIO_sendMaintenanceWriteResponse(stack, SRCID_GET(packet), TID_GET(packet), 0xff); + } + else + { + /* Forward this packet to the top of the stack. */ + stack->rxQueue = QueueEnqueue(stack->rxQueue); + } +#endif + /* Reset the reception counter. */ + stack->rxCounter = 0u; + + /* Update the ackId for the receiver. */ + stack->rxAckId = ACKID_INC(stack->rxAckId); + + /* Update status counter. */ + stack->statusInboundPacketComplete++; +} + + +static void handleLinkRequest(RioStack_t *stack, uint8_t cmd) +{ + /* Check the command of the link-request. */ + if(cmd == LINK_REQUEST_INPUT_STATUS) + { + /* Input-status requested. */ + /* Return input port status. */ + + /* Force the transmitter to send a link-response-symbol. */ + stack->txState = TX_STATE_SEND_LINK_RESPONSE; + } + else if(cmd == LINK_REQUEST_RESET_DEVICE) + { + /* Reset-device requested. */ + /* REMARK: Support this??? */ + } + else + { + /* Unrecognized command. */ + /* Dont do anything. */ + } + + /* Always cancel an ongoing frame when a link-request has been received. */ + stack->rxCounter = 0; + + /* Receiving this indicates the link partner having encountered a potential problem. */ + /* Count the number of times this happens. */ + stack->statusPartnerLinkRequest++; +} + + +static void sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = 0x0018ul << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcid) << 16; + content |= (uint32_t) 0x08ul << 8; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */ + content = ((uint32_t) hopCount) << 24; + content |= offset & (uint32_t) 0x00fffffcul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + QueueSetContent(stack->txQueue, 3ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 4ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static void receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset) +{ + uint32_t *packet; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + *hopCount = HOP_GET(packet); + *offset = CONFIG_OFFSET_GET(packet); +} + +static void sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t data) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* REMARK: What should we do if there are no buffers available to send the packet... */ + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = (uint32_t)0x0018ul << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = (uint32_t) srcid << 16; + content |= (uint32_t) 0x28ul << 8; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* hopcount(7:0)|reserved(23:0) */ + content = (uint32_t) (hopCount << 24); + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + + /* double-word 0 */ + /* Send the data in both words since this function cannot know the offset the request was sent to. */ + content = data; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + content = data; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 4ul, content); + + /* crc(15:0)|pad(15:0) */ + content = (uint32_t)crc << 16; + QueueSetContent(stack->txQueue, 5ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 6ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static void receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *data) +{ + uint32_t *packet; + + + ASSERT((data != NULL), "Buffer is not allocated."); + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + *hopCount = HOP_GET(packet); + *data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0); +} + +static void sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset, const uint32_t data ) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = 0x0018ul << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcid) << 16; + content |= (uint32_t)0x18ul << 8; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */ + content = ((uint32_t) hopCount) << 24; + content |= offset & (uint32_t)0x00fffffcul; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + + /* double-word 0 */ + /* Note that both words are filled in to avoid looking at the offset. The receiver will not + look at the other part anyway. The standard does not say anything about the value of the padding. */ + content = data; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 3ul, content); + content = data; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 4ul, content); + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + QueueSetContent(stack->txQueue, 5ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 6ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static void receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset, uint32_t *data ) +{ + uint32_t *packet; + + + ASSERT((data != NULL), "Buffer is not allocated."); + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + *hopCount = HOP_GET(packet); + *offset = CONFIG_OFFSET_GET(packet); + *data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0); +} + +static void sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* REMARK: What should we do if there are no buffers available to send the packet... */ + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = (uint32_t)0x0018ul << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = (uint32_t) srcid << 16; + content |= (uint32_t)0x38ul << 8; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* hopcount(7:0)|reserved(23:0) */ + content = hopCount << 24; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + + /* crc(15:0)|pad(15:0) */ + content = (uint32_t)crc << 16; + QueueSetContent(stack->txQueue, 3ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 4ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static void receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount) +{ + uint32_t *packet; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + *hopCount = HOP_GET(packet); +} + +/* REMARK: Use a packet pointer instead of using the QueueSetContent... */ +static void sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer, + const uint8_t ack) +{ + uint32_t content; + uint32_t size; + uint16_t wrsize = wrsizeGet(address, bufferSize); + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + ASSERT((wrsize != 0xffff), "Write access unsupported by protocol."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = ((uint32_t)0x0015ul) << 16; + content |= (uint32_t)destid; + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcid) << 16; + if(ack == 0u) + { + /* Send NWRITE. */ + content |= (uint32_t) TRANSACTION_WRITE_NWRITE << 12; + } + else + { + /* Send NWRITE_R. */ + content |= (uint32_t) TRANSACTION_WRITE_NWRITER << 12; + } + content |= (uint32_t) (wrsize & 0x0f00); + content |= (uint32_t) tid; + QueueSetContent(stack->txQueue, 1ul, content); + + /* address(28:0)|wdptr|xamsbs(1:0) */ + /* wrsize also contains wdptr in the lower nibble. */ + /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the + 34-bit address should be used, another mechanism to set it should be used. */ + content = (address & 0xfffffff8ul); + content |= ((uint32_t) (wrsize & 0x000f)) << 2; + QueueSetContent(stack->txQueue, 2ul, content); + + /* Place data buffer into the payload of the packet. */ + size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 12, address & 0x7, bufferSize, buffer); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, size+1); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static uint16_t receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, const uint16_t dataLength, uint8_t *data ) +{ + uint32_t *packet; + uint8_t offset; + uint16_t size; + uint8_t wrsize; + uint8_t wdptr; + + + ASSERT((data != NULL), "Buffer is not allocated."); + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + wrsize = WRSIZE_GET(packet); + wdptr = WDPTR_GET(packet); + wrsizeToOffset(wrsize, wdptr, &offset, &size); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + *address = ADDRESS_GET(packet) | offset; + + if(size > 16) + { + /* Remove header and crc from the size count. */ + size = ((QueueGetFrontSize(stack->rxQueue)-4) * 4); + } + + /* Check if there is enough room in the receiving buffer. */ + if(size <= dataLength) + { + return getPacketPayload(packet, 12, offset, size, data); + } + else + { + return 0; + } +} + +static void sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength) +{ + uint32_t content; + uint16_t crc = 0xffffu; + uint16_t rdsize = rdsizeGet(address, dataLength); + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + ASSERT((rdsize != 0xffff), "Read access unsupported by protocol."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = ((uint32_t) 0x0012ul) << 16; + content |= (uint32_t) destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcid) << 16; + content |= ((uint32_t) TRANSACTION_REQUEST_NREAD) << 12; + content |= (uint32_t) (rdsize & 0x0f00); + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* address(28:0)|wdptr|xamsbs(1:0) */ + /* rdsize also contains wdptr in the lower nibble. */ + /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the + 34-bit address should be used, another mechanism to set it should be used. */ + content = address & 0xfffffff8ul; + content |= ((uint32_t) (rdsize & 0x000f)) << 2; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 2ul, content); + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + QueueSetContent(stack->txQueue, 3ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 4ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static void receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, uint16_t *dataLength) +{ + uint32_t *packet; + uint8_t offset; + uint16_t size; + uint8_t rdsize; + uint8_t wdptr; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + rdsize = WRSIZE_GET(packet); + wdptr = WDPTR_GET(packet); + rdsizeToOffset(rdsize, wdptr, &offset, &size); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + *address = ADDRESS_GET(packet) | offset; + *dataLength = size; +} + +static void sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer) +{ + uint32_t content; + uint32_t size; + + + ASSERT((buffer != NULL), "Buffer is not allocated."); + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = 0x001dul << 16; + content |= (uint32_t) destid; + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */ + content = ((uint32_t) srcid) << 16; + content |= ((uint32_t) TRANSACTION_RESPONSE_WITH_PAYLOAD) << 12; + content |= (uint32_t) tid; + QueueSetContent(stack->txQueue, 1ul, content); + + /* Place data buffer into the payload of the packet. */ + size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, address & 0x7, bufferSize, buffer); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, size+1); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + + +static uint16_t receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + const uint32_t address, const uint16_t dataLength, uint8_t *data ) +{ + uint32_t *packet; + + + ASSERT((data != NULL), "Buffer is not allocated."); + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + + return getPacketPayload(packet, 8, address & 0x7, dataLength, data); +} + + +static void sendResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t status) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = (uint32_t)0x001dul << 16; + content |= destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */ + content = (uint32_t)srcid << 16; + content |= ((uint32_t)status & (uint32_t)0x0ful) << 8; + content |= tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* crc(15:0)|pad(15:0) */ + content = (uint32_t)crc << 16; + QueueSetContent(stack->txQueue, 2ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 3ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + + +static void receiveResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid) +{ + uint32_t *packet; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); +} + + +static void sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint16_t info ) +{ + uint32_t content; + uint16_t crc; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = 0x001aul << 16; + content |= (uint32_t) destid; + crc = Crc32(content, 0xffffu); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */ + content = ((uint32_t) srcid) << 16; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */ + content = ((uint32_t) info) << 16; + crc = Crc16(info, crc); + content |= crc; + QueueSetContent(stack->txQueue, 2ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 3ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + + +static void receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint16_t *info) +{ + uint32_t *packet; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *tid = TID_GET(packet); + *info = INFO_GET(packet); +} + + +static void sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, + const uint16_t bufferSize, const uint8_t* bufferData) +{ + uint32_t content; + uint32_t size; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + ASSERT((bufferSize <= 256), "Packet sizes larger than 256 are currently unsupported."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = ((uint32_t) 0x001bul) << 16; + content |= (uint32_t) destid; + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */ + content = ((uint32_t) srcid) << 16; + if(bufferSize <= 8u) + { + content |= ((uint32_t) 0x09ul) << 8; + } + else if(bufferSize <= 16u) + { + content |= ((uint32_t) 0x0aul) << 8; + } + else if(bufferSize <= 32u) + { + content |= ((uint32_t) 0x0bul) << 8; + } + else if(bufferSize <= 64u) + { + content |= ((uint32_t) 0x0cul) << 8; + } + else if(bufferSize <= 128u) + { + content |= ((uint32_t) 0x0dul) << 8; + } + else + { + content |= ((uint32_t) 0x0eul) << 8; + } + content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4; + content |= ((uint32_t)mailbox) >> 4; + QueueSetContent(stack->txQueue, 1ul, content); + + /* Place data buffer into the payload of the packet. */ + size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, 0, bufferSize, bufferData); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, size+1); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static uint16_t receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox, + const uint16_t dataLength, uint8_t *data ) +{ + uint32_t *packet; + uint32_t size; + + + ASSERT((data != NULL), "Buffer is not allocated."); + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + /* Get a pointer to the packet. */ + packet = QueueGetFrontBuffer(stack->rxQueue); + + /* The higher mailbox numbers are used with messages that cannot be multi-packets. */ + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *mailbox = XMBOX_GET(packet); + *mailbox <<= 2; + *mailbox |= LETTER_GET(packet); + *mailbox <<= 2; + *mailbox |= MBOX_GET(packet); + + /* Calculate the number of bytes to transfer. */ + /* Remove the header and crc from the size count. */ + size = (QueueGetFrontSize(stack->rxQueue)-3) * 4; + + /* Check if there is enough room in the receiving buffer. */ + if(size <= dataLength) + { + return getPacketPayload(packet, 8, 0, size, data); + } + else + { + return 0; + } + +} + +static void sendMessageResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, + const uint8_t status) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow."); + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = (uint32_t)0x001dul << 16; + content |= destid; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 0ul, content); + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|letter(1:0|mbox(1:0)|msgseg(3:0) */ + content = (uint32_t)srcid << 16; + content |= (uint32_t)0x1ul << 12; + content |= ((uint32_t)status & (uint32_t)0xful) << 8; + content |= ((uint32_t)mailbox & (uint32_t)0xful) << 4; + content |= ((uint32_t)mailbox) >> 4; + crc = Crc32(content, crc); + QueueSetContent(stack->txQueue, 1ul, content); + + /* crc(15:0)|pad(15:0) */ + content = (uint32_t)crc << 16; + QueueSetContent(stack->txQueue, 2ul, content); + + /* Set the size of the packet and place it in the queue. */ + QueueSetSize(stack->txQueue, 3ul); + stack->txQueue = QueueEnqueue(stack->txQueue); +} + +static void receiveMessageResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox) +{ + uint32_t *packet; + + + ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue."); + + packet = QueueGetFrontBuffer(stack->rxQueue); + + *destid = DESTID_GET(packet); + *srcid = SRCID_GET(packet); + *mailbox = XMBOX_GET(packet); + *mailbox <<= 2; + *mailbox |= LETTER_GET(packet); + *mailbox <<= 2; + *mailbox |= MBOX_GET(packet); +} + + +static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, + const uint16_t dataSize, uint8_t *data) +{ + uint32_t content = 0; + uint16_t packetIndex; + uint16_t payloadIndex; + uint16_t dataIndex; + + + /* Move bytes from inbound packet queue into the user buffer. */ + /* Long packets contain a CRC in byte 80-81, this is removed when the buffer + is copied. */ + packetIndex = payloadOffset; + payloadIndex = 0; + dataIndex = 0; + while(dataIndex < dataSize) + { + /* Check if a new word should be read from the inbound queue. */ + if((packetIndex & 0x3) == 0) + { + /* Get a new word. */ + content = packet[packetIndex>>2]; + } + else + { + /* Update the current word. Remove the MSB, it has already be moved + to the user buffer. */ + content <<= 8; + } + + /* Check if the current byte is CRC. */ + if((packetIndex != 80) && (packetIndex != 81) && (payloadIndex >= dataOffset)) + { + /* Not CRC. */ + /* Move the byte to the user buffer. */ + data[dataIndex++] = (content >> 24); + } + + /* Increment to the next position in the packet. */ + packetIndex++; + payloadIndex++; + } + + return dataIndex; +} + + +static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, + const uint16_t dataSize, const uint8_t *data) +{ + uint16_t crc = 0xffffu; + uint32_t content = 0; + uint16_t packetIndex; + uint16_t payloadIndex; + uint16_t dataIndex; + + + /*************************************************** + * Calculate the CRC for the packet header. + ***************************************************/ + for(packetIndex = 0; packetIndex < payloadOffset; packetIndex+=4) + { + crc = Crc32(packet[packetIndex>>2], crc); + } + + /*************************************************** + * Pad the data before the actual data is written. + ***************************************************/ + payloadIndex = 0; + while(payloadIndex < dataOffset) + { + content <<= 8; + + if((packetIndex & 0x3) == 3) + { + crc = Crc32(content, crc); + packet[packetIndex>>2] = content; + } + + payloadIndex++; + packetIndex++; + } + + /*************************************************** + * Write content and any embedded CRC. + ***************************************************/ + dataIndex = 0; + while(dataIndex < dataSize) + { + content <<= 8; + + /* Check if CRC or content should be entered into the packet. */ + if(packetIndex == 80) + { + /* CRC MSB. */ + content |= crc >> 8; + } + else if(packetIndex == 81) + { + /* CRC LSB. */ + content |= crc & 0xff; + } + else + { + /* Data content. */ + content |= data[dataIndex++]; + payloadIndex++; + } + + if((packetIndex & 0x3) == 3) + { + crc = Crc32(content, crc); + packet[packetIndex>>2] = content; + } + + packetIndex++; + } + + /*************************************************** + * Pad the data to an even double word. + ***************************************************/ + while((payloadIndex & 0x7) != 0) + { + content <<= 8; + + if((packetIndex & 0x3) == 3) + { + crc = Crc32(content, crc); + packet[packetIndex>>2] = content; + } + + packetIndex++; + payloadIndex++; + } + + /*************************************************** + * Write the CRC into the packet. + ***************************************************/ + if((packetIndex & 0x3) == 0) + { + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + } + else + { + /* double-wordN-LSB|crc(15:0) */ + content &= 0x0000ffff; + crc = Crc16(content, crc); + content <<= 16; + content |= crc; + } + packet[packetIndex>>2] = content; + + return (packetIndex>>2); +} + + +/* \note See the RapidIO standard part1 table 4-4 for details about + * {address, size}->{wdptr, wrsize} mapping. + */ +static uint16_t rdsizeGet(const uint32_t address, const uint16_t size) +{ + uint8_t wdptr; + uint8_t rdsize; + + + switch(size/8) + { + case 0: + /************************************************************** + * Sub double-word access. + **************************************************************/ + /* REMARK: The same code as in wrsizeGet for sub + double-word... use it instead??? */ + switch(size%8) + { + case 0: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 1: + /* Reading one byte. */ + /* Any address is allowed. */ + wdptr = (address >> 2) & 0x1; + rdsize = address & 0x3; + break; + case 2: + /* Reading two bytes. */ + /* Address 0, 2, 4, 6 are valid. */ + if((address & 0x1) == 0) + { + wdptr = (address >> 2) & 0x1; + rdsize = (address & 0x7) | 0x4; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 3: + /* Reading 3 bytes. */ + /* Address 0 and 5 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 5)) + { + wdptr = (address >> 2) & 0x1; + rdsize = 0x5ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 4: + /* Reading 4 bytes. */ + /* Address 0 and 4 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 4)) + { + wdptr = (address >> 2) & 0x1; + rdsize = 0x8ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 5: + /* Reading 5 bytes. */ + /* Address 0 and 3 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 3)) + { + wdptr = (address >> 1) & 0x1; + rdsize = 0x7ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 6: + /* Reading 6 bytes. */ + /* Addresses 0 and 2 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 2)) + { + wdptr = (address >> 1) & 0x1; + rdsize = 0x9ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + default: + /* Reading 7 bytes. */ + /* Addresses 0 and 1 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 1)) + { + wdptr = address & 0x1; + rdsize = 0xaul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + } + break; + case 1: + /* Reading 8 bytes. */ + /* Only even double-word address are valid. */ + if((address % 8) == 0) + { + wdptr = 0; + rdsize = 0xbul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 2: + /* Reading 16 bytes max. */ + /* Only even double-word address are valid. */ + if((address % 8) == 0) + { + wdptr = 1; + rdsize = 0xbul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 3: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 4: + /* Reading 32 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 0; + rdsize = 0xcul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 5: + case 6: + case 7: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 8: + /* Reading 64 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 1; + rdsize = 0xcul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 9: + case 10: + case 11: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 12: + /* Reading 96 bytes. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 0; + rdsize = 0xdul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 13: + case 14: + case 15: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 16: + /* Reading 128 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 1; + rdsize = 0xdul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 17: + case 18: + case 19: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 20: + /* Reading 160 bytes. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 0; + rdsize = 0xeul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 21: + case 22: + case 23: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 24: + /* Reading 192 bytes. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 1; + rdsize = 0xeul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 25: + case 26: + case 27: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 28: + /* Reading 224 bytes. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 0; + rdsize = 0xful; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + case 29: + case 30: + case 31: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + case 32: + /* Reading 256 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 1; + rdsize = 0xful; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + } + break; + default: + /* Not supported by protocol. */ + wdptr = 0xff; + rdsize = 0xff; + break; + } + + return ((((uint16_t) rdsize) << 8) | ((uint16_t) wdptr)); +} + + +void rdsizeToOffset(uint8_t rdsize, uint8_t wdptr, uint8_t *offset, uint16_t *size) +{ + switch(rdsize) + { + case 0: + case 1: + case 2: + case 3: + *offset = wdptr << 2; + *offset |= rdsize; + *size = 1; + break; + case 4: + case 6: + *offset = wdptr << 2; + *offset |= rdsize & 0x02; + *size = 2; + break; + case 5: + *offset = wdptr * 5; + *size = 3; + break; + case 8: + *offset = wdptr * 4; + *size = 4; + break; + case 7: + *offset = wdptr * 3; + *size = 5; + break; + case 9: + *offset = wdptr * 2; + *size = 6; + break; + case 10: + *offset = wdptr * 1; + *size = 7; + break; + case 11: + *offset = 0; + *size = 8 + 8*wdptr; + break; + case 12: + *offset = 0; + *size = 32 + 32*wdptr; + break; + case 13: + *offset = 0; + *size = 96 + 32*wdptr; + break; + case 14: + *offset = 0; + *size = 160 + 32*wdptr; + break; + case 15: + *offset = 0; + *size = 224 + 32*wdptr; + break; + } +} + + +static uint16_t wrsizeGet(const uint32_t address, const uint16_t size) +{ + uint8_t wdptr; + uint8_t wrsize; + + + switch(size/8) + { + case 0: + /************************************************************** + * Sub double-word access. + **************************************************************/ + switch(size%8) + { + case 0: + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + break; + case 1: + /* Writing one byte. */ + /* Any address is allowed. */ + wdptr = (address >> 2) & 0x1; + wrsize = address & 0x3; + break; + case 2: + /* Writing two bytes. */ + /* Address 0, 2, 4, 6 are valid. */ + if((address & 0x1) == 0) + { + wdptr = (address >> 2) & 0x1; + wrsize = (address & 0x7) | 0x4; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 3: + /* Writing 3 bytes. */ + /* Address 0 and 5 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 5)) + { + wdptr = (address >> 2) & 0x1; + wrsize = 0x5ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 4: + /* Writing 4 bytes. */ + /* Address 0 and 4 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 4)) + { + wdptr = (address >> 2) & 0x1; + wrsize = 0x8ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 5: + /* Writing 5 bytes. */ + /* Address 0 and 3 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 3)) + { + wdptr = (address >> 1) & 0x1; + wrsize = 0x7ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 6: + /* Writing 6 bytes. */ + /* Addresses 0 and 2 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 2)) + { + wdptr = (address >> 1) & 0x1; + wrsize = 0x9ul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + default: + /* Writing 7 bytes. */ + /* Addresses 0 and 1 are valid. */ + if(((address & 0x7) == 0) || + ((address & 0x7) == 1)) + { + wdptr = address & 0x1; + wrsize = 0xaul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + } + break; + case 1: + /* Writing 8 bytes. */ + /* Only even double-word address are valid. */ + if((address % 8) == 0) + { + wdptr = 0; + wrsize = 0xbul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 2: + /* Writing 16 bytes max. */ + /* Only even double-word address are valid. */ + if((address % 8) == 0) + { + wdptr = 1; + wrsize = 0xbul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 3: + case 4: + /* Writing 32 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 0; + wrsize = 0xcul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 5: + case 6: + case 7: + case 8: + /* Writing 64 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 1; + wrsize = 0xcul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + /* Writing 128 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 1; + wrsize = 0xdul; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + /* Writing 256 bytes max. */ + /* Only even double-word address are valid. */ + if((address & 0x7) == 0) + { + wdptr = 1; + wrsize = 0xful; + } + else + { + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + } + break; + default: + /* Not supported by protocol. */ + wdptr = 0xff; + wrsize = 0xff; + break; + } + + return ((((uint16_t) wrsize) << 8) | ((uint16_t) wdptr)); +} + + +void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size) +{ + switch(wrsize) + { + case 0: + case 1: + case 2: + case 3: + *offset = wdptr << 2; + *offset |= wrsize; + *size = 1; + break; + case 4: + case 6: + *offset = wdptr << 2; + *offset |= wrsize & 0x02; + *size = 2; + break; + case 5: + *offset = wdptr * 5; + *size = 3; + break; + case 8: + *offset = wdptr * 4; + *size = 4; + break; + case 7: + *offset = wdptr * 3; + *size = 5; + break; + case 9: + *offset = wdptr * 2; + *size = 6; + break; + case 10: + *offset = wdptr * 1; + *size = 7; + break; + case 11: + *offset = 0; + *size = 8 + 8*wdptr; + break; + case 12: + *offset = 0; + *size = 32 + 32*wdptr; + break; + case 13: + *offset = 0; + *size = 128*wdptr; + break; + case 14: + *offset = 0; + *size = 0; + break; + case 15: + *offset = 0; + *size = 256*wdptr; + break; + } +} + + +static RioSymbol CreateControlSymbol( const uint8_t stype0, + const uint8_t parameter0, const uint8_t parameter1, + const uint8_t stype1, const uint8_t cmd) +{ + RioSymbol s; + + s.type = RIO_SYMBOL_TYPE_CONTROL; + + s.data = ((uint32_t)stype0 & (uint32_t)0x07ul) << 21; + s.data |= ((uint32_t)parameter0 & (uint32_t)0x1ful) << 16; + s.data |= ((uint32_t)parameter1 & (uint32_t)0x1ful) << 11; + s.data |= ((uint32_t)stype1 & (uint32_t)0x07ul) << 8; + s.data |= ((uint32_t)cmd & (uint32_t)0x7ul) << 5; + s.data |= Crc5(s.data, 0x1fu); + + return s; +} + + +static uint8_t Crc5( const uint32_t data, const uint8_t crc) +{ + static const uint8_t crcTable[] = { + 0x00u, 0x15u, 0x1fu, 0x0au, 0x0bu, 0x1eu, 0x14u, 0x01u, + 0x16u, 0x03u, 0x09u, 0x1cu, 0x1du, 0x08u, 0x02u, 0x17u, + 0x19u, 0x0cu, 0x06u, 0x13u, 0x12u, 0x07u, 0x0du, 0x18u, + 0x0fu, 0x1au, 0x10u, 0x05u, 0x04u, 0x11u, 0x1bu, 0x0eu + }; + + uint8_t result; + uint8_t index; + + result = crc; + index = (uint8_t)((data >> 19) & (uint32_t)0x1ful) ^ result; + result = crcTable[index]; + index = (uint8_t)((data >> 14) & (uint32_t)0x1ful) ^ result; + result = crcTable[index]; + index = (uint8_t)((data >> 9) & (uint32_t)0x1ful) ^ result; + result = crcTable[index]; + index = (uint8_t)((data >> 4) & (uint32_t)0x1eul) ^ result; + result = crcTable[index]; + + return result; +} + + +static uint16_t Crc16( const uint16_t data, const uint16_t crc) +{ + static const uint16_t crcTable[] = { + 0x0000u, 0x1021u, 0x2042u, 0x3063u, 0x4084u, 0x50a5u, 0x60c6u, 0x70e7u, + 0x8108u, 0x9129u, 0xa14au, 0xb16bu, 0xc18cu, 0xd1adu, 0xe1ceu, 0xf1efu, + 0x1231u, 0x0210u, 0x3273u, 0x2252u, 0x52b5u, 0x4294u, 0x72f7u, 0x62d6u, + 0x9339u, 0x8318u, 0xb37bu, 0xa35au, 0xd3bdu, 0xc39cu, 0xf3ffu, 0xe3deu, + 0x2462u, 0x3443u, 0x0420u, 0x1401u, 0x64e6u, 0x74c7u, 0x44a4u, 0x5485u, + 0xa56au, 0xb54bu, 0x8528u, 0x9509u, 0xe5eeu, 0xf5cfu, 0xc5acu, 0xd58du, + 0x3653u, 0x2672u, 0x1611u, 0x0630u, 0x76d7u, 0x66f6u, 0x5695u, 0x46b4u, + 0xb75bu, 0xa77au, 0x9719u, 0x8738u, 0xf7dfu, 0xe7feu, 0xd79du, 0xc7bcu, + 0x48c4u, 0x58e5u, 0x6886u, 0x78a7u, 0x0840u, 0x1861u, 0x2802u, 0x3823u, + 0xc9ccu, 0xd9edu, 0xe98eu, 0xf9afu, 0x8948u, 0x9969u, 0xa90au, 0xb92bu, + 0x5af5u, 0x4ad4u, 0x7ab7u, 0x6a96u, 0x1a71u, 0x0a50u, 0x3a33u, 0x2a12u, + 0xdbfdu, 0xcbdcu, 0xfbbfu, 0xeb9eu, 0x9b79u, 0x8b58u, 0xbb3bu, 0xab1au, + 0x6ca6u, 0x7c87u, 0x4ce4u, 0x5cc5u, 0x2c22u, 0x3c03u, 0x0c60u, 0x1c41u, + 0xedaeu, 0xfd8fu, 0xcdecu, 0xddcdu, 0xad2au, 0xbd0bu, 0x8d68u, 0x9d49u, + 0x7e97u, 0x6eb6u, 0x5ed5u, 0x4ef4u, 0x3e13u, 0x2e32u, 0x1e51u, 0x0e70u, + 0xff9fu, 0xefbeu, 0xdfddu, 0xcffcu, 0xbf1bu, 0xaf3au, 0x9f59u, 0x8f78u, + 0x9188u, 0x81a9u, 0xb1cau, 0xa1ebu, 0xd10cu, 0xc12du, 0xf14eu, 0xe16fu, + 0x1080u, 0x00a1u, 0x30c2u, 0x20e3u, 0x5004u, 0x4025u, 0x7046u, 0x6067u, + 0x83b9u, 0x9398u, 0xa3fbu, 0xb3dau, 0xc33du, 0xd31cu, 0xe37fu, 0xf35eu, + 0x02b1u, 0x1290u, 0x22f3u, 0x32d2u, 0x4235u, 0x5214u, 0x6277u, 0x7256u, + 0xb5eau, 0xa5cbu, 0x95a8u, 0x8589u, 0xf56eu, 0xe54fu, 0xd52cu, 0xc50du, + 0x34e2u, 0x24c3u, 0x14a0u, 0x0481u, 0x7466u, 0x6447u, 0x5424u, 0x4405u, + 0xa7dbu, 0xb7fau, 0x8799u, 0x97b8u, 0xe75fu, 0xf77eu, 0xc71du, 0xd73cu, + 0x26d3u, 0x36f2u, 0x0691u, 0x16b0u, 0x6657u, 0x7676u, 0x4615u, 0x5634u, + 0xd94cu, 0xc96du, 0xf90eu, 0xe92fu, 0x99c8u, 0x89e9u, 0xb98au, 0xa9abu, + 0x5844u, 0x4865u, 0x7806u, 0x6827u, 0x18c0u, 0x08e1u, 0x3882u, 0x28a3u, + 0xcb7du, 0xdb5cu, 0xeb3fu, 0xfb1eu, 0x8bf9u, 0x9bd8u, 0xabbbu, 0xbb9au, + 0x4a75u, 0x5a54u, 0x6a37u, 0x7a16u, 0x0af1u, 0x1ad0u, 0x2ab3u, 0x3a92u, + 0xfd2eu, 0xed0fu, 0xdd6cu, 0xcd4du, 0xbdaau, 0xad8bu, 0x9de8u, 0x8dc9u, + 0x7c26u, 0x6c07u, 0x5c64u, 0x4c45u, 0x3ca2u, 0x2c83u, 0x1ce0u, 0x0cc1u, + 0xef1fu, 0xff3eu, 0xcf5du, 0xdf7cu, 0xaf9bu, 0xbfbau, 0x8fd9u, 0x9ff8u, + 0x6e17u, 0x7e36u, 0x4e55u, 0x5e74u, 0x2e93u, 0x3eb2u, 0x0ed1u, 0x1ef0u + }; + + uint16_t result; + uint8_t index; + + result = crc; + index = (uint8_t) ((data >> 8) ^ (result >> 8)); + result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8)); + index = (uint8_t) ((data) ^ (result >> 8)); + result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8)); + + return result; +} + + +static uint16_t Crc32( const uint32_t data, uint16_t crc) +{ + crc = Crc16((uint16_t) (data >> 16), crc); + crc = Crc16((uint16_t) (data), crc); + return crc; +} + + + + + +static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer) +{ + Queue_t q; + + q.size = size; + q.available = size; + q.windowSize = 0u; + q.windowIndex = 0u; + q.frontIndex = 0u; + q.backIndex = 0u; + q.buffer_p = buffer; + + return q; +} + + +static uint8_t QueueAvailable( const Queue_t q) +{ + return q.available; +} + + +static bool_t QueueEmpty( const Queue_t q) +{ + return (bool_t) (q.available == q.size); +} + + +static uint8_t QueueLength( const Queue_t q) +{ + return q.size - q.available; +} + + +static Queue_t QueueEnqueue( Queue_t q) +{ + q.backIndex++; + if(q.backIndex == q.size) + { + q.backIndex = 0; + } + q.available--; + return q; +} + + +static Queue_t QueueDequeue( Queue_t q) +{ + q.frontIndex++; + if(q.frontIndex == q.size) + { + q.frontIndex = 0; + } + q.available++; + if(q.windowSize == 0) + { + q.windowIndex = q.frontIndex; + } + else + { + q.windowSize--; + } + return q; +} + + +static bool_t QueueWindowEmpty( const Queue_t q) +{ + return (bool_t) ((q.available + q.windowSize) == q.size); +} + + +static Queue_t QueueWindowReset(Queue_t q) +{ + q.windowIndex = q.frontIndex; + q.windowSize = 0; + return q; +} + + +static Queue_t QueueWindowNext(Queue_t q) +{ + q.windowIndex++; + if(q.windowIndex == q.size) + { + q.windowIndex = 0; + } + q.windowSize++; + return q; +} + + +static void QueueSetSize( Queue_t q, const uint32_t size) +{ + (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0] = size; +} + + +static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content) +{ + (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[index+1ul] = content; +} + + +static uint32_t QueueGetFrontSize( Queue_t q) +{ + return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[0]; +} + + +static uint32_t QueueGetFrontContent( const Queue_t q, const uint32_t index) +{ + return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[index+1ul]; +} + + +static uint32_t *QueueGetFrontBuffer( const Queue_t q ) +{ + return &((q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[1]); +} + + +static uint32_t QueueGetBackSize( const Queue_t q) +{ + return (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0]; +} + + +static uint32_t *QueueGetBackBuffer( const Queue_t q ) +{ + return &((q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[1]); +} + + +#ifdef MODULE_TEST +#include +#define PrintS(s) \ + { \ + FILE *fd; \ + fd=fopen("testspec.txt", "a"); \ + fputs(s "\n", fd); \ + fclose(fd); \ + } + +#define TESTSTART(s) printf(s) +#define TESTEND printf(" passed.\n"); + +#define TESTCOND(got) \ + if (!(got)) \ + { \ + printf("ERROR at line %u:%s=%u (0x%08x)\n", \ + __LINE__, #got, (got), (got)); \ + exit(1); \ + } + +#define TESTEXPR(got, expected) \ + if ((got)!=(expected)) \ + { \ + printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", \ + __LINE__, #got, (got), (got), (expected), (expected)); \ + exit(1); \ + } + +#define TESTSYMBOL(got, expected) testSymbol(__LINE__, #got, (got), (expected)) + +void testSymbol(uint32_t line, char *expression, RioSymbol got, RioSymbol expected) +{ + if ((got).type==(expected).type) + { + switch ((got).type) + { + case RIO_SYMBOL_TYPE_ERROR: + case RIO_SYMBOL_TYPE_IDLE: + break; + case RIO_SYMBOL_TYPE_CONTROL: + if((got).data != (expected).data) + { + if(STYPE0_GET((got).data) != STYPE0_GET((expected).data)) + { + printf("ERROR at line %u:STYPE0=0x%02x expected=0x%02x\n", + line, STYPE0_GET((got).data), STYPE0_GET((expected).data)); + } + if(PARAMETER0_GET((got).data) != PARAMETER0_GET((expected).data)) + { + printf("ERROR at line %u:PARAMETER0=0x%02x expected=0x%02x\n", + line, PARAMETER0_GET((got).data), PARAMETER0_GET((expected).data)); + } + if(PARAMETER1_GET((got).data) != PARAMETER1_GET((expected).data)) + { + printf("ERROR at line %u:PARAMETER1=0x%02x expected=0x%02x\n", + line, PARAMETER1_GET((got).data), PARAMETER1_GET((expected).data)); + } + if(STYPE1_GET((got).data) != STYPE1_GET((expected).data)) + { + printf("ERROR at line %u:STYPE1=0x%02x expected=0x%02x\n", + line, STYPE1_GET((got).data), STYPE1_GET((expected).data)); + } + if(CMD_GET((got).data) != CMD_GET((expected).data)) + { + printf("ERROR at line %u:CMD=0x%02x expected=0x%02x\n", + line, CMD_GET((got).data), CMD_GET((expected).data)); + } + if(CRC5_GET((got).data) != CRC5_GET((expected).data)) + { + printf("ERROR at line %u:CRC5=0x%02x expected=0x%02x\n", + line, CRC5_GET((got).data), CRC5_GET((expected).data)); + } + exit(1); + } + break; + case RIO_SYMBOL_TYPE_DATA: + if((got).data != (expected).data) + { + printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", + line, expression, (got).data, (got).data, (expected).data, (expected).data); + exit(1); + } + break; + } + } + else + { + printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", + line, expression, (got).type, (got).type, (expected).type, (expected).type); + exit(1); + } +} + + + +uint32_t testConfigWriteData; + +uint8_t createDoorbell(uint32_t *doorbell, uint8_t ackId, uint16_t destid, uint16_t srcId, uint8_t tid, uint16_t info) +{ + uint16_t crc; + uint32_t content; + + /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */ + /* ackId is set when the packet is transmitted. */ + content = 0x001aul << 16; + content |= (uint32_t) destid; + crc = Crc32(content, 0xffffu); + doorbell[0] = (((uint32_t) ackId) << 27) | content; + + /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= (uint32_t) tid; + crc = Crc32(content, crc); + doorbell[1] = content; + + /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */ + content = ((uint32_t) info) << 16; + crc = Crc16(info, crc); + content |= ((uint32_t) crc); + doorbell[2] = content; + + return 3; + +} + +uint32_t testConfigRead(RioStack_t *stack, uint32_t offset) +{ + switch(offset) + { + case 0: + return 0x80000006; + case 4: + return 0x00a100a2; + case 8: + return testConfigWriteData; + default: + return 0x00000000; + } +} + +void testConfigWrite(RioStack_t *stack, uint32_t offset, uint32_t data) +{ + switch(offset) + { + case 8: + testConfigWriteData = data; + break; + default: + /* Dont do anything. */ + break; + } +} + +/******************************************************************************* + * Module test for this file. + *******************************************************************************/ +int32_t main(void) +{ + RioStack_t stack; + RioStackObserver_t observer; + uint32_t rxPacketBuffer[RIO_BUFFER_SIZE*8], txPacketBuffer[RIO_BUFFER_SIZE*8]; + RioSymbol s, c, d; + int i, j, k; + uint16_t length; + uint16_t srcid; + uint8_t tid; + uint8_t hop; + uint8_t mailbox; + uint16_t info; + uint32_t address; + uint32_t data; + uint8_t payload8[256]; + uint8_t payload8Expected[256]; + uint32_t packet[69]; + uint32_t packetLength; + + + /************************************************************************* + * Test prelude. + * Setup the RIO stack for operation. + *************************************************************************/ + + /* Setup callback handlers for config-space accesses in the implementation- + defined address range. */ + observer.configRead = testConfigRead; + observer.configWrite = testConfigWrite; + + /* Open the stack and set the port status to initialized. */ + RIO_open(&stack, &observer, NULL, + RIO_BUFFER_SIZE*8, &rxPacketBuffer[0], + RIO_BUFFER_SIZE*8, &txPacketBuffer[0], + 0xb03b, 0x0000, 0x00000000, 0x0000, 0x0000, 0x0000, 0xffff); + + /* Set the port timeout. */ + RIO_portSetTimeout(&stack, 1); + + /* Set the current port time. */ + RIO_portSetTime(&stack, 0); + + /* Set master enable. */ + RIO_writeConfig(&stack, + PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET), 0x40000000); + + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack"); + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC1"); + PrintS("Description: Test link initialization and normal packet exchange."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send packets when port is uninitialized."); + PrintS("Result: All packets should be ignored during initialization."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step1"); + /******************************************************************************/ + + /* Place a packet in the outbound queue to check that it is received once + the transmitter is placed in the correct state. */ + RIO_sendDoorbell(&stack, 1, 0, 0xdeaf); + + /* Check that only idle symbols are transmitted when the port has not been + initialied even if statuses are received. */ + for(i = 0; i < 1024; i++) + { + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0)); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + + /******************************************************************************/ + TESTEND; + /*****************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Set port initialized and get symbols from the stack."); + PrintS("Result: Status-control-symbols should be generated each 256 symbol."); + PrintS("----------------------------------------------------------------------"); + /*****************************************************************************/ + TESTSTART("TG_riostack-TC1-Step2"); + /*****************************************************************************/ + + /* Set the port status to intialized. */ + RIO_portSetStatus(&stack, 1); + + /* Set port time. */ + RIO_portSetTime(&stack, 1); + + /* Check that status-control-symbols are transmitted once every 256 symbol. */ + for(j = 0; j < 15; j++) + { + for(i = 0; i < 255; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Add a status-control-symbol to the receiver."); + PrintS("Result: Status-control-symbols should be generated each 15 symbol."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step3"); + /*****************************************************************************/ + + /* Insert a status-control-symbol in the receive. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0)); + + /* Check that status-control-symbols are transmitted once every 16 symbol. */ + for(i = 0; i < 15; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Add a packet to the receiver."); + PrintS("Result: Packet should be ignored until the link is initialized."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step4"); + /*****************************************************************************/ + + /* Send a packet. Note that the start and end of the packet contains a status. */ + packetLength = createDoorbell(packet, 0, 0, 0, 0, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0)); + + /* Check that packet was not received. */ + TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_NONE); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Add four more status-control-symbols followed by one with error in "); + PrintS(" CRC5. Then send a packet."); + PrintS("Result: The receiver should remain in port initialized and packet should "); + PrintS(" still be ignored."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step5"); + /*****************************************************************************/ + + /* Send 4 more status-control-symbols followed by one erronous. */ + for(i = 0; i < 4; i++) + { + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0)); + } + c = CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0); + c.data ^= 1; + RIO_portAddSymbol(&stack, c); + + /* Send a packet. Note that the start and end of the packet contains status. */ + packetLength = createDoorbell(packet, 0, 0, 0, 0, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0)); + + /* Check that the packet was ignored. */ + TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_NONE); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 6:"); + PrintS("Action: Add six more status-control-symbols. Then send a packet."); + PrintS("Result: The receiver should enter link initialized and the packet should "); + PrintS(" be received."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step6"); + /*****************************************************************************/ + + /* Send 6 more status-control-symbols. */ + for(i = 0; i < 6; i++) + { + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0)); + } + + /* Send a packet and check that it is accepted. */ + /* The ackId on receiver in testobject is updated when this has been transmitted. */ + packetLength = createDoorbell(packet, 0, 0, 0, 0, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0)); + + /* Check that the packet is received. */ + TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_DOORBELL); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 7:"); + PrintS("Action: Get symbols from transmitter."); + PrintS("Result: Status-control-symbols should still be generated each 15 symbol "); + PrintS("until a total of 15 status-control-symbols has been transmitted. Once these "); + PrintS("has been transmitted, the transmitter will be link initialized."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step7"); + /*****************************************************************************/ + + /* Note that the available buffers in the receiver should have decremented once + since the previously received packet has not been read from the application + side of the stack yet. */ + for(j = 0; j < 14; j++) + { + for(i = 0; i < 15; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 8:"); + PrintS("Action: Get the first symbol from the transmitter once the link-intialized "); + PrintS(" state has been entered."); + PrintS("Result: A packet-accepted-symbol should be received for the newly received "); + PrintS(" packet."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step8"); + /*****************************************************************************/ + + c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 0, 7, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 9:"); + PrintS("Action: Get the next symbols from the transmitter."); + PrintS("Result: The packet placed in the outbound queue at startup should be "); + PrintS(" received. Dont acknowledge the packet yet."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step9"); + /*****************************************************************************/ + + /* Create a packet. */ + packetLength = createDoorbell(packet, 0, 1, 0xffff, 0, 0xdeaf); + + /* Receive the start of the frame. */ + c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Receive the data of the frame. */ + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + + /* Receive the end of the frame. */ + c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTSYMBOL(s, c); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 10:"); + PrintS("Action: Remove the packet from the inbound queue. Dont acknowledge the"); + PrintS(" transmitted packet yet."); + PrintS("Result: Check that status-control-symbols are sent each 256 symbol and that "); + PrintS(" the buffer count is updated when the inbound packet has been read."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step10"); + /*****************************************************************************/ + + /* Simulate the application reading the received packet to free one reception + buffer. */ + RIO_packetRemove(&stack); + + /* Check that the status-control-symbols are generated each 256 symbol. */ + for(i = 0; i < 255; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + + /* Check that the buffer status has been updated. */ + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 11:"); + PrintS("Action: Send a packet when an acknowledge has not been received."); + PrintS("Result: Only idle and status control symbols should be transmitted until "); + PrintS(" the packet-accepted symbol has been received."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step11"); + /*****************************************************************************/ + + /* Place a packet in the outbound queue. */ + RIO_sendDoorbell(&stack, 2, 1, 0xc0de); + + packetLength = createDoorbell(packet, 1, 2, 0xffff, 1, 0xc0de); + + /* Receive the start of the frame. */ + c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Receive the data of the frame. */ + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + + /* Receive the end of the frame. */ + c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTSYMBOL(s, c); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 12:"); + PrintS("Action: Send a packet-accepted symbol."); + PrintS("Result: Check that the new packet is transmitted."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step12"); + /*****************************************************************************/ + + /* Send acknowledge for the first frame. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 0, 1, STYPE1_NOP, 0)); + + /* Check that status-control-symbols are transmitted once every 256 symbol with + updated ackId. */ + for(i = 0; i < 255; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 13:"); + PrintS("Action: Send a packet-accepted symbol."); + PrintS("Result: Check that only idle and status-control-symbols are transmitted "); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step13"); + /*****************************************************************************/ + + /* Acknowledge the second frame. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 1, 1, STYPE1_NOP, 0)); + + /* Check that status-control-symbols are transmitted once every 256 symbol with + updated ackId. */ + for(i = 0; i < 255; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC2"); + PrintS("Description: Test flow control."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send packets to receiver but don't acknowledge them."); + PrintS("Result: The reception queue of the stack is full."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step1"); + /******************************************************************************/ + + /* Fill input queue in receiver. */ + for(j = 0; j < 8; j++) + { + packetLength = createDoorbell(packet, 1+j, 0, 0, 1+j, 0); + + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0)); + + c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 1+j, 7-j, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send a packet when the inbound queue of the stack is full."); + PrintS("Result: The stack sends a packet-retry symbol. The receiver will end up in "); + PrintS("input-retry-stopped state."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step2"); + /******************************************************************************/ + + /* Send another packet. */ + packetLength = createDoorbell(packet, 9, 0, 0, 9, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0)); + + /* Receive indication from stack that the packet must be retried. */ + c = CreateControlSymbol(STYPE0_PACKET_RETRY, 9, 0, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send a packet when the receiver is in input-retry-stopped."); + PrintS("Result: The receiver should ignore the new packet."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step3"); + /******************************************************************************/ + + /* Resend the packet. */ + packetLength = createDoorbell(packet, 9, 0, 0, 9, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0)); + s = RIO_portGetSymbol(&stack); + + /* Check that nothing is transmitted. */ + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + + /* REMARK: Send other symbols here to check that they are handled as expected... */ + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send restart-from-retry and resend the previous packet."); + PrintS("Result: The receiver should leave the input-retry-stopped state and receive "); + PrintS(" the new frame."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step4"); + /******************************************************************************/ + + /* Send restart-from-retry. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_RESTART_FROM_RETRY, 0)); + + /* Check that the transaction id is correct and remove a packet from the inbound + queue. One entry in the inbound queue will be empty. */ + RIO_receiveDoorbell(&stack, &srcid, &tid, &info); + TESTEXPR(tid, 1); + RIO_packetRemove(&stack); + + /* Check that the buffer status has changed to show that a buffer is available. */ + s = RIO_portGetSymbol(&stack); + while(s.type == RIO_SYMBOL_TYPE_IDLE) + { + s = RIO_portGetSymbol(&stack); + } + c = CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Resend the packet and check that it is received. */ + packetLength = createDoorbell(packet, 9, 0, 0, 9, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0)); + c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 0, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Place receiver in input-retry-stopped state."); + PrintS("Result: Check that packets may be transmitted normally."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step5"); + /******************************************************************************/ + + /* Send another packet and check that the receiver indicates that it should be retried. */ + packetLength = createDoorbell(packet, 10, 0, 0, 10, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0)); + c = CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 0, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send two packets to see that the first acknowledge has been processed. */ + RIO_sendDoorbell(&stack, 0, 2, 0xfeed); + RIO_sendDoorbell(&stack, 0, 3, 0xdeed); + + /* Get the first packet. */ + packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed); + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + + /* Get the second packet. */ + packetLength = createDoorbell(packet, 3, 0, 0xffff, 3, 0xdeed); + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTSYMBOL(s, c); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Indicate the packets must be retransmitted. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 2, 1, STYPE1_NOP, 0)); + + /* Receive confirmation that the packet will be retransmitted. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_RESTART_FROM_RETRY, 0); + s = RIO_portGetSymbol(&stack); + TESTSYMBOL(s, c); + + /* Get the retransmission of the first packet. */ + packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed); + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + + /* Get the retransmission of the second packet. */ + packetLength = createDoorbell(packet, 3, 0, 0xffff, 3, 0xdeed); + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTSYMBOL(s, c); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Confirm the reception of the packets. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 2, 1, STYPE1_NOP, 0)); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 3, 1, STYPE1_NOP, 0)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 6:"); + PrintS("Action: Send status-control-symbol to show that no packets can be "); + PrintS(" transmitted."); + PrintS("Result: No packets should be transmitted."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step6"); + /******************************************************************************/ + + /* Send status with bufferStatus set to zero. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 0, STYPE1_NOP, 0)); + + /* Send a packet. */ + RIO_sendDoorbell(&stack, 0, 4, 0xf00d); + + /* Check that nothing is transmitted but status-control-symbols. */ + for(i = 0; i < 255; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 7:"); + PrintS("Action: Indicate free buffers and receive a frame, then request it to be "); + PrintS("retried."); + PrintS("Result: The packet should be retransmitted."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step7"); + /******************************************************************************/ + + /* Send status with bufferStatus set to available. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 1, STYPE1_NOP, 0)); + + /* Get the packet but request it to be retried. */ + packetLength = createDoorbell(packet, 4, 0, 0xffff, 4, 0xf00d); + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 4, 1, STYPE1_NOP, 0)); + + /* Check the acknowledge of the retransmission. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_RESTART_FROM_RETRY, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Get the packet and acknowledge it. */ + packetLength = createDoorbell(packet, 4, 0, 0xffff, 4, 0xf00d); + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 4, 1, STYPE1_NOP, 0)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 8:"); + PrintS("Action: Read all inbound packets from the reception queue."); + PrintS("Result: The buffer status should be updated."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step8"); + /******************************************************************************/ + + for(j = 0; j < 8; j++) + { + RIO_receiveDoorbell(&stack, &srcid, &tid, &info); + TESTEXPR(tid, j+2); + RIO_packetRemove(&stack); + + for(i = 0; i < 255; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + s = RIO_portGetSymbol(&stack); + c = CreateControlSymbol(STYPE0_STATUS, 10, j+1, STYPE1_NOP, 0); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 9:"); + PrintS("Action: Send a restart-from-retry to make the receiver leave the "); + PrintS(" input-retry-stopped state."); + PrintS("Result: New packets should be received again."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step9"); + /******************************************************************************/ + + /* Send restart-from-retry. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_RESTART_FROM_RETRY, 0)); + + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC3"); + PrintS("Description: Test receiver error handling."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send invalid ack id in packet."); + PrintS("Result: Input-error-stopped state should be entered and link-response "); + PrintS(" should indicate an ackId error."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step1"); + /******************************************************************************/ + + /* Send packet with invalid ackId, same as sent previously. */ + packetLength = createDoorbell(packet, 9, 0, 0, 10, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0)); + + /* Check that the packet is not accepted with cause error in ackId. */ + c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 1, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send a link-request. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS)); + + /* Check that a link-response is returned. */ + /* Note that the status of the input-port will be reported as ok since a + link-request has been received. */ + c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check that a status is transmitted directly after the link-response. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send packet with invalid CRC."); + PrintS("Result: Input-error-stopped state should be entered and link-response "); + PrintS(" should indicate a CRC error."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step2"); + /******************************************************************************/ + + /* Send packet with invalid crc. */ + packetLength = createDoorbell(packet, 10, 0, 0, 10, 0); + packet[0] ^= 0x00000001; + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < packetLength; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0)); + + /* Check that the packet is not accepted with cause error in ackId. */ + c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 4, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send a link-request. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS)); + + /* Check that a link-response is returned. */ + /* Note that the status of the input-port will be reported as ok since a + link-request has been received. */ + c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check that a status is transmitted directly after the link-response. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send a packet that is too short."); + PrintS("Result: Input-error-stopped state should be entered and link-response "); + PrintS(" should indicate a packet error."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step3"); + /******************************************************************************/ + + /* Send packet with valid ackid and crc but too short. */ + packetLength = createDoorbell(packet, 10, 0, 0, 10, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0)); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[0]; + RIO_portAddSymbol(&stack, d); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = ((uint32_t) Crc32(packet[0] & 0x07ffffff, 0xffff)) << 16; + RIO_portAddSymbol(&stack, d); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0)); + + /* Check that the packet is not accepted with cause error in ackId. */ + c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send a link-request. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS)); + + /* Check that a link-response is returned. */ + /* Note that the status of the input-port will be reported as ok since a + link-request has been received. */ + c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check that a status is transmitted directly after the link-response. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send a packet that is too long."); + PrintS("Result: Input-error-stopped state should be entered and link-response "); + PrintS(" should indicate a packet error."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step4"); + /******************************************************************************/ + + /* Send packet with too many data symbols and without a end-of-packet. */ + packetLength = createDoorbell(packet, 10, 0, 0, 10, 0); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0)); + for(i = 0; i < 70; i++) + { + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + RIO_portAddSymbol(&stack, d); + } + + /* Check that the packet is not accepted with cause error in ackId. */ + c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send a link-request. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS)); + + /* Check that a link-response is returned. */ + /* Note that the status of the input-port will be reported as ok since a + link-request has been received. */ + c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check that a status is transmitted directly after the link-response. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Send a data symbol without starting a packet."); + PrintS("Result: Input-error-stopped state should be entered and link-response "); + PrintS(" should indicate a packet error."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step5"); + /******************************************************************************/ + + /* Send a data symbol. */ + packetLength = createDoorbell(packet, 10, 0, 0, 10, 0); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[0]; + RIO_portAddSymbol(&stack, d); + + /* Check that the packet is not accepted with cause error in ackId. */ + c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send a link-request. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS)); + + /* Check that a link-response is returned. */ + /* Note that the status of the input-port will be reported as ok since a + link-request has been received. */ + c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check that a status is transmitted directly after the link-response. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 6:"); + PrintS("Action: Send end-of-packet without matching start."); + PrintS("Result: Input-error-stopped state should be entered and link-response "); + PrintS(" should indicate a packet error."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step6"); + /******************************************************************************/ + + /* Send end-of-packet. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0)); + + /* Check that the packet is not accepted with cause error in ackId. */ + c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send a link-request. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS)); + + /* Check that a link-response is returned. */ + /* Note that the status of the input-port will be reported as ok since a + link-request has been received. */ + c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check that a status is transmitted directly after the link-response. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 7:"); + PrintS("Action: Send a symbol indicating a codec error."); + PrintS("Result: Input-error-stopped state should be entered and link-response "); + PrintS(" should indicate a symbol error."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step7"); + /******************************************************************************/ + + /* Send error-symbol. */ + s.type = RIO_SYMBOL_TYPE_ERROR; + RIO_portAddSymbol(&stack, s); + + /* Check that the packet is not accepted with cause error in ackId. */ + c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 5, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send a link-request. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS)); + + /* Check that a link-response is returned. */ + /* Note that the status of the input-port will be reported as ok since a + link-request has been received. */ + c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check that a status is transmitted directly after the link-response. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC4"); + PrintS("Description: Test transmitter error handling."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send acknowledge for a frame that has not been transmitted and "); + PrintS(" without any frame being expected."); + PrintS("Result: The transmitter should enter output-error-stopped and send "); + PrintS(" link-request."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step1"); + /******************************************************************************/ + + /* Packet acknowledge for unsent frame. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0)); + + /* Check that a link-request is received as the transmitter enters + output-error-stopped state. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send link-response with expected ackId. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 5, 16, STYPE1_NOP, 0)); + + /* Send a status directly afterwards. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_NOP, 0)); + + /* Check that packets are relayed after this. */ + RIO_sendDoorbell(&stack, 0, 5, 2); + packetLength = createDoorbell(packet, 5, 0, 0xffff, 5, 2); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send a packet and send acknowledge for a previous frame. Then send "); + PrintS(" a link-response indicating that the packet was received (accepted "); + PrintS(" but reply corrupted)."); + PrintS("Result: The transmitter should enter output-error-stopped state and send "); + PrintS(" link-request and proceed with the next packet."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step2"); + /******************************************************************************/ + + /* Send a packet. */ + RIO_sendDoorbell(&stack, 0, 6, 2); + packetLength = createDoorbell(packet, 6, 0, 0xffff, 6, 2); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send acknowledge for another packet. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0)); + + /* Check that a link-request is received as the transmitter enters + output-error-stopped state. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send link-response with expected ackId. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0)); + + /* Send a status directly afterwards. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 7, 1, STYPE1_NOP, 0)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send a packet and let the packet-accepted time out. Then send a "); + PrintS(" link-response indicating that the packet was not received."); + PrintS("Result: The transmitter should enter output-error-stopped state, send a"); + PrintS(" link-request and then resend the packet."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step3"); + /******************************************************************************/ + + /* Set the time at frame transmission. */ + RIO_portSetTime(&stack, 2); + + /* Send an output packet. */ + RIO_sendDoorbell(&stack, 0, 7, 2); + + /* Receive the transmitted packet. */ + packetLength = createDoorbell(packet, 7, 0, 0xffff, 7, 2); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Indicate that time has passed to trigger a timeout. */ + RIO_portSetTime(&stack, 3); + + /* Check that a link-request is received as the transmitter enters + output-error-stopped state. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send link-response with expected ackId. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0)); + + /* Send a status directly afterwards. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 7, 1, STYPE1_NOP, 0)); + + /* Receive retransmitted packet. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send acknowledge for the retransmitted packet. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 7, 1, STYPE1_NOP, 0)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send a packet and then indicate that the packet was not accepted. "); + PrintS(" Then send a link-response indicating that the packet was not received."); + PrintS("Result: The transmitter should enter output-error-stopped state, send a"); + PrintS(" link-request and then resend the packet."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step4"); + /******************************************************************************/ + + /* Send an output packet. */ + RIO_sendDoorbell(&stack, 0, 8, 3); + + /* Receive the transmitted packet. */ + packetLength = createDoorbell(packet, 8, 0, 0xffff, 8, 3); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send packet-not-accepted indicating CRC error. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 4, STYPE1_NOP, 0)); + + /* Check that a link-request is received as the transmitter enters + output-error-stopped state. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send link-response with expected ackId. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 8, 16, STYPE1_NOP, 0)); + + /* Send a status directly afterwards. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 8, 1, STYPE1_NOP, 0)); + + /* Receive retransmitted packet. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send acknowledge for the retransmitted packet. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 8, 1, STYPE1_NOP, 0)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Send a packet-retry for an unexpected packet. Then send a"); + PrintS(" link-response indicating the expected ackId and a normal packet."); + PrintS("Result: The transmitter should enter output-error-stopped state, send a"); + PrintS(" link-request and then the normal packet."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step5"); + /******************************************************************************/ + + /* Send packet-retry indicating that a packet should be retransmitted. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 8, 1, STYPE1_NOP, 0)); + + /* Check that a link-request is received as the transmitter enters + output-error-stopped state. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, + STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send link-response with expected ackId. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 9, 16, STYPE1_NOP, 0)); + + /* Send a status directly afterwards. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0)); + + /* Send an output packet. */ + RIO_sendDoorbell(&stack, 0, 9, 4); + + /* Receive retransmitted packet. */ + packetLength = createDoorbell(packet, 9, 0, 0xffff, 9, 4); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Send acknowledge for the retransmitted packet. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 1, STYPE1_NOP, 0)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 6:"); + PrintS("Action: Fill outbound queue with packets, then check retransmission when "); + PrintS(" packet-retry is encountered. "); + PrintS("Result: Packets should be retried until packet-accepted is received."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step6"); + /******************************************************************************/ + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 20, 0xbabe); + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 21, 0xbabe); + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 22, 0xbabe); + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 23, 0xbabe); + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 24, 0xbabe); + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 25, 0xbabe); + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 26, 0xbabe); + + TESTCOND(RIO_sendAvailable(&stack, 0)); + RIO_sendDoorbell(&stack, 0, 27, 0xbabe); + + TESTCOND(!RIO_sendAvailable(&stack, 0)); + + /* Receive transmitted packet. */ + packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 11, 0, 0xffff, 21, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 13, 0, 0xffff, 23, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 14, 0, 0xffff, 24, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 15, 0, 0xffff, 25, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 16, 0, 0xffff, 26, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 17, 0, 0xffff, 27, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + for(i = 0; i < 10; i++) + { + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE); + } + + /* Request retransmission. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 1, STYPE1_NOP, 0)); + + /* Acknowledge retransmission. */ + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_RESTART_FROM_RETRY, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + /* Check retransmitted packets. */ + packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 11, 0, 0xffff, 21, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + + /* Acknowledge. */ + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 10, 1, STYPE1_NOP, 0)); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 11, 1, STYPE1_NOP, 0)); + + packetLength = createDoorbell(packet, 13, 0, 0xffff, 23, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 14, 0, 0xffff, 24, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 12, 1, STYPE1_NOP, 0)); + + packetLength = createDoorbell(packet, 15, 0, 0xffff, 25, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 13, 1, STYPE1_NOP, 0)); + + packetLength = createDoorbell(packet, 16, 0, 0xffff, 26, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 14, 1, STYPE1_NOP, 0)); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + packetLength = createDoorbell(packet, 17, 0, 0xffff, 27, 0xbabe); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + for(i = 0; i < packetLength; i++) + { + s = RIO_portGetSymbol(&stack); + d.type = RIO_SYMBOL_TYPE_DATA; + d.data = packet[i]; + TESTEXPR(s.type, d.type); + TESTEXPR(s.data, d.data); + } + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 15, 1, STYPE1_NOP, 0)); + c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0); + s = RIO_portGetSymbol(&stack); + TESTEXPR(s.type, c.type); + TESTEXPR(s.data, c.data); + + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 16, 1, STYPE1_NOP, 0)); + RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 17, 1, STYPE1_NOP, 0)); + + + /************************************************************************* + * Reset ackIds to be able to use the stack in loopback for the testcases + * below. + *************************************************************************/ + + stack.rxAckId = 0; + stack.rxAckIdAcked = 0; + stack.txAckId = 0; + stack.txAckIdWindow = 0; + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC5"); + PrintS("Description: Test MAINTENANCE-READ-REQUEST, MAINTENANCE-READ-RESPONSE,"); + PrintS(" MAINTENANCE-WRITE-REQUEST and MAINTENANCE-WRITE-RESPONSE packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send two read requests to read identity and address of stack."); + PrintS("Result: The identity and address defined at RIO_open should be returned."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC5-Step1"); + /******************************************************************************/ + + /* Send two read requests. */ + RIO_sendMaintenanceReadRequest(&stack, 0xffff, 10, 0, 0x00000000); + RIO_sendMaintenanceReadRequest(&stack, 0xffff, 11, 0, 0x00000060); + + TESTEXPR(RIO_outboundQueueLength(&stack), 2); + + while(RIO_inboundQueueLength(&stack) != 2) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data); + TESTEXPR(srcid, 0xffff); + TESTEXPR(tid, 10); + TESTEXPR(hop, 0xff); + TESTEXPR(data, 0x0000b03b); + RIO_packetRemove(&stack); + + RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data); + TESTEXPR(srcid, 0xffff); + TESTEXPR(tid, 11); + TESTEXPR(hop, 0xff); + TESTEXPR(data, 0x0000ffff); + RIO_packetRemove(&stack); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send a write requests to write base device id of the stack."); + PrintS("Result: The identity and address defined at RIO_open should be returned."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC5-Step2"); + /******************************************************************************/ + + /* Write base device id. */ + RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 12, 0, 0x00000060, 0xdead); + while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 12); + TESTEXPR(hop, 0xff); + RIO_packetRemove(&stack); + + /* Read back the written base device id. */ + RIO_sendMaintenanceReadRequest(&stack, 0xffff, 14, 0, 0x00000060); + while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_READ_RESPONSE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 14); + TESTEXPR(hop, 0xff); + TESTEXPR(data, 0x0000dead); + RIO_packetRemove(&stack); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send a write requests to write to the implementation defined "); + PrintS(" configuration space of the stack."); + PrintS("Result: The same data should be returned."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC5-Step3"); + /******************************************************************************/ + + /* Write to implementation defined space. */ + RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 14, 0, 0x00010004, 0x01020304); + RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 15, 0, 0x00010008, 0xc0debabe); + RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 16, 0, 0x0001000c, 0x05060708); + + while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 14); + TESTEXPR(hop, 0xff); + RIO_packetRemove(&stack); + + while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 15); + TESTEXPR(hop, 0xff); + RIO_packetRemove(&stack); + + while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 16); + TESTEXPR(hop, 0xff); + RIO_packetRemove(&stack); + + /* Read from implementation defined space. */ + RIO_sendMaintenanceReadRequest(&stack, 0xffff, 14, 0, 0x00010000); + RIO_sendMaintenanceReadRequest(&stack, 0xffff, 15, 0, 0x00010004); + RIO_sendMaintenanceReadRequest(&stack, 0xffff, 16, 0, 0x00010008); + RIO_sendMaintenanceReadRequest(&stack, 0xffff, 17, 0, 0x0001000c); + + while(RIO_inboundQueueLength(&stack) != 4) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 14); + TESTEXPR(hop, 0xff); + TESTEXPR(data, 0x80000006); + RIO_packetRemove(&stack); + + RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 15); + TESTEXPR(hop, 0xff); + TESTEXPR(data, 0x00a100a2); + RIO_packetRemove(&stack); + + RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 16); + TESTEXPR(hop, 0xff); + TESTEXPR(data, 0xc0debabe); + RIO_packetRemove(&stack); + + RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data); + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 17); + TESTEXPR(hop, 0xff); + TESTEXPR(data, 0x00000000); + RIO_packetRemove(&stack); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC6"); + PrintS("Description: Test NREAD packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send one byte using NREAD and receive it at the other side."); + PrintS("Result: The same NREAD should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC6-Step1"); + /******************************************************************************/ + + for(j = 0; j < 8; j++) + { + RIO_sendNread(&stack, 0x0060, j, 0xaaaaaaaa+j, 1); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveNread(&stack, &srcid, &tid, &address, &length); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0xaaaaaaaa+j); + TESTEXPR(length, 1); + + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send two bytes using NREAD and receive it at the other side."); + PrintS("Result: The same NREAD should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC6-Step2"); + /******************************************************************************/ + + for(j = 0; j < 4; j++) + { + RIO_sendNread(&stack, 0x0060, j, 0x00000008+2*j, 2); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveNread(&stack, &srcid, &tid, &address, &length); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0x00000008+2*j); + TESTEXPR(length, 2); + + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send three to seven bytes using NREAD and receive it at the other "); + PrintS(" side."); + PrintS("Result: The same NREAD should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC6-Step3"); + /******************************************************************************/ + + for(k = 3; k < 8; k++) + { + for(j = 0; j < 2; j++) + { + RIO_sendNread(&stack, 0x0060, j, 0x00000008+(8-k)*j, k); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveNread(&stack, &srcid, &tid, &address, &length); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0x00000008+(8-k)*j); + TESTEXPR(length, k); + + RIO_packetRemove(&stack); + } + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send one and two double words using NREAD and receive it at the "); + PrintS(" other side."); + PrintS("Result: The same NREAD should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC6-Step4"); + /******************************************************************************/ + + for(j = 0; j < 2; j++) + { + RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 8*j+8); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveNread(&stack, &srcid, &tid, &address, &length); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0x00000008+8*j); + TESTEXPR(length, 8*j+8); + + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 5:"); + PrintS("Action: Send multiple of four full double words using NREAD and receive it"); + PrintS("at the other side."); + PrintS("Result: The same NREAD should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC6-Step5"); + /******************************************************************************/ + + for(j = 0; j < 8; j++) + { + RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 32*j+32); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveNread(&stack, &srcid, &tid, &address, &length); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0x00000008+8*j); + TESTEXPR(length, 32*j+32); + + RIO_packetRemove(&stack); + } + + /* REMARK: Add negative testcase where all unallowed address, size combinations + are sent...*/ + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC7"); + PrintS("Description: Test NWRITER packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send one byte using NWRITER and receive it at the other side."); + PrintS("Result: The same NWRITER should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC7-Step1"); + /******************************************************************************/ + + for(j = 0; j < 8; j++) + { + for(i = 0; i < 1; i++) + { + payload8[i] = i+j+1; + payload8Expected[i] = 0; + } + + RIO_sendNwrite(&stack, 0x0060, 0xaaaaaaaa+j, 1, payload8); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected); + + TESTEXPR(length, 1); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0xaaaaaaaa+j); + + for(i = 0; i < 1; i++) + { + TESTEXPR(payload8Expected[i], i+j+1); + } + + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send two bytes using NWRITE and receive it at the other side."); + PrintS("Result: The same NWRITE should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC7-Step2"); + /******************************************************************************/ + + for(j = 0; j < 4; j++) + { + for(i = 0; i < 2; i++) + { + payload8[i] = i+j; + payload8Expected[i] = 0; + } + + RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+2*j, 2, payload8); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0x00000008+2*j); + TESTEXPR(length, 2); + + for(i = 0; i < 2; i++) + { + TESTEXPR(payload8Expected[i], i+j); + } + + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 3:"); + PrintS("Action: Send three to seven bytes using NWRITE and receive it at the other "); + PrintS(" side."); + PrintS("Result: The same NWRITE should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC7-Step3"); + /******************************************************************************/ + + for(k = 3; k < 8; k++) + { + for(j = 0; j < 2; j++) + { + for(i = 0; i < k; i++) + { + payload8[i] = i+j+1; + payload8Expected[i] = 0; + } + + RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+(8-k)*j, k, payload8); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0x00000008+(8-k)*j); + TESTEXPR(length, k); + + for(i = 0; i < k; i++) + { + TESTEXPR(payload8Expected[i], i+j+1); + } + + RIO_packetRemove(&stack); + } + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 4:"); + PrintS("Action: Send full double words using NWRITE and receive it at the other side."); + PrintS("Result: The same NWRITE should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC7-Step4"); + /******************************************************************************/ + + for(j = 1; j < 32; j++) + { + for(i = 0; i < 8*j; i++) + { + payload8[i] = i+j+1; + payload8Expected[i] = 0; + } + + RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+8*j, 8*j, payload8); + + while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(address, 0x00000008+8*j); + TESTEXPR(length, 8*j); + + for(i = 0; i < 8*j; i++) + { + TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1)); + } + + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC8"); + PrintS("Description: Test RESPONSE packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send one byte using RESPONSE_WITH_PAYLOAD and receive it at the "); + PrintS(" other side."); + PrintS("Result: The same RESPONSE_WITH_PAYLOAD should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC8-Step1"); + /******************************************************************************/ + + for(j = 0; j < 8; j++) + { + for(i = 0; i < 1; i++) + { + payload8[i] = i+j+1; + payload8Expected[i] = 0; + } + + RIO_sendResponseDonePayload(&stack, 0x0060, j, 0x00000008+j, 1, payload8); + + while(RIO_eventPoll(&stack) != RIO_EVENT_RESPONSE_DONE_PAYLOAD) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + length = RIO_receiveResponseDonePayload(&stack, &srcid, &tid, 0x00000008+j, 1, payload8Expected); + + TESTEXPR(tid, j); + TESTEXPR(srcid, 0xdead); + TESTEXPR(length, 1); + + for(i = 0; i < 1; i++) + { + TESTEXPR(payload8Expected[i], i+j+1); + } + + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC9"); + PrintS("Description: Test DOORBELL packet and its response."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send a doorbell."); + PrintS("Result: The received doorbell should have the same properties as the sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC9-Step1"); + /******************************************************************************/ + + RIO_sendDoorbell(&stack, 0x0060, 16, 0xbabe); + + while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveDoorbell(&stack, &srcid, &tid, &info); + + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 16); + TESTEXPR(info, 0xbabe); + RIO_packetRemove(&stack); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send a response that is used for doorbells."); + PrintS("Result: The same data should be returned."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC9-Step2"); + /******************************************************************************/ + + RIO_sendResponseDone(&stack, 0x0060, 16); + + while(RIO_eventPoll(&stack) != RIO_EVENT_RESPONSE_DONE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveResponseDone(&stack, &srcid, &tid); + + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 16); + RIO_packetRemove(&stack); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC10"); + PrintS("Description: Test MESSAGE packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send increasing number of byte using MESSAGE on all mailboxes"); + PrintS(" and receive it at the other side."); + PrintS("Result: The same MESSAGE on the correct mailbox should be received as has"); + PrintS(" been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC10-Step1"); + /******************************************************************************/ + + for(k = 0; k < 256; k++) + { + for(j = 1; j < 256; j++) + { + for(i = 0; i < j; i++) + { + payload8[i] = i+j+1; + payload8Expected[i] = 0; + } + + RIO_sendMessage(&stack, 0x0060, k, j, payload8); + + while(RIO_eventPoll(&stack) != RIO_EVENT_MESSAGE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + length = RIO_receiveMessage(&stack, &srcid, &mailbox, sizeof(payload8Expected), payload8Expected); + + TESTEXPR(srcid, 0xdead); + TESTEXPR(mailbox, k); + TESTEXPR(length, (((j-1)/8)+1)*8); + + for(i = 0; i < j; i++) + { + TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1)); + } + + RIO_packetRemove(&stack); + } + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Send a MESSAGE-RESPONSE from all mailboxes."); + PrintS("Result: The same MESSAGE-RESPONSE should be received as has been sent."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC10-Step2"); + /******************************************************************************/ + + for(i = 0; i < 256; i++) + { + RIO_sendMessageResponseDone(&stack, 0x0060, i); + + while(RIO_eventPoll(&stack) != RIO_EVENT_MESSAGE_RESPONSE_DONE) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveMessageResponseDone(&stack, &srcid, &mailbox); + + TESTEXPR(srcid, 0xdead); + TESTEXPR(mailbox, i); + RIO_packetRemove(&stack); + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riostack-TC11"); + PrintS("Description: Test reading and writing raw packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send a packet using normal functions then copy it using the "); + PrintS(" packetGet() and packetSet() functions. "); + PrintS("Result: The same packet should be received when copied."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC11-Step1"); + /******************************************************************************/ + + RIO_sendDoorbell(&stack, 0x0060, 1, 0xca1e); + + while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + RIO_receiveDoorbell(&stack, &srcid, &tid, &info); + + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 1); + TESTEXPR(info, 0xca1e); + + packetLength = RIO_packetGet(&stack, sizeof(packet)/4, packet); + RIO_packetSet(&stack, packetLength, packet); + + while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL) + { + s = RIO_portGetSymbol(&stack); + RIO_portAddSymbol(&stack, s); + } + + TESTEXPR(srcid, 0xdead); + TESTEXPR(tid, 1); + TESTEXPR(info, 0xca1e); + RIO_packetRemove(&stack); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + + return 0; +} +#endif + +/*************************** end of file **************************************/
1.0.1/sw/stack/riostack.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/sw/stack/rioconfig.h =================================================================== --- 1.0.1/sw/stack/rioconfig.h (nonexistent) +++ 1.0.1/sw/stack/rioconfig.h (revision 29) @@ -0,0 +1,95 @@ +/******************************************************************************* + * + * RapidIO IP Library Core + * + * This file is part of the RapidIO IP library project + * http://www.opencores.org/cores/rio/ + * + * Description: + * This file contains the implementation dependent information needed to build + * the riostack. Replace declarations and definitions in this file to customize + * for your own compiler environment. + * + * 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 + * + *******************************************************************************/ + +#ifndef __RIO_CONFIG +#define __RIO_CONFIG + +/******************************************************************************* +* Includes +*******************************************************************************/ + +#include +#include + +/******************************************************************************* +* Global typedefs +*******************************************************************************/ + +#ifndef ASSERT +#ifdef MODULE_TEST +#include +#define ASSERT(c, s) (c)?:fprintf(stderr, s) +#endif +#endif + +#ifndef ASSERT0 +#ifdef MODULE_TEST +#include +#define ASSERT0(s) fprintf(stderr, s) +#endif +#endif + +#ifndef DEBUG_OUT +#define DEBUG_OUT(...) +#endif + +#define DEBUG_STATE(...) /*DEBUG_OUT(__VA_ARGS__)*/ +#define DEBUG_FRAMING_RX(...) /*DEBUG_OUT(__VA_ARGS__)*/ +#define DEBUG_FRAMING_TX(...) /*DEBUG_OUT(__VA_ARGS__)*/ + +typedef uint8_t bool_t; + + +/******************************************************************************* +* Global declarations +*******************************************************************************/ + +/******************************************************************************* +* Global function prototypes +*******************************************************************************/ + +#endif // __RIO_CONFIG + +/*************************** end of file **************************************/
1.0.1/sw/stack/rioconfig.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/sw/stack/riostack.h =================================================================== --- 1.0.1/sw/stack/riostack.h (nonexistent) +++ 1.0.1/sw/stack/riostack.h (revision 29) @@ -0,0 +1,1736 @@ +/******************************************************************************* + * + * RapidIO IP Library Core + * + * This file is part of the RapidIO IP library project + * http://www.opencores.org/cores/rio/ + * + * Description: + * This file contains the function prototypes and types that are needed to be + * able to use the riostack.c module. + * + * 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 + * + *******************************************************************************/ + +/** + * \file riostack.h + */ + +#ifndef _RIOSTACK_H +#define _RIOSTACK_H + +/******************************************************************************* + * Includes + *******************************************************************************/ + +#include "rioconfig.h" + + +/******************************************************************************* + * Global typedefs + *******************************************************************************/ + +/* The maximum size of a RapidIO packet. */ +#define RIO_PACKET_SIZE ((uint8_t)69u) + +/* The size of a maximum sized RapidIO packet when stored in memory. */ +/* One entry contains a header with the used buffer size. */ +#define RIO_BUFFER_SIZE (RIO_PACKET_SIZE+1u) + +/* Configuration space offsets. */ +#define DEVICE_IDENTITY_CAR ((uint32_t)0x00000000ul) +#define DEVICE_INFORMATION_CAR ((uint32_t)0x00000004ul) +#define ASSEMBLY_IDENTITY_CAR ((uint32_t)0x00000008ul) +#define ASSEMBLY_INFORMATION_CAR ((uint32_t)0x0000000cul) +#define PROCESSING_ELEMENT_FEATURES_CAR ((uint32_t)0x00000010ul) +#define SWITCH_PORT_INFORMATION_CAR ((uint32_t)0x00000014ul) +#define SOURCE_OPERATIONS_CAR ((uint32_t)0x00000018ul) +#define DESTINATION_OPERATIONS_CAR ((uint32_t)0x0000001cul) +#define SWITCH_ROUTE_TABLE_DESTINATION_ID_LIMIT_CAR ((uint32_t)0x00000034ul) +#define PROCESSING_ELEMENT_LOGICAL_LAYER_CONTROL_CSR ((uint32_t)0x0000004cul) +#define BASE_DEVICE_ID_CSR ((uint32_t)0x00000060ul) +#define HOST_BASE_DEVICE_ID_LOCK_CSR ((uint32_t)0x00000068ul) +#define COMPONENT_TAG_CSR ((uint32_t)0x0000006cul) +#define STANDARD_ROUTE_CONFIGURATION_DESTINATION_ID_SELECT_CSR ((uint32_t)0x00000070ul) +#define STANDARD_ROUTE_CONFIGURATION_PORT_SELECT_CSR ((uint32_t)0x00000074ul) +#define STANDARD_ROUTE_DEFAULT_PORT_CSR ((uint32_t)0x00000078ul) +#define EXTENDED_FEATURES_OFFSET ((uint32_t)0x00000100ul) +#define IMPLEMENTATION_DEFINED_OFFSET ((uint32_t)0x00010000ul) +#define LP_SERIAL_REGISTER_BLOCK_HEADER(offset) (offset) +#define PORT_LINK_TIMEOUT_CONTROL_CSR(offset) ((offset) + 0x00000020ul) +#define PORT_RESPONSE_TIMEOUT_CONTROL_CSR(offset) ((offset) + 0x00000024ul) +#define PORT_GENERAL_CONTROL_CSR(offset) ((offset) + 0x0000003cul) +#define PORT_N_LOCAL_ACKID_CSR(offset, n) ((offset) + (0x00000048ul+((n)*0x00000020ul))) +#define PORT_N_ERROR_AND_STATUS_CSR(offset, n) ((offset) + (0x00000058ul+((n)*0x00000020ul))) +#define PORT_N_CONTROL_CSR(offset, n) ((offset) + (0x0000005cul+((n)*0x00000020ul))) + + +/* Define the different types of RioSymbols. */ +typedef enum +{ + RIO_SYMBOL_TYPE_IDLE, RIO_SYMBOL_TYPE_CONTROL, + RIO_SYMBOL_TYPE_DATA, RIO_SYMBOL_TYPE_ERROR +} RioSymbolType; + + +/* + * RapidIO symbol definition. + * Idle symbol: Sent when nothing else to send. Does not use the data field. + * Control symbol: Sent when starting, ending and acknowleding a packet. Data + * is right aligned, (Unused, C0, C1, C2) where C0 is transmitted/received first. + * Data symbol: Sent to transfer packets. Uses the full data field, (D0, D1, + * D2, D3) where D0 is transmitted/received first. + * Error symbols are created when a symbols could not be created and the stack + * should know about it. + */ +typedef struct +{ + RioSymbolType type; + uint32_t data; +} RioSymbol; + + +/* Define different events that may happen in the stack. */ +typedef enum +{ + RIO_EVENT_NONE, + RIO_EVENT_NREAD, RIO_EVENT_NWRITE, RIO_EVENT_NWRITE_R, + RIO_EVENT_DOORBELL, RIO_EVENT_MESSAGE, + RIO_EVENT_MAINT_READ_REQUEST, RIO_EVENT_MAINT_WRITE_REQUEST, + RIO_EVENT_MAINT_READ_RESPONSE, RIO_EVENT_MAINT_WRITE_RESPONSE, + RIO_EVENT_RESPONSE_DONE, RIO_EVENT_RESPONSE_DONE_PAYLOAD, + RIO_EVENT_RESPONSE_RETRY, RIO_EVENT_RESPONSE_ERROR, + RIO_EVENT_MESSAGE_RESPONSE_DONE, RIO_EVENT_MESSAGE_RESPONSE_RETRY, + RIO_EVENT_MESSAGE_RESPONSE_ERROR +} RioEventType; + + +/* Define different states the link may be in. */ +typedef enum +{ + RIO_STATUS_UNINITIALIZED, + RIO_STATUS_ENUMERATION, + RIO_STATUS_OPERATIONAL +} RioStatusType; + + +/* Receiver states. */ +typedef enum +{ + RX_STATE_UNINITIALIZED, RX_STATE_PORT_INITIALIZED, RX_STATE_LINK_INITIALIZED, + RX_STATE_INPUT_RETRY_STOPPED, RX_STATE_INPUT_ERROR_STOPPED +} RioReceiverState; + + +/* Transmitter states. */ +typedef enum +{ + TX_STATE_UNINITIALIZED, TX_STATE_PORT_INITIALIZED, TX_STATE_LINK_INITIALIZED, + TX_STATE_SEND_PACKET_RETRY, TX_STATE_SEND_PACKET_NOT_ACCEPTED, TX_STATE_SEND_LINK_RESPONSE, + TX_STATE_OUTPUT_RETRY_STOPPED, TX_STATE_OUTPUT_ERROR_STOPPED +} RioTransmitterState; + + +/* Queue definition. */ +typedef struct +{ + uint8_t size; + uint8_t available; + uint8_t windowSize; + uint8_t windowIndex; + uint8_t frontIndex; + uint8_t backIndex; + uint32_t *buffer_p; +} Queue_t; + +/* Forward declaration for the RioStack-structure. */ +struct RioStack_t; + +/* Structure to enter callback function pointers in. */ +typedef struct +{ + uint32_t (*configRead)(struct RioStack_t *stack, uint32_t offset); + void (*configWrite)(struct RioStack_t *stack, uint32_t offset, uint32_t data); +} RioStackObserver_t; + + +/* Define the structure to keep all the RapidIO stack variables. */ +typedef struct RioStack_t +{ + /* Receiver variables. */ + RioReceiverState rxState; + uint8_t rxCounter; + uint16_t rxCrc; + uint8_t rxStatusReceived; + uint8_t rxAckId; + uint8_t rxAckIdAcked; + uint8_t rxErrorCause; + Queue_t rxQueue; + + /* Transmitter variables. */ + RioTransmitterState txState; + uint8_t txCounter; + uint16_t txStatusCounter; + uint8_t txFrameState; + uint32_t txFrameTimeout[32]; + uint8_t txAckId; + uint8_t txAckIdWindow; + uint8_t txBufferStatus; + Queue_t txQueue; + + /* Common protocol stack variables. */ + uint32_t portTime; + uint32_t portTimeout; + + /* Common protocol stack variables updated visible via the configuration space. */ + uint16_t deviceIdentity; + uint16_t deviceVendorIdentity; + uint32_t deviceRev; + uint16_t assyIdentity; + uint16_t assyVendorIdentity; + uint16_t assyRev; + uint16_t baseDeviceId; + uint32_t hostBaseDeviceIdLock; + uint32_t componentTag; + uint8_t host; + uint8_t masterEnable; + uint8_t discovered; + + /** The number of successfully received packets. */ + uint32_t statusInboundPacketComplete; + + /** The number of retried received packets. + This will happen if the receiver does not have resources available when an inbound packet is received. */ + uint32_t statusInboundPacketRetry; + + /** The number of received erronous control symbols. + This may happen if the inbound link has a high bit-error-rate. */ + uint32_t statusInboundErrorControlCrc; + + /** The number of received packets with an unexpected ackId. + This may happen if the inbound link has a high bit-error-rate. */ + uint32_t statusInboundErrorPacketAckId; + + /** The number of received packets with a checksum error. + This may happen if the inbound link has a high bit-error-rate. */ + uint32_t statusInboundErrorPacketCrc; + + /** The number of received symbols that contains an illegals character. + This may happen if the inbound link has a high bit-error-rate or if characters are missing in the + inbound character stream. */ + uint32_t statusInboundErrorIllegalCharacter; + + /** The number of general errors encountered at the receiver that does not fit into the other categories. + This happens if too short or too long packets are received. */ + uint32_t statusInboundErrorGeneral; + + /** The number of received packets that were discarded since they were unsupported by the stack. + This will happen if an inbound packet contains information that cannot be accessed using the function API + of the stack. */ + uint32_t statusInboundErrorPacketUnsupported; + + /** The number of successfully transmitted packets. */ + uint32_t statusOutboundPacketComplete; + + /** The number of retried transmitted packets. + This will happen if the receiver at the link-partner does not have resources available when an outbound + packet is received. */ + uint32_t statusOutboundPacketRetry; + + /** The number of outbound packets that has had its retransmission timer expired. + This happens if the latency of the system is too high or if a packet is corrupted due to a high + bit-error-rate on the outbound link. */ + uint32_t statusOutboundErrorTimeout; + + /** The number of packet-accepted that was received that contained an unexpected ackId. + This happens if the transmitter and the link-partner is out of synchronization, probably due + to a software error. */ + uint32_t statusOutboundErrorPacketAccepted; + + /** The number of packet-retry that was received that contained an unexpected ackId. + This happens if the transmitter and the link-partner is out of synchronization, probably due to + a software error. */ + uint32_t statusOutboundErrorPacketRetry; + + /** The number of received link-requests. + This happens if the link-partner transmitter has found an error and need to resynchronize itself + to the receiver. */ + uint32_t statusPartnerLinkRequest; + + /** The number of received erronous control symbols at the link-partner receiver. + This may happen if the outbound link has a high bit-error-rate. */ + uint32_t statusPartnerErrorControlCrc; + + /** The number of received packets with an unexpected ackId at the link-partner receiver. + This may happen if the outbound link has a high bit-error-rate. */ + uint32_t statusPartnerErrorPacketAckId; + + /** The number of received packets with a checksum error at the link-partner receiver. + This may happen if the outbound link has a high bit-error-rate. */ + uint32_t statusPartnerErrorPacketCrc; + + /** The number of received symbols that contains an illegals character at the link-parter receiver. + This may happen if the outbound link has a high bit-error-rate or if characters are missing in the + outbound character stream. */ + uint32_t statusPartnerErrorIllegalCharacter; + + /** The number of general errors encountered at the receiver that does not fit into the other categories. + This happens depending on the link-partner implementation. */ + uint32_t statusPartnerErrorGeneral; + + /* Callback structure. */ + const RioStackObserver_t *observer; + + /* Private user data. */ + const void *private; +} RioStack_t; + + +/******************************************************************************* + * Global function prototypes + *******************************************************************************/ + +/** + * \brief Open the RapidIO stack for operation. + * + * \param[in] stack Stack instance to operate on. + * \param[in] observer Callback structure to use when events happen. + * \param[in] private Pointer to an opaque data area containing private user data. + * \param[in] rxPacketBufferSize Number of words to use as reception buffer. This + * argument specifies the size of rxPacketBuffer. + * \param[in] rxPacketBuffer Pointer to buffer to store inbound packets in. + * \param[in] txPacketBufferSize Number of words to use as transmission buffer. This + * argument specifies the size of txPacketBuffer. + * \param[in] txPacketBuffer Pointer to buffer to store outbound packets in. + * \param[in] configDeviceVendorId Constant to use as deviceVendorIdentity when + * accessed in configuration space. (See Part 1, chapter 5.4.1) + * \param[in] configDeviceId Constant to use as deviceIdentity when accessed in + * configuration space. (See Part 1, chapter 5.4.1) + * \param[in] configDeviceRevisionId Constant to use as deviceRev when accessed in + * configuration space. (See Part 1, chapter 5.4.2) + * \param[in] configAssyVendorId Constant to use as assyVendorIdentity when accessed in + * configuration space. (See Part 1, chapter 5.4.3) + * \param[in] configAssyId Constant to use as assyIdentity when accessed in + * configuration space. (See Part 1, chapter 5.4.3) + * \param[in] configAssyRevisionId Constant to use as assyRev when accessed in + * configuration space. (See Part 1, chapter 5.4.4) + * \param[in] configBaseDeviceId The deviceId (source address) to use at startup when + * sending packets. + * + * This function initializes all internally used variables in the stack. The stack will + * however not be operational until the transcoder has signalled that it is ready for + * other symbols than idle. This is done using the function RIO_setPortStatus(). Once + * this function has been called it is possible to get and set symbols and to issue + * requests. The requests will be transmitted once the link initialization has + * been completed. + * + * The rxPacket/txPacket arguments are word buffers that are used internally to store the + * inbound and outbound packet queues. + * + * The config argument constants are used as identification when maintenance packets + * are received and replied to. They should be set to make the device where the stack + * is used easily identifiable on the net. + * + * \note The reception buffers can only support maximum 31 buffers. + */ +void RIO_open( RioStack_t *stack, const RioStackObserver_t *observer, const void *private, + const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer, + const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer, + const uint16_t configDeviceVendorId, const uint16_t configDeviceId, + const uint32_t configDeviceRevisionId, const uint16_t configAssyVendorId, + const uint16_t configAssyId, const uint16_t configAssyRevisionId, + const uint16_t configBaseDeviceId ); + +/******************************************************************************************* + * Stack status functions. + * Note that status counters are access directly in the stack-structure. + *******************************************************************************************/ + +/** + * \brief Get the status of the link. + * + * \param[in] stack The stack to operate on. + * \return Returns the status of the link. + * + * This function indicates if the link is up and ready to relay packets. + */ +RioStatusType RIO_getStatus( RioStack_t *stack ); + +/** + * \brief Get the number of pending outbound packets. + * + * \param[in] stack The stack to operate on. + * \return Returns the number of pending outbound packets. + * + * This function checks the outbound queue and returns the number of packets + * that are pending to be transmitted onto the link. + */ +uint8_t RIO_outboundQueueLength( RioStack_t *stack ); + +/** + * \brief Get the number of pending inbound packets. + * + * \param[in] stack The stack to operate on. + * \return Returns the number of pending inbound packets. + * + * This function checks the inbound queue and returns the number of packets + * that has been received but not read by the user yet. + */ +uint8_t RIO_inboundQueueLength( RioStack_t *stack ); + +/******************************************************************************************* + * Packet reception functions. + *******************************************************************************************/ + +/** + * \brief Check for new events. + * + * \param[in] stack The stack to operate on. + * \return Returns the value RIO_EVENT_NONE if no event is pending and + * something else if there are pending events. + * + * This function polls the incoming queue of packets and returns the + * type of packet present there. The return value from this function + * indicates which access functions that should be used to read the + * received packet. + * + * \note When a packet has been processed, RIO_packetRemove() must be called to free the + * used resources in the inbound queue. + */ +RioEventType RIO_eventPoll( RioStack_t *stack ); + +/** + * \brief Remove a packet from the stack. + * \param[in] stack The stack to operate on. + * + * Remove a pending packet from the stack. The incoming packet queue is updated + * to remove the received packet. + */ +void RIO_packetRemove( RioStack_t *stack ); + +/** + * \brief Check transmission buffers. + * + * \param[in] stack The stack to operate on. + * \param[in] size The size of the buffer that is about to be sent. + * \return Returns non-zero if a buffer with the specified size fits into the + * internal transmission buffers. + * + * Return if there are buffers available to send a packet of a specified size. + * + * \note If the response is negative, it might be positive later if outbound + * packets has been sent and new buffers becomes available. + * + * \note Set size to zero if there is no user definded payload. + */ +bool_t RIO_sendAvailable( RioStack_t *stack, const uint16_t size ); + +/** + * \brief Get a raw packet from inbound queue. + * + * \param[in] stack The stack to operate on. + * \param[in] length The size of the buffer to write the packet to. + * \param[in] dest Pointer to where to copy the raw packet. + * \return The number of words copied. + * + * This function copies a raw packet in the inbound queue into a word buffer. An assert + * will occur if the packet does not fit into the provided buffer. + * + * \note The packet is automatically removed from the inbound queue. Do not use + * RIO_packetRemove() to remove it. + */ +uint32_t RIO_packetGet( RioStack_t *stack, uint32_t length, uint32_t *dest); + +/** + * \brief Set a raw packet in outbound queue. + * + * \param[in] stack The stack to operate on. + * \param[in] length The size of the packet to write. + * \param[in] src Pointer to where to copy the raw packet from. + * + * This function copies a raw packet from a source buffer into the outbound queue. + * An assert will occur if the packet does not fit into the internal buffer. + * + * \note Calling this function resembles a send-function, the packet will be placed in the + * outbound queue for transmission. + * + * \note If the copied packet does not have a correct CRC it might lock the stack since + * retransmissions will be done until forever. + */ +void RIO_packetSet( RioStack_t *stack, uint32_t length, uint32_t *src); + +/******************************************************************************************* + * Configuration-space access methods. + *******************************************************************************************/ + +/** + * \brief Read configuration space. + * + * \param[in] stack The stack to operate on. + * \param[in] offset The configuration space address to read. + * \return The data read on the configuration space address specified. + * + * This function reads a configuration space offset and returns the content of + * the entry. + */ +uint32_t RIO_readConfig( RioStack_t *stack, const uint32_t offset ); + +/** + * \brief Write configuration space. + * + * \param[in] stack The stack to operate on. + * \param[in] offset The configuration space address to write to. + * \param[in] data The data to write to the configuration space. + * + * This function writes to a configuration space offset and sets the + * content to the specified data. + */ +void RIO_writeConfig( RioStack_t *stack, const uint32_t offset, const uint32_t data); + +/******************************************************************************************* + * Logical I/O MAINTENANCE-READ functions. + *******************************************************************************************/ + +/** + * \brief Send a maintenance read request. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to be returned in the response. + * \param[in] hopCount The hop_count to set in the read request. + * \param[in] offset The byte address in the configuration space to read. + * + * This function creates and sends a maintenance read request packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceReadRequest(RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset ); +#else +void RIO_sendMaintenanceReadRequest(RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset ); +#endif + +/** + * \brief Read a received maintenance read request. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the destination end point. + * \param[out] tid The transaction id to be returned in the response. + * \param[out] hopCount The hop_count to set in the read request. + * \param[out] offset The byte address in the configuration space to read. + * + * This function reads a received maintenance read request packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceReadRequest(RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset); +#else +void RIO_receiveMaintenanceReadRequest(RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset); +#endif + +/** + * \brief Send a maintenance read response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to be returned in the response. + * \param[in] hopCount The hop_count to set in the read request. + * \param[in] data The data to send in the response. + * + * This function creates a maintanance read response packet that should be + * sent when a request is received. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t data); +#else +void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount, const uint32_t data); +#endif + +/** + * \brief Read a received maintenance read response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the source end point. + * \param[out] tid The transaction id in the response. + * \param[out] hopCount The hop_count set in the read response. + * \param[out] data The data in the response. + * + * This function reads a received maintanance read response packet. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *data); +#else +void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *data); +#endif + +/******************************************************************************************* + * Logical I/O MAINTENANCE-WRITE functions. + *******************************************************************************************/ + +/** + * \brief Send a maintenance write request. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to be returned in the response. + * \param[in] hopCount The hop_count to set in the write request. + * \param[in] offset The byte address in the configuration space to write to. + * \param[in] data The data to write in configuration space. + * + * This function creates and sends a maintenance write request packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset, const uint32_t data ); +#else +void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount, const uint32_t offset, const uint32_t data ); +#endif + +/** + * \brief Read a received maintenance write request. + * + * \param[in] stack The stack to operate on. + * \param[out] destid The device id of the destination end point. + * \param[out] tid The transaction id to be returned in the response. + * \param[out] hopCount The hop_count to set in the write request. + * \param[out] offset The byte address in the configuration space to write to. + * \param[out] data The data to write in configuration space. + * + * This function creates and sends a maintenance write request packet. The reply + * is received using RIO_eventPoll-function and RIO_packetTid together with the return + * value from this function. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset, uint32_t *data ); +#else +void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount, uint32_t *offset, uint32_t *data ); +#endif + +/** + * \brief Send a maintenance write response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to be returned. + * \param[in] hopCount The hop_count to set in the write response. + * + * This function creates a maintanance write response packet from a pending + * maintenance read request. The generated packet are placed in the outbound + * packet queue. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint8_t hopCount); +#else +void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint8_t hopCount); +#endif + +/** + * \brief Read a received maintenance write response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the source end point. + * \param[out] tid The transaction id read in the response. + * \param[out] hopCount The hop_count read in the write response. + * + * This function creates a maintanance write response packet from a pending + * maintenance read request. The generated packet are placed in the outbound + * packet queue. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount); +#else +void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint8_t *hopCount); +#endif + +/******************************************************************************************* + * Logical I/O NWRITE/NWRITER functions. + *******************************************************************************************/ + +/** + * \brief Send an NWRITE request to write a byte array. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] address The byte address to write to. + * \param[in] dataLength The number of bytes to write. The largest allowed size is 256 bytes. + * \param[in] data A pointer to the array of bytes to write. + * + * This function creates and sends an NWRITE request packet to write a number + * of bytes to a specified address. No reply will be received. + * + * \note The address is a byte address, not a word address. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + * + * \note Not all combinations of addresses and sizes are allowed. See table below: + * ------------------------------------------------------------------------------------- + * size | valid byte in double-word + * ------------------------------------------------------------------------------------- + * 1 | 10000000, 01000000, 00100000, 00010000, 00001000, 00000100, 00000010, 00000001 + * 2 | 11000000, 00110000, 00001100, 00000011 + * 3 | 11100000, 00000111 + * 4 | 11110000, 00001111 + * 5 | 11111000, 00011111 + * 6 | 11111100, 00111111 + * 7 | 11111110, 01111111 + * 8*N | 11111111 (N={1...32}) + * -------------------------------------------------------------------------------------- + * See RapidIO 2.2 part1 table 4-4 for more details. Asserts will occurr if an invalid + * combination is detected. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, + const uint32_t address, const uint16_t dataLength, const uint8_t *data ); +#else +void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, + const uint32_t address, const uint16_t dataLength, const uint8_t *data ); +#endif + +/** + * \brief Send an NWRITER request to write a byte array. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to set in the response. + * \param[in] address The byte address to write to. + * \param[in] dataLength The number of bytes to write. The largest allowed size is 256 bytes. + * \param[in] data A pointer to the array of bytes to write. + * + * This function creates and sends an NWRITE request packet to write a number + * of bytes to a specified address. A reply will be received when the write has been completed. + * + * \note The address is a byte address, not a word address. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + * + * \note Not all combinations of addresses and sizes are allowed. See table below: + * ------------------------------------------------------------------------------------- + * size | valid byte in double-word + * ------------------------------------------------------------------------------------- + * 1 | 10000000, 01000000, 00100000, 00010000, 00001000, 00000100, 00000010, 00000001 + * 2 | 11000000, 00110000, 00001100, 00000011 + * 3 | 11100000, 00000111 + * 4 | 11110000, 00001111 + * 5 | 11111000, 00011111 + * 6 | 11111100, 00111111 + * 7 | 11111110, 01111111 + * 8*N | 11111111 (N={1...32}) + * -------------------------------------------------------------------------------------- + * See RapidIO 2.2 part1 table 4-4 for more details. Asserts will occurr if an invalid + * combination is detected. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength, const uint8_t *data ); +#else +void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength, const uint8_t *data ); +#endif + +/** + * \brief Read a received NWRITE/NWRITER request. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the destination end point. + * \param[out] tid The transaction id in the response. Undefined value when NWRITE is read. + * \param[out] address The byte address to write to. + * \param[in] dataLength The number of bytes allocated in data. + * \param[in] data A pointer to the array of bytes to copy to. + * \return The number of bytes copied into data. + * + * This function reads a received NWRITE/NWRITER request packet to write a number + * of bytes to a specified address. Used to receive both NWRITE and NWRITER. The payload + * of the packet is copied into the provided buffer pointed to by data. + * + * \note The address is a byte address, not a word address. + */ +#ifdef RIO_TRANSPARENT +uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, const uint16_t dataLength, uint8_t *data ); +#else +uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint32_t *address, const uint16_t dataLength, uint8_t *data ); +#endif + +/******************************************************************************************* + * Logical I/O NREAD functions. + *******************************************************************************************/ + +/** + * \brief Send an NREAD request to read a byte array. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to set in the response. + * \param[in] address The byte address to write to. + * \param[in] dataLength The number of bytes to write. The largest allowed size is 256 bytes. + * + * This function creates and sends an NWRITE request packet to write a number + * of bytes to a specified address. A reply will be received when the write has been completed. + * + * \note The address is a byte address, not a word address. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + * + * \note Not all combinations of address and length are allowed. See table below: + * ------------------------------------------------------------------------------------- + * size | valid byte in double-word + * ------------------------------------------------------------------------------------- + * 1 | 10000000, 01000000, 00100000, 00010000, 00001000, 00000100, 00000010, 00000001 + * 2 | 11000000, 00110000, 00001100, 00000011 + * 3 | 11100000, 00000111 + * 4 | 11110000, 00001111 + * 5 | 11111000, 00011111 + * 6 | 11111100, 00111111 + * 7 | 11111110, 01111111 + * ------------------------------------------------------------------------------------- + * For full double-words the following byte sizes are allowed: + * 8, 16, 32, 64, 96, 128, 160, 192, 224, 256 + * -------------------------------------------------------------------------------------- + * See RapidIO 2.2 part1 table 4-4 for more details. Asserts will occurr if an invalid + * combination is detected. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength); +#else +void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength); +#endif + +/** + * \brief Read a received NREAD request. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the destination end point. + * \param[out] tid The transaction id in the response. + * \param[out] address The byte address to write to. + * \param[in] dataLength The number of bytes allocated in data. + * + * This function reads a received NREAD request packet to read a number + * of bytes at a specified address. + * + * \note The address is a byte address, not a word address. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint32_t *address, uint16_t *dataLength); +#else +void RIO_receiveNread( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint32_t *address, uint16_t *dataLength); +#endif + +/******************************************************************************************* + * Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR + * functions. + *******************************************************************************************/ + +/** + * \brief Send a response with data payload. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The destination identifier of the response. + * \param[in] tid The transaction identifier for the reply. It should correspond to + * the tid in the received packet for which this response is sent. + * \param[in] address The byte address that was read. It should correspond to + * the address in the received packet for which this response is sent. + * \param[in] dataLength The size of the data buffer to return in the reply. It + * should correspond to the dataLength in the received packet for which this response + * is sent. + * \param[in] data The data buffer to return in the reply. + * + * This function creates a response packet with the specified destination + * identifier, transaction id and data payload. The generated packet are placed + * in the outbound packet queue. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength, const uint8_t *data); +#else +void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint32_t address, const uint16_t dataLength, const uint8_t *data); +#endif + +/** + * \brief Read payload from a response with payload. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the destination end point. + * \param[out] tid The transaction id in the response. + * \param[in] address The byte address that was read. It should correspond to + * the address in the received packet for which this response is sent. + * \param[in] dataLength The size of the data buffer to return in the reply. It + * should correspond to the dataLength in the received packet for which this response + * is sent. + * \param[in] data Pointer to a buffer to where the data in the response will be copied. + * \return The number of bytes copied from the data payload contained in the response. + * + * This function reads a response packet and returns a the byte payload contained within. + */ +#ifdef RIO_TRANSPARENT +uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + const uint32_t address, const uint16_t dataLength, uint8_t *data ); +#else +uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + const uint32_t address, const uint16_t dataLength, uint8_t *data ); +#endif + +/** + * \brief Send a response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device identifier of the target to send the response to. + * \param[in] tid The transaction id to send the response for. This should be the + * same value as the packet that this response was received with. + * + * This function is used to send a response indicating a successfull + * completion in reply to a previously received packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid ); + +#else +void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t tid ); + +#endif +/** + * \brief Read a received response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device identifier of the source of the response. + * \param[out] tid The transaction id in the response. + * + * This function is used to read a received response indicating a successfull + * completion in reply to a previously sent packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid ); + +#else +void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *tid ); + +#endif +/** + * \brief Send a retry response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device identifier of the target to send the response to. + * \param[in] tid The transaction id to send the response for. This should be the + * same value as the packet that this response was received with. + * + * This function is used to send a response indicating a busy resource + * in reply to a previously received packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid ); + +#else +void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t tid ); + +#endif +/** + * \brief Read a received retry response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device identifier of the source of the response. + * \param[out] tid The transaction id in the response. + * + * This function is used to read a received response indicating a retry condition + * in reply to a previously sent packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid ); + +#else +void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *tid ); + +#endif +/** + * \brief Send a error response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device identifier of the target to send the response to. + * \param[in] tid The transaction id to send the response for. This should be the + * same value as the packet that this response was received with. + * + * This function is used to send a response indicating a busy resource + * in reply to a previously received packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid ); +#else +void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t tid ); +#endif + +/** + * \brief Read a received error response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device identifier of the source of the response. + * \param[out] tid The transaction id in the response. + * + * This function is used to read a received response indicating an error condition + * in reply to a previously sent packet. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid ); +#else +void RIO_receiveResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *tid ); +#endif + +/******************************************************************************************* + * Logical message passing DOORBELL and MESSAGE functions. + *******************************************************************************************/ + +/** + * \brief Send a doorbell. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to be returned in the response. + * \param[in] info The information to send with the doorbell. + * \return An identifier that maps to the doorbell response that are received using + * RIO_packetTid. + * + * This function is used to send a doorbell to a remote endpoint. A response + * should be sent when the doorbell has been processed using the RIO_sendResponseDone(), + * RIO_sendResponseRetry() or RIO_sendResponseError() functions. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, + const uint16_t info); +#else +void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint8_t tid, + const uint16_t info); +#endif + +/** + * \brief Read a received a doorbell. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the source end point. + * \param[out] tid The transaction id to be returned in the response. + * \param[out] info The information to send with the doorbell. + * + * This function is used to read a received doorbell from a remote endpoint. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, + uint16_t *info); +#else +void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, + uint16_t *info); +#endif + +/** + * \brief Send a message. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination endpoint. + * \param[in] mailbox The mailbox to send the message to. + * \param[in] dataLength The size of the buffer to copy to. + * \param[in] buffer A byte pointer to the message payload to send. + * + * This function sends a single packet message to a destination mailbox. + * + * \note Mailbox 0-15 can support multipacket (when support is enabled) + * messages and 16-255 can only handle singlepacket messages. Dont use mailbox + * 0-15 unless you know that there will be large packets transmitted on it. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, + const uint16_t dataLength, const uint8_t *data ); +#else +void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox, + const uint16_t dataLength, const uint8_t *data ); +#endif + +/** + * \brief Read a received message. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device id of the source endpoint. + * \param[out] mailbox The mailbox the message is received on. + * \param[in] dataLength The size of the buffer to copy to. + * \param[in] data A byte pointer to the message payload to read. + * \return The number of bytes copied. A zero will be returned if unable to copy. + * + * This function reads a single packet message to a destination mailbox. + */ +#ifdef RIO_TRANSPARENT +uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox, + const uint16_t dataLength, uint8_t *data ); +#else +uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox, + const uint16_t dataLength, uint8_t *data ); +#endif + +/******************************************************************************************* + * Logical message passing MESSAGE-RESPONSE functions. + *******************************************************************************************/ + +/** + * \brief Send a message response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device identifier of the target to send the response to. + * \param[in] mailbox The mailbox to send the response to. + * + * This function is used to send a message response indicating a successfull + * completion in reply to a previously received message. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox ); +#else +void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox ); +#endif + +/** + * \brief Read a received message response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device identifier of the source endpoint. + * \param[out] mailbox The mailbox the response is for. + * + * This function is used to read a received message response indicating a successfull + * completion in reply to a previously sent message. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox ); +#else +void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox ); +#endif + +/** + * \brief Send a message retry response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device identifier of the target to send the response to. + * \param[in] mailbox The mailbox to send the response to. + * + * This function is used to send a message response indicating a busy resource + * in reply to a previously received message. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox ); +#else +void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox ); +#endif + +/** + * \brief Read a received message retry response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device identifier of the source endpoint. + * \param[out] mailbox The mailbox the response is for. + * + * This function is used to read a received message retry response indicating a retry + * condition in reply to a previously sent message. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox ); +#else +void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox ); +#endif + +/** + * \brief Send a message error response. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device identifier of the target to send the response to. + * \param[in] mailbox The mailbox to send the response to. + * + * This function is used to send a message response indicating a busy resource + * in reply to a previously received message. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +#ifdef RIO_TRANSPARENT +void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox ); +#else +void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox ); +#endif + +/** + * \brief Read a received message error response. + * + * \param[in] stack The stack to operate on. + * \param[out] srcid The device identifier of the source endpoint. + * \param[out] mailbox The mailbox the response is for. + * + * This function is used to read a received message error response indicating an error + * condition in reply to a previously sent message. + */ +#ifdef RIO_TRANSPARENT +void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox ); +#else +void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox ); +#endif + +/******************************************************************************************* + * Port functions (backend API towards physical device) + *******************************************************************************************/ + +/** + * \brief Set a port current time. + * + * \param[in] stack The stack to operate on. + * \param[in] time The current time without unit. + * + * This function indicates to the stack the current time and this is used internally + * to calculate when a packet timeout should be triggered. Use this together with RIO_setPortTimeout() + * to allow for the stack to handle timeouts. + */ +void RIO_portSetTime( RioStack_t *stack, const uint32_t time); + +/** + * \brief Set a port timeout limit. + * + * \param[in] stack The stack to operate on. + * \param[in] time The time out threshold. + * + * The time to wait for a response from the link partner. The unit of the + * timeout value should be the same as the time used in RIO_setPortTime(). + * + * This function is used to set a timeout threshold value and is used to know when + * an acknowledge should have been received from a link partner. + */ +void RIO_portSetTimeout( RioStack_t *stack, const uint32_t time); + +/** + * \brief Set a ports status. + * + * \param[in] stack The stack to operate on. + * \param[in] initialized The state of the port. + * + * If set to non-zero, the symbol encoder/decoder indicates to the stack that + * it is successfully encoding/decoding symbol, i.e. synchronized to the link. + * + * This function indicates to the stack if the port that are encoding/decoding + * symbols are ready to accept other symbols than idle-symbols. If the + * encoding/decoding loses synchronization then this function should be called + * with an argument equal to zero to force the stack to resynchronize the link. + */ +void RIO_portSetStatus( RioStack_t *stack, const uint8_t initialized ); + +/** + * \brief Add a new symbol to the RapidIO stack. + * + * \param[in] stack The stack to operate on. + * \param[in] s A symbol received from a port. + * + * This function is used to insert new data, read from a port, into the stack. The + * symbols will be concatenated to form packets that can be accessed using other + * functions. + */ +void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s ); + +/** + * \brief Get the next symbol to transmit on a port. + * + * \param[in] stack The stack to operate on. + * \return A symbol that should be sent on a port. + * + * This function is used to fetch new symbols to transmit on a port. Packets that + * are inserted are split into symbols that are accessed with this function. + */ +RioSymbol RIO_portGetSymbol( RioStack_t *stack ); + + +/******************************************************************************************* + * DEPRECATED + * Will be removed. + *******************************************************************************************/ + +/** + * \brief Read packet transaction identification. + * \param[in] stack The stack to operate on. + * \return The identification of the packet. This matches a transaction identifier + * that are set as argument when a send-function are called. + * + * This function is used to correlate a sent packet to a received response. + * + * \note This function cannot be used when receiving messages on mailboxes. Use + * RIO_readMessageMailbox() instead. + */ +uint8_t RIO_packetTid( RioStack_t *stack ); + +/** + * \brief Read packet destination identification. + * \param[in] stack The stack to operate on. + * \return The destination device identifier of the packet. + * + * This function is used to get the destination device identifier of a received packet. + */ +uint16_t RIO_packetDestination( RioStack_t *stack ); + +/** + * \brief Read packet source identification. + * \param[in] stack The stack to operate on. + * \return The source device identifier of the packet. + * + * This function is used to get the source device identifier of a received packet. + */ +uint16_t RIO_packetSource( RioStack_t *stack ); + +/** + * \brief Read a maintenance read request hop count value. + * + * \param[in] stack The stack to operate on. + * \return The hopcount value of the packet. + * + * This function returns the hop count value of a received maintenance read + * request packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint8_t RIO_readMaintenanceReadRequestHop( RioStack_t *stack ); + +/** + * \brief Read a maintenance read request offset value. + * + * \param[in] stack The stack to operate on. + * \return The offset value of the packet. + * + * This function returns the offset value of a received maintenance read + * request packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint32_t RIO_readMaintenanceReadRequestOffset( RioStack_t *stack ); + +/** + * \brief Read a maintenance read response hop count value. + * + * \param[in] stack The stack to operate on. + * \return The hop count value of the packet. + * + * This function returns the hop count value of a received maintenance read + * response packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint8_t RIO_readMaintenanceReadResponseHop( RioStack_t *stack ); + +/** + * \brief Read a maintenance read response offset value. + * + * \param[in] stack The stack to operate on. + * \return The offset value of the packet. + * + * This function returns the offset value of a received maintenance read + * response packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint32_t RIO_readMaintenanceReadResponse( RioStack_t *stack ); + +/** + * \brief Read a maintenance write request hop count value. + * + * \param[in] stack The stack to operate on. + * \return The hopcount value of the packet. + * + * This function returns the hop count value of a received maintenance write + * request packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint8_t RIO_readMaintenanceWriteRequestHop( RioStack_t *stack ); + +/** + * \brief Read a maintenance write request offset value. + * + * \param[in] stack The stack to operate on. + * \return The offset value of the packet. + * + * This function returns the offset value of a received maintenance write + * request packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint32_t RIO_readMaintenanceWriteRequestOffset( RioStack_t *stack ); + +/** + * \brief Read a maintenance write request data value. + * + * \param[in] stack The stack to operate on. + * \return The data value of the packet. + * + * This function returns the data value of a received maintenance write + * request packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint32_t RIO_readMaintenanceWriteRequestData( RioStack_t *stack ); + +/** + * \brief Read a maintenance write response hop count value. + * + * \param[in] stack The stack to operate on. + * \return The hopcount value of the packet. + * + * This function returns the hop count value of a received maintenance write + * response packet. + * + * \note In normal operational mode, the stack answers maintenance requests + * automatically without user intervention. This function should only be + * called if the stack is compiled in transparent mode. + */ +uint8_t RIO_readMaintenanceWriteResponseHop( RioStack_t *stack ); + +/** + * \brief Send an NWRITE request to write a byte. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] address The byte address to write to. + * \param[in] data The byte data to write. + * This function creates and sends an NWRITE request packet. No reply will be received. + * + * \note The address is a byte address, not a word address. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +void RIO_sendNwrite8( RioStack_t *stack, const uint16_t destid, const uint32_t address, const uint8_t data ); + +/** + * \brief Send an NWRITE_R request to write a byte. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to be returned in the response. + * \param[in] address The byte address to write to. + * \param[in] data The byte data to write. + * \return An identifier that maps to the packet transaction identifier that are received using + * RIO_packetTid. + * + * This function creates and sends an NWRITE_R request packet. A reply should be received + * when the write has been completed. + * + * \note The address is a byte address, not a word address. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +void RIO_sendNwriteR8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data ); + +/** + * \brief Get the byte address from an NWRITE or NWRITE_R packet. + * + * \param[in] stack The stack to operate on. + * \return The byte address contained in the NWRITE or NWRITE_R packet. + * + * This function reads a received an NWRITE or NWRITE_R request packet and fetches the address + * contained within. + * + * \note The address is a byte address, not a word address. + */ +uint32_t RIO_readNwriteAddress8( RioStack_t *stack ); + +/** + * \brief Get the number of bytes to write from an NWRITE or NWRITE_R packet. + * + * \param[in] stack The stack to operate on. + * \return The number of bytes requested to be written in a NWRITE or NWRITE_R packet. + * + * This function reads a received an NWRITE or NWRITE_R request packet and fetches the + * number of bytes requested to be written. + * + * \note The returned size is the number of bytes. + */ +uint8_t RIO_readNwriteSize8( RioStack_t *stack ); + +/** + * \brief Get the byte to write from a NWRITE or NWRITE_R packet. + * + * \param[in] stack The stack to operate on. + * \return The byte requested to be written in a NWRITE or NWRITE_R packet. + * + * This function reads a received an NWRITE or NWRITE_R request packet and fetches the + * byte to write. + */ +uint8_t RIO_readNwritePayload8( RioStack_t *stack ); + + +/** + * \brief Send a NREAD request to read a byte. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device id of the destination end point. + * \param[in] tid The transaction id to be returned in the response. + * \param[in] address The byte address to read. + * \return An identifier that maps to the packet identifier that are received using + * RIO_packetTid. + * + * This function creates and sends an NREAD request packet. The response packet will + * contain one byte of data. The reply is received using RIO_readResponseDone8(). + * + * \note The address is a byte address, not a word address. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +void RIO_sendNread8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address ); + + +/** + * \brief Get the byte address from a NREAD packet. + * + * \param[in] stack The stack to operate on. + * \return The byte address contained in a NREAD packet. + * + * This function reads a received an NREAD request packet and fetches the address + * contained within. + * + * \note The address is a byte address, not a word address. + */ +uint32_t RIO_readNreadAddress8( RioStack_t *stack ); + +/** + * \brief Get the number of bytes to read from a NREAD packet. + * + * \param[in] stack The stack to operate on. + * \return The number of bytes requested to read in a NREAD packet. + * + * This function reads a received an NREAD request packet and fetches the + * number of bytes to return in the reply. + * + * \note The returned size is the number of bytes. + */ +uint8_t RIO_readNreadSize8( RioStack_t *stack ); + +/** + * \brief Get a doorbell info field. + * + * \param[in] stack The stack to operate on. + * \return The info field of a doorbell. + * + * This function is used to read and return the info field of a received doorbell. + */ +uint16_t RIO_readDoorbellInfo( RioStack_t *stack ); + +/** + * \brief Send a byte message. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The device identifier of the target to send the message to. + * \param[in] mbox The mailbox to send the message to. + * \param[in] size The number of bytes to send. + * \param[in] data A pointer to an array of bytes to send. The parameter size indicates + * the number of bytes to send. + * + * This functions sends a message to a mailbox in an end-point target. A message response + * should be sent when the message has been processed using the RIO_sendMessageResponseDone(), + * RIO_sendMessageResponseRetry() or RIO_sendMessageResponseError() functions. + * + * \note All sizes that are transmitted are even double words. If 48-bits are + * sent then 64 bits will be received on the other side with the last bits + * padded to zero. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +void RIO_sendMessage8( RioStack_t *stack, const uint16_t destid, const uint8_t mbox, const uint16_t size, const uint8_t *data ); + +/** + * \brief Read a received message mailbox. + * + * \param[in] stack The stack to operate on. + * \return The mailbox of a received message. + * + * This function returns the mailbox of an incoming message. + */ +uint8_t RIO_readMessageMbox( RioStack_t *stack ); + +/** + * \brief Read a received message payload size in bytes. + * + * \param[in] stack The stack to operate on. + * \return The size in bytes of the received message payload. + * + * This function returns the number of bytes that was received in + * an incoming message. + * + * \note All sizes that are actually transmitted are even double words. If + * 48-bits are sent then 64 bits will be received on the other side with + * the last bits padded to zero. + */ +uint16_t RIO_readMessageSize8( RioStack_t *stack ); + +/** + * \brief Get the payload of a received message. + * + * \param[in] stack The stack to operate on. + * \param[out] buffer A byte pointer to where to place the payload. + * \return None + * This function is used to copy the byte content of a received message. + */ +void RIO_readMessagePayload8( RioStack_t *stack, uint8_t *buffer ); + +/** + * \brief Send a response with one byte data payload. + * + * \param[in] stack The stack to operate on. + * \param[in] destid The destination identifier of the response. + * \param[in] tid The transaction identifier for the reply. It should correspond to + * the tid in the received packet for which this response is sent. + * \param[in] address The byte address that was read. + * \param[in] data The data to return in the reply. + * + * This function creates a response packet with the specified destination + * identifier, transaction id and data payload. The generated packet are placed + * in the outbound packet queue. + * + * \note Call RIO_sendAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + */ +void RIO_sendResponseDone8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data ); + +/** + * \brief Read a one byte payload from a response. + * + * \param[in] stack The stack to operate on. + * \return The byte data payload contained in the response. + * + * This function reads a response packet and returns a one byte payload + * contained within. + */ +uint8_t RIO_readResponseDone8( RioStack_t *stack ); + +/** + * \brief Get the target mailbox. + * + * \param[in] stack The stack to operate on. + * \return The target mailbox. + * + * This function is used to get the target mailbox of a message response. + */ +uint8_t RIO_readMessageResponseMbox( RioStack_t *stack ); + +#endif /* _RIO_STACK_H */ + +/*************************** end of file **************************************/
1.0.1/sw/stack/riostack.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/sw/codec/riocodecuart.c =================================================================== --- 1.0.1/sw/codec/riocodecuart.c (nonexistent) +++ 1.0.1/sw/codec/riocodecuart.c (revision 29) @@ -0,0 +1,548 @@ +/******************************************************************************* + * + * RapidIO IP Library Core + * + * This file is part of the RapidIO IP library project + * http://www.opencores.org/cores/rio/ + * + * Description: + * This file contains code that can serialize and deserialize rio symbols onto + * and from an 8-bit UART transmission channel. + * + * 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 + * + *******************************************************************************/ + +#include + +typedef enum +{ + RIO_SYMBOL_TYPE_IDLE, RIO_SYMBOL_TYPE_CONTROL, + RIO_SYMBOL_TYPE_DATA, RIO_SYMBOL_TYPE_ERROR +} RioSymbolType; + +typedef struct +{ + RioSymbolType type; + uint32_t data; +} RioSymbol; + +typedef struct +{ + +} RioStack_t; + +void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s ); +RioSymbol RIO_portGetSymbol( RioStack_t *stack ); + + +void receiveByte(RioStack_t *stack, uint8_t incoming) +{ + static RioSymbol rxSymbol; + static uint8_t flagFound = 0; + static uint8_t symbolCounter = 0; + + + if(incoming != 0x7e) + { + if(incoming != 0x7d) + { + if(flagFound) + { + incoming ^= 0x20; + } + else + { + /* Dont do anything. */ + } + + switch(symbolCounter) + { + case 0: + rxSymbol.type = RIO_SYMBOL_TYPE_ERROR; + rxSymbol.data = incoming; + symbolCounter++; + break; + case 1: + rxSymbol.type = RIO_SYMBOL_TYPE_ERROR; + rxSymbol.data <<= 8; + rxSymbol.data |= incoming; + symbolCounter++; + break; + case 2: + rxSymbol.type = RIO_SYMBOL_TYPE_CONTROL; + rxSymbol.data <<= 8; + rxSymbol.data |= incoming; + symbolCounter++; + break; + case 3: + rxSymbol.type = RIO_SYMBOL_TYPE_DATA; + rxSymbol.data <<= 8; + rxSymbol.data |= incoming; + + RIO_portAddSymbol(stack, rxSymbol); + + rxSymbol.data = 0x00000000; + symbolCounter = 0; + break; + } + + flagFound = 0; + } + else + { + flagFound = 1; + } + } + else + { + if(symbolCounter == 0) + { + rxSymbol.type = RIO_SYMBOL_TYPE_IDLE; + RIO_portAddSymbol(stack, rxSymbol); + } + else + { + RIO_portAddSymbol(stack, rxSymbol); + } + + symbolCounter = 0; + } +} + +uint8_t transmitByte(RioStack_t *stack) +{ + uint8_t returnValue; + static uint8_t symbolCounter = 3; + static uint8_t stuffing = 0; + static RioSymbol txSymbol; + uint8_t outbound; + + + /* Check if the previous symbol has been sent. */ + if((symbolCounter == 3) && (stuffing == 0)) + { + /* Symbol sent. */ + + /* Get a new symbol. */ + txSymbol = RIO_portGetSymbol(stack); + if(txSymbol.type == RIO_SYMBOL_TYPE_CONTROL) + { + txSymbol.data <<= 8; + } + } + else + { + /* Symbol not sent. */ + /* Continue to send the old symbol. */ + } + + /* Check if a flag should be sent. */ + if ((txSymbol.type == RIO_SYMBOL_TYPE_IDLE) || + ((stuffing == 0) && (symbolCounter == 0) && (txSymbol.type == RIO_SYMBOL_TYPE_CONTROL))) + { + /* A flag needs to be sent. */ + /* An idle symbol should be sent as a flag and a control symbol should always be + terminated by a flag. */ + returnValue = 0x7e; + symbolCounter = 3; + stuffing = 0; + } + else + { + /* A flag does not need to be sent. */ + + /* Get the current byte in the symbol. */ + outbound = txSymbol.data >> (8*symbolCounter); + + /* Check if stuffing is active. */ + if(!stuffing) + { + /* No stuffing active. */ + + /* Check if the current byte needs to be stuffed. */ + if((outbound != 0x7e) && (outbound != 0x7d)) + { + /* The current byte does not need to be stuffed. */ + returnValue = outbound; + symbolCounter = (symbolCounter - 1) & 0x3; + } + else + { + /* The current byte needs to be stuffed. */ + returnValue = 0x7d; + stuffing = 1; + } + } + else + { + /* Stuffing is active. */ + /* An escape sequence has been sent, transmit the original data but change it to not being a flag. */ + returnValue = outbound ^ 0x20; + stuffing = 0; + symbolCounter = (symbolCounter - 1) & 0x3; + } + } + + return returnValue; +} + + + +/******************************************************************************* + * Module test code. + *******************************************************************************/ + +#define TESTEXPR(got, expected) \ + if ((got)!=(expected)) \ + { \ + printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", \ + __LINE__, #got, (got), (got), (expected), (expected)); \ + exit(1); \ + } +static RioSymbol txSymbol; +static uint8_t txNewSymbol; +static RioSymbol rxSymbol; +static uint8_t rxNewSymbol; +void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s ) +{ + rxNewSymbol = 1; + rxSymbol = s; +} +RioSymbol RIO_portGetSymbol( RioStack_t *stack ) +{ + if(txNewSymbol) + { + txNewSymbol = 0; + return txSymbol; + } + else + { + RioSymbol s; + s.type = RIO_SYMBOL_TYPE_ERROR; + return s; + } +} +int main(int argc, char *argv[]) +{ + RioStack_t *stack; + + /*************************************************************** + * Test receiver. + ***************************************************************/ + + /* Receive a flag. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_IDLE); + + /* Receive not a flag followed by flag. */ + rxNewSymbol = 0; + receiveByte(stack, 0xaa); + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_ERROR); + + /* Receive not a flag twice followed by flag. */ + rxNewSymbol = 0; + receiveByte(stack, 0xaa); + receiveByte(stack, 0x55); + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_ERROR); + + /* Receive a control symbol followed by flag. */ + rxNewSymbol = 0; + receiveByte(stack, 0x11); + receiveByte(stack, 0x22); + receiveByte(stack, 0x33); + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL); + TESTEXPR(rxSymbol.data, 0x00112233); + + /* Receive a data symbol. */ + rxNewSymbol = 0; + receiveByte(stack, 0x44); + receiveByte(stack, 0x55); + receiveByte(stack, 0x66); + receiveByte(stack, 0x77); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA); + TESTEXPR(rxSymbol.data, 0x44556677); + + /* Receive a back-to-back data symbol. */ + rxNewSymbol = 0; + receiveByte(stack, 0x88); + receiveByte(stack, 0x99); + receiveByte(stack, 0xaa); + receiveByte(stack, 0xbb); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA); + TESTEXPR(rxSymbol.data, 0x8899aabb); + + /* Receive a back-to-back control symbol. */ + rxNewSymbol = 0; + receiveByte(stack, 0xcc); + receiveByte(stack, 0xdd); + receiveByte(stack, 0xee); + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL); + TESTEXPR(rxSymbol.data, 0x00ccddee); + + /* Test control symbol with one stuffed byte. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0xff); + receiveByte(stack, 0x01); + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL); + TESTEXPR(rxSymbol.data, 0x007eff01); + + /* Test control symbol with two stuffed bytes. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0xff); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5d); + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL); + TESTEXPR(rxSymbol.data, 0x007eff7d); + + /* Test control symbol with three stuffed bytes. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5d); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5d); + receiveByte(stack, 0x7e); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_CONTROL); + TESTEXPR(rxSymbol.data, 0x007d7e7d); + + /* Test data symbol with one stuffed byte. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0x00); + receiveByte(stack, 0x01); + receiveByte(stack, 0x02); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA); + TESTEXPR(rxSymbol.data, 0x7e000102); + + /* Test data symbol with two stuffed bytes. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5d); + receiveByte(stack, 0x03); + receiveByte(stack, 0x04); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA); + TESTEXPR(rxSymbol.data, 0x7e7d0304); + + /* Test data symbol with three stuffed bytes. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5d); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0x05); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA); + TESTEXPR(rxSymbol.data, 0x7e7d7e05); + + /* Test data symbol with four stuffed bytes. */ + rxNewSymbol = 0; + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5d); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5e); + receiveByte(stack, 0x7d); + receiveByte(stack, 0x5d); + TESTEXPR(rxNewSymbol, 1); + TESTEXPR(rxSymbol.type, RIO_SYMBOL_TYPE_DATA); + TESTEXPR(rxSymbol.data, 0x7e7d7e7d); + + /*************************************************************** + * Test transmitter. + ***************************************************************/ + + /* Test transmission of idle symbol. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_IDLE; + TESTEXPR(transmitByte(stack), 0x7e); + + /* Test transmission of control symbol. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_CONTROL; + txSymbol.data = 0x00112233; + TESTEXPR(transmitByte(stack), 0x11); + TESTEXPR(transmitByte(stack), 0x22); + TESTEXPR(transmitByte(stack), 0x33); + TESTEXPR(transmitByte(stack), 0x7e); + + /* Test transmission of data symbol. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_DATA; + txSymbol.data = 0x44556677; + TESTEXPR(transmitByte(stack), 0x44); + TESTEXPR(transmitByte(stack), 0x55); + TESTEXPR(transmitByte(stack), 0x66); + TESTEXPR(transmitByte(stack), 0x77); + + /* Test transmission of back-to-back data symbol. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_DATA; + txSymbol.data = 0x8899aabb; + TESTEXPR(transmitByte(stack), 0x88); + TESTEXPR(transmitByte(stack), 0x99); + TESTEXPR(transmitByte(stack), 0xaa); + TESTEXPR(transmitByte(stack), 0xbb); + + /* Test transmission of back-to-back control symbol. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_CONTROL; + txSymbol.data = 0xffccddee; + TESTEXPR(transmitByte(stack), 0xcc); + TESTEXPR(transmitByte(stack), 0xdd); + TESTEXPR(transmitByte(stack), 0xee); + TESTEXPR(transmitByte(stack), 0x7e); + + /* Test transmission of back-to-back control symbol. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_CONTROL; + txSymbol.data = 0xff010203; + TESTEXPR(transmitByte(stack), 0x01); + TESTEXPR(transmitByte(stack), 0x02); + TESTEXPR(transmitByte(stack), 0x03); + TESTEXPR(transmitByte(stack), 0x7e); + + /* Test transmission of control symbol with one stuffed byte. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_CONTROL; + txSymbol.data = 0xff7e0102; + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x01); + TESTEXPR(transmitByte(stack), 0x02); + TESTEXPR(transmitByte(stack), 0x7e); + + /* Test transmission of stuffed control symbol with two stuffed bytes. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_CONTROL; + txSymbol.data = 0xff7e7d01; + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5d); + TESTEXPR(transmitByte(stack), 0x01); + TESTEXPR(transmitByte(stack), 0x7e); + + /* Test transmission of stuffed control symbol with three stuffed bytes. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_CONTROL; + txSymbol.data = 0xff7e7d7e; + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5d); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x7e); + + /* Test transmission of data symbol with one stuffed byte. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_DATA; + txSymbol.data = 0x7e010203; + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x01); + TESTEXPR(transmitByte(stack), 0x02); + TESTEXPR(transmitByte(stack), 0x03); + + /* Test transmission of data symbol with two stuffed byte. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_DATA; + txSymbol.data = 0x7e7d0102; + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5d); + TESTEXPR(transmitByte(stack), 0x01); + TESTEXPR(transmitByte(stack), 0x02); + + /* Test transmission of data symbol with three stuffed byte. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_DATA; + txSymbol.data = 0x7e7d7e01; + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5d); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x01); + + /* Test transmission of data symbol with four stuffed byte. */ + txNewSymbol = 1; + txSymbol.type = RIO_SYMBOL_TYPE_DATA; + txSymbol.data = 0x7e7d7e7d; + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5d); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5e); + TESTEXPR(transmitByte(stack), 0x7d); + TESTEXPR(transmitByte(stack), 0x5d); + + /*************************************************************** + * Test complete. + ***************************************************************/ + + printf("Test complete.\n"); +}
1.0.1/sw/codec/riocodecuart.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: 1.0.1/doc/rio.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: 1.0.1/doc/rio.pdf =================================================================== --- 1.0.1/doc/rio.pdf (nonexistent) +++ 1.0.1/doc/rio.pdf (revision 29)
1.0.1/doc/rio.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: 1.0.1/doc/rio.odt =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: 1.0.1/doc/rio.odt =================================================================== --- 1.0.1/doc/rio.odt (nonexistent) +++ 1.0.1/doc/rio.odt (revision 29)
1.0.1/doc/rio.odt Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ 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.