SBUS
File:Sbus-diagram.png | |
sbus.c | |
sbus.h |
Overview
While many CPUs contain some type of parallel interface that we can use for FPGA communication, the Cavium CNS2132 only has an SPI interface. It functions quite well, however some programming considerations must be made with this processor. Since SPI cannot be shared, we have implemented the SBUS which is a locking mechanism to communicate to the 128k of registers in the FPGA. We use this on all of our applications that communicate with the FPGA which includes sdctl, nandctl, xuartctl, daqctl, spiflashctl, dioctl, and ts7500ctl.
If you use the ctl applications as libraries, they will abstract this.
Code Example
This example shows accessing DIO directly without dioctl.
#include "sbus.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#define DIO_Z 2
/*******************************************************************************
* Main: accept input from the command line and act accordingly.
*******************************************************************************/
int main(int argc, char **argv)
{
int pin;
int val;
int returnedValue;
// Check for invalid command line arguments
if ((argc > 4) | (argc < 3))
{
printf("Usage: %s <get|set> <pin#> <set_value (0|1|2)>\n", argv[0]);
return 1;
}
// We only want to get val if there are more than 3 command line arguments
if (argc == 3)
pin = strtoul(argv[2], NULL, 0);
else
{
pin = strtoul(argv[2], NULL, 0);
val = strtoul(argv[3], NULL, 0);
}
// If anything other than pins 5 through 40, fail program
assert(pin <= 40 && pin >= 5);
// Parse through the command line arguments, check for valid inputs, and exec
if (!(strcmp(argv[1], "get")) && (argc == 3))
{
sbuslock();
returnedValue = getdiopin(pin);
sbusunlock();
printf("pin#%d = %d \n", pin, returnedValue);
}
else if(!(strcmp(argv[1], "set")) && (argc == 4) && (val <= 2))
{
sbuslock();
setdiopin(pin, val);
sbusunlock();
printf("pin#%d set to %d\n", pin, val);
}
else
{
printf("Usage: %s <get|set> <pin#> <set_value (0|1|2)>\n", argv[0]);
return 1;
}
return 0;
}
SBUS to FPGA Protocol
For the most part, the application and kernel level programmer will not be interested in the following sections as the below information is completely abstracted away from the user by the SBUS C API and the various TS-specific utilities. Even the FPGA programmer is abstracted from the details of this protocol by the spi_sbus.v Verilog module which turns the SBUS SPI traffic into WISHBONE bus cycles.
The SBUS protocol allows for 16 specific 16 bit registers (32-bytes of register space) to be read or written and has provision for the FPGA internal WISHBONE bus cycles to take any amount of time to be ack'ed through the mechanism of SBUS retries. SPI bandwidth efficient burst register reads/writes are also possible when writing/reading continuously to the same address.
The general protocol consists of a 24-bit SPI transaction framed by the SPI CS#. Bits are clocked in on the rising edge and the first MOSI (input) bit signifies whether the bus cycle is a read or write. This is followed by the 4 address bits MSB first. The remaining 19 bits depend on whether the cycle is a read or write. For reads, the WISHBONE bus cycle is started as soon as the last address bit is clocked in.
The 24-bit SPI SBUS data format - bit 23 (WE) is first on wire:
16-bit WISHBONE READ operation 23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| --|--|--|--|--|--|--|--|--|--------------------------------------------| SI: 0|A3|A2|A1|A0| | | | B|<------------should be zero---------------->| SO: |X2|X1|X0|MSB<----------returned READ data----------->LSB| 16-bit WISHBONE WRITE operation: 23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| --|--|--|--|--|-----------------------------------------------|--|--|--| SI: 1|A3|A2|A1|A0|MSB<-----------WRITE data------------------>LSB|N2|N1|N0| SO: |Y2|Y1|Y0| * A3-A0: Address bits (sent by CPU) * X2-X0: ack bits for reads (sent by FPGA). If any are 1, the following data is valid. If they are all 0, the WISHBONE cycle did not complete in time and must be immediately retried. * Y2-Y0: ack bits for write (sent by FPGA). If any are 1, the write cycle was completed. If all are 0, the WISHBONE write did not complete and must be immediately retried. * B: Burst read. Setting this to 1 starts another WISHBONE read cycle for the same address. See "SBUS Burst mode" below. * N2-N0: For burst writes, this represents bits 15-13 of the next burst write data, otherwise these bits are Dont-Cares. See "SBUS Burst mode" below.