Pulse generator for the Red Pitaya2016-10-13
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
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[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).
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).
We wrote a simple Verilog core to generate a digital pulse of specified width and period, as shown in the simulation below:
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
`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.