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

Subversion Repositories rio

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /rio
    from Rev 49 to Rev 50
    Reverse comparison

Rev 49 → Rev 50

/tags/1.0.2-release/sw/stack/test_riostack.c
0,0 → 1,1955
/*******************************************************************************
*
* RapidIO IP Library Core
*
* This file is part of the RapidIO IP library project
* http://www.opencores.org/cores/rio/
*
* Description:
* This file contains automatic regression tests for riopacket. Compile and
* run it by using:
* gcc -o testriostack test_riostack.c riopacket.c -fprofile-arcs -ftest-coverage
* ./testriostack
* gcov test_riostack.c
*
* To Do:
* -
*
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
*
*******************************************************************************
*
* Copyright (C) 2015 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 <stdio.h>
#include <stdlib.h>
 
#define MODULE_TEST
#include "riostack.c"
 
#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("\nERROR at line %u:%s=%u (0x%08x)\n", \
__LINE__, #got, (got), (got)); \
exit(1); \
}
 
#define TESTEXPR(got, expected) \
if ((got)!=(expected)) \
{ \
printf("\nERROR 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_t got, RioSymbol_t expected)
{
if ((got).type==(expected).type)
{
switch ((got).type)
{
case RIOSTACK_SYMBOL_TYPE_ERROR:
case RIOSTACK_SYMBOL_TYPE_IDLE:
break;
case RIOSTACK_SYMBOL_TYPE_CONTROL:
if((got).data != (expected).data)
{
if(STYPE0_GET((got).data) != STYPE0_GET((expected).data))
{
printf("\nERROR 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("\nERROR 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("\nERROR 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("\nERROR 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("\nERROR 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("\nERROR at line %u:CRC5=0x%02x expected=0x%02x\n",
line, CRC5_GET((got).data), CRC5_GET((expected).data));
}
exit(1);
}
break;
case RIOSTACK_SYMBOL_TYPE_DATA:
if((got).data != (expected).data)
{
printf("\nERROR 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("\nERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n",
line, expression, (got).type, (got).type, (expected).type, (expected).type);
exit(1);
}
}
 
 
 
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 = RIOPACKET_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 = RIOPACKET_Crc32(content, crc);
doorbell[1] = content;
 
/* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
content = ((uint32_t) info) << 16;
crc = RIOPACKET_Crc16(info, crc);
content |= ((uint32_t) crc);
doorbell[2] = content;
 
return 3;
 
}
 
/*******************************************************************************
* Module test for this file.
*******************************************************************************/
int32_t main(void)
{
RioStack_t stack;
uint32_t rxPacketBuffer[RIOSTACK_BUFFER_SIZE*8], txPacketBuffer[RIOSTACK_BUFFER_SIZE*8];
RioPacket_t rioPacket;
uint32_t packet[69];
RioSymbol_t s, c, d;
int i, j, k;
uint16_t length;
uint16_t dstid;
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 packetLength;
 
 
/*************************************************************************
* Test prelude.
* Setup the RIO stack for operation.
*************************************************************************/
 
/* Open the stack and set the port status to initialized. */
RIOSTACK_open(&stack, NULL,
RIOSTACK_BUFFER_SIZE*8, &rxPacketBuffer[0],
RIOSTACK_BUFFER_SIZE*8, &txPacketBuffer[0]);
 
/* Set the port timeout. */
RIOSTACK_portSetTimeout(&stack, 1);
 
/* Set the current port time. */
RIOSTACK_portSetTime(&stack, 0);
 
/******************************************************************************/
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. */
RIOPACKET_setDoorbell(&rioPacket, 1, 0xffff, 0, 0xdeaf);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
/* 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++)
{
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_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. */
RIOSTACK_portSetStatus(&stack, 1);
 
/* Set port time. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
/* Check that packet was not received. */
TESTEXPR(RIOSTACK_getInboundQueueLength(&stack), 0);
 
/******************************************************************************/
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++)
{
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
}
c = CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0);
c.data ^= 1;
RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
/* Check that the packet was ignored. */
TESTEXPR(RIOSTACK_getInboundQueueLength(&stack), 0);
 
/******************************************************************************/
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++)
{
RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
/* Check that the packet is received. */
TESTEXPR(RIOSTACK_getInboundQueueLength(&stack), 1);
 
/******************************************************************************/
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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_getInboundPacket(&stack, &rioPacket);
 
/* Check that the status-control-symbols are generated each 256 symbol. */
for(i = 0; i < 255; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
 
/* Check that the buffer status has been updated. */
s = RIOSTACK_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. */
RIOPACKET_setDoorbell(&rioPacket, 2, 0xffff, 1, 0xc0de);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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);
 
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
s = RIOSTACK_portGetSymbol(&stack);
 
/* Check that nothing is transmitted. */
TESTEXPR(s.type, RIOSTACK_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. */
RIOSTACK_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. */
RIOSTACK_getInboundPacket(&stack, &rioPacket);
RIOPACKET_getDoorbell(&rioPacket, &dstid, &srcid, &tid, &info);
TESTEXPR(tid, 1);
 
/* Check that the buffer status has changed to show that a buffer is available. */
s = RIOSTACK_portGetSymbol(&stack);
while(s.type == RIOSTACK_SYMBOL_TYPE_IDLE)
{
s = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 0, STYPE1_NOP, 0);
s = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
c = CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 0, STYPE1_NOP, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send two packets to see that the first acknowledge has been processed. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 2, 0xfeed);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 3, 0xdeed);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Get the first packet. */
packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed);
c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTSYMBOL(s, c);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Indicate the packets must be retransmitted. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTSYMBOL(s, c);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Confirm the reception of the packets. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 2, 1, STYPE1_NOP, 0));
RIOSTACK_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. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 0, STYPE1_NOP, 0));
 
/* Send a packet. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 4, 0xf00d);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Check that nothing is transmitted but status-control-symbols. */
for(i = 0; i < 255; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_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++)
{
RIOSTACK_getInboundPacket(&stack, &rioPacket);
RIOPACKET_getDoorbell(&rioPacket, &dstid, &srcid, &tid, &info);
TESTEXPR(tid, j+2);
for(i = 0; i < 255; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
s = RIOSTACK_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. */
RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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;
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[0];
RIOSTACK_portAddSymbol(&stack, d);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = ((uint32_t) RIOPACKET_Crc32(packet[0] & 0x07ffffff, 0xffff)) << 16;
RIOSTACK_portAddSymbol(&stack, d);
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
for(i = 0; i < packetLength; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
RIOSTACK_portAddSymbol(&stack, d);
}
for(; i < 70; i++)
{
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = i;
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[0];
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTSYMBOL(s, c);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_SYMBOL_TYPE_ERROR;
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send a link-request. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 5, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_NOP, 0));
 
/* Check that packets are relayed after this. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 5, 2);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
packetLength = createDoorbell(packet, 5, 0, 0xffff, 5, 2);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_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. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 6, 2);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
packetLength = createDoorbell(packet, 6, 0, 0xffff, 6, 2);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for another packet. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_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. */
RIOSTACK_portSetTime(&stack, 2);
 
/* Send an output packet. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 7, 2);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Receive the transmitted packet. */
packetLength = createDoorbell(packet, 7, 0, 0xffff, 7, 2);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Indicate that time has passed to trigger a timeout. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for the retransmitted packet. */
RIOSTACK_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. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 8, 3);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Receive the transmitted packet. */
packetLength = createDoorbell(packet, 8, 0, 0xffff, 8, 3);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send packet-not-accepted indicating CRC error. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 8, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for the retransmitted packet. */
RIOSTACK_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. */
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send link-response with expected ackId. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 9, 16, STYPE1_NOP, 0));
/* Send a status directly afterwards. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0));
 
/* Send an output packet. */
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 9, 4);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
/* Receive retransmitted packet. */
packetLength = createDoorbell(packet, 9, 0, 0xffff, 9, 4);
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
/* Send acknowledge for the retransmitted packet. */
RIOSTACK_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(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 20, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 21, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 22, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 23, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 24, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 25, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 26, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&stack) > 0);
RIOPACKET_setDoorbell(&rioPacket, 0, 0xffff, 27, 0xbabe);
RIOSTACK_setOutboundPacket(&stack, &rioPacket);
 
TESTCOND(RIOSTACK_getOutboundQueueAvailable(&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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
for(i = 0; i < 10; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, RIOSTACK_SYMBOL_TYPE_IDLE);
}
 
/* Request retransmission. */
RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
/* Acknowledge. */
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 10, 1, STYPE1_NOP, 0));
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
 
RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 14, 1, STYPE1_NOP, 0));
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_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 = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
for(i = 0; i < packetLength; i++)
{
s = RIOSTACK_portGetSymbol(&stack);
d.type = RIOSTACK_SYMBOL_TYPE_DATA;
d.data = packet[i];
TESTEXPR(s.type, d.type);
TESTEXPR(s.data, d.data);
}
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 15, 1, STYPE1_NOP, 0));
c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
s = RIOSTACK_portGetSymbol(&stack);
TESTEXPR(s.type, c.type);
TESTEXPR(s.data, c.data);
 
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 16, 1, STYPE1_NOP, 0));
RIOSTACK_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 17, 1, STYPE1_NOP, 0));
 
/******************************************************************************/
TESTEND;
/******************************************************************************/
 
return 0;
}
 
/*************************** end of file **************************************/
/tags/1.0.2-release/sw/stack/riostack.c
0,0 → 1,2166
/*******************************************************************************
*
* 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 from the lower-half by calling
* RIOSTACK_portAddSymbol() and symbols to transmit are fetched from the stack
* using RIOSTACK_portGetSymbol(). These two functions are the low-level interface
* towards a physical transmission channel.
* The function RIOSTACK_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 upper-half interface are the RIOSTACK_setOutboundPacket() function used to
* insert packets into the outbound transmission queue and RIOSTACK_getInboundPacket()
* is used to get packet from the inbound reception queue. The
* RIOSTACK_getInboundQueueLength() function is used to check if any packet is available
* for reading in the inbound reception queue.
*
* -----------------
* | 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:
* RIOSTACK_open(...);
* RIOSTACK_portSetTimeout(...);
* ...
* <Symbol transcoder is successfully decoding symbols from the link>
* RIOSTACK_portSetStatus(1);
*
* Bottom-half traffic handling:
* RIOSTACK_portSetTime(...);
* <get symbol from decoder>
* RIOSTACK_portAddSymbol(...);
* s = RIOSTACK_portGetSymbol(...);
* <send symbol to encoder>
*
* Receiving packets:
* if(RIOSTACK_getInboundQueueLength(...) > 0)
* {
* RIOSTACK_getInboundPacket(...);
* <process the new packet>
* }
*
* Transmitting packets:
* <create a new packet>
* if(RIOSTACK_getOutboundQueueAvailable(...) > 0)
* {
* RIOSTACK_setOutboundPacket(...);
* }
*
* More details about the usage can be found in the module tests in test_riostack.c.
*
* To Do:
* - Optimize the packing of stype0 and stype1 into control symbols.
*
* Author(s):
* - Magnus Rosenius, magro732@opencores.org
*
*******************************************************************************
*
* Copyright (C) 2015 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);
 
/**
* \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.
* \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_t 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 Create a queue with a specified size and a buffer attached to it.
*
* \param[in] size The number of entries in the queue.
* \param[in] buffer 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 int 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 int 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 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 QueueGetSize(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 RIOSTACK_open(RioStack_t *stack, void *private,
const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer,
const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer)
{
/* 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/RIOSTACK_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/RIOSTACK_BUFFER_SIZE), txPacketBuffer);
 
/* 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->statusOutboundLinkLatencyMax = 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 pointer to user private data. */
stack->private = private;
}
 
 
 
/*******************************************************************************************
* Stack status and queue access functions.
* Note that status counters are accessed directly in the stack-structure.
*******************************************************************************************/
 
int RIOSTACK_getStatus(RioStack_t *stack)
{
return !(((stack->rxState == RX_STATE_UNINITIALIZED) || (stack->rxState == RX_STATE_PORT_INITIALIZED)) &&
((stack->txState == TX_STATE_UNINITIALIZED) || (stack->txState == TX_STATE_PORT_INITIALIZED)));
}
 
 
 
void RIOSTACK_clearOutboundQueue(RioStack_t *stack)
{
while(!QueueEmpty(stack->txQueue))
{
stack->txQueue = QueueDequeue(stack->txQueue);
}
}
 
 
 
uint8_t RIOSTACK_getOutboundQueueLength(RioStack_t *stack)
{
return QueueLength(stack->txQueue);
}
 
 
 
uint8_t RIOSTACK_getOutboundQueueAvailable(RioStack_t *stack)
{
return QueueAvailable(stack->txQueue);
}
 
 
 
void RIOSTACK_setOutboundPacket(RioStack_t *stack, RioPacket_t *packet)
{
uint32_t *src, *dst;
uint32_t size;
uint32_t i;
 
 
ASSERT((QueueAvailable(stack->txQueue) > 0u),
"Transmission queue packet overflow.");
 
src = &packet->payload[0];
dst = QueueGetBackBuffer(stack->txQueue);
size = packet->size;
for(i = 0; i < size; i++)
{
dst[i] = src[i];
}
 
QueueSetSize(stack->txQueue, size);
stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
 
 
void RIOSTACK_clearInboundQueue(RioStack_t *stack)
{
while(!QueueEmpty(stack->rxQueue))
{
stack->rxQueue = QueueDequeue(stack->rxQueue);
}
}
 
 
 
uint8_t RIOSTACK_getInboundQueueLength(RioStack_t *stack)
{
return QueueLength(stack->rxQueue);
}
 
 
 
uint8_t RIOSTACK_getInboundQueueAvailable(RioStack_t *stack)
{
return QueueAvailable(stack->rxQueue);
}
 
 
 
void RIOSTACK_getInboundPacket(RioStack_t *stack, RioPacket_t *packet)
{
uint32_t *src, *dst;
uint32_t size;
uint32_t i;
 
 
ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
src = QueueGetFrontBuffer(stack->rxQueue);
dst = &packet->payload[0];
size = QueueGetSize(stack->rxQueue);
for(i = 0; i < size; i++)
{
dst[i] = src[i];
}
 
packet->size = size;
stack->rxQueue = QueueDequeue(stack->rxQueue);
}
 
 
 
/*******************************************************************************************
* Packet port functions.
*******************************************************************************************/
 
void RIOSTACK_portSetTime(RioStack_t *stack, const uint32_t time)
{
stack->portTime = time;
}
 
 
 
void RIOSTACK_portSetTimeout(RioStack_t *stack, const uint32_t time)
{
stack->portTimeout = time;
}
 
 
 
void RIOSTACK_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 RIOSTACK_portAddSymbol(RioStack_t *stack, const RioSymbol_t 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 == RIOSTACK_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;
}
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 RIOSTACK_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++;
}
break;
 
case RIOSTACK_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 <= RIOPACKET_SIZE_MAX))
{
/* 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 = RIOPACKET_Crc32(s.data & (uint32_t)0x03fffffful, 0xffffu);
}
else
{
/* This is not the first symbol. */
/* Continue to calculate the CRC of the packet. */
stack->rxCrc = RIOPACKET_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
{
/* 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++;
}
}
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++;
}
break;
 
case RIOSTACK_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++;
break;
 
case RIOSTACK_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 RIOSTACK_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;
break;
 
case STYPE1_LINK_REQUEST:
/* A link-request has been received. */
handleLinkRequest(stack, CMD_GET(s.data));
stack->rxState = RX_STATE_LINK_INITIALIZED;
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++;
}
break;
 
case RIOSTACK_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++;
break;
 
case RIOSTACK_SYMBOL_TYPE_DATA:
case RIOSTACK_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 RIOSTACK_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;
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 RIOSTACK_SYMBOL_TYPE_DATA:
case RIOSTACK_SYMBOL_TYPE_IDLE:
case RIOSTACK_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_t RIOSTACK_portGetSymbol(RioStack_t *stack )
{
RioSymbol_t 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 = RIOSTACK_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;
}
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 != QueueGetSize(stack->txQueue))
{
/* The packet has not been completly sent. */
 
/* Create a new data symbol to transmit. */
s.type = RIOSTACK_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. */
/* 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. */
/* 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. */
/* 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 = RIOSTACK_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. */
/* 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++;
}
}
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.
******************************************************************************/
 
/* 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;
 
/* 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 = RIOSTACK_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 = RIOSTACK_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 = RIOSTACK_SYMBOL_TYPE_IDLE;
break;
}
 
/* Return the created symbol. */
return s;
}
 
 
 
/*******************************************************************************
* Local RapidIO stack helper 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)
{
uint32_t linkLatency;
 
 
/* Check if an acknowledge is expected and that it is for a transmitted packet. */
if((stack->txAckId != stack->txAckIdWindow) && (ackId == stack->txAckId))
{
/* Acknowledge for a recently transmitted packet received. */
 
/* Check if the latency of this packet is larger than the largest encountered so far. */
linkLatency = stack->portTime - stack->txFrameTimeout[ackId];
if(linkLatency > stack->statusOutboundLinkLatencyMax)
{
stack->statusOutboundLinkLatencyMax = linkLatency;
}
 
/* 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
{
/* 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++;
}
 
/* 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)
{
/* 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++;
}
else
{
/* 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++;
}
 
/* 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;
}
}
 
 
 
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)
{
/* 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. */
 
/* 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. */
 
/* 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++;
}
}
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++;
}
}
else
{
/* Packet has not already started. */
handleNewPacketStart(stack);
}
}
 
 
 
static void handleEndOfPacket(RioStack_t *stack)
{
/* 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++;
}
}
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++;
}
}
 
 
 
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. */
stack->statusInboundPacketRetry++;
stack->txState = TX_STATE_SEND_PACKET_RETRY;
stack->rxState = RX_STATE_INPUT_RETRY_STOPPED;
}
}
 
 
 
static void handleNewPacketEnd(RioStack_t *stack)
{
/* Save the size of the packet. */
QueueSetSize(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul);
 
/* Always forward the packet to the top of the stack. */
stack->rxQueue = QueueEnqueue(stack->rxQueue);
 
/* Make sure the CRC is reset to an invalid value to avoid a packet
accidentally being accepted. */
stack->rxCrc = 0xffff;
 
/* 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 RioSymbol_t CreateControlSymbol(const uint8_t stype0,
const uint8_t parameter0, const uint8_t parameter1,
const uint8_t stype1, const uint8_t cmd)
{
RioSymbol_t s;
 
s.type = RIOSTACK_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;
}
 
 
/*******************************************************************************************
* Internal queue functions.
*******************************************************************************************/
 
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 int QueueEmpty(const Queue_t q)
{
return (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 int QueueWindowEmpty(const Queue_t q)
{
return ((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+(RIOSTACK_BUFFER_SIZE*q.backIndex))[0] = size;
}
 
 
 
static void QueueSetContent(Queue_t q, const uint32_t index, const uint32_t content)
{
(q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[index+1ul] = content;
}
 
 
 
static uint32_t QueueGetSize(Queue_t q)
{
return (q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[0];
}
 
 
 
static uint32_t QueueGetFrontContent(const Queue_t q, const uint32_t index)
{
return (q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[index+1ul];
}
 
 
 
static uint32_t *QueueGetFrontBuffer(const Queue_t q )
{
return &((q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.windowIndex))[1]);
}
 
 
 
static uint32_t *QueueGetBackBuffer(const Queue_t q )
{
return &((q.buffer_p+(RIOSTACK_BUFFER_SIZE*q.backIndex))[1]);
}
/*************************** end of file **************************************/
tags/1.0.2-release/sw/stack/riostack.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/sw/stack/test_riopacket.c =================================================================== --- tags/1.0.2-release/sw/stack/test_riopacket.c (nonexistent) +++ tags/1.0.2-release/sw/stack/test_riopacket.c (revision 50) @@ -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: + * This file contains automatic regression tests for riopacket. Compile and + * run it by using: + * gcc -o testriopacket test_riopacket.c -fprofile-arcs -ftest-coverage + * ./testriopacket + * gcov test_riopacket.c + * + * To Do: + * - + * + * Author(s): + * - Magnus Rosenius, magro732@opencores.org + * + ******************************************************************************* + * + * Copyright (C) 2015 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 +#include + +#define MODULE_TEST +#include "riopacket.c" + +#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("\nERROR at line %u:%s=%u (0x%08x)\n", \ + __LINE__, #got, (got), (got)); \ + exit(1); \ + } + +#define TESTEXPR(got, expected) \ + if ((got)!=(expected)) \ + { \ + printf("\nERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", \ + __LINE__, #got, (got), (got), (expected), (expected)); \ + exit(1); \ + } + +#define TESTPACKET(got, expected) testSymbol(__LINE__, #got, (got), (expected)) + +void testPacket(uint32_t line, char *expression, RioPacket_t got, RioPacket_t expected) +{ + int i; + + + if ((got).size==(expected).size) + { + for(i = 0; i < got.size; i++) + { + if(got.payload[i] != expected.payload[i]) + { + printf("\nERROR at line %u:%s:payload[%u]:=%u (0x%08x) expected=%u (0x%08x)\n", + line, expression, i, (got).payload[i], (got).payload[i], (expected).payload[i], (expected).payload[i]); + exit(1); + } + } + } + else + { + printf("\nERROR at line %u:%s:size=%u (0x%08x) expected=%u (0x%08x)\n", + line, expression, (got).size, (got).size, (expected).size, (expected).size); + exit(1); + } +} + +void packetClear(RioPacket_t *packet) +{ + uint32_t i; + + for(i = 0; i < RIOPACKET_SIZE_MAX; i++) + { + packet->payload[i] = 0xdeadbeef; + } +} + +/******************************************************************************* + * Module test for this file. + *******************************************************************************/ +int32_t main(void) +{ + RioPacket_t packet; + int i, j, k; + uint16_t length; + uint16_t dstidExpected, dstid; + uint16_t srcidExpected, srcid; + uint8_t tidExpected, tid; + uint8_t hopExpected, hop; + uint8_t mailboxExpected, mailbox; + uint16_t infoExpected, info; + uint32_t addressExpected, address; + uint32_t dataExpected, data; + + uint16_t payloadSizeExpected, payloadSize; + uint8_t payloadExpected[256], payload[256]; + + uint8_t buffer[512]; + uint16_t bufferSize; + + srand(0); + + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riopacket-TC1"); + PrintS("Description: Test packet initialization, validation and appending."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: "); + PrintS("Result: "); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC1-Step1"); + /******************************************************************************/ + + RIOPACKET_init(&packet); + + TESTEXPR(RIOPACKET_size(&packet), 0); + TESTCOND(!RIOPACKET_valid(&packet)); + + RIOPACKET_append(&packet, 0x001a0001); + + TESTEXPR(RIOPACKET_size(&packet), 1); + TESTCOND(!RIOPACKET_valid(&packet)); + + RIOPACKET_append(&packet, 0xffff0000); + + TESTEXPR(RIOPACKET_size(&packet), 2); + TESTCOND(!RIOPACKET_valid(&packet)); + + RIOPACKET_append(&packet, 0xdeaf9903); + + TESTEXPR(RIOPACKET_size(&packet), 3); + TESTCOND(RIOPACKET_valid(&packet)); + + /* Check that altering the ackid does not affect the validity of the packet. */ + packet.payload[0] |= 0xfc000000; + TESTCOND(RIOPACKET_valid(&packet)); + + /* Access the packet and check its content. */ + TESTEXPR(RIOPACKET_getFtype(&packet), RIOPACKET_FTYPE_DOORBELL); + TESTEXPR(RIOPACKET_getDestination(&packet), 0x0001); + TESTEXPR(RIOPACKET_getSource(&packet), 0xffff); + TESTEXPR(RIOPACKET_getTid(&packet), 0x00); + RIOPACKET_getDoorbell(&packet, &dstid, &srcid, &tid, &info); + TESTEXPR(dstid, 0x0001); + TESTEXPR(srcid, 0xffff); + TESTEXPR(tid, 0x00); + TESTEXPR(info, 0xdeaf); + + bufferSize = RIOPACKET_serialize(&packet, sizeof(buffer), buffer); + TESTEXPR(bufferSize, 13); + TESTEXPR(buffer[0], 0x03); + TESTEXPR(buffer[1], 0xfc); + TESTEXPR(buffer[2], 0x1a); + TESTEXPR(buffer[3], 0x00); + TESTEXPR(buffer[4], 0x01); + TESTEXPR(buffer[5], 0xff); + TESTEXPR(buffer[6], 0xff); + TESTEXPR(buffer[7], 0x00); + TESTEXPR(buffer[8], 0x00); + TESTEXPR(buffer[9], 0xde); + TESTEXPR(buffer[10], 0xaf); + TESTEXPR(buffer[11], 0x99); + TESTEXPR(buffer[12], 0x03); + + RIOPACKET_init(&packet); + RIOPACKET_deserialize(&packet, bufferSize, buffer); + TESTCOND(RIOPACKET_valid(&packet)); + TESTEXPR(RIOPACKET_getFtype(&packet), RIOPACKET_FTYPE_DOORBELL); + TESTEXPR(RIOPACKET_getDestination(&packet), 0x0001); + TESTEXPR(RIOPACKET_getSource(&packet), 0xffff); + TESTEXPR(RIOPACKET_getTid(&packet), 0x00); + RIOPACKET_getDoorbell(&packet, &dstid, &srcid, &tid, &info); + TESTEXPR(dstid, 0x0001); + TESTEXPR(srcid, 0xffff); + TESTEXPR(tid, 0x00); + TESTEXPR(info, 0xdeaf); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riopacket-TC2"); + PrintS("Description: Test maintenance packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: "); + PrintS("Result: "); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC2-Step1"); + /******************************************************************************/ + + RIOPACKET_init(&packet); + RIOPACKET_setMaintReadRequest(&packet, 0xc0de, 0xbabe, 0x13, 0x41, 0xffffffff); + RIOPACKET_getMaintReadRequest(&packet, &dstid, &srcid, &hop, &tid, &address); + + TESTCOND(RIOPACKET_valid(&packet)); + TESTEXPR(dstid, 0xc0de); + TESTEXPR(srcid, 0xbabe); + TESTEXPR(hop, 0x13); + TESTEXPR(tid, 0x41); + TESTEXPR(address, 0x00fffffc); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riopacket-TC3"); + PrintS("Description: Test input/output packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: "); + PrintS("Result: "); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC3-Step1"); + /******************************************************************************/ + + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("TG_riopacket-TC4"); + PrintS("Description: Test message passing packets."); + PrintS("Requirement: XXXXX"); + PrintS("----------------------------------------------------------------------"); + PrintS("Step 1:"); + PrintS("Action: Send a message with invalid payload length."); + PrintS("Result: No packet should be generated."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step1"); + /******************************************************************************/ + + RIOPACKET_setMessage(&packet, 0xdead, 0xbeef, 0xc0, 0, &payloadExpected[0]); + + TESTEXPR(packet.size, 0); + TESTCOND(!RIOPACKET_valid(&packet)); + + RIOPACKET_setMessage(&packet, 0xdead, 0xbeef, 0xc0, 257, &payloadExpected[0]); + + TESTEXPR(packet.size, 0); + TESTCOND(!RIOPACKET_valid(&packet)); + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + PrintS("----------------------------------------------------------------------"); + PrintS("Step 2:"); + PrintS("Action: Test sending all possible payload sizes on random deviceIds "); + PrintS(" and mailboxes."); + PrintS("Result: The content of the packet should be equal to what was entered."); + PrintS("----------------------------------------------------------------------"); + /******************************************************************************/ + TESTSTART("TG_riostack-TC4-Step2"); + /******************************************************************************/ + + for(i = 1; i <= 256; i++) + { + dstidExpected = rand(); + srcidExpected = rand(); + mailboxExpected = rand(); + + if((i%8) == 0) + { + payloadSizeExpected = 8*(i/8); + } + else + { + payloadSizeExpected = 8*(i/8+1); + } + + for(j = 0; j < i; j++) + { + payloadExpected[j] = rand(); + } + + RIOPACKET_setMessage(&packet, dstidExpected, srcidExpected, mailboxExpected, + i, &payloadExpected[0]); + TESTCOND(RIOPACKET_valid(&packet)); + + RIOPACKET_getMessage(&packet, &dstid, &srcid, &mailbox, &payloadSize, &(payload[0])); + TESTEXPR(dstid, dstidExpected); + TESTEXPR(srcid, srcidExpected); + TESTEXPR(mailbox, mailboxExpected); + TESTEXPR(payloadSize, payloadSizeExpected); + for(j = 0; j < i; j++) + { + TESTEXPR(payload[j], payloadExpected[j]); + } + } + + /******************************************************************************/ + TESTEND; + /******************************************************************************/ + + return 0; +} + +/*************************** end of file **************************************/ Index: tags/1.0.2-release/sw/stack/riopacket.c =================================================================== --- tags/1.0.2-release/sw/stack/riopacket.c (nonexistent) +++ tags/1.0.2-release/sw/stack/riopacket.c (revision 50) @@ -0,0 +1,3123 @@ +/******************************************************************************* + * + * RapidIO IP Library Core + * + * This file is part of the RapidIO IP library project + * http://www.opencores.org/cores/rio/ + * + * Description: + * This file contains an "object" that can create and parse RapidIO packets. + * It is used in the SW RapidIO stack, riostack.c, but can also be used + * stand-alone together with other software, for example to tunnel RapidIO + * packet over an arbitrary network. + * More details about the usage can be found in the module tests in + * test_riopacket.c. + * + * To Do: + * - Add packet handlers for 8-bit deviceIds. + * + * Author(s): + * - Magnus Rosenius, magro732@opencores.org + * + ******************************************************************************* + * + * Copyright (C) 2015 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 riopacket.c + */ + +/******************************************************************************* + * Includes + *******************************************************************************/ + +#include "riopacket.h" + +/* Let lint report errors and warnings only. */ +/*lint -w2 */ + + +/******************************************************************************* + * Local macro definitions + *******************************************************************************/ + +/* 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 STATUS_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)] + + + +/******************************************************************************* + * Local function prototypes + *******************************************************************************/ + +/* Functions to help get and set payload in the packets. */ +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); + + + +/******************************************************************************* + * Global function prototypes + *******************************************************************************/ + +/** + * \brief Initialize a packet to an empty packet. + * + * \param[in] packet The packet to operate on. + * + * This function sets the size of a packet to zero. + * + * \note Any previous content is NOT purged. + */ +void RIOPACKET_init(RioPacket_t *packet) +{ + packet->size = 0; +} + + +/** + * \brief Return the size of a packet. + * + * \param[in] packet The packet to operate on. + * \return The size of the packet. + * + * This function gets the size of a packet in words (32-bit). + */ +uint8_t RIOPACKET_size(RioPacket_t *packet) +{ + return packet->size; +} + + +/** + * \brief Append data to a packet. + * + * \param[in] packet The packet to operate on. + * \param[in] word The word to append. + * + * This function appends a specificed word (32-bit) to the end of a packet. + */ +void RIOPACKET_append(RioPacket_t *packet, uint32_t word) +{ + if(packet->size < RIOPACKET_SIZE_MAX) + { + packet->payload[packet->size] = word; + packet->size++; + } +} + + +/** + * \brief Check if a packet is a valid RapidIO packet. + * + * \param[in] packet The packet to operate on. + * \return The return value is zero if not ok, non-zero otherwise. + * + * This function checks if a packet has a correct length and a correct CRC. + * Both the embedded crc and the trailing crc are checked. + */ +int RIOPACKET_valid(RioPacket_t *packet) +{ + int returnValue; + uint32_t i; + uint16_t crc; + + + /* Check that the size of the packet is ok. */ + if((packet->size >= RIOPACKET_SIZE_MIN) && + (packet->size <= RIOPACKET_SIZE_MAX)) + { + /* The packet has a valid length. */ + + /* Calculate CRC on the first word and disregard the ackId. */ + crc = RIOPACKET_Crc32(packet->payload[0] & 0x03fffffful, 0xffffu); + + /* Check if the packet contains an embedded crc. */ + if(packet->size < 20) + { + /* The packet contains only one trailing crc. */ + for(i = 1; i < packet->size; i++) + { + crc = RIOPACKET_Crc32(packet->payload[i], crc); + } + returnValue = (crc == 0x0000u); + } + else + { + /* The packet contains both a trailing and an embedded crc. */ + + /* Read payload to the embedded crc. Include the embedded crc in + the crc calculation.*/ + for(i = 1; i < 20; i++) + { + crc = RIOPACKET_Crc32(packet->payload[i], crc); + } + + /* Check the embedded crc. */ + if(crc != ((uint16_t) (packet->payload[i] >> 16))) + { + /* The embedded crc is not ok. */ + returnValue = 0; + } + else + { + /* Read the rest of the payload including the trailing crc. */ + for(i = 20; i < packet->size; i++) + { + crc = RIOPACKET_Crc32(packet->payload[i], crc); + } + returnValue = (crc == 0x0000u); + } + } + } + else + { + /* The packet does not have a valid length. */ + returnValue = 0; + } + + return returnValue; +} + + +/** + * \brief Convert (serializes) a packet into an array of bytes. + * + * \param[in] packet The packet to operate on. + * \param[in] size The size of the buffer to write to. + * \param[out] buffer The address to write the result to. + * \return The number of bytes that were written. The value 0 will be returned if the + * serialized buffer does not fit into the provided buffer. + * + * This function serializes a packet into an array of bytes that can be transfered on + * a transmission channel. + */ +int RIOPACKET_serialize(RioPacket_t *packet, const uint16_t size, uint8_t *buffer) +{ + int returnValue; + int i; + + + /* Check if the packet fits into the provided buffer. */ + if(size >= ((4*packet->size)+1)) + { + /* The packet fits. */ + + /* Write the size of the packet and the packet content itself to the buffer. */ + buffer[0] = packet->size; + for(i = 0; i < packet->size; i++) + { + buffer[(4*i)+1] = (packet->payload[i] >> 24) & 0xff; + buffer[(4*i)+2] = (packet->payload[i] >> 16) & 0xff; + buffer[(4*i)+3] = (packet->payload[i] >> 8) & 0xff; + buffer[(4*i)+4] = (packet->payload[i] >> 0) & 0xff; + } + + /* Write the number of bytes that were written. */ + returnValue = (4*packet->size)+1; + } + else + { + /* The packet does not fit into the provided buffer. */ + returnValue = 0; + } + + return returnValue; +} + + +/** + * \brief Convert (deserializes) an array of bytes to a packet. + * + * \param[in] packet The packet to operate on. + * \param[in] size The size of the buffer to read from. + * \param[in] buffer The address to read from. + * \return The number of words contained in the resulting packet. The value 0 is + * returned if the deserialization was unsuccessfull. + * + * This function deserializes a packet from a byte array that was previously created + * by RIOPACKET_serialize(). + * + * \note It is recommended to use RIOPACKET_valid() to verify the integrity of the packet + * once it has been deserialized. + */ +int RIOPACKET_deserialize(RioPacket_t *packet, const uint16_t size, const uint8_t *buffer) +{ + int i; + uint32_t temp = 0; + + + /* Check if the buffer contains a valid packet length. */ + if(((buffer[0] >= RIOPACKET_SIZE_MIN) && + (buffer[0] <= RIOPACKET_SIZE_MAX)) && + ((4*buffer[0]+1) <= size)) + { + /* The buffer contains a valid packet length. */ + + /* Read the size of the packet and the packet content itself from the buffer. */ + packet->size = buffer[0]; + for(i = 0; (i < 4*packet->size); i++) + { + temp <<= 8; + temp |= buffer[i+1]; + if((i%4) == 3) + { + packet->payload[i/4] = temp; + } + } + } + else + { + /* The buffer does not contain a valid packet length. */ + packet->size = 0; + } + + return packet->size; +} + + +/** + * \brief Convert a packet into a printable buffer. + * + * \param[in] packet The packet to operate on. + * \param[in] buffer The address to write the string to. + * + * This function converts a packet into a human readable '\0'-terminated ASCII-format and + * write it to the argument buffer. + * + * \note The caller must guarantee that the destination buffer is large enough to contain + * the resulting string. + */ +#ifdef ENABLE_TOSTRING +#include +void RIOPACKET_toString(RioPacket_t *packet, char *buffer) +{ + uint8_t ftype; + uint8_t transaction; + uint16_t destId; + uint16_t srcId; + uint8_t tid; + + + ftype = RIOPACKET_getFtype(packet); + transaction = RIOPACKET_getTransaction(packet); + + /* Check the message type and switch on it. */ + switch(ftype) + { + case RIOPACKET_FTYPE_REQUEST: + /************************************************************************************** + * A REQUEST has been received. + **************************************************************************************/ + { + uint32_t address; + uint16_t payloadSize; + + + if(transaction == RIOPACKET_TRANSACTION_REQUEST_NREAD) + { + RIOPACKET_getNread(packet, &destId, &srcId, &tid, &address, &payloadSize); + sprintf(buffer, + "NREAD: dstid=%04x srcid=%04x tid=%02x address=%08x payloadSize=%04x", + destId, srcId, tid, address, payloadSize); + } + else + { + sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction); + } + } + break; + + case RIOPACKET_FTYPE_WRITE: + /************************************************************************************** + * An WRITE has been received. + **************************************************************************************/ + { + uint32_t address; + uint16_t payloadSize; + uint8_t payload[256]; + uint32_t index; + uint32_t i; + + + if(transaction == RIOPACKET_TRANSACTION_WRITE_NWRITE) + { + RIOPACKET_getNwrite(packet, &destId, &srcId, &address, &payloadSize, payload); + + index = sprintf(&buffer[0], + "NWRITE: dstid=%04x srcid=%04x address=%08x payloadSize=%04x", + destId, srcId, address, payloadSize); + for(i = 0; i < payloadSize; i++) + { + index += sprintf(&buffer[index], "%02x", payload[i]); + } + } + else if(transaction == RIOPACKET_TRANSACTION_WRITE_NWRITER) + { + RIOPACKET_getNwriteR(packet, &destId, &srcId, &tid, &address, &payloadSize, payload); + + index = sprintf(&buffer[0], + "NWRITER: dstid=%04x srcid=%04x tid=%02x address=%08x payloadSize=%04x", + destId, srcId, tid, address, payloadSize); + for(i = 0; i < payloadSize; i++) + { + index += sprintf(&buffer[index], "%02x", payload[i]); + } + } + else + { + sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction); + } + } + break; + + case RIOPACKET_FTYPE_MAINTENANCE: + /************************************************************************************** + * A maintenance packet has been received. + **************************************************************************************/ + { + uint8_t hop; + uint32_t offset; + uint32_t data; + + + /* Check the transaction to determine the type. */ + if(transaction == RIOPACKET_TRANSACTION_MAINT_READ_REQUEST) + { + /* Maintenance read request. */ + RIOPACKET_getMaintReadRequest(packet, &destId, &srcId, &hop, &tid, &offset); + sprintf(buffer, + "MAINTREADREQUEST: dstid=%04x srcid=%04x tid=%02x hop=%02x offset=%08x", + destId, srcId, tid, hop, offset); + } + else if(transaction == RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST) + { + /* Maintenance write request. */ + RIOPACKET_getMaintWriteRequest(packet, &destId, &srcId, &hop, &tid, &offset, &data); + sprintf(buffer, + "MAINTWRITEREQUEST: dstid=%04x srcid=%04x tid=%02x hop=%02x offset=%08x data=%08x", + destId, srcId, tid, hop, offset, data); + } + else if(transaction == RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE) + { + /* Maintenance read response. */ + RIOPACKET_getMaintReadResponse(packet, &destId, &srcId, &tid, &data); + sprintf(buffer, + "MAINTREADRESPONSE: dstid=%04x srcid=%04x tid=%02x data=%08x", + destId, srcId, tid, data); + } + else if(transaction == RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE) + { + /* Maintenance write repsonse. */ + RIOPACKET_getMaintWriteResponse(packet, &destId, &srcId, &tid); + sprintf(buffer, + "MAINTWRITERESPONSE: dstid=%04x srcid=%04x tid=%02x", + destId, srcId, tid); + } + else if(transaction == RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST) + { + uint32_t componentTag; + uint32_t portErrorDetect; + uint32_t implementationSpecific; + uint8_t portId; + uint32_t logicalTransportErrorDetect; + + /* Maintenance port write packet. */ + RIOPACKET_getMaintPortWrite(packet, &destId, &srcId, + &componentTag, &portErrorDetect, &implementationSpecific, + &portId, &logicalTransportErrorDetect); + sprintf(buffer, + "MAINTPORTWRITE: dstid=%04x srcid=%04x componentTag=%08x portErrorDetect=%08x" + "implementationSpecific=%08x portId=%02x logicalTransportErrorDetect=%08x", + destId, srcId, componentTag, portErrorDetect, implementationSpecific, portId, + logicalTransportErrorDetect); + } + else + { + sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction); + } + } + break; + + case RIOPACKET_FTYPE_DOORBELL: + /************************************************************************************** + * A doorbell packet has been received. + **************************************************************************************/ + { + uint16_t info; + + + RIOPACKET_getDoorbell(packet, &destId, &srcId, &tid, &info); + sprintf(buffer, + "DOORBELL: dstid=%04x srcid=%04x tid=%02x info=%04x", + destId, srcId, tid, info); + } + break; + + case RIOPACKET_FTYPE_MESSAGE: + /************************************************************************************** + * A messaget has been received. + **************************************************************************************/ + { + uint16_t payloadSize; + uint8_t payload[256]; + uint32_t index; + uint32_t i; + + + RIOPACKET_getMessage(packet, &destId, &srcId, &tid, &payloadSize, payload); + + index = sprintf(&buffer[0], + "MESSAGE: dstid=%04x srcid=%04x mailbox=%02x payloadSize=%04x", + destId, srcId, tid, payloadSize); + for(i = 0; i < payloadSize; i++) + { + index += sprintf(&buffer[index], "%02x", payload[i]); + } + } + break; + + case RIOPACKET_FTYPE_RESPONSE: + /************************************************************************************** + * A response packet has been received. + **************************************************************************************/ + { + uint8_t status; + uint16_t payloadSize; + uint8_t payload[256]; + + + if(transaction == RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD) + { + RIOPACKET_getResponseNoPayload(packet, &destId, &srcId, &tid, &status); + sprintf(buffer, + "RESPONSENOPAYLOAD: dstid=%04x srcid=%04x tid=%02x status=%02x", + destId, srcId, tid, status); + } + else if(transaction == RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE) + { + RIOPACKET_getResponseMessage(packet, &destId, &srcId, &tid, &status); + sprintf(buffer, + "RESPONSEMESSAGE: dstid=%04x srcid=%04x mailbox=%02x status=%02x", + destId, srcId, tid, status); + } + else if(transaction == RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD) + { + uint32_t i; + uint32_t index; + + + RIOPACKET_getResponseWithPayload(packet, &destId, &srcId, &tid, 0, &payloadSize, payload); + + index = sprintf(&buffer[0], + "RESPONSEWITHPAYLOAD: dstid=%04x srcid=%04x tid=%02x payloadSize=%04x ", + destId, srcId, tid, payloadSize); + for(i = 0; i < payloadSize; i++) + { + index += sprintf(&buffer[index], "%02x", payload[i]); + } + } + else + { + sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction); + } + } + break; + + default: + /************************************************************************************** + * Unsupported ftype. + **************************************************************************************/ + sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction); + break; + } + + return; +} +#endif + + +/** + * \brief Return the ftype of a packet. + * + * \param[in] packet The packet to operate on. + * \return The ftype of the packet. + * + * This function gets the ftype of a packet. + */ +uint8_t RIOPACKET_getFtype(RioPacket_t *packet) +{ + return FTYPE_GET(packet->payload); +} + + +/** + * \brief Return the destination deviceId of a packet. + * + * \param[in] packet The packet to operate on. + * \return The destination deviceId of the packet. + * + * This function gets the destination deviceId of a packet. + */ +uint16_t RIOPACKET_getDestination(RioPacket_t *packet) +{ + return DESTID_GET(packet->payload); +} + + +/** + * \brief Return the source deviceId of a packet. + * + * \param[in] packet The packet to operate on. + * \return The source deviceId of the packet. + * + * This function gets the source deviceId of a packet. + */ +uint16_t RIOPACKET_getSource(RioPacket_t *packet) +{ + return SRCID_GET(packet->payload); +} + + +/** + * \brief Return the transaction of a packet. + * + * \param[in] packet The packet to operate on. + * \return The transaction of the packet. + * + * This function gets the transaction field of a packet. + * + * \note Not all packets contain a transaction field. + */ +uint8_t RIOPACKET_getTransaction(RioPacket_t *packet) +{ + return TRANSACTION_GET(packet->payload); +} + + +/** + * \brief Return the transaction identifier of a packet. + * + * \param[in] packet The packet to operate on. + * \return The transaction identifier of the packet. + * + * This function gets the transaction identifier field of a packet. + * + * \note Not all packets contain a transaction identifier field. + */ +uint8_t RIOPACKET_getTid(RioPacket_t *packet) +{ + return TID_GET(packet->payload); +} + + +/******************************************************************************************* + * Logical I/O MAINTENANCE-READ functions. + *******************************************************************************************/ + +/** + * \brief Set the packet to contain a maintenance read request. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] hop The hop_count to set in the packet. + * \param[in] tid The transaction identifier to set in the packet. + * \param[in] offset The byte address in the configuration space to read. + * + * This function sets the content of a packet to a maintenance read request packet containing + * a request to read one word in configuration space. + * + */ +void RIOPACKET_setMaintReadRequest(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, uint8_t hop, + uint8_t tid, uint32_t offset) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 but must be set to zero. */ + content = 0x00180000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_READ_REQUEST << 12; + content |= (uint32_t) 8ul << 8; + content |= (uint32_t) tid; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */ + content = ((uint32_t) hop) << 24; + content |= offset & 0x00fffffcul; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[2] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[3] = content; + + /* Set the size of the packet. */ + packet->size = 4; +} + + +/** + * \brief Get entries from a maintenance read request. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] hop The hop_count in this packet. + * \param[out] tid The transaction id to be returned in the response to this request. + * \param[out] offset The byte address in the configuration space to read. + * + * This function returns the content of a packet as if it contained a maintenance read + * request packet. + * + * \note Use the ftype and transaction fields to see if the packet is indeed a + * maintenance read request. + * \note If the packet does not contain a maintenance read request, the result + * will be undefined. + */ +void RIOPACKET_getMaintReadRequest(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, uint8_t *hop, + uint8_t *tid, uint32_t *offset) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *hop = HOP_GET(packet->payload); + *offset = CONFIG_OFFSET_GET(packet->payload); +} + + +/** + * \brief Set the packet to contain a maintenance read response. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] tid The transaction identifier to set in the packet. + * \param[in] data The data to send in the packet. + * + * This function sets the content of a packet to a maintanance read response packet + * containing a response to a request reading one word in configuration space. + */ +void RIOPACKET_setMaintReadResponse(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, uint32_t data) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 = 0x00180000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|srcTID(7:0) */ + content = (uint32_t) srcId << 16; + content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE << 12; + content |= (uint32_t) RIOPACKET_RESPONSE_STATUS_DONE << 8; + content |= (uint32_t) tid; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* hopcount(7:0)|reserved(23:0) */ + /* HopCount should always be set to 0xff in responses. */ + content = 0xff000000ul; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[2] = 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 = RIOPACKET_Crc32(content, crc); + packet->payload[3] = content; + content = data; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[4] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[5] = content; + + /* Set the size of the packet. */ + packet->size = 6; +} + + +/** + * \brief Get entries from a maintenance read response. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] tid The transaction identifier in the response. + * \param[out] data The data in the response. + * + * This function returns the content of a packet as if it contained a maintenance + * read response packet. + * + * \note Use the ftype and transaction fields to see if the packet is indeed a + * maintenance read response. + * \note If the packet does not contain a maintenance read response, the result + * will be undefined. + */ +void RIOPACKET_getMaintReadResponse(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, uint32_t *data) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *data = DOUBLE_WORD_MSB_GET(packet->payload, 0) | DOUBLE_WORD_LSB_GET(packet->payload, 0); +} + + +/******************************************************************************************* + * Logical I/O MAINTENANCE-WRITE functions. + *******************************************************************************************/ + +/** + * \brief Set the packet to contain a maintenance write request. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] hop The hop_count to set in the packet. + * \param[in] tid The transaction identifier to set in the packet. + * \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 sets the content of a packet to a maintenance write request packet + * containing a request to write one word in configuration space. + */ +void RIOPACKET_setMaintWriteRequest(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, uint8_t hop, + uint8_t tid, uint32_t offset, uint32_t data) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 = 0x00180000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST << 12; + content |= (uint32_t) 8ul << 8; + content |= (uint32_t) tid; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */ + content = ((uint32_t) hop) << 24; + content |= offset & 0x00fffffcul; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[2] = 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 = RIOPACKET_Crc32(content, crc); + packet->payload[3] = content; + content = data; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[4] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[5] = content; + + /* Set the size of the packet. */ + packet->size = 6; +} + + +/** + * \brief Get entries from a maintenance write request. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] hop The hop_count in this packet. + * \param[out] tid The transaction id in this packet. + * \param[out] offset The byte address in the configuration space to read. + * \param[out] data The data to requested to be written in configuration space. + * + * This function returns the content of a packet as if it contained a maintenance write + * request packet. + * + * \note Use the ftype and transaction fields to see if the packet is indeed a + * maintenance write request. + * \note If the packet does not contain a maintenance write request, the result + * will be undefined. + */ +void RIOPACKET_getMaintWriteRequest(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, uint8_t *hop, + uint8_t *tid, uint32_t *offset, uint32_t *data) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *hop = HOP_GET(packet->payload); + *offset = CONFIG_OFFSET_GET(packet->payload); + *data = DOUBLE_WORD_MSB_GET(packet->payload, 0) | DOUBLE_WORD_LSB_GET(packet->payload, 0); +} + + +/** + * \brief Set the packet to contain a maintenance write response. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] tid The transaction identifier to set in the packet. + * + * This function sets the content of a packet to a maintanance write response packet + * containing a response to a request writing one word in configuration space. + */ +void RIOPACKET_setMaintWriteResponse(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 = 0x00180000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE << 12; + content |= (uint32_t) RIOPACKET_RESPONSE_STATUS_DONE << 8; + content |= (uint32_t) tid; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* hopcount(7:0)|reserved(23:0) */ + /* HopCount should always be set to 0xff in responses. */ + content = 0xff000000ul; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[2] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[3] = content; + + /* Set the size of the packet. */ + packet->size = 4; +} + + +/** + * \brief Get entries from a maintenance write response. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] tid The transaction identifier in the response. + * + * This function returns the content of a packet as if it contained a maintenance + * write response packet. + * + * \note Use the ftype and transaction fields to see if the packet is indeed a + * maintenance write response. + * \note If the packet does not contain a maintenance write response, the result + * will be undefined. + */ +void RIOPACKET_getMaintWriteResponse(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); +} + + +/******************************************************************************************* + * Logical I/O MAINTENANCE-PORTWRITE functions. + *******************************************************************************************/ + +/** + * \brief Set the packet to contain a maintenance port-write request. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] componentTag The value of the componentTag register to set in the packet. + * \param[in] portErrorDetect The value of the Port N Error Detect CSR to set in the packet. + * \param[in] implementationSpecific An implementation specific value to set in the packet. + * \param[in] portId The port ID of the port to set in the packet. + * \param[in] logicalTransportErrorDetect The value of the Logical/Transport Layer + * Error Detect CSR to set in the packet. + * + * This function sets the content of a packet to a maintenance port-write request packet. + */ +void RIOPACKET_setMaintPortWrite(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint32_t componentTag, uint32_t portErrorDetect, + uint32_t implementationSpecific, uint8_t portId, + uint32_t logicalTransportErrorDetect) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 = 0x00180000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = (uint32_t) srcId << 16; + content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST << 12; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* hopcount(7:0)|reserved(23:0) */ + content = 0x00000000ul; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[2] = content; + + /* double-word 0 */ + content = componentTag; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[3] = content; + content = portErrorDetect; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[4] = content; + + /* double-word 1 */ + content = implementationSpecific << 8; + content |= (uint32_t) portId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[5] = content; + content = logicalTransportErrorDetect; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[6] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[7] = content; + + /* Set the size of the packet. */ + packet->size = 8; +} + + +/** + * \brief Get entries from a maintenance port-write request. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The device id of the destination end point. + * \param[out] srcId The device id of the source end point. + * \param[out] componentTag The value of the componentTag register in this packet. + * \param[out] portErrorDetect The value of the Port N Error Detect CSR in this packet. + * \param[out] implementationSpecific An implementation specific value in this packet. + * \param[out] portId The port ID of the port in this packet. + * \param[out] logicalTransportErrorDetect The value of the Logical/Transport Layer + * Error Detect CSR in this packet. + * + * This function returns the content of a packet as if it contained a maintenance port-write + * request packet. + * + * \note Use the ftype and transaction fields to see if the packet is indeed a + * maintenance port-write request. + * \note If the packet does not contain a maintenance port-write request, the result + * will be undefined. + */ +void RIOPACKET_getMaintPortWrite(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint32_t *componentTag, uint32_t *portErrorDetect, + uint32_t *implementationSpecific, uint8_t *portId, + uint32_t *logicalTransportErrorDetect) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *componentTag = packet->payload[3]; + *portErrorDetect = packet->payload[4]; + *implementationSpecific = packet->payload[5] >> 8; + *portId = (uint8_t) (packet->payload[5] & 0xff); + *logicalTransportErrorDetect = packet->payload[6]; +} + + +/******************************************************************************************* + * Logical I/O NWRITE/NWRITER functions. + *******************************************************************************************/ + +/** + * \brief Set a packet to contain an NWRITE. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] address The byte address in IO-space to write to. + * \param[in] payloadSize The number of bytes to write. The largest allowed size is 256 bytes. + * \param[in] payload A pointer to the array of bytes to write. + * + * This function sets the content of a packet to an NWRITE containing a request + * to write the number of bytes specified by payloadSize to the address specified by the + * address argument. + * + * \note The address is a byte address. + * + * \note Not all combinations of addresses and sizes are allowed. The packet will be empty + * if an unallowed address/payloadSize combination is used. Use RIOPACKET_getWritePacketSize() + * to get the maximum size to use based on the address and payloadSize. + */ +void RIOPACKET_setNwrite(RioPacket_t *packet, uint16_t destId, uint16_t srcId, + uint32_t address, uint16_t payloadSize, uint8_t *payload) +{ + uint32_t content; + uint16_t wrsize; + + + /* Convert the address and size to the wrsize field and check if the combination is valid. */ + wrsize = wrsizeGet(address, payloadSize); + if(wrsize != 0xffff) + { + /* The address and size field combination is valid. */ + + /* 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 = 0x00150000ul; + content |= (uint32_t) destId; + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= (uint32_t) RIOPACKET_TRANSACTION_WRITE_NWRITE << 12; + content |= (uint32_t) (wrsize & 0x0f00); + packet->payload[1] = 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; + packet->payload[2] = content; + + /* Place the payload buffer into the payload of the packet. */ + /* This function also calculates the CRC. */ + packet->size = setPacketPayload(&(packet->payload[0]), 12, address & 0x7, payloadSize, payload); + } + else + { + /* The address and size field combination is not valid. */ + /* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */ + packet->size = 0; + } +} + + +/** + * \brief Get entries from a NWRITE. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] address The byte address into IO-space requested to be written. + * \param[out] payloadSize The number of bytes requested to be written. + * \param[out] payload The data requested to be written. + * + * This function returns the content of a packet as if it contained an NWRITE. + * + * \note The address is a byte address. + * + * \note Any padding contained in double-word0 will be removed and the content + * will be placed where the payload pointer is pointing. + */ +void RIOPACKET_getNwrite(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, + uint32_t *address, uint16_t *payloadSize, uint8_t *payload) +{ + uint8_t wrsize; + uint8_t wdptr; + uint8_t offset = 0; + uint16_t size = 0; + + + wrsize = WRSIZE_GET(packet->payload); + wdptr = WDPTR_GET(packet->payload); + wrsizeToOffset(wrsize, wdptr, &offset, &size); + + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *address = ADDRESS_GET(packet->payload) | offset; + + if(size > 16) + { + size = 4*(packet->size-4); + } + else + { + /* The size already contains the correct value. */ + } + + + *payloadSize = getPacketPayload(&(packet->payload[0]), 12, offset, size, payload); +} + + + +/** + * \brief Set a packet to contain an NWRITER. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] tid The transaction identifier to set in the packet. + * \param[in] address The byte address in IO-space to write to. + * \param[in] payloadSize The number of bytes to write. The largest allowed size is 256 bytes. + * \param[in] payload A pointer to the array of bytes to write. + * + * This function sets the content of a packet to an NWRITER containing a request + * to write the number of bytes specified by payloadSize to the address specified by the + * address argument. This packet requires a RESPONSE containing the transaction identifier + * specified in this packet. + * + * \note The address is a byte address. + * + * \note Not all combinations of addresses and sizes are allowed. The packet will be empty + * if an unallowed address/payloadSize combination is used. Use RIOPACKET_getWritePacketSize() + * to get the maximum size to use based on the address and payloadSize. + */ +void RIOPACKET_setNwriteR(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid, + uint32_t address, uint16_t payloadSize, uint8_t *payload) +{ + uint32_t content; + uint16_t wrsize; + + + /* Convert the address and size to the wrsize field and check if the combination is valid. */ + wrsize = wrsizeGet(address, payloadSize); + if(wrsize != 0xffff) + { + /* The address and size field combination is valid. */ + + /* 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 = 0x00150000ul; + content |= (uint32_t) destId; + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= (uint32_t) RIOPACKET_TRANSACTION_WRITE_NWRITER << 12; + content |= (uint32_t) (wrsize & 0x0f00); + content |= (uint32_t) tid; + packet->payload[1] = 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; + packet->payload[2] = content; + + /* Place the payload buffer into the payload of the packet. */ + /* This function also calculates the CRC. */ + packet->size = setPacketPayload(&(packet->payload[0]), 12, address & 0x7, payloadSize, payload); + } + else + { + /* The address and size field combination is not valid. */ + /* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */ + packet->size = 0; + } +} + + +/** + * \brief Get entries from a NWRITER. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] tid The transaction id in this packet. + * \param[out] address The byte address into IO-space requested to be written. + * \param[out] payloadSize The number of bytes requested to be written. + * \param[out] payload The data requested to be written. + * + * This function returns the content of a packet as if it contained an NWRITER. + * + * \note The address is a byte address. + * + * \note Any padding contained in double-word0 will be removed and the content + * will be placed where the payload pointer is pointing. + */ +void RIOPACKET_getNwriteR(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid, + uint32_t *address, uint16_t *payloadSize, uint8_t *payload) +{ + uint8_t wrsize; + uint8_t wdptr; + uint8_t offset = 0; + uint16_t size = 0; + + + wrsize = WRSIZE_GET(packet->payload); + wdptr = WDPTR_GET(packet->payload); + wrsizeToOffset(wrsize, wdptr, &offset, &size); + + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *address = ADDRESS_GET(packet->payload) | offset; + + if(size > 16) + { + size = 4*(packet->size-4); + } + else + { + /* The size already contains the correct value. */ + } + + *payloadSize = getPacketPayload(&(packet->payload[0]), 12, offset, size, payload); +} + + +/******************************************************************************************* + * Logical I/O NREAD functions. + *******************************************************************************************/ + +/** + * \brief Set a packet to contain an NREAD. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] tid The transaction id to set in the response. + * \param[in] address The byte address to read from. + * \param[in] payloadSize The number of bytes to read. The largest allowed size is 256 bytes. + * + * This function sets the content of a packet to an NREAD containing a request + * to read the number of bytes specified by payloadSize from the address specified by the + * address argument. + * + * \note The address is a byte address. + * + * \note Not all combinations of address and length are allowed. The packet will be empty + * if an unallowed address/payloadSize combination is used. Use RIOPACKET_getReadPacketSize() + * to get the maximum size to use based on the address and payloadSize. + */ +void RIOPACKET_setNread(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid, + uint32_t address, uint16_t payloadSize) +{ + uint32_t content; + uint16_t crc = 0xffffu; + uint16_t rdsize; + + + /* Convert the address and size to the rdsize field and check if the combination is valid. */ + rdsize = rdsizeGet(address, payloadSize); + if(rdsize != 0xffff) + { + /* The address and size field combination is valid. */ + + /* 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 = 0x00120000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= ((uint32_t) RIOPACKET_TRANSACTION_REQUEST_NREAD) << 12; + content |= (uint32_t) (rdsize & 0x0f00); + content |= (uint32_t) tid; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = 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 = RIOPACKET_Crc32(content, crc); + packet->payload[2] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[3] = content; + + /* Set the size of the packet. */ + packet->size = 4; + } + else + { + /* The address and size field combination is not valid. */ + /* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */ + packet->size = 0; + } +} + + +/** + * \brief Get entries from an NREAD. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] tid The transaction id in this packet. + * \param[out] address The byte address into IO-space requested to be written. + * \param[out] payloadSize The number of bytes requested to be read. + * + * This function returns the content of a packet as if it contained an NREAD. + * + * \note The address is a byte address. + */ +void RIOPACKET_getNread(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid, + uint32_t *address, uint16_t *payloadSize) +{ + uint8_t rdsize; + uint8_t wdptr; + uint8_t offset = 0; + uint16_t size = 0; + + + rdsize = WRSIZE_GET(packet->payload); + wdptr = WDPTR_GET(packet->payload); + rdsizeToOffset(rdsize, wdptr, &offset, &size); + + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *address = ADDRESS_GET(packet->payload) | offset; + *payloadSize = size; +} + + + +/******************************************************************************************* + * Logical message passing DOORBELL and MESSAGE functions. + *******************************************************************************************/ + +/** + * \brief Set a packet to contain a DOORBELL. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] tid The transaction identifier to set in the packet. + * \param[in] info The information to send with the doorbell. + * + * This function sets the content of a packet to a DOORBELL. + */ +void RIOPACKET_setDoorbell(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid, + uint16_t info) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 = 0x001a0000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= (uint32_t) tid; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */ + content = ((uint32_t) info) << 16; + crc = RIOPACKET_Crc16(info, crc); + content |= crc; + packet->payload[2] = content; + + /* Set the size of the packet. */ + packet->size = 3; +} + + +/** + * \brief Get entries from a DOORBELL. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] tid The transaction identifier in this packet. + * \param[out] info The information field in this packet. + * + * This function returns the content of a packet as if it contained a DOORBELL. + */ +void RIOPACKET_getDoorbell(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid, + uint16_t *info) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *info = INFO_GET(packet->payload); +} + + +/** + * \brief Set a packet to contain a MESSAGE. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] mailbox The mailbox to send the message to. + * \param[in] payloadSize The number of bytes to place into the message. + * \param[in] payload A pointer to the array of bytes to place into the message. + * + * This function sets the content of a packet to contain a MESSAGE. + * + * \note The mailbox argument maps to the packet fields as: + * {xmbox(3:0), letter(1:0), mbox(1:0)} which means that mailbox 0-15 can support + * multipacket messages and 16-255 can handle only single packet messages. + * + * \note The payload size has to be larger than zero and less than 256. + * + * \note Only payloads of even double-words are supported by the protocol itself. Payload + * that is shorter will be padded. + */ +void RIOPACKET_setMessage(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t mailbox, + uint16_t payloadSize, uint8_t *payload) +{ + uint32_t content; + + + /* Make sure that the message payload size is larger than zero. */ + if((payloadSize > 0) && (payloadSize <= 256)) + { + /* The payload size is larger than zero. */ + + /* 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 = 0x001b0000ul; + content |= (uint32_t) destId; + packet->payload[0] = content; + + /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0)|mbox(1:0)|msgseg(3:0)/xmbox(3:0) */ + content = ((uint32_t) srcId) << 16; + if(payloadSize <= 8u) + { + content |= 0x00000900ul; + } + else if(payloadSize <= 16u) + { + content |= 0x00000a00ul; + } + else if(payloadSize <= 32u) + { + content |= 0x00000b00ul; + } + else if(payloadSize <= 64u) + { + content |= 0x00000c00ul; + } + else if(payloadSize <= 128u) + { + content |= 0x00000d00ul; + } + else + { + content |= 0x00000e00ul; + } + content |= (((uint32_t) mailbox) & 0xful) << 4; + content |= ((uint32_t) mailbox) >> 4; + packet->payload[1] = content; + + /* Place data buffer into the payload of the packet and set the size. */ + packet->size = setPacketPayload(&(packet->payload[0]), 8, 0, payloadSize, payload); + } + else + { + /* The payload size is not allowed. */ + /* Unable to create the new packet. */ + packet->size = 0; + } +} + + +/** + * \brief Get entries from a MESSAGE. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] mailbox The mailbox the message is received on. + * \param[out] payloadSize The number of bytes in the payload. + * \param[out] payload The payload of the packet. + * + * This function returns the content of a packet as if it contained a MESSAGE. + * + * \note The mailbox argument maps to the packet fields as: + * {xmbox(3:0), letter(1:0), mbox(1:0)} which means that mailbox 0-15 can support + * multipacket messages and 16-255 can handle only single packet messages. + * + * \note Only payloads of even double-words are supported by the protocol itself so the + * returned payloadSize is always an even multiple of eight. + */ +void RIOPACKET_getMessage(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *mailbox, + uint16_t *payloadSize, uint8_t *payload) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *mailbox = XMBOX_GET(packet->payload); + *mailbox <<= 2; + *mailbox |= LETTER_GET(packet->payload); + *mailbox <<= 2; + *mailbox |= MBOX_GET(packet->payload); + *payloadSize = getPacketPayload(&(packet->payload[0]), 8, 0, (packet->size-3)*4, payload); +} + + + + +/******************************************************************************************* + * Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR + * functions. + *******************************************************************************************/ + +/** + * \brief Set a packet to contain a RESPONSE without payload. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] tid The transaction id to send the response for. + * \param[in] status The status to send in the packet. + * + * This function sets the content of a packet to contain a RESPONSE without payload. + * + * \note The tid field must be the same value as the packet contained that this is the + * response for. + * + * \note The status field should be either of the values RIOPACKET_RESPONSE_STATUS_XXXX. + */ +void RIOPACKET_setResponseNoPayload(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, uint8_t status) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 = 0x001d0000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */ + content = ((uint32_t) srcId) << 16; + content |= ((uint32_t) RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD) << 12; + content |= ((uint32_t) (status & 0xf)) << 8; + content |= (uint32_t) tid; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[2] = content; + + /* Set the size of the packet. */ + packet->size = 3; +} + + +/** + * \brief Get entries from a RESPONSE without payload. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] tid The transaction identifier in this packet. + * \param[out] status The status in this packet. + * + * This function returns the content of a packet as if it contained a RESPONSE. + */ +void RIOPACKET_getResponseNoPayload(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, uint8_t *status) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *status = STATUS_GET(packet->payload); +} + + + +/** + * \brief Set a packet to contain a RESPONSE also containing payload. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] tid The transaction id to send the response for. + * \param[in] offset The offset into the payload to start to write the input payload to. + * \param[in] payloadSize The size of the payload to return in the reply. + * \param[in] payload The payload to return in the reply. + * + * This function sets the content of a packet to contain a RESPOSE with payload. + * + * \note The tid field must be the same value as the packet contained that this is the + * response for. + * + * \note The offset field can be used to offset the payload in a response to, for + * example, an NREAD. + * + * \note The payloadSize must match the size of the packet that this is the + * response for. + */ +void RIOPACKET_setResponseWithPayload(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, uint8_t offset, + uint16_t payloadSize, uint8_t *payload) +{ + 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 = 0x001d0000ul; + content |= (uint32_t) destId; + packet->payload[0] = content; + + /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */ + /* status=DONE is 0. */ + content = ((uint32_t) srcId) << 16; + content |= ((uint32_t) RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD) << 12; + content |= (uint32_t) tid; + packet->payload[1] = content; + + packet->size = setPacketPayload(&(packet->payload[0]), 8, offset & 0x7, payloadSize, payload); +} + +/** + * \brief Get entries from a RESPONSE containing payload. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] tid The transaction identifier in this packet. + * \param[in] offset The offset into the payload to start reading from. + * \param[out] payloadSize The number of bytes in the payload. + * \param[out] payload The payload of the packet. + * + * This function returns the content of a packet as if it contained a RESPONSE with payload. + * + * \note The offset field can be used to read the payload in a response to, for + * example, an NREAD. + */ +void RIOPACKET_getResponseWithPayload(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, uint8_t offset, + uint16_t *payloadSize, uint8_t *payload) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *tid = TID_GET(packet->payload); + *payloadSize = getPacketPayload(&(packet->payload[0]), 8, offset & 0x7, (packet->size-3)*4, payload); +} + + + +/** + * \brief Set a packet to contains a RESPONSE to a message. + * + * \param[in] packet The packet to operate on. + * \param[in] destId The deviceId to use as destination in the packet. + * \param[in] srcId The deviceId to use as source in the packet. + * \param[in] mailbox The mailbox to send the message to. + * \param[in] status The status to send in the packet. + * + * This function is used to send a response indicating a successfull + * completion in reply to a previously received packet. + * + * \note The mailbox field should contain the same value as the packet that this is the + * response to. + * + * \note The status field should be either of the values RIOPACKET_RESPONSE_STATUS_XXXX. + */ +void RIOPACKET_setResponseMessage(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t mailbox, uint8_t status) +{ + uint32_t content; + uint16_t crc = 0xffffu; + + + /* 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 = 0x001d0000ul; + content |= (uint32_t) destId; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[0] = 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) RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE) << 12; + content |= ((uint32_t) (status & 0xf)) << 8; + content |= ((uint32_t) (mailbox & 0xf)) << 4; + content |= ((uint32_t) mailbox) >> 4; + crc = RIOPACKET_Crc32(content, crc); + packet->payload[1] = content; + + /* crc(15:0)|pad(15:0) */ + content = ((uint32_t) crc) << 16; + packet->payload[2] = content; + + /* Set the size of the packet. */ + packet->size = 3; +} + +/** + * \brief Get entries from a RESPONSE to a message. + * + * \param[in] packet The packet to operate on. + * \param[out] destId The destination deviceId in this packet. + * \param[out] srcId The source deviceId in this packet. + * \param[out] mailbox The mailbox the response should be sent to. + * \param[out] status The status in the packet. + * + * This function returns the content of a packet as if it contained a RESPONSE to a message. + */ +void RIOPACKET_getResponseMessage(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *mailbox, uint8_t *status) +{ + *destId = DESTID_GET(packet->payload); + *srcId = SRCID_GET(packet->payload); + *mailbox = XMBOX_GET(packet->payload); + *mailbox <<= 2; + *mailbox |= LETTER_GET(packet->payload); + *mailbox <<= 2; + *mailbox |= MBOX_GET(packet->payload); + *status = STATUS_GET(packet->payload); +} + + +/** + * \brief Calculate a new CRC16 value. + * + * \param[in] data The new data (16-bit) to update the current crc value with. + * \param[in] crc The old crc value that should be updated. + * \returns The new crc value based on the input arguments. + * + * This function calculates a new crc value using the generator polynom + * P(X)=x16+x12+x5+1. It is defined in RapidIO 3.0 part6 chapter 2.4.2. + */ +uint16_t RIOPACKET_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; +} + + +/** + * \brief Calculate a new CRC16 value. + * + * \param[in] data The new data (32-bit) to update the current crc value with. + * \param[in] crc The old crc value that should be updated. + * \returns The new crc value based on the input arguments. + * + * This function calculates a new crc value using the generator polynom + * P(X)=x16+x12+x5+1. It is defined in RapidIO 3.0 part6 chapter 2.4.2. + */ +uint16_t RIOPACKET_Crc32(const uint32_t data, uint16_t crc) +{ + crc = RIOPACKET_Crc16((uint16_t) (data >> 16), crc); + crc = RIOPACKET_Crc16((uint16_t) (data), crc); + return crc; +} + + +/** + * \brief Get the maximum size of an NWRITE payload. + * + * \param[in] address The starting address to write to in the NWRITE. + * \param[in] size The total size of the access to NWRITE. + * \returns The maximum number of bytes that are allowed to send in a single + * NWRITE packet that conforms to the RapidIO standard. + * + * This function calculates the maximum sized NWRITE packet payload that are + * possible to send without breaking the limitations in the RapidIO specification. + * It is intended to be called repeatedly. + * + * Example: An area with address=0x00007 and size=258 needs to be written. + * Call RIOPACKET_getWritePacketSize(0x00007, 258)->1. + * Send an NWRITE to address=0x00007 and size=1. + * Update the address and size with the returned value-> + * address+=1->address=0x00008 size-=1->size=257. + * Call RIOPACKET_getWritePacketSize(0x00008, 257)->256. + * Send an NWRITE to address=0x00008 and size=256. + * Update the address and size with the returned value-> + * address+=256->address=0x00108 size-=256->size=1. + * Call RIOPACKET_getWritePacketSize(0x00108, 1)->1. + * Send an NWRITE to address=0x00108 and size=1. + * Update the address and size with the returned value-> + * address+=1->address=0x00109 size-=1->size=0. + * All the data has been written. + * + */ +uint32_t RIOPACKET_getWritePacketSize(uint32_t address, uint32_t size) +{ + uint32_t returnValue; + + + switch(address%8) + { + case 0: + if(size >= 256) + { + returnValue = 256; + } + else if(size >= 8) + { + returnValue = size - (size % 8); + } + else + { + returnValue = size; + } + break; + case 1: + if(size >= 7) + { + returnValue = 7; + } + else + { + returnValue = 1; + } + break; + case 2: + if(size >= 6) + { + returnValue = 6; + } + else if(size >= 2) + { + returnValue = 2; + } + else + { + returnValue = 1; + } + break; + case 3: + if(size >= 5) + { + returnValue = 5; + } + else + { + returnValue = 1; + } + break; + case 4: + if(size >= 4) + { + returnValue = 4; + } + else if(size >= 2) + { + returnValue = 2; + } + else + { + returnValue = 1; + } + break; + case 5: + if(size >= 3) + { + returnValue = 3; + } + else + { + returnValue = 1; + } + break; + case 6: + if(size >= 2) + { + returnValue = 2; + } + else + { + returnValue = 1; + } + break; + default: + returnValue = 1; + break; + } + + return returnValue; +} + + +/** + * \brief Get the maximum size of an NREAD payload. + * + * \param[in] address The starting address to read from in the NREAD. + * \param[in] size The total size of the access to NREAD. + * \returns The maximum number of bytes that are allowed to send in a single + * NREAD packet that conforms to the RapidIO standard. + * + * This function calculates the maximum sized NREAD packet payload that are + * possible to send without breaking the limitations in the RapidIO specification. + * It is intended to be called repeatedly. + * + * Example: An area with address=0x00007 and size=258 needs to be read. + * Call RIOPACKET_getReadPacketSize(0x00007, 258)->1. + * Send an NREAD to address=0x00007 and size=1. + * Update the address and size with the returned value-> + * address+=1->address=0x00008 size-=1->size=257. + * Call RIOPACKET_getReadPacketSize(0x00008, 257)->256. + * Send an NREAD to address=0x00008 and size=256. + * Update the address and size with the returned value-> + * address+=256->address=0x00108 size-=256->size=1. + * Call RIOPACKET_getReadPacketSize(0x00108, 1)->1. + * Send an NREAD to address=0x00108 and size=1. + * Update the address and size with the returned value-> + * address+=1->address=0x00109 size-=1->size=0. + * All the data has been read. + * + */ +uint32_t RIOPACKET_getReadPacketSize(uint32_t address, uint32_t size) +{ + uint32_t returnValue; + + + switch(address%8) + { + case 0: + if(size >= 256) + { + returnValue = 256; + } + else if(size >= 224) + { + returnValue = 224; + } + else if(size >= 192) + { + returnValue = 192; + } + else if(size >= 160) + { + returnValue = 160; + } + else if(size >= 128) + { + returnValue = 128; + } + else if(size >= 96) + { + returnValue = 96; + } + else if(size >= 64) + { + returnValue = 64; + } + else if(size >= 32) + { + returnValue = 32; + } + else if(size >= 16) + { + returnValue = 16; + } + else if(size >= 8) + { + returnValue = 8; + } + else + { + returnValue = size; + } + break; + case 1: + if(size >= 7) + { + returnValue = 7; + } + else + { + returnValue = 1; + } + break; + case 2: + if(size >= 6) + { + returnValue = 6; + } + else if(size >= 2) + { + returnValue = 2; + } + else + { + returnValue = 1; + } + break; + case 3: + if(size >= 5) + { + returnValue = 5; + } + else + { + returnValue = 1; + } + break; + case 4: + if(size >= 4) + { + returnValue = 4; + } + else if(size >= 2) + { + returnValue = 2; + } + else + { + returnValue = 1; + } + break; + case 5: + if(size >= 3) + { + returnValue = 3; + } + else + { + returnValue = 1; + } + break; + case 6: + if(size >= 2) + { + returnValue = 2; + } + else + { + returnValue = 1; + } + break; + default: + returnValue = 1; + break; + } + + return returnValue; +} + + + +/******************************************************************************* + * Locally used helper functions. + *******************************************************************************/ + +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 payload bytes from RapidIO packet into a 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 = RIOPACKET_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 = RIOPACKET_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 = RIOPACKET_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 = RIOPACKET_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 = RIOPACKET_Crc16(content, crc); + content <<= 16; + content |= crc; + } + packet[packetIndex>>2] = content; + + return (packetIndex>>2)+1; +} + + + +/* \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. + **************************************************************/ + 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; + } +} + +/*************************** end of file **************************************/ Index: tags/1.0.2-release/sw/stack/rioconfig.h =================================================================== --- tags/1.0.2-release/sw/stack/rioconfig.h (nonexistent) +++ tags/1.0.2-release/sw/stack/rioconfig.h (revision 50) @@ -0,0 +1,64 @@ +/******************************************************************************* + * + * 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. + * + * No copyright for this file since it has to be changed. + * + * To Do: + * - + * + * Author(s): + * - Magnus Rosenius, magro732@opencores.org + * + *******************************************************************************/ + +#ifndef __RIO_CONFIG +#define __RIO_CONFIG + +/******************************************************************************* +* Includes +*******************************************************************************/ + +#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(...) fprintf(stderr, __VA_ARGS__) +#endif + +/******************************************************************************* +* Global declarations +*******************************************************************************/ + +/******************************************************************************* +* Global function prototypes +*******************************************************************************/ + +#endif // __RIO_CONFIG + +/*************************** end of file **************************************/
tags/1.0.2-release/sw/stack/rioconfig.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/sw/stack/riostack.h =================================================================== --- tags/1.0.2-release/sw/stack/riostack.h (nonexistent) +++ tags/1.0.2-release/sw/stack/riostack.h (revision 50) @@ -0,0 +1,456 @@ +/******************************************************************************* + * + * 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 API of the riostack.c module. + * + * To Do: + * - + * + * Author(s): + * - Magnus Rosenius, magro732@opencores.org + * + ******************************************************************************* + * + * Copyright (C) 2015 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" +#include "riopacket.h" + + +/******************************************************************************* + * Global typedefs + *******************************************************************************/ + +/* The size of a maximum sized RapidIO packet when stored in memory. */ +/* One entry contains a header with the used buffer size. */ +#define RIOSTACK_BUFFER_SIZE (RIOPACKET_SIZE_MAX+1u) + + +/* Define the different types of RioSymbols. */ +typedef enum + { + RIOSTACK_SYMBOL_TYPE_IDLE, RIOSTACK_SYMBOL_TYPE_CONTROL, + RIOSTACK_SYMBOL_TYPE_DATA, RIOSTACK_SYMBOL_TYPE_ERROR + } RioSymbolType_t; + + +/* + * 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_t type; + uint32_t data; +} RioSymbol_t; + + +/* 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_t; + + +/* 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_t; + + +/* 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; + + + +/* Define the structure to keep all the RapidIO stack variables. */ +typedef struct +{ + /* Receiver variables. */ + RioReceiverState_t 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_t 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; + + /** 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 maximum time between a completed outbound packet and the reception of its pcakcet-accepted control-symbol. */ + uint32_t statusOutboundLinkLatencyMax; + + /** 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; + + /* Private user data. */ + void* private; +} RioStack_t; + + +/******************************************************************************* + * Global function prototypes + *******************************************************************************/ + +/** + * \brief Open the RapidIO stack for operation. + * + * \param[in] stack Stack instance to operate on. + * \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. + * + * 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 RIOSTACK_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 RIOSTACK_open(RioStack_t *stack, void *private, + const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer, + const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer); + +/******************************************************************************************* + * 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, zero if link is uninitialized and non-zero if + * the link is initialized. + * + * This function indicates if the link is up and ready to relay packets. + */ +int RIOSTACK_getStatus(RioStack_t *stack); + +/** + * \brief Clear outbound queue. + * + * \param[in] stack The stack to operate on. + * + * This function clears all pending packet in the outbound queue. + */ +void RIOSTACK_clearOutboundQueue(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 RIOSTACK_getOutboundQueueLength(RioStack_t *stack); + +/** + * \brief Get the number of available outbound packets. + * + * \param[in] stack The stack to operate on. + * \return Returns the number of available outbound packets. + * + * This function checks the outbound queue and returns the number of packets + * that are available before the queue is full. + */ +uint8_t RIOSTACK_getOutboundQueueAvailable(RioStack_t *stack); + +/** + * \brief Add a packet to the outbound queue. + * + * \param[in] stack The stack to operate on. + * \param[in] packet The packet to send. + * + * This function sends a packet. + * + * \note The packet CRC is not checked. It must have been checked before it is used as + * argument to this function. + * + * \note Call RIOSTACK_outboundQueueAvailable() before this function is called to make sure + * the outbound queue has transmission buffers available. + * + * \note Use RIOSTACK_getStatus() to know when a packet is allowed to be transmitted. + */ +void RIOSTACK_setOutboundPacket(RioStack_t *stack, RioPacket_t *packet); + +/** + * \brief Clear inbound queue. + * + * \param[in] stack The stack to operate on. + * + * This function clears all pending packet in the inbound queue. + */ +void RIOSTACK_clearInboundQueue(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 RIOSTACK_getInboundQueueLength(RioStack_t *stack); + +/** + * \brief Get the number of available inbound packets. + * + * \param[in] stack The stack to operate on. + * \return Returns the number of available inbound packets. + * + * This function checks the inbound queue and returns the number of packets + * that can be received without the queue is full. + */ +uint8_t RIOSTACK_getInboundQueueAvailable(RioStack_t *stack); + +/** + * \brief Get, remove and return a packet from the inbound queue. + * + * \param[in] stack The stack to operate on. + * \param[in] packet The packet to receive to. + * + * This function moves a packet from the inbound packet queue to the location of the packet + * in the argument list. + */ +void RIOSTACK_getInboundPacket(RioStack_t *stack, RioPacket_t *packet); + +/******************************************************************************************* + * 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 RIOSTACK_setPortTimeout() + * to allow for the stack to handle timeouts. + */ +void RIOSTACK_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 RIOSTACK_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 RIOSTACK_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 RIOSTACK_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 RIOSTACK_portAddSymbol( RioStack_t *stack, const RioSymbol_t 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_t RIOSTACK_portGetSymbol( RioStack_t *stack ); + +#endif /* _RIOSTACK_H */ + +/*************************** end of file **************************************/
tags/1.0.2-release/sw/stack/riostack.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/sw/stack/riopacket.h =================================================================== --- tags/1.0.2-release/sw/stack/riopacket.h (nonexistent) +++ tags/1.0.2-release/sw/stack/riopacket.h (revision 50) @@ -0,0 +1,267 @@ +/******************************************************************************* + * + * 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 public API for riopacket. + * + * To Do: + * - + * + * Author(s): + * - Magnus Rosenius, magro732@opencores.org + * + ******************************************************************************* + * + * Copyright (C) 2015 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 riopacket.c + */ + +#ifndef __RIOPACKET_H +#define __RIOPACKET_H + +/******************************************************************************* + * Includes + *******************************************************************************/ + +#include "rioconfig.h" + + +/******************************************************************************* + * Global typedefs + *******************************************************************************/ + +/* The maximum size of a RapidIO packet in words (32-bit). */ +#define RIOPACKET_SIZE_MIN 3u +#define RIOPACKET_SIZE_MAX 69u + +/* 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))) + +/* Packet ftype constants. */ +#define RIOPACKET_FTYPE_REQUEST 0x2 +#define RIOPACKET_FTYPE_WRITE 0x5 +#define RIOPACKET_FTYPE_MAINTENANCE 0x8 +#define RIOPACKET_FTYPE_DOORBELL 0xa +#define RIOPACKET_FTYPE_MESSAGE 0xb +#define RIOPACKET_FTYPE_RESPONSE 0xd + +/* Transaction constants. */ +#define RIOPACKET_TRANSACTION_MAINT_READ_REQUEST 0ul +#define RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST 1ul +#define RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE 2ul +#define RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE 3ul +#define RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST 4ul +#define RIOPACKET_TRANSACTION_WRITE_NWRITE 4ul +#define RIOPACKET_TRANSACTION_WRITE_NWRITER 5ul +#define RIOPACKET_TRANSACTION_REQUEST_NREAD 4ul +#define RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD 0ul +#define RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE 1ul +#define RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD 8ul + +/* Response status constants. */ +#define RIOPACKET_RESPONSE_STATUS_DONE 0ul +#define RIOPACKET_RESPONSE_STATUS_RETRY 3ul +#define RIOPACKET_RESPONSE_STATUS_ERROR 7ul + + +/* The structure containing a RapidIO packet. */ +typedef struct +{ + /* Size in words. */ + uint8_t size; + uint32_t payload[RIOPACKET_SIZE_MAX]; +} RioPacket_t; + + + +/******************************************************************************* + * Global function prototypes + *******************************************************************************/ + +void RIOPACKET_init(RioPacket_t *packet); +uint8_t RIOPACKET_size(RioPacket_t *packet); +void RIOPACKET_append(RioPacket_t *packet, uint32_t word); + +int RIOPACKET_valid(RioPacket_t *packet); + +int RIOPACKET_serialize(RioPacket_t *packet, const uint16_t size, uint8_t *buffer); +int RIOPACKET_deserialize(RioPacket_t *packet, const uint16_t size, const uint8_t *buffer); + +#ifdef ENABLE_TOSTRING +#include +void RIOPACKET_toString(RioPacket_t *packet, char *buffer); +#endif + +uint8_t RIOPACKET_getFtype(RioPacket_t *packet); +uint16_t RIOPACKET_getDestination(RioPacket_t *packet); +uint16_t RIOPACKET_getSource(RioPacket_t *packet); +uint8_t RIOPACKET_getTransaction(RioPacket_t *packet); +uint8_t RIOPACKET_getTid(RioPacket_t *packet); + +void RIOPACKET_setMaintReadRequest(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, uint8_t hop, + uint8_t tid, uint32_t offset); +void RIOPACKET_getMaintReadRequest(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, uint8_t *hop, + uint8_t *tid, uint32_t *offset); + +void RIOPACKET_setMaintReadResponse(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, uint32_t data); +void RIOPACKET_getMaintReadResponse(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, uint32_t *data); + +void RIOPACKET_setMaintWriteRequest(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, uint8_t hop, + uint8_t tid, uint32_t offset, uint32_t data); +void RIOPACKET_getMaintWriteRequest(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, uint8_t *hop, + uint8_t *tid, uint32_t *offset, uint32_t *data); + +void RIOPACKET_setMaintWriteResponse(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid); +void RIOPACKET_getMaintWriteResponse(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid); + +void RIOPACKET_setMaintPortWrite(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint32_t componentTag, uint32_t portErrorDetect, + uint32_t implementationSpecific, uint8_t portId, + uint32_t logicalTransportErrorDetect); +void RIOPACKET_getMaintPortWrite(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint32_t *componentTag, uint32_t *portErrorDetect, + uint32_t *implementationSpecific, uint8_t *portId, + uint32_t *logicalTransportErrorDetect); + +void RIOPACKET_setNwrite(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint32_t address, uint16_t payloadSize, uint8_t *payload); +void RIOPACKET_getNwrite(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint32_t *address, uint16_t *payloadSize, uint8_t *payload); + +void RIOPACKET_setNwriteR(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, + uint32_t address, uint16_t payloadSize, uint8_t *payload); +void RIOPACKET_getNwriteR(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, + uint32_t *address, uint16_t *payloadSize, uint8_t *payload); + +void RIOPACKET_setNread(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, + uint32_t address, uint16_t payloadSize); +void RIOPACKET_getNread(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, + uint32_t *address, uint16_t *payloadSize); + + +void RIOPACKET_setDoorbell(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, uint16_t info); +void RIOPACKET_getDoorbell(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, uint16_t *info); + +void RIOPACKET_setMessage(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t mailbox, + uint16_t size, uint8_t *payload); +void RIOPACKET_getMessage(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *mailbox, + uint16_t *size, uint8_t *payload); + + +void RIOPACKET_setResponseNoPayload(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, uint8_t status); +void RIOPACKET_getResponseNoPayload(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, uint8_t *status); + +void RIOPACKET_setResponseWithPayload(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t tid, uint8_t offset, + uint16_t size, uint8_t *payload); +void RIOPACKET_getResponseWithPayload(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *tid, uint8_t offset, + uint16_t *size, uint8_t *payload); + +void RIOPACKET_setResponseMessage(RioPacket_t *packet, + uint16_t destId, uint16_t srcId, + uint8_t mailbox, uint8_t status); +void RIOPACKET_getResponseMessage(RioPacket_t *packet, + uint16_t *destId, uint16_t *srcId, + uint8_t *mailbox, uint8_t *status); + +uint16_t RIOPACKET_Crc16( const uint16_t data, const uint16_t crc); +uint16_t RIOPACKET_Crc32( const uint32_t data, uint16_t crc); + +uint32_t RIOPACKET_getReadPacketSize(uint32_t address, uint32_t size); +uint32_t RIOPACKET_getWritePacketSize(uint32_t address, uint32_t size); + +#endif + +/*************************** end of file **************************************/ Index: tags/1.0.2-release/sw/codec/riocodecuart.c =================================================================== --- tags/1.0.2-release/sw/codec/riocodecuart.c (nonexistent) +++ tags/1.0.2-release/sw/codec/riocodecuart.c (revision 50) @@ -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"); +}
tags/1.0.2-release/sw/codec/riocodecuart.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/bench/vhdl/TestRioSwitch.vhd =================================================================== --- tags/1.0.2-release/bench/vhdl/TestRioSwitch.vhd (nonexistent) +++ tags/1.0.2-release/bench/vhdl/TestRioSwitch.vhd (revision 50) @@ -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;
tags/1.0.2-release/bench/vhdl/TestRioSwitch.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/bench/vhdl/TestRioPcsUart.vhd =================================================================== --- tags/1.0.2-release/bench/vhdl/TestRioPcsUart.vhd (nonexistent) +++ tags/1.0.2-release/bench/vhdl/TestRioPcsUart.vhd (revision 50) @@ -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;
tags/1.0.2-release/bench/vhdl/TestRioPcsUart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/bench/vhdl/TestUart.vhd =================================================================== --- tags/1.0.2-release/bench/vhdl/TestUart.vhd (nonexistent) +++ tags/1.0.2-release/bench/vhdl/TestUart.vhd (revision 50) @@ -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;
tags/1.0.2-release/bench/vhdl/TestUart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/bench/vhdl/TestRioSerial.vhd =================================================================== --- tags/1.0.2-release/bench/vhdl/TestRioSerial.vhd (nonexistent) +++ tags/1.0.2-release/bench/vhdl/TestRioSerial.vhd (revision 50) @@ -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;
tags/1.0.2-release/bench/vhdl/TestRioSerial.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/bench/vhdl/TestRioPacketBuffer.vhd =================================================================== --- tags/1.0.2-release/bench/vhdl/TestRioPacketBuffer.vhd (nonexistent) +++ tags/1.0.2-release/bench/vhdl/TestRioPacketBuffer.vhd (revision 50) @@ -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;
tags/1.0.2-release/bench/vhdl/TestRioPacketBuffer.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/rtl/vhdl/RioSwitch.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/RioSwitch.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/RioSwitch.vhd (revision 50) @@ -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;
tags/1.0.2-release/rtl/vhdl/RioSwitch.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/rtl/vhdl/RioCommon.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/RioCommon.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/RioCommon.vhd (revision 50) @@ -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;
tags/1.0.2-release/rtl/vhdl/RioCommon.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/rtl/vhdl/RioSerial.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/RioSerial.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/RioSerial.vhd (revision 50) @@ -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;
tags/1.0.2-release/rtl/vhdl/RioSerial.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/rtl/vhdl/RioPacketBuffer.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/RioPacketBuffer.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/RioPacketBuffer.vhd (revision 50) @@ -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;
tags/1.0.2-release/rtl/vhdl/RioPacketBuffer.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/rtl/vhdl/RioPcsUart.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/RioPcsUart.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/RioPcsUart.vhd (revision 50) @@ -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;
tags/1.0.2-release/rtl/vhdl/RioPcsUart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/rtl/vhdl/Uart.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/Uart.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/Uart.vhd (revision 50) @@ -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; +
tags/1.0.2-release/rtl/vhdl/Uart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/rtl/vhdl/srio_pcs_struct.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/srio_pcs_struct.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/srio_pcs_struct.vhd (revision 50) @@ -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: tags/1.0.2-release/rtl/vhdl/RioWbBridge.vhd =================================================================== --- tags/1.0.2-release/rtl/vhdl/RioWbBridge.vhd (nonexistent) +++ tags/1.0.2-release/rtl/vhdl/RioWbBridge.vhd (revision 50) @@ -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;
tags/1.0.2-release/rtl/vhdl/RioWbBridge.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.0.2-release/doc/rio.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.0.2-release/doc/rio.pdf =================================================================== --- tags/1.0.2-release/doc/rio.pdf (nonexistent) +++ tags/1.0.2-release/doc/rio.pdf (revision 50)
tags/1.0.2-release/doc/rio.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.0.2-release/doc/rio.odt =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.0.2-release/doc/rio.odt =================================================================== --- tags/1.0.2-release/doc/rio.odt (nonexistent) +++ tags/1.0.2-release/doc/rio.odt (revision 50)
tags/1.0.2-release/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.