basil

Basil is a modular readout framework intended to allow simple and fast data acquisition systems (DAQ) design. It consists of different hardware components, FPGA firmware modulus and a Python based contol software.

Contents:

Introduction

Basil is a modular readout framework intended to allow simple and fast data acquisition systems (DAQ) design. It consists of different hardware components, FPGA firmware modulus and a Python based control software.

Features

Firmware:
Software:
  • layer structure following hardware

  • generation based on yaml file

  • register abstract layer (RAL)

  • simulator interface allows software test against simulated RTL (thanks to cocotb )

Installation

From host folder run:

python setup.py install

or

pip install -e "git+https://github.com/SiLab-Bonn/basil.git#egg=basil&subdirectory=host"

Simulation

Thank to Chris Higgs basil has a simulation interface (SiSim) with allow communication with simulator as if talking to real hardware.

To make simulation one need:
  • verilog simulator (ex. Icarus )

  • cocotb library

  • set interface type to SiSim

Basil unit tests make extensive use of this feature. See tests folder.

License

If not stated otherwise.

Host Software:

The host software is distributed under the BSD 3-Clause (“BSD New” or “BSD Simplified”) License.

FPGA Firmware:

The FPGA software is distributed under the GNU Lesser General Public License, version 3.0 (LGPLv3).

Hardware

Basil also allows easy integration with custom Hardware.

For our purpuse we developed general purpose hardware components which connect to custom DUTs. The MultiIO board (MIO) implements the main FPGA for digital IO, memory ressources, and the interface (USB 2.0) to the PC. To add analog functionality, the Gerneral Purpose Analog Card (GPAC) was developed. It connects to the MultiIO board and provides 4 programmable power supplies, 12 current sources, 4 voltage sources, 4 fast ADC channels, digital IO with scalable voltages, LVDS, and a programmable injection pulse generator. The device under test (DUT) will be connected with a custom PCB to the MIO/GPAC hardware.

  • MultiIO - Digital IO card with FPGA and USB 2.0 interface

  • MIO3 - Digital IO card with FPGA and USB 3.0 interface based on Enclustra KX1 module

  • GPAC - General Purpose Analog Card

MIO (Multi IO Card)

The “S3 Multi IO System” is developed as an easy to use multi purpose digital IO card. It includes a free programmable Xilinx Spartan3 FPGA, SRAM Memory, USB2.0 Interface and a 8051 microcontroller with I2C and SPI functionality. It is designed to provide sufficient digital IO capability to any kind of daughter card.

_images/MIO.jpg
Features:
Silicon devices
  • Xilinx Spartan3 FPGA - XC3S1000 FG320 4C

  • Cypress USB Controller - CY7C68013A 128AXC

  • Cypress async. SRAM - CY7C1061AV33 10ZXC

  • Programmable clock generator - Cypress CY22150

IO connections
  • USB2.0 B-type as host interface

  • Multi-IO-Connector with 80 user IO´s (VccIO 1:2 V to 3:3 V)

  • Agilent debug connector (1253-3620)

  • JTAG connection

  • RJ-45 connector for 2 LVDS transmitter and 2 LVDS receiver

  • Header with I2C and SPI functionality

  • Header with additional FPGA user IO´s

  • 3 buffered LVTTL outputs with LEMO

  • 3 buffered LVTTL inputs with LEMO

Power supply
  • via external 5V supply

  • via USB cable

Configuration capability
  • via JTAG

  • via USB2.0

Documentation for MIO card.

GPAC (General Purpose Analog Card)

GPAC Card is developed as an easy to use multi purpose analog IO card compatible with MIO Card.

_images/MIO_GPAC_DUT.png
Features:
  • 4 regulated power supples, 0.8-1.83/2.83 V, max. 1000 mA, (controlled by I2C)

  • 4 RX and 4 TX LVDS Lines

  • 4 channel ADC, 25MS, 14bit

  • 16 CMOS Outputs

  • 8 CMOS Inouts

  • 12 current source/sink, -1mA to +1mA, 12bit (controlled by I2C)

  • 4 voltage outputs, 0-2.048 V, 12bit (controlled by I2C)

  • 64x (4 available to DUT) channel slow ADC for monitoring (controlled by I2C)

  • Injection Pulse Generator with programmable voltage levels (high and low)

Documentation for GPAC card.

MIO3 (Multi IO Card USB3)

TBD.

LX9

LX9 Board.

4 channel FE-I4 adepter with TLU:

_images/lx9_fei4_a.jpg _images/lx9_fei4_b.jpg

Firmware

FPGA firmware consists of very simple single master bus definition and set of standard modules used by DAQ systems.

Typical firmware consists of basil bus connecting all modules. Control modules witch provide configuration to DUT (like SPI/GPIO) and data taking modules (like data receivers). Received data (32 bit) are stored in the FIFO (large extremal memory) and can be continuously pulled from host application. Data from different modules are identified by source codding in 32bit data words.

basil bus

single write
single read

Software

The software framework has a modular structure that reflects the firmware and adds extra layers to make hardware interface user friendly. It loosely follows Register Abstract Layer (RAL) concepts. All the layers are automatically created based on yaml configuration file.

_images/basil_layers.png

Yaml configuration file

TBD

Transfer Layer (TL)

Implements communication interface like UART, USB, Ethernet or Simulation. Every TL interface implements 2 functions:

class basil.TL.TransferLayer.TransferLayer(conf)[source]

Transfer Layer implements minimum API needed access to hardware. On error raise IOError.

init()[source]

Initialize and connect to hardware.

read()[source]

Read access.

Return type

None

write(data)[source]

Write access.

Parameters

data (iterable) – array/list of bytes

Return type

None

Hardware Layer (HL)

Implements drivers for basil modules and external devices. Drivers can reference other drivers within HL.

Register Layer (RL)

Implements Register Level Abstraction. Allow to user/control software to work on DUT registers without taking thinking about underlying levels.

Modules

Driver

class basil.HL.gpio.gpio(intf, conf)[source]

GPIO interface

reset()[source]

Soft reset the module.

Driver

class basil.HL.spi.spi(intf, conf)[source]

Implement serial programming interface (SPI) driver.

get_data(size=None, addr=None)[source]

Gets data for incoming stream

get_en()[source]

Gets state of enable.

get_repeat()[source]

Gets Number of repetitions of sequence with delay ‘wait’ (if 0 –> repeat forever)

get_size()[source]

Get size of shift register length

get_wait()[source]

Gets time delay between repetitions in clock cycles

is_done()[source]

Get the status of transfer/sequence.

reset()[source]

Soft reset the module.

set_data(data, addr=0)[source]

Sets data for outgoing stream

set_en(value)[source]

Enable start on external EXT_START signal (inside FPGA)

set_repeat(value)[source]

If 0: Repeat sequence forever Other: Number of repetitions of sequence with delay ‘wait’

set_size(value)[source]

Number of clock cycles for shifting in data ex. length of matrix shift register (number of pixels daisy chained)

set_wait(value)[source]

Sets time delay between repetitions in clock cycles

start()[source]

Starts the shifting data

Driver

class basil.HL.seq_gen.seq_gen(intf, conf)[source]

Sequencer generator controller interface for seq_gen FPGA module.

Driver

class basil.HL.pulse_gen.pulse_gen(intf, conf)[source]

Pulser generator

get_en()[source]

Return info if pulse starts with a fixed delay w.r.t. shift register finish signal (true) or if it only starts with .start() (false)

set_delay(value)[source]

Pulse delay w.r.t. shift register finish signal [in clock cycles(?)]

set_en(value)[source]

If true: The pulse comes with a fixed delay with respect to the external trigger (EXT_START). If false: The pulse comes only at software start.

set_repeat(value)[source]

Pulse repetition in range of 0-255

set_width(value)[source]

Pulse width in terms of clock cycles

start()[source]

Software start of pulse at random time

Driver

class basil.HL.seq_rec.seq_rec(intf, conf)[source]

Sequencer receiver controller interface for seq_rec FPGA module.

Driver

class basil.HL.cmd_seq.cmd_seq(intf, conf)[source]

FEI4 Command Sequencer Controller Interface for cmd_seq FPGA module.

Driver

class basil.HL.fei4_rx.fei4_rx(intf, conf)[source]

FEI4 receiver controller interface for fei4_rx FPGA module

Driver

class basil.HL.fast_spi_rx.fast_spi_rx(intf, conf)[source]

Fast SPI interface

reset()[source]

Soft reset the module.

Driver

class basil.HL.tlu.tlu(intf, conf)[source]

TLU controller interface

Driver

class basil.HL.tdc_s3.tdc_s3(intf, conf)[source]

TDC controller interface

Driver

class basil.HL.sram_fifo.sram_fifo(intf, conf)[source]

SRAM FIFO controller interface for sram_fifo FPGA module.

property FIFO_INT_SIZE

Get FIFO size in units of integers (32 bit).

fifo_sizeint

FIFO size in units of integers (32 bit).

get_FIFO_INT_SIZE()[source]

Get FIFO size in units of integers (32 bit).

fifo_sizeint

FIFO size in units of integers (32 bit).

get_data()[source]

Reading data in SRAM.

arraynumpy.ndarray

Array of unsigned integers (32 bit).

get_fifo_int_size()[source]

Deprecated Get FIFO size in units of integers (32 bit).

fifo_sizeint

FIFO size in units of integers (32 bit).

get_fifo_size()[source]

Deprecated Get FIFO size in units of bytes (8 bit).

fifo_sizeint

FIFO size in units of bytes (8 bit).

get_read_error_counter()[source]

Deprecated Get read error counter.

fifo_sizeint

Read error counter (read attempts when SRAM is empty).

get_size()[source]

Deprecated

Driver

class basil.HL.fadc_rx.fadc_rx(intf, conf)[source]

Fast ADC channel receiver

set_align_to_sync(value)[source]

Align data taking to a synchronization signal, reset signal is the synchronization signal (hard coded connection in Verilog source code)

set_single_data(value)[source]

Driver

class basil.HL.i2c.i2c(intf, conf)[source]

Implement master i2c programming interface driver.

property is_ready
raises ExceptionType

IOError

Transfer not acknowledged.

read(addr, size)[source]

Read access.

Parameters
  • addr (char) – i2c slave address

  • size (int) – size of transfer

Returns

data byte array

Return type

array.array(‘B’)

write(addr, data)[source]

Write access.

Parameters
  • addr (char) – i2c slave address

  • data (iterable) – array/list of bytes

Return type

None

Examples

Example of project can be found in examples folder.

For more usecases check also tests folder.

spi

An example shows how to create a simple spi interface.

_images/spi_example.png

Instantiate a verilog spi module in the firmware verilog code.

localparam SPI_BASEADDR = 32'h1000;
localparam SPI_HIGHADDR = 32'h1FFF;

spi
#(
    .BASEADDR(SPI_BASEADDR),
    .HIGHADDR(SPI_HIGHADDR),
    .MEM_BYTES(4)
)  i_spi
(
    .BUS_CLK(BUS_CLK),
    .BUS_RST(BUS_RST),
    .BUS_ADD(BUS_ADD),
    .BUS_DATA(BUS_DATA),
    .BUS_RD(BUS_RD),
    .BUS_WR(BUS_WR),

    .SPI_CLK(SPI_CLK),

    .SCLK(SCLK),
    .SDI(SDI),
    .SDO(SDO),
    .SEN(SEN),
    .SLD(SLD)
);

Create a configuration file.

transfer_layer:
  - name  : intf
    type  : SiSim

hw_drivers:
  - name      : spi
    type      : spi
    interface : intf
    base_addr : 0x1000
    mem_bytes : 2

  - name        : CNT
    type        : StdRegister
    hw_driver   : spi
    size        : 16
    fields:
      - name    : EN
        size    : 1
        offset  : 15
      - name    : OUT
        size    : 15
        offset  : 14

Write control program.

dut = Dut('spi.yaml')
dut.init()

dut['CNT']['EN'] = 1
dut['CNT']['OUT'] = 0x00f0
dut['CNT'].write()
dut['CNT'].start()

while not dut['CNT'].is_ready():
    pass

Result of simulation:

_images/spi_example_timing.png

A workin example can be seen in tests/test_SimSpi.py.

gpio

TBD.

Indices and tables