Loading...

Configuration

Command Structure

All Nixel512 SPI commands are 32-bit values composed of an 8-bit command or operation code (OpCode) <31:24>, an 8-bit register address <23:16>, and 16-bit data or payload <15:0>. Below are the available operation codes followed by examples of common register operations.

OpCodeNameDescriptionExpected behavior
0x00NOPNo OperationNone
0x01SOFT_RSTSoft ResetResets all registers to default values (Requires 13ms delay after reset)
0x02SOFT_CMDSpecial OperationExecutes special commands
0x40READRead RegisterReturns register value
0xC0WRITEWrite RegisterWrites value to register

Read from the DAC register:

uint32_t read_cmd = 0x40000000;         // OpCode for READ
uint32_t reg_addr = 0x02;		// Register address to read
uint32_t read_reg_cmd = read_cmd | (reg_addr << 16);
// Result: 0x40020000
// Expected response: 0x40020xxx where xxx is the register value

Register read operations return 16-bit values and require waiting for a response. To validate the response, you can use any of the following methods:

  • Upper 8 bits of response should match sent OpCode
  • Register address in response should match sent address
  • Behavior is undefined for invalid register addresses

Write to the DAC register:

uint32_t write_cmd = 0xC0000000;		// OpCode for WRITE
uint32_t dac_addr = 0x02;		// Register address (e.g., VDAC00_VCM_LNA)
uint32_t dac_value = 0x0908;	// Value to write
uint32_t write_dac_cmd = write_cmd | (dac_addr << 16) | dac_value; // Result: 0xC0020908

Register write operations must provide 16-bit values and do not generate a response. DAC writes common use values between 0x0000 and 0x0FFF (12-bit DAC) while IDAC writes common use values between 0x00 and 0x7F (7-bit IDAC).

Both read and write operations require a valid register address to function properly (0x00 to 0x65).

Recording Parameters

Panel Organization ModeResolution
Panel 0Nixels 0–63
Panel 1Nixels 64–127
Panel 2Nixels 128–191
Panel 3Nixels 192–255
ADC Configuration ModeResolutionSampling RateMinimum Clock
010-bit32 kHz40 MHz
112-bit16 kHz80 MHz
212-bit32 kHz160 MHz
314-bit8 kHz160 MHz
416-bit2 kHz160 MHz
Bandwidth and Gain High-pass corner3.8 Hz to 460 Hz (s_lna registers)
Low-pass corner1.45 kHz to 14 kHz (s_lna registers)
Gain settings13 V/V (27 μV rms noise) to 200 V/V (4.5 μV rms noise)

Each nixel corresponds to two electrodes: one odd, one even. The first four nixels of each panel are LFP nixels and the rest are spike nixels. If you need 512-channel operation, all nixels must be enabled.

Troubleshooting

If you are not getting data:

  1. Ensure the SPI clock is precisely 1/4 the main clock frequency.
  2. Verify proper power supply voltages (1.2V digital, 2.5V analog).
  3. Check reference electrode configurations per panel.

NOTE: The Nixel512 ADC architecture uses a dual sample and hold configuration per channel. Due to a capacitor mismatch, there is a systematic alternating DC offset between readouts (ping-pong artifact). For high fidelity recordings, it is important to remove this error using a digital filter. This can be done in several ways, but in all cases the filter should have high rejection at half the sample rate.

Recording Configuration

Recording Setup Sequence

The Nixel 512 chip supports simultaneous recording from up to 512 electrodes across four identical panels. This section describes the sequence of operations required to configure and start recording with the Nixel 512 ASIC.

Reset Nixel

Reset the Nixel 512 chip by issuing the reset command (bring chip pin rstb low). Wait a minimum of 13 ms for the reset to complete.

reset_nixel512();
// wait 13 ms for reset to take effect

Enable Channels

Configure power-down registers. Nixels are organized in groups of 16 nixels per register, with a total of 16 registers (256 nixels total). Each nixel within a register can be individually enabled or disabled. This is done by writing 0 (enable) or 1 (power down) to registers 0x23 to 0x32.

// enable all nixels except for first and last:
write_register(0x23, 0x0001);
write_register(0x24, 0x0000);
...
write_register(0x31, 0x0000);
write_register(0x32, 0x8000);

Configure LNA Inputs

Each nixel has positive (LNA+) and negative (LNA-) low-noise amplifier inputs. Each input is connected to a switch that can be connected to a number of inputs detailed in the table below. Register 0x15 controls the switches for LFP nixels, and register 0x20 controls switches for the spike nixels. Each is a 16-bit register. Bits [15:11] set the positive input switch (spe[4:0]) and bits [10:6] set the negative input switch.

Low noise amplifier diagram showing input identities

spe[4:0]LNA+sne[4:0]LNA-
0b0_0000high-z0b0_0000high-z
0b0_0001sub0b0_0001sub
0b0_0010ela<1>0b0_0010ela<0>
0b0_0100ela<0>0b0_0100ela<1>
0b0_1000elr_glb0b0_1000elr_glb
0b1_0000elt_glb<1>0b1_0000elt_glb<0>

Set Sample Rate and Bit Depth

The Nixel 512 chip uses a single slope ADC: a global counter and corresponding ramping signal both increment at the beginning of each sampling period. When the ramping signal surpasses the LNA’s output voltage, the global counter is recorded and stored as that nixel’s digitized, binary sample. The sampling rate is changed by controlling the stop value for the global counter (aka. line time) and ramping signal, as shown below:

// Note: if using any of the on-chip DACs, we recommend using a line time that is a multiple of the DAC sampling rate
uint16_t new_line_time = (ASIC01_CLK_FREQ / desired_sampling_rate_u32) - 1;

// Enusre the same line time for all panels:
write_register(LINE_TIME_PANEL0, new_line_time);
write_register(LINE_TIME_PANEL1, new_line_time);
write_register(LINE_TIME_PANEL2, new_line_time);
write_register(LINE_TIME_PANEL3, new_line_time);

In the example above, bit depth is log2(new_line_time). E.g. for a 160 MHz clock and for 32 kS/s sampling rate, our line time is 5000 (for bit depth ~12).

In order to orchestrate proper timing of the ramp signal and counter, you must adhere to the following timing:

On chip timing

Internal SignalsSETRESET
phi_sh1994899
phi_rstb*1494899
rst_ramp49299
enable_ramp2494849
enable_cmp3494799
clear_cmp4999
dtest_cmp149199
start_adc2494849
Line Time Duration5000

phi_rstb* - denotes the inversion of phi_rst shown in the diagram above, where the reset is applied (the ramp is disabled) to start.

The example code below shows reasonable default values.

// the global counter uses a 0-based index
write_register(RST_PHI_SH, new_line_time - 100);
write_register(RST_PHI_RSTB, new_line_time - 50);
write_register(RST_ENABLE_RAMP, new_line_time - 150);
write_register(RST_ENABLE_CMP, new_line_time - 200);
write_register(RST_START_ADC, new_line_time - 150);

In addition to the above global counter settings, you must also update the ramp signal appropriately. On chip DACs generate the ramp signal. You must ensure that the DAC starting and final voltage are in range.

Set the start voltage at 0.2 V or greater:

double start_voltage = 0.5;
uint16_t new_ideal_start_code;
voltage_to_vdac_code(start_voltage, new_ideal_start_code);
write_register(VDAC04_VREF_INT, new_ideal_start_code);

Set the start voltage + ramp swing (ramp_delta_v) below 1.8 V:

uint16_t rst_enable_ramp = read_register(RST_ENABLE_RAMP);
uint16_t rst_rst_ramp = read_register(RST_RST_RAMP);
uint16_t integration_time_clocks = rst_enable_ramp - rst_rst_ramp;
double integration_time = integration_time_clocks /
static_cast<double>(ASIC01_CLK_FREQ);
// integrator input current and integration cap set elsewheree --see docs
double ramp_delta_v = integration_time * integrator_input_current / integration_cap;

The ramp midpoint must be set using the following:

double final_voltage = start_voltage + ramp_delta_v;
double ideal_midpoint_v = (start_voltage + final_voltage) / 2.0;
write_register(VDAC05_VREF_RAMP, new_ideal_midpoint_code);

Finally, set the sample rate to the following:

double actual_sample_rate = ASIC01_CLK_FREQ / (new_line_time);

Configure Reference Routing

Nixel 512 reference routing is configured via the d_elref[15:0] register (0x1C). Each panel (k) has its own reference routing, which can be set to either internal, or external mode. These refer to reference source. External reference mode is when the panel receives two reference inputs from the panel’s external reference bus (elr[1:0]). Internal reference mode disconnects external inputs, even if they are present. When using internal reference, signal inputs are either left floating, or connected to internal test signal generators.

Reference is selected using a 4-bit binary signal applied per panel (elref_k[3:0]); 2-bits for external reference, and 2-bits for internal reference. This selection is made using 2 bits per mode. 0000, 1100, and 0011 are the most relevant options for reference selection.

  • 0000 leaves reference inputs floating in a given panel (k:0, 1, 2, or 3).
  • 1100 connects external references to the panel's global reference bus.
  • 0011 connects internal test signal generators, vDAC-7 and vDAC-8, to the panel’s global reference bus (elr_glb<1:0>).
elref_k[3:0]reference source
0b0000high-z
0b0011{vdac7_vtest, vdac8_vref_test}
0b1100elr[1:0]

Initiate Start Sequence

Initiate the recording start sequence using one of the following SPI command sequences:

// Normal recording:
const std::vector<uint32_t> START_CMDS = {0x00000000, 0xC0000010, 0x02000F00, 0xC036000F, 0xC05D00FF, 0x00000000, 0x00000000, 0x00000000};

// Fixed pattern output (by default, 0x2301):
const std::vector<uint32_t> START_DESER_TEST = {0x00000000, 0xC0000010, 0xC03AF924, 0x02000F00, 0xC05D00FF, 0x00000000, 0x00000000, 0x00000000};


// Incrementing output:
const std::vector<uint32_t> START_INCR_TEST = {0x00000000, 0xC0000010, 0xC03AF249, 0x02000F00, 0xC05D00FF, 0x00000000, 0x00000000, 0x00000000};

Stop Recording

The sequence is stopped by issuing the reset command: reset_nixel512();.