Pulse generator for the Red Pitaya
2016-10-13We 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).
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:
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.
FPGA design source code
https://github.com/Koheron/koheron-sdk/tree/master/examples/red-pitaya/pulse-generator