Skip to content

Commit

Permalink
Redpitaya FFT (#444)
Browse files Browse the repository at this point in the history
* add examples/redpitaya/fft

* jquery.flot.canvas in downloads

* add fft in build_examples.sh [ci skip]
  • Loading branch information
minjungkh committed Dec 7, 2017
1 parent 44d322a commit 8035602
Show file tree
Hide file tree
Showing 25 changed files with 1,719 additions and 534 deletions.
3 changes: 2 additions & 1 deletion build_examples.sh
Expand Up @@ -12,4 +12,5 @@ make CONFIG=examples/red-pitaya/laser-controller/config.yml MODE=$mode $target
make CONFIG=examples/red-pitaya/pulse-generator/config.yml MODE=$mode $target
make CONFIG=examples/red-pitaya/adc-dac/config.yml MODE=$mode $target
make CONFIG=examples/red-pitaya/cluster/config.yml MODE=$mode $target
make CONFIG=examples/red-pitaya/dual-dds/config.yml MODE=$mode $target
make CONFIG=examples/red-pitaya/dual-dds/config.yml MODE=$mode $target
make CONFIG=examples/red-pitaya/fft/config.yml MODE=$mode $target
1 change: 0 additions & 1 deletion examples/alpha250/fft/config.yml
Expand Up @@ -96,4 +96,3 @@ web:
- ./web/clock-generator.ts
- ./web/index.html
- ./web/main.css

117 changes: 65 additions & 52 deletions examples/red-pitaya/fft/block_design.tcl
@@ -1,48 +1,13 @@
source $project_path/tcl/ports.tcl
source $board_path/config/ports.tcl
source $board_path/base_system.tcl

# Add PS and AXI Interconnect
set board_preset $board_path/config/board_preset.tcl
source $sdk_path/fpga/lib/starting_point.tcl
source $sdk_path/fpga/lib/laser_controller.tcl

# Add ADCs and DACs
source $sdk_path/fpga/lib/redp_adc_dac.tcl
set adc_dac_name adc_dac
add_redp_adc_dac $adc_dac_name

# Rename clocks
set adc_clk $adc_dac_name/adc_clk

# Add processor system reset synchronous to adc clock
set rst_adc_clk_name proc_sys_reset_adc_clk
cell xilinx.com:ip:proc_sys_reset:5.0 $rst_adc_clk_name {} {
ext_reset_in $ps_name/FCLK_RESET0_N
slowest_sync_clk $adc_clk
}

# Add config and status registers
source $sdk_path/fpga/lib/ctl_sts.tcl
add_ctl_sts $adc_clk $rst_adc_clk_name/peripheral_aresetn

# Connect LEDs
connect_port_pin led_o [get_slice_pin [ctl_pin led] 7 0]

# Connect ADC to status register
for {set i 0} {$i < [get_parameter n_adc]} {incr i} {
connect_pins [sts_pin adc$i] adc_dac/adc[expr $i + 1]
}

# Add XADC for monitoring of Zynq temperature

create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_analog_io_rtl:1.0 Vp_Vn

cell xilinx.com:ip:xadc_wiz:3.3 xadc_wiz_0 {
} {
Vp_Vn Vp_Vn
s_axi_lite axi_mem_intercon_0/M[add_master_interface 0]_AXI
s_axi_aclk ps_0/FCLK_CLK0
s_axi_aresetn proc_sys_reset_0/peripheral_aresetn
# Connect raw ADC data to status register
connect_cell adc_dac {
adc1 [sts_pin adc0]
adc2 [sts_pin adc1]
}
assign_bd_address [get_bd_addr_segs xadc_wiz_0/s_axi_lite/Reg]

####################################
# Direct Digital Synthesis
Expand All @@ -55,20 +20,21 @@ for {set i 0} {$i < 2} {incr i} {
DDS_Clock_Rate [expr [get_parameter adc_clk] / 1000000]
Parameter_Entry Hardware_Parameters
Phase_Width 32
Output_Width 14
Output_Width 16
Phase_Increment Programmable
Latency_Configuration Configurable
Latency 9
} {
aclk adc_dac/adc_clk
}

connect_pins adc_dac/dac[expr $i+1] [get_slice_pin dds$i/m_axis_data_tdata 13 0]
connect_pins adc_dac/dac[expr $i+1] [get_slice_pin dds$i/m_axis_data_tdata 15 2]

cell pavel-demin:user:axis_variable:1.0 phase_increment$i {
cell pavel-demin:user:axis_constant:1.0 phase_increment$i {
AXIS_TDATA_WIDTH 32
} {
cfg_data [ctl_pin phase_incr$i]
aclk adc_dac/adc_clk
aresetn $rst_adc_clk_name/peripheral_aresetn
M_AXIS dds$i/S_AXIS_CONFIG
}

Expand All @@ -82,12 +48,12 @@ source $project_path/tcl/power_spectral_density.tcl
source $sdk_path/fpga/modules/bram_accumulator/bram_accumulator.tcl
source $sdk_path/fpga/lib/bram_recorder.tcl

power_spectral_density::create psd [get_parameter fft_size] [get_parameter adc_width]
power_spectral_density::create psd [get_parameter fft_size]

cell koheron:user:latched_mux:1.0 mux_psd {
N_INPUTS 2
SEL_WIDTH 1
WIDTH 14
WIDTH [get_parameter adc_width]
} {
clk adc_dac/adc_clk
clken [get_constant_pin 1 1]
Expand All @@ -96,11 +62,9 @@ cell koheron:user:latched_mux:1.0 mux_psd {
}

connect_cell psd {
adc1 mux_psd/dout
adc2 [get_constant_pin 0 [expr [get_parameter adc_width] - 1]]
data mux_psd/dout
clk adc_dac/adc_clk
tvalid [ctl_pin psd_valid]
ctl_sub [ctl_pin substract_mean]
ctl_fft [ctl_pin ctl_fft]
}

Expand Down Expand Up @@ -132,8 +96,57 @@ connect_cell bram_accum {
add_bram_recorder psd_bram psd
connect_cell psd_bram {
clk adc_dac/adc_clk
rst $rst_adc_clk_name/peripheral_reset
rst proc_sys_reset_adc_clk/peripheral_reset
addr bram_accum/addr_out
wen bram_accum/wen
adc bram_accum/m_axis_tdata
}

####################################
# Demodulation
####################################

source $project_path/tcl/demodulator.tcl

demodulator::create demodulator

connect_cell demodulator {
s_axis_data_a [get_concat_pin [list [get_constant_pin 0 2] adc_dac/adc1 [get_constant_pin 0 16]]]
s_axis_data_b dds0/m_axis_data_tdata
s_axis_tvalid dds0/m_axis_data_tvalid
aclk adc_dac/adc_clk
aresetn proc_sys_reset_adc_clk/peripheral_aresetn
}

# Use AXI Stream clock converter (ADC clock -> FPGA clock)
set idx [add_master_interface 0]

cell xilinx.com:ip:axis_clock_converter:1.1 adc_clock_converter {
TDATA_NUM_BYTES 4
} {
s_axis_tdata demodulator/m_axis_tdata
s_axis_tvalid demodulator/m_axis_tvalid
s_axis_aresetn proc_sys_reset_adc_clk/peripheral_aresetn
m_axis_aresetn proc_sys_reset_0/peripheral_aresetn
s_axis_aclk adc_dac/adc_clk
m_axis_aclk ps_0/FCLK_CLK0
}

# Add AXI stream FIFO
cell xilinx.com:ip:axi_fifo_mm_s:4.1 adc_axis_fifo {
C_USE_TX_DATA 0
C_USE_TX_CTRL 0
C_USE_RX_CUT_THROUGH true
C_RX_FIFO_DEPTH 8192
C_RX_FIFO_PF_THRESHOLD 4096
} {
s_axi_aclk ps_0/FCLK_CLK0
s_axi_aresetn proc_sys_reset_0/peripheral_aresetn
S_AXI axi_mem_intercon_0/M${idx}_AXI
AXI_STR_RXD adc_clock_converter/M_AXIS
}

assign_bd_address [get_bd_addr_segs adc_axis_fifo/S_AXI/Mem0]
set memory_segment [get_bd_addr_segs /ps_0/Data/SEG_adc_axis_fifo_Mem0]
set_property offset [get_memory_offset adc_fifo] $memory_segment
set_property range [get_memory_range adc_fifo] $memory_segment
49 changes: 37 additions & 12 deletions examples/red-pitaya/fft/config.yml
Expand Up @@ -3,14 +3,19 @@ name: fft
board: boards/red-pitaya

cores:
- fpga/cores/redp_adc_v1_0
- fpga/cores/redp_dac_v1_0
- fpga/cores/axi_ctl_register_v1_0
- fpga/cores/axi_sts_register_v1_0
- fpga/cores/dna_reader_v1_0
- fpga/cores/latched_mux_v1_0
- fpga/cores/axis_variable_v1_0
- fpga/cores/axis_constant_v1_0
- fpga/cores/redp_adc_v1_0
- fpga/cores/redp_dac_v1_0
- fpga/cores/psd_counter_v1_0
- fpga/cores/comparator_v1_0
- fpga/cores/saturation_v1_0
- fpga/cores/pdm_v1_0
- fpga/cores/at93c46d_spi_v1_0
- fpga/cores/bus_multiplexer_v1_0

memory:
- name: control
Expand All @@ -24,46 +29,66 @@ memory:
range: 64K
- name: demod
offset: '0x60000000'
range: 16K
range: 8K
- name: psd
offset: '0x70000000'
range: 16K
range: 8K
- name: adc_fifo
offset: '0x43C10000'
range: 32K

control_registers:
- led
- substract_mean
- mmcm
- ctl_fft
- psd_valid
- psd_input_sel
- phase_incr[2]
- laser_current
- laser_control
- power_setpoint
- eeprom_ctl

status_registers:
- adc[n_adc]
- cycle_index
- eeprom_sts
- pid_control

parameters:
fclk0: 200000000
fclk0: 187500000
adc_clk: 125000000
dac_width: 14
adc_width: 14
pwm_width: 12
n_adc: 2
fft_size: 2048
n_cycles: 2048
n_cycles: 1023
cic_differential_delay: 1
cic_decimation_rate: 250
cic_n_stages: 6

xdc:
- ./xdc/ports.xdc
- ./xdc/clocks.xdc
- boards/red-pitaya/config/ports.xdc
- boards/red-pitaya/config/clocks.xdc
- ./expansion_connector.xdc

drivers:
- server/drivers/common.hpp
- ./fft.hpp
- server/drivers/xadc.hpp
- server/drivers/laser.hpp
- server/drivers/eeprom.hpp
- ./drivers/fft.hpp
- ./drivers/demodulator.hpp
- ./drivers/redpitaya_adc_calibration.hpp

web:
- web/koheron.ts
- web/jquery.flot.d.ts
- web/laser.ts
- ./web/fft.ts
- ./web/app.ts
- ./web/control.ts
- ./web/plot.ts
- ./web/index.html

- web/main.css
98 changes: 98 additions & 0 deletions examples/red-pitaya/fft/drivers/demodulator.hpp
@@ -0,0 +1,98 @@
/// demodulator driver
///
/// (c) Koheron

#ifndef __DRIVERS_DEMODULATOR_HPP__
#define __DRIVERS_DEMODULATOR_HPP__

#include <context.hpp>

#include <array>

// http://www.xilinx.com/support/documentation/ip_documentation/axi_fifo_mm_s/v4_1/pg080-axi-fifo-mm-s.pdf
namespace Fifo_regs {
constexpr uint32_t rdfr = 0x18;
constexpr uint32_t rdfo = 0x1C;
constexpr uint32_t rdfd = 0x20;
constexpr uint32_t rlr = 0x24;
}

constexpr uint32_t fifo_buff_size = 8192 * 256;

class Demodulator
{
public:
Demodulator(Context& _ctx)
: ctx(_ctx)
, ctl(ctx.mm.get<mem::control>())
, adc_fifo_map(_ctx.mm.get<mem::adc_fifo>())
{
start_fifo_acquisition();
}

~Demodulator() {
fifo_acquisition_started = false;
fifo_thread.join();
}

void reset_fifo() {adc_fifo_map.write<Fifo_regs::rdfr>(0x000000A5);}
int32_t read_fifo() {return adc_fifo_map.read<Fifo_regs::rdfd>();}
uint32_t get_fifo_length() {return (adc_fifo_map.read<Fifo_regs::rlr>() & 0x3FFFFF) >> 2;}

std::vector<int32_t>& get_vector(uint32_t n_pts) {
last_buffer_vect.resize(n_pts);
std::lock_guard<std::mutex> lock(mutex);
uint32_t start_idx = fifo_buff_idx - (fifo_buff_idx % 2);
for (uint32_t i = 0; i < n_pts; i++) {
last_buffer_vect[n_pts - 1 - i] = fifo_buffer[(start_idx - 1 - i) % fifo_buff_size];
}
return last_buffer_vect;
}

void start_fifo_acquisition();

private:
Context& ctx;
Memory<mem::control>& ctl;
Memory<mem::adc_fifo>& adc_fifo_map;

std::mutex mutex;

std::atomic<bool> fifo_acquisition_started{false};
std::atomic<uint32_t> fifo_buff_idx{0};
std::array<int32_t, fifo_buff_size> fifo_buffer;

std::vector<int32_t> last_buffer_vect;
std::thread fifo_thread;
void fifo_acquisition_thread();

};

inline void Demodulator::start_fifo_acquisition() {
if (! fifo_acquisition_started) {
fifo_buffer.fill(0);
fifo_thread = std::thread{&Demodulator::fifo_acquisition_thread, this};
fifo_thread.detach();
}
}

inline void Demodulator::fifo_acquisition_thread()
{
using namespace std::chrono_literals;
fifo_acquisition_started = true;
while (fifo_acquisition_started) {
{
std::lock_guard<std::mutex> lock(mutex);
const uint32_t n_pts = get_fifo_length();
ctx.log<INFO>("fifo_length: %d \n", n_pts);
for (size_t i = 0; i < n_pts; i++) {
fifo_buffer[fifo_buff_idx] = read_fifo();
fifo_buff_idx = (fifo_buff_idx + 1) % fifo_buff_size;
}
}
std::this_thread::sleep_for(10ms);
}
}


#endif // __DRIVERS_DEMODULATOR_HPP__

0 comments on commit 8035602

Please sign in to comment.