FpgaManager
Software API Documentation
Examples

Code examples to showcase how to get started with FPGA Manager. Error handling is kept at a minimum to show the bare necessities. The examples can be run against a reference design target.

.NET Core Hello World

FPGA Manager assembly hello world.

{
using System;
class Program
{
static void Main(string[] args)
{
using (var mgr = new FPGAMgr.FpgaManagerApi(FPGAMgr.ApiUrl.UDP("192.168.33.12")))
{
Console.WriteLine($"FPGA Manager Version: {mgr.Details.BaseDllVersion} / {mgr.Details.ApiDllVersion}");
var memory = mgr.CreateMemoryMap(0);
mgr.Open();
Console.WriteLine($"Register: {memory.ReadRegister(0x10001000):X8}");
}
}
}
}

.NET Core Basic Memory I/O

Basic memory access done quick.

{
using System;
class Program
{
static void Main(string[] args)
{
using (var mgr = new FPGAMgr.FpgaManagerApi(FPGAMgr.ApiUrl.UDP("192.168.33.12")))
{
// create MmAccess on Stream 0
var memory = mgr.CreateMemoryMap(0);
mgr.Open();
// Blocking register write/read to/from 0x10001000
memory.WriteRegister(0x10001000, 0xDEADBEEF);
var registerValue = memory.ReadRegister(0x10001000);
Console.WriteLine($"Read {registerValue:X8} from register");
// Blocking mailbox (fifo aperture) read of 100 entries
var fifoBuffer = new UInt32[100];
memory.ReadMailbox(0x10001000, fifoBuffer);
// write all 100 entries back to fifo
memory.WriteMailbox(0x10001000, fifoBuffer);
var byteBuffer = new byte[100];
// Blocking read of contiguous memory
memory.ReadContiguous(0x00000000, byteBuffer, 0, byteBuffer.Length);
// and write it back
memory.WriteContiguous(0x00000000, byteBuffer, 0, byteBuffer.Length);
}
}
}
}

.NET Core Simple Stream Loopback

Push data trough a byte stream in TAP fashion.

{
using System;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using (var mgr = new FPGAMgr.FpgaManagerApi(FPGAMgr.ApiUrl.UDP("192.168.33.12")))
{
// create MmAccess on Stream 0 and bi-directional stream on Stream 1
var memory = mgr.CreateMemoryMap(0);
var stream = mgr.CreateStream(1, FPGAMgr.StreamType.ByteStream, FPGAMgr.StreamDirection.Bidirectional);
mgr.Open();
// configure reference design loopack mode
memory.WriteRegister(0x10002000, 0);
// prepare send and receive buffer
const int TransferSize = 1100;
var bufferOut = new byte[TransferSize];
var bufferIn = new byte[TransferSize];
new Random().NextBytes(bufferOut); // fill write buffer with random data
// enqueue non-blocking read
var readTask = stream.ReadAsync(bufferIn);
// write data to stream into loopback
stream.Write(bufferOut);
// wait until we've received all data
var transferred = (await readTask).TransferredLength;
var matches = bufferOut.SequenceEqual(bufferIn);
Console.WriteLine($"Read {transferred} bytes, data {(matches ? "matches" : "does not match")}");
}
}
}
}

.NET Core Register Bank Helper

Hassle free handling of IP register offsets

{
using System;
class Program
{
static void Main(string[] args)
{
using (var mgr = new FPGAMgr.FpgaManagerApi(FPGAMgr.ApiUrl.UDP("192.168.33.12")))
{
// create MmAccess on Stream 0
var memory = mgr.CreateMemoryMap(0);
mgr.Open();
// create register bank helpers
var bankBabe = new FPGAMgr.RegisterBank(0x10001000, memory);
var bankBram = new FPGAMgr.RegisterBank(0x00000000, memory);
var bankLedz = new FPGAMgr.RegisterBank(0x10000000, memory);
// Read constant from 0x10001000
Console.WriteLine($"Read {bankBabe.ReadRegister(0):X8} from register");
// Turn on the LED at address 0x10000000
bankLedz.WriteRegister(0, 1);
var byteBuffer = new byte[100];
// Read 100 bytes from blockram starting at address 0x00000047
bankBram.ReadContiguous(0x00000047, byteBuffer, 0, byteBuffer.Length);
// and write it to location 0x00000147
memory.WriteContiguous(0x00000147, byteBuffer, 0, byteBuffer.Length);
}
}
}
}

C++ Hello World

FPGA Manager C++ API hello world.

#include "FpgaManager.h"
#include <iostream>
int main()
{
fpgamgr::FpgaManager mgr(fpgamgr::types::ApiUrl::UDP("192.168.33.12"));
std::cout << "FPGA Manager Version: " << mgr.Details() << std::endl;
auto& mm = mgr.CreateMemoryMap(0);
mgr.Open();
std::cout << "Register: " << std::hex << mm.ReadRegister(0x10001000) << std::endl;
return 0;
}

C++ Simple Stream Loopback

Push data trough a byte stream

#include "FpgaManager.h"
#include <iostream>
#include <vector>
#include <random>
#include <mutex>
#include <algorithm>
#include <condition_variable>
int main()
{
fpgamgr::FpgaManager mgr(fpgamgr::types::ApiUrl::UDP("192.168.33.12"));
// create MmAccess on Stream 0 and bi-directional stream on Stream 1
auto& memory = mgr.CreateMemoryMap(0);
auto& stream = mgr.CreateStream(1, fpgamgr::StreamType::ByteStream, fpgamgr::StreamDirection::Bidirectional);
mgr.Open();
// configure reference design loopack mode
memory.WriteRegister(0x10002000, 0);
// prepare send and receive buffer
constexpr int TransferSize = 1100;
std::vector<uint8_t> buffer_out(TransferSize);
std::vector<uint8_t> buffer_in(TransferSize);
{
// fill write buffer with random data
std::random_device rnd_device;
std::mt19937 rnd_engine(rnd_device());
std::uniform_int_distribution<int> distribution(0, 255);
std::generate(buffer_out.begin(), buffer_out.end(), [&] { return distribution(rnd_engine); });
}
// signaling infrastructure
std::mutex mx;
std::condition_variable cv;
// enqueue non-blocking read
stream.ReadAsync(buffer_in.data(), buffer_in.size(),
[&cv](const fpgamgr::IStream::TransferDetails& details)
{
std::cout << "transferred " << details.transferred << " bytes of " << details.requested << " requested" << std::endl;
cv.notify_one();
});
// write data to stream into loopback
stream.Write(buffer_out.data(), buffer_out.size());
// wait until we've received all data
{
std::unique_lock<std::mutex> lk(mx);
cv.wait(lk);
}
// compare buffers
bool matches = 0 == std::memcmp(buffer_in.data(), buffer_out.data(), buffer_in.size());
std::cout << "received data " << (matches ? "matches" : "does not match") << std::endl;
return 0;
}

AnsiC Hello World

FPGA Manager library hello world.

#include "FpgaManagerApi.h"
#include <stdio.h>
#include <stdint.h>
int main()
{
SystemHandle sysHandle = NULL;
SystemApi_Create(&sysHandle);
uint8_t major, minor;
SystemApi_GetSwVersion(sysHandle, &major, &minor);
printf("FPGA Manager Version: %d.%02d\n", major, minor);
DeviceHandle devHandle = NULL;
DeviceApi_Create(&devHandle, "udp://192.168.33.12", 1);
MmAccessHandle mmHandle = NULL;
MmAccessApi_Create(&mmHandle);
DeviceApi_CreateMmAccess(devHandle, mmHandle, 0);
DeviceApi_Open(devHandle);
MmAccessApi_Open(mmHandle);
uint8_t buffer[4];
MmAccessApi_Read(mmHandle, buffer, sizeof(buffer), 0x10001000, false, false, NULL);
printf("Register: %02x%02x%02x%02x\n", buffer[3], buffer[2], buffer[1], buffer[0]);
MmAccessApi_Close(mmHandle, false);
DeviceApi_Close(devHandle, false);
MmAccessApi_Delete(&mmHandle);
DeviceApi_Delete(&devHandle);
SystemApi_Delete(&sysHandle);
return 0;
}