Modules

Contents

Modules#

Modules connect to a simple single-master bus. Every module has a similar set of parameters and pins for bus integration. The full list of firmware modules can be found in the firmware/modules folder, and their Python drivers in basil/HL.

The following parameters, pins, and registers are common to all bus-connected modules. Individual modules add their own on top of these.

Common parameters:

Name

Default

Description

BASEADDR

0

Defines base address of module (start address) in memory map space

HIGHADDR

0

Defines last module address in memory map space

ABUSWIDTH

16

Address bus width

DBUSWIDTH

8

Data bus width

Common pins:

Name

Size

Direction

Description

BUS_RST

1

input

Synchronous reset, active high

BUS_CLK

1

input

Bus clock

BUS_WR

1

input

Write strobe, active high

BUS_RD

1

input

Read strobe, active high

BUS_ADD

ABUSWIDTH

input

Address bus

BUS_DATA

DBUSWIDTH

inout

Data bus

Common registers:

Name

Address

r/w

Description

RESET

0

wo

Soft reset on write to address

VERSION

0

ro

Module version

gpio - General purpose IO#

General purpose input output (gpio) is a generic pins whose behavior, including whether it is an input or output pin, can be controlled by the user at run time.

Unit test/Example: test_SimGpio.v test_SimGpio.py

Usage notes

  • StdRegister usage: Rather than reading/writing the raw INPUT and OUTPUT bytes directly, instantiate a StdRegister in the basil configuration YAML with named fields for each GPIO bit. This provides access like daq["gpio0"]["RST_B"] = 1 followed by .write() to push the full byte to hardware.

  • Direction: Each pin’s direction is set by IO_DIRECTION at compile time. Runtime direction changes via the DIRECTION register require IO_TRI to be enabled for the corresponding pin.

Parameters:

Name

Default

Description

IO_WIDTH

8

Defines io width in bits

IO_DIRECTION

0

Defines direction for every pin separate, 0 - input, 1 - output

IO_TRI

0

instantiate tri-state buffer for given pin

Pins:

Name

Size

Direction | Description

IO

IO_WIDTH

IO_DIRECTION/IO_TRI | General purpose pins

Registers:

Name

Address

Description

RESET

0

Soft reset active on write to address

INPUT

1 to BYTE

Readback of state of pin

OUTPUT

1+BYTE to 2*BYTE

Set output state on pin

DIRECTION

1+2*BYTE to 3*BYTE

Tri-state pin (if enabled)

Where: BYTE = IO_WIDTH/8+1

Driver:

GPIO hardware layer for Basil.

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

GPIO interface.

get_data()[source]#

Read the GPIO INPUT register. Returns the current logic levels on all pins as a byte array. Reads the physical pin state regardless of direction configuration.

get_output_en()[source]#

Return the output enable mask. Each bit indicates whether the corresponding pin is in output mode (1) or input mode (0).

init()[source]#

Initialize the hardware.

reset()[source]#

Soft reset the module.

set_data(value)[source]#

Set the GPIO OUTPUT register. Writes the full IO_WIDTH byte to the FPGA, driving output pins to the specified logic levels. Typically used via StdRegister .write() for field-level access.

set_output_en(value)[source]#

Set the output enable mask. Each bit enables output mode for the corresponding pin (1=output, 0=high-impedance/input). Requires IO_TRI to be configured in the firmware parameter.

spi - Serial peripheral interface#

Module implements master serial peripheral interface. Supports simple internal loops.

Unit test/Example: test_SimSpi.v test_SimSpi.py

Usage notes

  • External start: When EN is set, the SPI transfer can be triggered via the EXT_START pin instead of a software write to START.

  • Repeat mode: A value of 0 in the REPEAT register causes the transfer to repeat forever.

  • START and DONE share the same address: The START (write-only) and DONE (read-only) registers are aliased at the same address. Writing to address 1 triggers a start, reading address 1 returns the done flag. This pattern is consistent across seq_gen, spi, and pulse_gen.

Parameters:

Name

Default

Description

MEM_BYTES

16

Amount of memory allocated for data (maximum single transfer in bytes)

Pins:

Name

Size

Direction

Description

SPI_CLK

1

input

clock used for SPI transfers

SCLK

1

output

external clock (active only during transfers)

SDO

1

input

incoming data

SDI

1

output

outgoing data

SEN

1

output

active high during transfer

SLD

1

output

active high strobe indicating end of transfer

EXT_START

1

input

active high start signal (synchronous to SPI_CLK)

Registers:

Name

Address

Bits

r/w

Default

Description

START / DONE

1

wo/ro

0

Start transfer / Indicate transfer finish

SIZE

4 - 3

[15:0]

r/w

MEM_BYTES*8

Set the size of transfer in bits

WAIT

8 - 5

[31:0]

r/w

4

Waits after every transfer if REPEAT != 0

REPEAT

12 - 9

[31:0]

r/w

1

Repeat transfer count (0 -> forever)

EN

13

[0]

r/w

0

Enable external start (0 -> soft start only)

MEM_BYTES

15 - 14

[15:0]

ro

MEM_BYTES

Byte size of memory

DATA_OUT

16 to 16+MEM_BYTES-1

r/w

unknown

Memory for outgoing data

DATA_IN

16+MEM_BYTES to 16+2*MEM_BYTES-1

r/w

unknown

Memory for incoming data

Driver:

Serial programming interface (SPI) driver for FPGA-based SPI modules.

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

Implement serial programming interface (SPI) driver.

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

Read data from the SPI receive memory at the bus memory offset.

Incoming bytes captured from SDO are stored here.

Args:

size (int, optional): Number of bytes to read (default all). addr (int, optional): Byte offset into memory.

get_en()[source]#

Return the enable state.

get_mem_size()[source]#

Return the SPI memory size in bytes (from MEM_BYTES register at address 14-15). This is the maximum single transfer size.

get_repeat()[source]#

Get number of repetitions of sequence with delay ‘wait’ (if 0 –> repeat forever).

get_size()[source]#

Get size of shift register length.

get_wait()[source]#

Get time delay between repetitions in clock cycles.

init()[source]#

Initialize hardware layer and query memory bytes.

is_done()[source]#

Return True if the SPI transfer is complete, False if still in progress.

Aliases is_ready.

property is_ready#

Read the DONE/READY register at address 1. Returns True when the transfer is complete, False while shifting.

reset()[source]#

Soft reset the SPI module. Aborts any in-progress transfer, clears internal state.

set_data(data, addr=0)[source]#

Write data to the SPI transmit memory at the bus memory offset.

Data bytes are shifted out MSB-first on SDI.

Args:

data (bytes): Data to write. addr (int, optional): Byte offset into memory.

set_en(value)[source]#

Enable start on external EXT_START signal (inside FPGA).

When enabled, the SPI transfer starts on the external EXT_START signal.

set_repeat(value)[source]#

Set the number of repetitions of the sequence with delay ‘wait’.

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

set_size(value)[source]#

Set the number of clock cycles for shifting in data.

For example, length of matrix shift register (number of pixels daisy chained).

set_wait(value)[source]#

Set the time delay between repetitions in clock cycles.

Time delay between repetitions in clock cycles.

start()[source]#

Start shifting data.

seq_gen - Pattern generator#

Module implements a simple sequencer/pattern generator based on block ram. Supports 2 levels of internal loops and external start.

Unit test/Example: test_SimSeq.v test_SimSeq.py

Usage notes

  • Tracks: The seq_gen supports OUT_BITS from 1 to at least 256. Each output bit is a separate track. To fill track data in software, instantiate a TrackRegister in the basil configuration YAML. This provides named track access like daq["seq0"]["INIT"][0:40] = bitarray("...").

  • Start: The sequence can be started via a write to the START register (software start), or via the SEQ_EXT_START pin with EN_EXT_START set (external start). The external start is typically driven by a GPIO or pulse_gen output.

  • Repeat mode: A value of 0 in the REPEAT register causes the sequence to repeat forever (until reset or reconfiguration).

  • Output hold: When the sequence finishes or stops, the last output state is held on SEQ_OUT — it does not return to zero. The sequencer does not reset its outputs on completion.

  • START and READY share the same address: The START (write-only) and DONE (read-only) registers are aliased at the same address. Writing to address 1 triggers a start, reading address 1 returns the done flag. This pattern is consistent across seq_gen, spi, and pulse_gen.

Parameters:

Name

Default

Description

MEM_BYTES

16384

Amount of memory allocated for data (in bytes)

OUT_BITS

8

Size (bit) for output pattern - word size

Pins:

Name

Size

Direction

Description

SEQ_EXT_START

1

input

external start signal (synchronous to SEQ_CLK)

SEQ_CLK

1

input

external clock used for driving sequence

SEQ_OUT

OUT_BITS

output

sequencer output

Registers:

Name

Address

Bits

r/w

Default

Description

RESET / VERSION

0

wo/ro

Soft reset on write / Firmware version

START / DONE

1

wo/ro

0

Start sequence on write / Indicates sequence finished

EN_EXT_START

2

[0]

r/w

0

Enable external start

CLK_DIV

3

[7:0]

r/w

1

Internal division factor for SEQ_CLK

SIZE

7 - 4

[31:0]

r/w

out_words

Set the size of sequence (in output words)

WAIT

11 - 8

[31:0]

r/w

0

Waits after every sequence if REPEAT != 0 (0 -> forever)

REPEAT

15 - 12

[31:0]

r/w

1

Repeat sequence count (0 -> forever)

REP_START

19 - 16

[31:0]

r/w

0

Position from which pattern will start in repeat mode (first sequence always starts at 0)

NESTED_START

23 - 20

[31:0]

r/w

0

Position from which pattern will start for nested loop

NESTED_STOP

27 - 24

[31:0]

r/w

0

Position to which pattern will stop for nested loop

NESTED_REPEAT

31 - 28

[31:0]

r/w

0

Repeat count for nested loop

MEM_BYTES

35 - 32

[31:0]

ro

MEM_BYTES

Memory size (read only)

DATA

64 to 64+MEM_BYTES-1

r/w

unknown

Memory for pattern

Driver:

Sequence generator driver for the seq_gen FPGA module.

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

Sequence generator controller interface for seq_gen FPGA module.

get_clk_divide()[source]#

Return the clock division factor.

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

Read sequencer memory (the pattern data) via the bus interface.

Args:

size: Number of bytes to read (default: all). addr: Optional byte offset into memory.

Returns:

bytes: The pattern data.

get_done()[source]#

Alias for is_ready. Returns True if sequencer is finished.

get_en_ext_start()[source]#

Return whether external start is enabled.

get_mem_size()[source]#

Return the memory size in bytes.

get_nested_repeat()[source]#

Return the nested loop repeat count.

get_nested_start()[source]#

Return the nested loop start position.

get_nested_stop()[source]#

Return the nested loop stop position.

get_repeat()[source]#

Return the repeat count.

get_repeat_start()[source]#

Return the repeat start position.

get_size()[source]#

Return the configured sequence size in output words.

get_wait()[source]#

Return the configured wait cycles between repetitions.

init()[source]#

Initialize the sequencer and read the memory size from hardware.

is_done()[source]#

Return True if the sequencer has finished its sequence.

Includes all repeats. Returns False while running. Aliases is_ready.

property is_ready#

Read the DONE/READY register (addr 1, bit 0).

Returns True when the sequencer is idle and ready to accept a new start trigger. While the sequence is running (including all configured repetitions) this reads False.

The @property decorator makes this an attribute-like access — call it without parentheses as daq["seq0"].is_ready, not .is_ready().

.is_done() and .get_done() are aliases that return the same value.

reset()[source]#

Soft reset the sequencer.

Clears internal counters and output state on the next clock edge. Must have a rising edge on the sequencer clock before new data is written to memory.

set_clk_divide(value)[source]#

Set the clock division factor for SEQ_CLK.

The sequencer advances one step every CLK_DIV + 1 clock cycles. Default: 1 (divide by 1, i.e. full rate). Address 3.

set_data(data, addr=0)[source]#

Write sequencer memory (the pattern data) via the bus interface.

Data is interleaved per track by the TrackRegister RL.

Args:

data: Bytes to write to sequencer memory. addr: Optional byte offset into memory.

set_en_ext_start(value)[source]#

Enable or disable external start via the SEQ_EXT_START pin.

When enabled (1), the SEQ_EXT_START pin rising edge triggers the sequence. When disabled (0), only software .start() works. Address 2.

set_nested_repeat(value)[source]#

Set the nested loop repeat count. 0 = disabled. Addresses 28-31.

set_nested_start(value)[source]#

Set the nested loop start position. Addresses 20-23.

set_nested_stop(value)[source]#

Set the nested loop stop position. Addresses 24-27.

set_repeat(value)[source]#

Set the repeat count.

0 = repeat forever. The sequence repeats from REP_START (or 0) each time. Addresses 12-15.

set_repeat_start(value)[source]#

Set the repeat start position.

When repeating, the sequence jumps to this position instead of starting from 0. Addresses 16-19.

set_size(value)[source]#

Set the number of output words in the sequence.

Each word contains OUT_BITS (one sample per track). Addresses 4-7.

set_wait(value)[source]#

Set wait cycles inserted between repetitions.

Only applies when REPEAT > 0. Addresses 8-11.

start()[source]#

Start the sequencer.

Writes to the START register (addr 1). The sequence begins on the next SEQ_CLK edge after the write. Only effective when DONE/READY is high (sequence not already running).

pulse_gen - Pulse generator#

Simple pulse generator with configurable delay and width.

Unit test/Example: test_SimSeq.v test_SimSeq.py

Usage notes

  • Start: The pulse can be started via a write to the START register (software start), or via the EXT_START pin with EN set (external start).

  • Repeat mode: A value of 0 in the REPEAT register causes the pulse to repeat forever.

  • START and READY share the same address: The START (write-only) and READY (read-only) registers are aliased at the same address. Writing to address 1 triggers a start, reading address 1 returns the ready flag. This pattern is consistent across seq_gen, spi, and pulse_gen.

Pins:

Name

Size

Direction

Description

EXT_START

1

input

active high start signal (synchronous to PULSE_CLK)

PULSE_CLK

1

input

module clock

PULSE

1

output

output pulse

Registers:

Name

Address

Bits

r/w

Default

Description

RESET / VERSION

0

wo/ro

Soft reset on write / Firmware version

START / READY

1

wo/ro

0

Software start on write / Indicate finish

EN

2

[0]

r/w

0

Enable external start

DELAY

6 - 3

[31:0]

r/w

0

Pulse delay from start

WIDTH

10 - 7

[31:0]

r/w

0

Pulse width

REPEAT

14 - 11

[31:0]

r/w

1

Repeat count (0 -> forever)

Driver:

Register-based interface to the pulse_gen hardware block.

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

Pulse generator.

get_delay()[source]#

Return the pulse delay in clock cycles.

get_en()[source]#

Return whether the pulse uses a fixed delay w.r.t. the shift register finish signal.

get_repeat()[source]#

Return the repeat count.

get_width()[source]#

Return the pulse width in clock cycles.

is_done()[source]#

Return True if the pulse generator has finished all repetitions, False if still active. Alias of is_ready.

property is_ready#

Return True when the pulse generator is idle and ready to accept a new start trigger.

Reads the READY register (addr 1, bit 0). While the pulse is running (including all configured repetitions) this reads False.

The @property decorator makes this an attribute-like access - call it without parentheses as daq["pulse0"].is_ready, not .is_ready().

.is_done() is an alias that returns the same value.

reset()[source]#

Soft reset the pulse generator. Clears internal state on the next clock edge.

set_delay(value)[source]#

Set the pulse delay in clock cycles from start.

The delay is relative to the start trigger (software .start() or EXT_START pin).

set_en(value)[source]#

Configure whether the pulse synchronizes with an external trigger.

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]#

Set the repeat count. 0 = repeat forever. The pulse repeats with the configured DELAY and WIDTH each time. Max 255.

set_width(value)[source]#

Set the pulse width in terms of clock cycles.

start()[source]#

Software start of pulse at random time.

rrp_arbiter - Round-robin arbiter#

Round-robin arbiter for data (32 bit) streams with priority. Data streams multiplexer.

Parameters:

Name

Default

Description

WIDTH

4

Number of incoming data streams

Pins:

Name

Size

Direction

Description

WRITE_REQ

WIDTH

input

indicate will of writing data

HOLD_REQ

WIDTH

input

wait for writing for given stream (priority)

DATA_IN

WIDTH*32

input

incoming data for arbitration

READ_GRANT

WIDTH

output

indicate to stream that data has been accepted

READY_OUT

1

input

indicate ready for outgoing stream

WRITE_OUT

1

output

indicate will of write to outgoing stream

DATA_OUT

32

output

outgoing data stream

No Python driver — this module operates autonomously in the FPGA fabric.

seq_rec - Data recorder#

Simple module that allow recording arbitrary data vector.

Unit test/Example: test_SimSeq.v test_SimSeq.py

Driver:

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

Sequencer receiver controller interface for seq_rec FPGA module.

cmd_seq - Command generator (FE-I4)#

Generate arbitrary single bit data stream and clock (mainly to generate FE-I4 commands). Supports hardware loops and Manchester data encoding.

Driver:

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

FEI4 Command Sequencer Controller Interface for cmd_seq FPGA module.

fei4_rx - FE-I4 data receiver#

Allows continuous data recording from FE-I4. Received data are propagated to FIFO data interface. Implements auto synchronization and data error monitoring.

Driver:

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

FEI4 receiver controller interface for fei4_rx FPGA module

fast_spi_rx - Fast serial receiver#

This module can continuous capture serial data on each rising edge of it’s capture clock. Received data is packed into 32-bit words and propagated to a FIFO data interface. While originally intended for SPI (hence the naming), it can be used for any serial data.

Unit tests

Unit tests for this module have not yet been implemented.

Usage notes

  • Data output format: Each 32-bit FIFO word is formatted as [31:28] IDENTIFIER, [27:N] Frame counter, [N-1:0] Captured data where N = DATA_SIZE. The IDENTIFIER field differentiates multiple fast_spi_rx instances merged into the same downstream FIFO stream. The frame counter increments on every SEN falling edge, allowing reconstruction of multi-word captures. When a capture spans multiple FIFO words, all words carry the same frame counter value.

  • FIFO flush behavior: A FIFO word is written when DATA_SIZE bits have been captured, or when SEN falls (flushing any partially-filled word). An incomplete frame is never lost — it is always written to the FIFO when SEN goes low.

  • Reset: The soft reset (RESET register write or BUS_RST) is synchronised to SEQ_CLK via a CDC synchroniser. At least one rising edge of SEQ_CLK must occur after reset is released for it to take effect. If SEQ_CLK is not running when reset is asserted, the reset will not complete.

Parameters#

Name

Default

Description

ABUSWIDTH

16

Width of the bus address bus

IDENTIFIER

4’b0001

Instance identifier packed into bits [31:28] of each FIFO word

DATA_SIZE

16

Number of serial data bits packed into a single FIFO word

Pins#

Name

Size

Direction

Description

SEQ_CLK

1

input

Capture clock (serial data sampled on rising edge)

SDI

1

input

Serial data input (sampled on SEQ_CLK rising edge)

SEN

1

input

Serial enable (active high, frames the capture)

FIFO_READ

1

input

Read strobe (pop one word from the output FIFO)

FIFO_EMPTY

1

output

FIFO empty flag

FIFO_DATA

32

output

FIFO data output (32-bit word)

Registers#

Name

Address

Bits

r/w

Default

Description

RESET

0

wo

Soft reset (synchronous to SEQ_CLK, takes effect on next edge)

VERSION

0

[7:0]

ro

Firmware version

EN

2

[0]

r/w

0

Enable capture (set high to arm)

LOST_COUNT

3

[7:0]

ro

0

Lost data counter (incremented on CDC FIFO overflow)

Unit tests

Unit tests for this module have not yet been implemented.

Driver:

Fast SPI receive interface for reading variable-width serial data.

Provides a register-level hardware layer to arm/disarm capture, query frame-size configuration, check for lost words, and parse 32-bit FIFO words into (identifier, frame_counter, spi_data) tuples.

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

Fast SPI interface with variable data width support.

The module outputs 32-bit words containing: - IDENTIFIER (4 bits) - Frame counter (28 - DATA_SIZE bits) - SPI data (DATA_SIZE bits)

The DATA_SIZE parameter must match the DATA_SIZE parameter used in the FPGA firmware (fast_spi_rx_core.v).

Captured data is read via the dedicated FIFO output ports (not the register bus). At the system level, these feed into a SiTCP FIFO stream accessed through daq[“fifo0”].get_data().

get_en()[source]#

Return whether capture is armed (True) or disarmed (False).

get_lost_count()[source]#

Return the count of lost data words due to CDC FIFO overflow.

Non-zero indicates the capture rate exceeded the readout rate.

get_size()[source]#

Return the DATA_SIZE (SPI data width in bits) used for parsing captured words.

Reads the value from the hardware DATA_SIZE register (addr 4).

parse_word(word)[source]#

Parse a 32-bit FIFO word into (identifier, frame_counter, spi_data).

The split between frame counter and captured data is determined by get_size(). Useful for parsing words read via daq[“fifo0”].get_data().

Args:

word: A 32-bit integer from the fast_spi_rx output FIFO.

Returns:

tuple: (identifier, frame_counter, spi_data)

reset()[source]#

Soft reset the module. Clears internal counters and shift registers on the next SEQ_CLK edge.

set_en(value)[source]#

Arm/disarm capture.

When enabled, serial data on SDI is captured on each rising edge of SEQ_CLK while SEN is high.

tlu - Trigger logic unit#

General purpose trigger module and EUDAQ Telescope/TLU communication module. Trigger IDs received by the TLU are propagated to FIFO data interface.

NOTE:
  1. TRIGGER_ENABLE register has to be set to true to enable trigger FSM.

  2. EXT_TRIGGER_ENABLE and TRIGGER_ACKNOWLEDGE input signals needs to be synchronous to TRIGGER_CLOCK.

  3. Data words have the MSB always high to allow identification of trigger data words. The remaining 31 bits are data.

  4. All selected trigger inputs are ORed. Trigger inputs are connected to TRIGGER input. Trgger inputs are selected by applying a bit mask to TRIGGER_SELECT.

  5. All selected veto inputs are ORed. Veto inputs are connected to TRIGGER_VETO input. Veto inputs are selected by applying a bit mask to TRIGGER_VETO_SELECT.

  6. If TRIGGER_LOW_TIMEOUT_ERROR_COUNTER in TLU handshake mode is not 0, the busy signal might be broken.

  7. If TLU_TRIGGER_ACCEPT_ERROR_COUNTER in TLU handshake mode is not 0, the TLU might be not configured properly (must be in handshake mode) or short pulses are appearing on the trigger line. Possible solution is to increase TRIGGER_HANDSHAKE_ACCEPT_WAIT_CYCLES.

  8. TLU_TRIGGER_MAX_CLOCK_CYCLES should always be one more clock cycle than the bit lenght of the trigger data to return the trigger line to logical low.

TRIGGER_MODE[1:0]:
  1. 0 = normal trigger mode (receiving triggers from input TRIGGER)

  2. 1 = EUDAQ TLU - no handshake

  3. 2 = EUDAQ TLU - simple handshake

  4. 3 = EUDAQ TLU - trigger data handshake

DATA_FORMAT[1:0]:
  1. 0 = trigger number according to TRIGGER_MODE

  2. 1 = time stamp only

  3. 2 = combined, 15bit time stamp + 16bit trigger number

  4. 3 = n/a

Unit test/Example: test_SimTlu.v test_SimTlu.py

Parameters:

Name

Default

Description

DIVISOR

8

Defines TLU clock speed. TLU clock is divided by Divisor.

TLU_TRIGGER_MAX_CLOCK_CYCLES

17

Number of clock cycles send to the TLU. Bit lenght of trigger data is -1.

WIDTH

8 (max. 32)

Bus width of the trigger input and trigger veto input.

TIMESTAMP_N_OF_BIT

32

Bus width of time stamp.

Pins:

Name

Size

Direction

Description

TRIGGER_CLK

1

input

clock for module

TRIGGER_ENABLED

1

output (sync)

assert signal when trigger FSM is enabled and running

TRIGGER_SELECTED

WIDTH (max. 32)

output (sync)

selected trigger inputs

TLU_ENABLED

1

output (sync)

assert signal when trigger mode is != 0 (EUDAQ TLU)

TRIGGER

WIDTH (max. 32)

input (async)

extenel trigger (see also WIDTH parameter)

TRIGGER_VETO

WIDTH (max. 32)

input (async)

external veto (see also WIDTH parameter)

TIMESTAMP_RESET

1

input (async)

resetting timestamp counter

EXT_TRIGGER_ENABLE

1

input (sync)

enables sync with other external devices/modules

TRIGGER_ACKNOWLEDGE

1

input (sync)

signal/flag from external devices/modules if ready

TRIGGER_ACCEPTED_FLAG

1

output

flag if trigger is valid and was accepted

FIFO_PREEMPT_REQ

1

output

fast signal that put arbiter on hold

TLU_TRIGGER

1

input (async)

TLU trigger input

TLU_RESET

1

input (async)

TLU reset input

TLU_BUSY

1

output

TLU busy output

TLU_CLOCK

1

output

TLU clock output

EXT_TIMESTAMP

TIMESTAMP_N_OF_BIT

input (sync)

timestamp from external source (optional)

TIMESTAMP

TIMESTAMP_N_OF_BIT

output (sync)

internal timestamp provided for other devices/modules

Registers:

Name

Address

Bits

r/w

Default

Description

RESET

0

wo

reset

VERSION

0

[7:0]

ro

0

version

TRIGGER_MODE

1

[1:0]

r/w

0

external/TLU trigger mode

TRIGGER_DATA_MSB_FIRST

1

[2]

r/w

0

TLU trigger number MSB

TRIGGER_ENABLE

1

[3]

r/w

0

enable trigger FSM

USE_EXT_TIMESTAMP

1

[4]

r/w

0

use timestamp from EXT_TIMESTAMP input

DATA_FORMAT

2

[1:0]

r/w

0

format of trigger number output

EN_TLU_RESET_TIMESTAMP

2

[5]

r/w

0

reset time stamp to 0 on TLU reset (handsh. mode only)

EN_TLU_VETO

2

[6]

r/w

0

assert TLU veto when external veto

TRIGGER_LOW_TIMEOUT

3

[7:0]

r/w

255

max. wait cycles for TLU trigger low (0=off)

CURRENT_TLU_TRIGGER_NUMBER

7 - 4

[31:0]

ro

last TLU trigger number

TRIGGER_COUNTER

11 - 8

[31:0]

r/w

0

trigger counter value

LOST_DATA_COUNTER

12

[7:0]

ro

lost data counter

TRIGGER_SELECT

13 - 16

[31:0]

r/w

0

selecting trigger input (see also WIDTH parameter)

TRIGGER_VETO_SELECT

17 - 20

[31:0]

r/w

0

selecting veto input (see also WIDTH parameter)

TRIGGER_INVERT

21 - 24

[31:0]

r/w

0

inverting selected trigger input

MAX_TRIGGERS

25 - 28

[31:0]

r/w

0

maximum triggers, use 0 for unltd. triggers

TRIGGER_HANDSHAKE_ACCEPT_WAIT_CYCLES

29

[7:0]

r/w

3

TLU trigger minimum length in TLU clock cycles

HANDSHAKE_BUSY_VETO_WAIT_CYCLES

30

[7:0]

r/w

0

additional wait cycles before de-asserting TLU busy

TRIGGER_LOW_TIMEOUT_ERROR_COUNTER

31

[7:0]

ro

trigger low timeout error counter

TLU_TRIGGER_ACCEPT_ERROR_COUNTER

32

[7:0]

ro

trigger accept error counter

TRIGGER_THRESHOLD

33

[7:0]

r/w

0

trigger minimum length in TLU clock cycles

SOFT_TRIGGER

34

[7:0]

wo

n/a

manual software trigger (requires TRIGGER_MODE=0)

TRIGGER_DATA_DELAY

35

[7:0]

r/w

0

additional TLU data delay for longer cables

Driver:

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

TLU controller interface

tdc - Time-to-digital converter#

Simple time to digital converter. This module digitizes (12 bit resolution) input pulse (TDC_IN) and calculates distance (8 bit resolution) between TDC_IN and TRIG_IN (e.g. trigger signal and hit). Calculated values (see data format, always 32-bit) are propagated to FIFO data interface.

NOTE:
  1. Use BROADCAST parameter in order to share fast (640 MHz sampled) trigger signal with other tdc modules.

  2. TDC_IN needs to be longer than one cycle of CLK320, distance of TDC_IN and TRIG_IN needs to be longer than one clock cycle of DV_CLK.

  3. TRIG_IN needs to come before (at least one clock cycle of DV_CLK) TDC_IN.

  4. ARM_TDC and EXT_EN are assumed to be slower than DV_CLK.

Unit test/Example: test_SimTdc.v test_SimTdc.py

Data format (Standard)

DATA IDENTIFIER (4 bit)

EVENT_COUNTER (16 bit)

TDC value (12 bit)

Data format (in case of EN_WRITE_TIMESTAMP)

DATA IDENTIFIER (4 bit)

TIMESTAMP (16 bit)

TDC value (12 bit)

Data format (in case of EN_TRIGGER_DIST)

DATA IDENTIFIER (4 bit)

TRIGGER DIST (8 bit)

TIMESTAMP/EVENT COUNTER (8 bit)

TDC value (12 bit)

Parameters:

Name

Default

Description

CLKDV

4 (min. 2)

Factor of CLK160 to DV_CLK, minimal divider of 2.

DATA_IDENTIFIER

4’b0100

4-bit data identifier for TDC words.

FAST_TDC

1

If FAST_TDC is 1, 640 MHz sampling of input TDC_IN is done, else 320 MHz sampling is done.

FAST_TRIGGER

1

If FAST_TRIGGER is 1, 640 MHz sampling of input TRIG_IN is done, else 320 MHz sampling is done.

BROADCAST

0

If BROADCAST is 1, 640 MHz sampled trigger signal can be shared with other TDC modules.

Pins:

Name

Size

Direction

Description

CLK320

1

input

320 MHz clock

CLK160

1

input

160 MHz clock

DV_CLK

1

input

clock for ?

TDC_IN

1

input

input pulse which is digitized

TDC_OUT

1

ouput

output TDC pulse

TRIG_IN

1

input

input trigger signal (distance between TRIG_IN and TDC_IN is calculated)

TRIG_OUT

1

output

output TRIG pulse

FAST_TRIGGER_IN

CLKDV x 4

input

input of fast trigger signal (in BROADCAST mode use FAST_TRIGGER_OUT as input)

FAST_TRIGGER_OUT

CLKDV x 4

output

outgoing fast sampled trigger signal

ARM_TDC

1

input

enable TDC for single measurement

EXT_EN

1

input

enable TDC for a fixed time period

TIMESTAMP

16

input

timestamp counter from other modules (e.g. tlu module)

Registers:

Name

Address

Bits

r/w

Default

Description

RESET

0

wo

reset

VERSION

0

[7:0]

ro

0

version

ENABLE

1

[0]

r/w

0

enable TDC module

ENABLE_EXTERN

1

[1]

r/w

0

external enable

EN_ARMING

1

[2]

r/w

0

enable arming

EN_WRITE_TIMESTAMP

1

[3]

r/w

0

write timestamp to output data (see data format description )

EN_TRIGGER_DIST

1

[4]

r/w

0

write trigger distance to output data

EN_NO_WRITE_TRIG_ERR

1

[5]

r/w

0

EN_INVERT_TDC

1

[6]

r/w

0

invert TDC input

EN_INVERT_TRIGGER

1

[7]

r/w

0

invert trigger input

EVENT_COUNTER

2

[31:0]

ro

event counter value

LOST_DATA_COUNTER

6

[7:0]

ro

lost data counter

Driver:

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

TDC controller interface

Tdl Tdc - Tapped Delay Line based Time to Digital Converter#

  • utils/3_stage_synchronizer.v

  • utils/flag_domain_crossing.v

  • utils/generic_fifo.v

  • utils/cdc_syncfifo.v

  • utils/clock_divider.v

  • 30ps RMS accuracy

  • 40ns shortest reliably detectable pulse length

  • 400us dynamic range

Before every experiment, the Tdc should be calibrated, ideally after it had time running to warm up. This can be done as follows:

chip['TDL_TDC'].EN_CALIBRATION_MOD = 1
time.sleep(1)
chip['TDL_TDC'].EN_CALIBRATION_MOD = 0

This will cause the Tdc to write many CALIB words to the fifo. Subsequently any required configuration bits for the particular experiment may be set. During analysis the recorded calibration stream is easily incorporated:

calib_data_indices = chip['TDL_TDC'].is_calib_word(collected_data)

if any(calib_data_indices) :
    calib_values = chip['TDL_TDC'].get_raw_tdl_values(np.array(collected_data[calib_data_indices]))
    chip['TDL_TDC'].set_calib_values(calib_values)
    logging.info("Calibration set using %s samples" % len(calib_values))

Optionally, you can view a histogram of the calibration using chip['TDL_TDC'].plot_calib_values(calib_values).

If measurements are made over a longer time span, recalibration might be necessary, however note that the above example lumps all the calibration(s) in collected_data together.

The calibrated basil module can then be used the following way:

time_word_indices = chip['TDL_TDC'].is_time_word(collected_data)
time_data = collected_data[time_word_indices]
if any(calib_data_indices) :
        time_in_ns = chip['TDL_TDC'].tdc_word_to_time(time_data[0])

Under examples/tdc_bdaq you can find an example implementation of the module along side a sequence generator to generate test signals. The TDC uses the external Si570 oscillator while the signal generator uses the external Si550. The script generates pulses of varying trigger distance and creates a plot of the difference of measured and expected time values, alongside errorbars of the standard deviation.

Unit test/Example: test_SimTdl_Tlu.v test_SimTdl_Tlu.py

Name

Default

Description

DATA_IDENTIFIER

4’b0100

4-bit data identifier for TDC words.

Name

Size

Direction

Description

CLK480

1

input

480 MHz clock

CLK160

1

input

160 MHz clock

CALIB_CLK

1

input

Any clock that is uncorrelated. For example the ethernet clock CLK125RX.

tdc_in

1

input

input pulse which is digitized

trig_in

1

input

input trigger signal (distance between TRIG_IN and TDC_IN can be measured)

arm_tdc

1

input

enable TDC for single measurement

ext_en

1

input

enable TDC for a fixed time period

timestamp

16

input

timestamp counter from other modules (e.g. tlu module)

Name

Address

Bits

r/w

Default

Description

RESET

0

wo

reset

VERSION

0

[7:0]

ro

3

version

ENABLE

1

[0]

r/w

0

enable TDC module (*)

ENABLE_EXTERN

1

[1]

r/w

0

external enable (*)

EN_ARMING

1

[2]

r/w

0

enable arming (*)

EN_WRITE_TIMESTAMP

1

[3]

r/w

0

write timestamp to output data (see data format description )

EN_TRIGGER_DIST

1

[4]

r/w

0

write trigger distance to output data

EN_NO_WRITE_TRIG_ERR

1

[5]

r/w

0

NOT IMPLEMENTED

EN_INVERT_TDC

1

[6]

r/w

0

invert TDC input (*)

EN_INVERT_TRIGGER

1

[7]

r/w

0

invert trigger input (*)

EVENT_COUNTER

2

[31:0]

ro

event counter value (*)

LOST_DATA_COUNTER

6

[7:0]

ro

lost data counter (*)

TDL_MISS_COUNTER

7

[7:0]

ro

signal transistions not registered by delay line (*)

EN_CALIBRATION_MODE

8

[0]

ro

sample and write calibration data

The Tdc module uses a state machine to send various types of 32 bit data words, however the first seven bits always follow the same structure:

DATA IDENTIFIER (4 bit)

WORD TYPE (3 bit)

Data (25 bits)

The three bit codes for the individual word types can be found in word_broker.v, but the basil driver can decode these without manual effort. The words containing the tdc information are in the following order:

[TRIGGERED] -> RISING -> FALLING -> [TIMESTAMP]

TRIGGERED is only sent if EN_TRIGGER_DIST, and TIMESTAMP only if EN_WRITE_TIMESTAMP is set. Note however, that this sequence can be interrupted and appear incomplete, for example if the module is reset during a measurement.

In the following, we list how the remaining 25 bits are allocated for the various words.

160 Mhz Counter (16 bits)

480 Mhz Counter (2 bits)

Delay Line (7 bits)

This word comes after the FALLING word, but the Timestamp is actually sampled two 160Mhz clock cycles after a measurement has been started.

Timestamp (16 bits)

0 (9 bits)

If the Tdc is set for self-calibration using EN_CALIBRATION_MODE, it will repeatedly send this word.

0 (16 bits)

480 Mhz Counter (2 bits)

Delay Line (7 bits)

If a reset is issued to the Tdc, either as a global bus reset or through basil, this word is sent. It might be useful for resetting a state machine decoding the words on the receiving end. The Timestamp included is sampled as soon as the reset signal has passed the clock domain crossing circuitry.

Timestamp (16 bits)

0 (9 bits)

The TDC is built around the delay line found in the Link jTDC which uses about 200 delay elements of which only every second is sampled. This is done because the bin size variance is very large so that if every tap is used, hardly more precision will be obtained. However, this relatively long delay line can be sampled with a lower rate without missing signals. Implementations using every tap usually use several delay lines of about 100 elements which are then sampled using different clock phases. One such implementation can be found in the Link master thesis of Benjamin Blase, which will also give interesting insights to TDC architecture considerations. The priority encoder of this TDC, i.e. the module converting the delay line thermometer code to binary, is based on his work.

In order to sample the delay elements at a high enough rate while still being able to process them, we use a 3x multisampling approach: There is a shift register shifting in the entire information of the delay line using the 3x clock and at every slow clock tick the contents of the shift register are copied for further processing in the slow clock domain. Only then do we detect signal transitions and convert the thermometer code to binary.

_images/delayline.png

The most distinct design choice in this implementation is that it uses only a single delay line for measuring rising and falling edges of two inputs. As rising and falling edges propagate delay elements differently it makes sense to treat with distinct calibrations or even separate delay lines. To circumvent this additional space requirement and complexity, we use a multiplexer co-ordinating which input, in which polarity, gets seen by the delay elements. This induces a lower bound on width of pulses we can measure as this input multiplexer needs some time to switch between signals. To drive the multiplexer we use a simple state machine, which also drives the word output generation in the word_broker module.

_images/architecture.png

Driver:

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

TDC controller interface

calib_sum = np.float64(92.0)#
calib_vector = array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,        1., 1., 1., 1., 1., 1., 1.])#

timestamp - Timestamp#

Simple timestamp recorder.

Unit test/Example: test_Timestamp.v test_Timestamp.py

Pins:

Name

Size

Direction

Description

EXT_ENABLE

1

input

active high accept DI signal (synchronous to CLK)

CLK

1

input

module clock

DI

1

input

input signal

EXT_TIMESTAMP

64

input

external timestamp timestamp pulse

TIMESTAMP_OUT

64

output

Registers:

Name

Address

Bits

r/w

Default

Description

EN

2

[0]

r/w

enable module

EXT_TIMESTMP

2

[1]

r/w

0

use external timestamp

EXT_ENABLE

2

[2]

r/w

0

enable external start

Driver:

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

Implement timestamp driver.

reset()[source]#

Soft reset the module.

bram_fifo - data FIFO (BRAM)#

Data FIFO implemented based on internal BRAM memory. Can be continuously pooled for data.

Driver:

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

BRAM-backed FIFO controller.

The corresponding firmware module stores incoming 32-bit FIFO words in FPGA BRAM. The regular base_addr configuration key addresses the control registers, while base_data_addr must point to the 32-bit data window used by get_data().

FIFO_SIZE reports the amount of buffered data in bytes. The driver rounds this down to complete 32-bit words before reading data.

property FIFO_INT_SIZE#

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

Returns#

fifo_sizeint

FIFO size in units of integers (32 bit).

get_FIFO_INT_SIZE()[source]#

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

Returns#

fifo_sizeint

FIFO size in units of integers (32 bit).

get_data()[source]#

Read all currently buffered complete 32-bit words.

The method reads FIFO_SIZE twice and uses the smaller value to avoid requesting more data while the FIFO size is changing. Data are read from base_data_addr and returned as little-endian unsigned 32-bit integers.

Returns#

arraynumpy.ndarray

Array of unsigned 32-bit FIFO words.

reset()[source]#

Soft-reset the FIFO and wait briefly for the firmware to settle.

sram_fifo - data FIFO (SRAM)#

Data FIFO implemented using external 16-bit SRAM memory. Incoming 32-bit FIFO words are buffered internally and written to SRAM as two 16-bit words. Data are read back from SRAM through the USB_READ / USB_DATA interface.

Parameters:

Name

Default

Description

BASEADDR

16’h0000

Base address for the control register bus

HIGHADDR

16’h0000

High address for the control register bus

ABUSWIDTH

16

Address bus width

DEPTH

21’h10_0000

FIFO depth in 16-bit SRAM words

FIFO_ALMOST_FULL_THRESHOLD

95

Almost-full threshold in percent

FIFO_ALMOST_EMPTY_THRESHOLD

5

Almost-empty threshold in percent

Pins:

Name

Size

Direction

Description

SRAM_A

20

output

External SRAM address bus

SRAM_IO

16

inout

External SRAM data bus

SRAM_BHE_B

1

output

SRAM upper-byte enable, active low

SRAM_BLE_B

1

output

SRAM lower-byte enable, active low

SRAM_CE1_B

1

output

SRAM chip enable, active low

SRAM_OE_B

1

output

SRAM output enable, active low

SRAM_WE_B

1

output

SRAM write enable, active low

USB_READ

1

input

Read strobe for the USB data output

USB_DATA

8

output

USB data output

FIFO_READ_NEXT_OUT

1

output

Request next 32-bit input FIFO word

FIFO_EMPTY_IN

1

input

Input FIFO empty flag

FIFO_DATA

32

input

Input FIFO data word

FIFO_NOT_EMPTY

1

output

SRAM FIFO contains data

FIFO_FULL

1

output

SRAM FIFO is full

FIFO_NEAR_FULL

1

output

SRAM FIFO crossed the almost-full threshold

FIFO_READ_ERROR

1

output

A read was attempted while the SRAM FIFO was empty

Registers:

Name

Address

r/w

Description

RESET

0

wo

Soft reset on write to address

VERSION

0

ro

Module version

ALMOST_FULL_THRESHOLD

1

r/w

Almost-full threshold value

ALMOST_EMPTY_THRESHOLD

2

r/w

Almost-empty threshold value

READ_ERROR_COUNTER

3

ro

Read attempts while the SRAM FIFO is empty

FIFO_SIZE

4 - 7

ro

Stored FIFO data size in bytes

The FIFO_SIZE register is exposed as a 32-bit value by the Python driver. The firmware currently reports a 22-bit byte count and returns zero for the upper byte at address 7.

Driver:

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

External-SRAM-backed FIFO controller.

The corresponding firmware module stores incoming 32-bit FIFO words in an external 16-bit SRAM. The regular base_addr configuration key addresses the control registers. base_data_addr must point to the transfer-layer data path used by get_data() to drain buffered FIFO words.

FIFO_SIZE reports the amount of buffered data in bytes. The driver rounds this down to complete 32-bit words before reading data.

property FIFO_INT_SIZE#

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

Returns#

fifo_sizeint

FIFO size in units of integers (32 bit).

get_FIFO_INT_SIZE()[source]#

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

Returns#

fifo_sizeint

FIFO size in units of integers (32 bit).

get_data()[source]#

Read all currently buffered complete 32-bit words.

The method reads FIFO_SIZE twice and uses the smaller value to avoid requesting more data while the FIFO size is changing. Data are read from base_data_addr and returned as little-endian unsigned 32-bit integers.

Returns#

arraynumpy.ndarray

Array of unsigned 32-bit FIFO words.

get_fifo_int_size()[source]#

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

Returns#

fifo_sizeint

FIFO size in units of integers (32 bit).

get_fifo_size()[source]#

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

Returns#

fifo_sizeint

FIFO size in units of bytes (8 bit).

get_read_error_counter()[source]#

Deprecated Get read error counter.

Returns#

fifo_sizeint

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

get_size()[source]#

Deprecated

reset()[source]#

Soft-reset the FIFO and wait briefly for the firmware to settle.

set_almost_empty_threshold(value)[source]#

Set the 8-bit almost-empty threshold register.

FIFO_NEAR_FULL is deasserted again once the SRAM occupancy falls below the fraction of DEPTH represented by this value.

set_almost_full_threshold(value)[source]#

Set the 8-bit almost-full threshold register.

The firmware compares this value against the SRAM occupancy as a fraction of DEPTH and asserts FIFO_NEAR_FULL once the threshold is reached.

gpac_adc_rx - ADC receiver (GPAC)#

Received data are propagated to FIFO data interface.

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)

m26_rx - MIMOSA26 data receiver#

Allows continuous data recording from MIMOSA26. Received data are propagated to FIFO data interface. Implements error monitoring.

Driver:

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

Mimosa 26 RX interface

reset()[source]#

Soft reset the module.

i2c - I2C peripheral interface#

Module implements master i2c peripheral interface.

Unit test/Example: test_SimI2c.v test_SimI2c.py

Parameters:

Name

Default

Description

MEM_BYTES

16

Amount of memory (bytes) allocated for data (maximum single transfer in bytes)

Pins:

Name

Size

Direction

Description

I2C_CLK

1

input

clock used for i2c transfers (internally devided by 4)

I2C_SDA

1

inout

SDA

I2C_SCL

1

inout

SCL

Registers:

Name

Address

Bits

r/w

Default

Description

START

1

wo

start transfer on write to address

READY

1

[0]

ro

0

indicate transfer finish

NO_ACK

1

[1]

ro

0

status of previous transfer

SIZE

4 - 3

[15:0]

r/w

0

size of transfer (in bytes)

ADDR

2

[7:0]

r/w

0

i2c slave address

MEM_BYTES

7 - 6

[15:0]

ro

MEM_BYTES

size of memory (bytes)

DATA

8 to 8+MEM_BYTES-1

r/w

unknown

memory for data

Driver:

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

Implement master i2c programming interface driver.

property is_ready#
Raises:

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

jtag - JTAG master#

Module implements master jtag peripheral interface. Supports simple internal loops.

Unit test/Example: test_SimJtagMaster.v test_SimJtagMaster.py

Parameters:

Name

Default

Description

MEM_BYTES

16

Amount of meemory allocated for data (maximum single transfer in bytes)

Pins:

Name

Size

Direction

Description

JTAG_CLK

1

input

clock used for SPI transfers

TCK

1

output

external clock (active only during transfers)

TDO

1

input

incoming data

TDI

1

output

outgoing data

TMS

1

output

jtag machine state control pin

SEN

1

output

active high during transfer

SLD

1

output

active high strobe indicating end of transfer

Registers:

Name

Address

Bits

r/w

Default

Description

START

1

wo

start transfer on write to address

DONE

1

[0]

ro

0

indicate transfer finish

BIT_OUT

4 - 3

[15:0]

r/w

MEM_BYTES*8

set the size of transfer in bits

WAIT

8 - 5

[31:0]

r/w

4

waits after every transfer if REPEAT != 0

WORD_COUNT

10 - 9

[15:0]

r/w

1

number of word to be sent (1 word = BIT_OUT bit long)

JTAG COMMAND

12 - 11

[15:0]

r/w

0

JTAG command 0 = SCAN_IR, 1 = SCAN_DR

MEM_BYTES

15 - 14

[15:0]

ro

MEM_BYTES

byte size of memory

DATA_OUT

16 to 16+MEM_BYTES-1

r/w

unknown

memory for outgoing data

DATA_IN

16+MEM_BYTES to 16+2*MEM_BYTES-1

r/w

unknown

memory for incoming data

Driver:

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

SPI based JTAG interface

get_command()[source]#

IR_SCAN or DR_SCAN

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

Gets data for incoming stream

reset()[source]#

Soft reset the module.

scan_dr(data, readback=True, word_size=None)[source]#

Data must be a list of BitLogic or string of raw data

scan_ir(data, readback=True)[source]#

Data must be a list of BitLogic

set_command(value)[source]#

IR_SCAN or DR_SCAN

set_data(data, addr=0)[source]#

Sets data for outgoing stream

start()[source]#

Starts the shifting data

uart - UART slave#

Provides UART to basil interface.

utils#

Various Verilog modules used by basil.

  • 3_stage_synchronizer

  • bus_to_ip

  • cdc_pulse_sync

  • cdc_pulse_sync_cnt

  • cdc_syncfifo

  • CG_MOD_neg

  • CG_MOD_pos

  • clock_divider

  • ddr_des

  • fifo_32_to_8

  • flag_domain_crossing

  • flag_domain_crossing_ce

  • generic_fifo

  • IDDR

  • IDDR_s3

  • ODDR

  • ODDR_s3

  • pulse_gen_rising

  • RAMB16_S1_S2

  • RAMB16_S1_S9

  • rbcp_to_bus

  • reset_gen

  • simple_arbiter

  • three_stage_synchronizer_ce

Arduino firmware#

Arduino Firmware for Environment Readout (temperature, humidity/pressure)#

Arduino Nano firmware to read out NTCs via the 8 analog input pins A0 to A7 and the internal (multiplexed) ADC.

NTC inputs require a voltage divider configuration, supplied with the 3.3 V Arduino rail.The voltage drop over the NTC is the input to the analog pin. The conversion from ADC value to degree Celsius can take place in the firmware.

Additionally, a pure analog read out is possible for processing of humidity and pressure sensors.

Arduino Firmware for NTC Readout#

Arduino Nano firmware to read out NTCs via the 8 analog input pins A0 to A7 and the internal (multiplexed) ADC. The REF and 3V3 need to be connected on the Arduino. Each input requires a voltage divider configuration, supplied with the 3.3 V Arduino rail. The voltage drop over the NTC is the input to the analog pin. The conversion from ADC value to degree Celsius takes place in the firmware.

Arduino Firmware for SiLab Relay Board#

Simple firmware for Arduino to take commands on serial port via USB and switch DigitalIO pins on and off accordingly. So far, all pins get initialized as LOW outputs, because of compatibility with 8 channel relay card.

Arduino Firmware for I2C over Serial#

Arduino Nano firmware to write and read an I2C bus over the Arduinos serial interface. The lines reqired by I2C are GND, VCC(3v3 or 5V), SDA (A4) and SCL (A5). The firmware receives read/write commands over serial, accesses the I2C bus and answers the results over serial.