Pulse generator for the Red Pitaya


October 13, 2016

We present the design of a simple pulse generator for the Red Pitaya. The design uses standard Xilinx IP blocks and a custom Verilog core that outputs a signal valid that is driven high when the pulse is played on the DAC.

Pulse shape is stored in a Block RAM that can be written from Linux. ADC data is written in a FIFO that can be read from Linux. The FIFO only accepts ADC data when a pulse is played on the DAC.

Vivado block design

The valid signal is shown in green in the figure below. It is connected to the DAC Block RAM and the ADC FIFO.

The ouput port doutb of the DAC BRAM is 32 bits wide. doutb[13:0] and doutb[29:16] are respectively connected to DAC1 and DAC2 (purple). Note that the pulse_generator core also outputs a signal cnt that increments at each clock cycle when valid is high. The signal is used to specify the address of the data that should be played by the BRAM (red).

Vivado block design

The blue connections show the ADC data path. The FIFO has a width of 32 bits, which allows to store the two ADC channels plus a start signal that identifies the beginning of a pulse. An AXI clock converter is used to move data from the ADC clock domain (125 MHz) to the interconnect clock domain (200 MHz).

Verilog core

We wrote a simple Verilog core to generate a digital pulse of specified width and period, as shown in the simulation below:

Simulation of a pulse generator Verilog core

The core consists of a counter cnt_reg that increments between 0 and pulse_period - 1 at each clock cycle. The value of cnt_reg is compared to pulse_width to obtain the valid signal:

`timescale 1 ns / 1 ps

module pulse_generator #
(
  parameter integer PULSE_WIDTH_WIDTH = 8,
  parameter integer PULSE_PERIOD_WIDTH = 16
)
(
  input wire clk,
  input wire [PULSE_WIDTH_WIDTH-1:0] pulse_width,
  input wire [PULSE_PERIOD_WIDTH-1:0] pulse_period,
  input wire rst,
  output reg valid,
  output reg [PULSE_PERIOD_WIDTH-1:0] cnt,
  output reg start
);

reg rst_reg;
reg [PULSE_PERIOD_WIDTH-1:0] cnt_reg;
initial cnt_reg = 0;

always @(posedge clk) begin
  start <= (cnt_reg == 0);
  valid <= (cnt_reg < pulse_width);
  rst_reg <= rst;
  cnt <= cnt_reg;
end

always @(posedge clk) begin
  if (!rst_reg & rst) begin
    cnt_reg <= 0;
  end else begin
    if (cnt_reg < pulse_period - 1) begin
      cnt_reg <= cnt_reg + 1;
    end else begin
      cnt_reg <= 0;
    end
  end
end

endmodule

Controlling the instrument with Python

Below is a screenshot of a simple Python Matplotlib animation that displays the acquired pulses. Pulse width is 128 (1.024 µs) and pulse period is 125 000 (1 ms i.e. pulse rate of 1 kHz). The animation runs displays the last 64 contiguous pulses gathered from the FIFO every 64 ms.

Screenshot of matplotlib animation

FPGA design source code

https://github.com/Koheron/koheron-sdk/tree/master/examples/red-pitaya/pulse-generator