Expand description
§XVC Server Library
This crate provides a foundation for implementing Xilinx Virtual Cable (XVC) servers that handle JTAG communication with FPGA devices over network connections.
§Overview
XVC is a protocol used by Xilinx design tools to interact with FPGA devices remotely. This library abstracts the protocol handling and provides a server implementation that can work with different backend device drivers.
§Architecture
The crate is built around two main components:
XvcServerTrait: Defines the interface that backend drivers must implement to handle low-level JTAG operations (TCK configuration and vector shifting)server::Server: A generic server that handles XVC protocol communication, message parsing, and client connections
§How It Works
- A backend driver (e.g., kernel driver, UIO device) implements the
XvcServertrait - The driver is wrapped in a
server::Serverinstance - The server listens for TCP connections and processes XVC protocol messages
- Each message is dispatched to the backend driver for actual JTAG operations
- Results are serialized and sent back to the client
§Protocol Support
This implementation supports the XVC 1.0 protocol with the following operations:
- GetInfo: Query server capabilities (version, max vector size)
- SetTck: Configure the JTAG Test Clock (TCK) period
- Shift: Perform JTAG vector shifting (TMS/TDI/TDO)
For detailed protocol information, see the xvc_protocol crate.
§Basic Usage
§Implementing a Backend Driver
Create a struct that implements the XvcServer trait:
use xvc_server::XvcServer;
struct MyDriver {
// device-specific fields
}
impl XvcServer for MyDriver {
fn set_tck(&self, period_ns: u32) -> u32 {
// Configure hardware TCK period
period_ns
}
fn shift(&self, num_bits: u32, tms: &[u8], tdi: &[u8]) -> Box<[u8]> {
// Perform JTAG shifting and return TDO data
Box::default()
}
}§Starting the Server
use xvc_server::server::{Server, Config};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
let driver = MyDriver::new()?;
let config = Config::default();
let server = Server::new(driver, config);
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 2542);
server.listen(addr).await?;§Error Handling
The XVC 1.0 protocol specification does not support error reporting in the Shift operation. If a shift operation fails, an empty result is returned to the client. For other operations, standard I/O errors are propagated as appropriate.
§Configuration
Server behavior can be customized via server::Config:
- max_vector_size: Maximum size of JTAG vectors (default: 10 MiB)
- read_write_timeout: Socket I/O timeout duration (default: 30 seconds)
§Logging
This crate uses the log crate for diagnostics. Enable logging to see:
- Client connections and disconnections
- Protocol messages being processed
- Configuration details and error conditions
Configure logging with an implementation like env_logger:
env_logger::init();§Thread Model
The server is async (tokio) and accepts connections concurrently, but enforces at-most-one active client at a time. A second connection attempt while a client is active is immediately rejected. This matches the XVC protocol assumption of a single JTAG session and prevents interleaved access to the hardware state machine.
Backend methods (set_tck, shift) are called via block_in_place, so the server
requires a multi-thread tokio runtime.
Modules§
Traits§
- XvcServer
- Trait that backend drivers must implement to provide JTAG functionality.