From 58d04322534bc1902e23ddd0c92b4e6e0127a066 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:42:18 +0000 Subject: [PATCH 01/38] Init Resync FPGA image --- src/fpga/bd/bd.tcl | 41 ++++++++++++++++++++++++++++++----- src/fpga/bd/waveform_gen.tcl | 26 ++++++++++++++++++---- src/fpga/hdl/sequence_slice.v | 2 ++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 8e2e13fc..206a1a32 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -796,6 +796,7 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { create_bd_pin -dir O -from 0 -to 0 m_axis_data_tvalid_1 create_bd_pin -dir I -from 15 -to 0 offset create_bd_pin -dir O -from 1 -to 0 ramp_state_1 + create_bd_pin -dir I resync_dac create_bd_pin -dir I start_ramp_down # Create instance: signal_calib_0, and set properties @@ -899,10 +900,11 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net enable_ramping_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp_0/enableRamping] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_pins aresetn] [get_bd_pins signal_ramp_0/aresetn] [get_bd_pins waveform_awg1/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] [get_bd_pins waveform_gen_3/aresetn] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] - connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_calib_0/calib_limit_lower] [get_bd_pins signal_cfg_slice_0/calib_limit_lower] - connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_calib_0/calib_limit_upper] [get_bd_pins signal_cfg_slice_0/calib_limit_upper] + connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] + connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] connect_bd_net -net signal_cfg_slice_0_calib_offset [get_bd_pins signal_calib_0/calib_offset] [get_bd_pins signal_cfg_slice_0/calib_offset] connect_bd_net -net signal_cfg_slice_0_calib_scale [get_bd_pins signal_calib_0/calib_scale] [get_bd_pins signal_cfg_slice_0/calib_scale] connect_bd_net -net signal_cfg_slice_0_comp_0_amp [get_bd_pins signal_cfg_slice_0/comp_0_amp] [get_bd_pins waveform_gen_0/amplitude] @@ -990,6 +992,7 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { create_bd_pin -dir O -from 0 -to 0 m_axis_data_tvalid_1 create_bd_pin -dir I -from 15 -to 0 offset create_bd_pin -dir O -from 1 -to 0 ramp_state_0 + create_bd_pin -dir I resync_dac create_bd_pin -dir I start_ramp_down # Create instance: signal_calib_0, and set properties @@ -1094,9 +1097,10 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] connect_bd_net -net ramping_enable_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp/enableRamping] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] - connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_calib_0/calib_limit_lower] [get_bd_pins signal_cfg_slice_0/calib_limit_lower] - connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_calib_0/calib_limit_upper] [get_bd_pins signal_cfg_slice_0/calib_limit_upper] + connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] + connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] connect_bd_net -net signal_cfg_slice_0_calib_offset [get_bd_pins signal_calib_0/calib_offset] [get_bd_pins signal_cfg_slice_0/calib_offset] connect_bd_net -net signal_cfg_slice_0_calib_scale [get_bd_pins signal_calib_0/calib_scale] [get_bd_pins signal_cfg_slice_0/calib_scale] connect_bd_net -net signal_cfg_slice_0_comp_0_amp [get_bd_pins signal_cfg_slice_0/comp_0_amp] [get_bd_pins waveform_gen_0/amplitude] @@ -1576,7 +1580,7 @@ proc create_hier_cell_system_1 { parentCell nameHier } { # Create instance: image_version, and set properties set image_version [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 image_version ] set_property -dict [ list \ - CONFIG.CONST_VAL {8} \ + CONFIG.CONST_VAL {9} \ CONFIG.CONST_WIDTH {32} \ ] $image_version @@ -2099,6 +2103,7 @@ proc create_hier_cell_sequencer { parentCell nameHier } { create_bd_pin -dir I -type rst keep_alive_aresetn create_bd_pin -dir O -from 31 -to 0 oa_dac create_bd_pin -dir O -from 31 -to 0 pdm_sts + create_bd_pin -dir O -from 1 -to 0 resync_dac create_bd_pin -dir O -from 1 -to 0 seq_ramp_down # Create instance: axi_bram_ctrl_0, and set properties @@ -2251,6 +2256,7 @@ proc create_hier_cell_sequencer { parentCell nameHier } { connect_bd_net -net sequence_slice_0_pdm_value_1 [get_bd_pins pdm_2/din] [get_bd_pins sequence_slice_0/pdm_value_1] connect_bd_net -net sequence_slice_0_pdm_value_2 [get_bd_pins pdm_3/din] [get_bd_pins sequence_slice_0/pdm_value_2] connect_bd_net -net sequence_slice_0_pdm_value_3 [get_bd_pins pdm_4/din] [get_bd_pins sequence_slice_0/pdm_value_3] + connect_bd_net -net sequence_slice_0_resync_dac [get_bd_pins resync_dac] [get_bd_pins sequence_slice_0/resync_dac] connect_bd_net -net util_vector_logic_7_Res [get_bd_pins dout] [get_bd_pins util_vector_logic_7/Res] connect_bd_net -net xlconcat_0_dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconcat_1_dout [get_bd_pins oa_dac] [get_bd_pins xlconcat_1/dout] @@ -2313,6 +2319,7 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { create_bd_pin -dir I -from 31 -to 0 oa_dac create_bd_pin -dir O -from 1 -to 0 ramp_state_0 create_bd_pin -dir O -from 1 -to 0 ramp_state_1 + create_bd_pin -dir I -from 1 -to 0 resync_dac create_bd_pin -dir I -from 1 -to 0 seq_ramp_down create_bd_pin -dir I -from 1 -to 0 start_ramp_down create_bd_pin -dir O -from 31 -to 0 synth_tdata @@ -2405,6 +2412,23 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { CONFIG.DOUT_WIDTH {1} \ ] $xlslice_5 + # Create instance: xlslice_6, and set properties + set xlslice_6 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_6 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {0} \ + CONFIG.DIN_TO {0} \ + CONFIG.DIN_WIDTH {2} \ + ] $xlslice_6 + + # Create instance: xlslice_7, and set properties + set xlslice_7 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_7 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {2} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_7 + # Create interface connections connect_bd_intf_net -intf_net awg_0_bram_1 [get_bd_intf_pins awg_0_bram] [get_bd_intf_pins signal_compose/awg_bram] connect_bd_intf_net -intf_net awg_1_bram_1 [get_bd_intf_pins awg_1_bram] [get_bd_intf_pins signal_compose1/awg_bram] @@ -2422,6 +2446,7 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { connect_bd_net -net enable_ramping_slice_0_start_ramp_down_0 [get_bd_pins enable_ramping_slice_0/start_ramp_down_0] [get_bd_pins signal_compose/start_ramp_down] connect_bd_net -net enable_ramping_slice_0_start_ramp_down_1 [get_bd_pins enable_ramping_slice_0/start_ramp_down_1] [get_bd_pins signal_compose1/start_ramp_down] connect_bd_net -net oa_dac_1 [get_bd_pins oa_dac] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins xlslice_6/Din] [get_bd_pins xlslice_7/Din] connect_bd_net -net seq_ramp_down_1 [get_bd_pins seq_ramp_down] [get_bd_pins enable_ramping_slice_0/seq_ramp_down] connect_bd_net -net signal_compose1_S [get_bd_pins signal_compose1/S] [get_bd_pins xlconcat_2/In1] connect_bd_net -net signal_compose1_m_axis_data_tvalid_1 [get_bd_pins signal_compose1/m_axis_data_tvalid_1] [get_bd_pins util_vector_logic_1/Op2] @@ -2438,6 +2463,8 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { connect_bd_net -net xlslice_3_Dout [get_bd_pins signal_compose/offset] [get_bd_pins xlslice_3/Dout] connect_bd_net -net xlslice_4_Dout [get_bd_pins signal_compose/disable_dac] [get_bd_pins xlslice_4/Dout] connect_bd_net -net xlslice_5_Dout [get_bd_pins signal_compose1/disable_dac] [get_bd_pins xlslice_5/Dout] + connect_bd_net -net xlslice_6_Dout [get_bd_pins signal_compose/resync_dac] [get_bd_pins xlslice_6/Dout] + connect_bd_net -net xlslice_7_Dout [get_bd_pins signal_compose1/resync_dac] [get_bd_pins xlslice_7/Dout] # Restore current instance current_bd_instance $oldCurInst @@ -3391,6 +3418,7 @@ proc create_root_design { parentCell } { connect_bd_net -net selectio_wiz_2_clk_out [get_bd_pins clk_wiz_1/clk_in1] [get_bd_pins selectio_wiz_2/clk_out] connect_bd_net -net selectio_wiz_2_data_in_to_device [get_bd_pins reset_manager_0/sata_trigger] [get_bd_pins selectio_wiz_2/data_in_to_device] connect_bd_net -net sequencer_enable_dac [get_bd_pins fourier_synth_standard/enable_dac] [get_bd_pins sequencer/enable_dac] + connect_bd_net -net sequencer_resync_dac [get_bd_pins fourier_synth_standard/resync_dac] [get_bd_pins sequencer/resync_dac] connect_bd_net -net sequencer_seq_ramp_down [get_bd_pins fourier_synth_standard/seq_ramp_down] [get_bd_pins sequencer/seq_ramp_down] connect_bd_net -net system_FCLK_RESET0_N [get_bd_pins system/FCLK_RESET0_N] [get_bd_pins util_vector_logic_1/Op1] connect_bd_net -net system_cfg_data [get_bd_pins fourier_synth_standard/cfg_data] [get_bd_pins system/dac_cfg] @@ -3434,7 +3462,6 @@ proc create_root_design { parentCell } { # Restore current instance current_bd_instance $oldCurInst - validate_bd_design save_bd_design } # End of create_root_design() @@ -3447,3 +3474,5 @@ proc create_root_design { parentCell } { create_root_design "" +common::send_gid_msg -ssname BD::TCL -id 2053 -severity "WARNING" "This Tcl script was generated from a block design that has not been validated. It is possible that design <$design_name> may result in errors during validation." + diff --git a/src/fpga/bd/waveform_gen.tcl b/src/fpga/bd/waveform_gen.tcl index f56db04a..ac9b77b2 100644 --- a/src/fpga/bd/waveform_gen.tcl +++ b/src/fpga/bd/waveform_gen.tcl @@ -128,6 +128,7 @@ xilinx.com:ip:dds_compiler:6.0\ xilinx.com:ip:mult_gen:12.0\ jbeuke:user:signal_generator:1.0\ xilinx.com:ip:xlconcat:2.1\ +xilinx.com:ip:xlconstant:1.1\ " set list_ips_missing "" @@ -203,12 +204,13 @@ proc create_root_design { parentCell } { set freq [ create_bd_port -dir I -from 47 -to 0 freq ] set m_axis_data_tvalid_1 [ create_bd_port -dir O m_axis_data_tvalid_1 ] set phase [ create_bd_port -dir I -from 47 -to 0 phase ] + set resync [ create_bd_port -dir I resync ] set wave [ create_bd_port -dir O -from 15 -to 0 -type data wave ] # Create instance: axis_variable_A_channel_1, and set properties set axis_variable_A_channel_1 [ create_bd_cell -type ip -vlnv pavel-demin:user:axis_variable:1.0 axis_variable_A_channel_1 ] set_property -dict [ list \ - CONFIG.AXIS_TDATA_WIDTH {96} \ + CONFIG.AXIS_TDATA_WIDTH {104} \ ] $axis_variable_A_channel_1 # Create instance: dds_compiler_A_channel_1, and set properties @@ -233,10 +235,11 @@ proc create_root_design { parentCell } { CONFIG.POFF1 {0} \ CONFIG.Parameter_Entry {System_Parameters} \ CONFIG.PartsPresent {Phase_Generator_and_SIN_COS_LUT} \ - CONFIG.Phase_Increment {Programmable} \ + CONFIG.Phase_Increment {Streaming} \ CONFIG.Phase_Offset_Angles1 {0} \ CONFIG.Phase_Width {48} \ - CONFIG.Phase_offset {Programmable} \ + CONFIG.Phase_offset {Streaming} \ + CONFIG.Resync {true} \ CONFIG.S_PHASE_Has_TUSER {Not_Required} \ CONFIG.Spurious_Free_Dynamic_Range {84} \ ] $dds_compiler_A_channel_1 @@ -261,15 +264,27 @@ proc create_root_design { parentCell } { CONFIG.CFG_DATA_WIDTH {48} \ ] $signal_generator_0 + # Create instance: xlconcat_0, and set properties + set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + # Create instance: xlconcat_A_channel_1, and set properties set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] set_property -dict [ list \ CONFIG.IN0_WIDTH {48} \ CONFIG.IN1_WIDTH {48} \ + CONFIG.IN2_WIDTH {8} \ + CONFIG.NUM_PORTS {3} \ ] $xlconcat_A_channel_1 + # Create instance: xlconstant_0, and set properties + set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] + set_property -dict [ list \ + CONFIG.CONST_VAL {0} \ + CONFIG.CONST_WIDTH {7} \ + ] $xlconstant_0 + # Create interface connections - connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_CONFIG] + connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_PHASE] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_DATA [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_DATA] [get_bd_intf_pins signal_generator_0/s_axis] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_PHASE [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_PHASE] [get_bd_intf_pins signal_generator_0/s_axis_phase] @@ -280,10 +295,13 @@ proc create_root_design { parentCell } { connect_bd_net -net mult_gen_0_P [get_bd_ports wave] [get_bd_pins mult_gen_0/P] connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] connect_bd_net -net phase_A_channel_1_slice1_Dout [get_bd_ports cfg_data] [get_bd_pins signal_generator_0/cfg_data] + connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins xlconcat_0/In0] connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins signal_generator_0/aresetn] connect_bd_net -net signal_generator_0_m_axis_tdata [get_bd_pins mult_gen_0/B] [get_bd_pins signal_generator_0/m_axis_tdata] connect_bd_net -net signal_generator_0_m_axis_tvalid [get_bd_ports m_axis_data_tvalid_1] [get_bd_pins signal_generator_0/m_axis_tvalid] + connect_bd_net -net xlconcat_0_dout [get_bd_pins xlconcat_0/dout] [get_bd_pins xlconcat_A_channel_1/In2] connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] + connect_bd_net -net xlconstant_0_dout [get_bd_pins xlconcat_0/In1] [get_bd_pins xlconstant_0/dout] # Create address segments diff --git a/src/fpga/hdl/sequence_slice.v b/src/fpga/hdl/sequence_slice.v index 7e3f15f8..67b36e07 100644 --- a/src/fpga/hdl/sequence_slice.v +++ b/src/fpga/hdl/sequence_slice.v @@ -11,6 +11,7 @@ module sequence_slice( output [10:0] pdm_value_2, output [10:0] pdm_value_3, output [1:0] enable_dac, + output [1:0] resync_dac, output [3:0] enable_pdm, output [1:0] enable_dac_ramp_down ); @@ -41,6 +42,7 @@ assign pdm_value_3[10:0] = seq_data_int[90:80]; // Flags assign enable_dac[1:0] = seq_data_int[97:96]; assign enable_pdm[3:0] = seq_data_int[101:98]; +assign resync_dac[1:0] = seq_data_init[31:30]; assign enable_dac_ramp_down[0] = seq_data_int[112]; assign enable_dac_ramp_down[1] = seq_data_int[113]; From ed6f10164c817b331dcb7f20d8c199797a8f32c1 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:42:44 +0000 Subject: [PATCH 02/38] Init resync rp-lib --- src/lib/rp-daq-lib.c | 26 ++++++++++++++++++++++++++ src/lib/rp-daq-lib.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index ffa18329..37f26941 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -637,6 +637,32 @@ int setEnableDAC(int8_t value, int channel, int index) { return 0; } +int setResyncDACAll(int8_t value, int channel) { + for(int i=0; i= 2) { + return -2; + } + + if (value < 0 || value >= 2) + return -1; + + int bitpos = 14 + channel; + // Reset bit is in the 2-th channel + int offset = 8 * index + 2; + // clear the bit + *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); + // set the bit + *((int16_t *)(pdm_cfg + offset)) |= (value << bitpos); + //printf("%d reset pdm\n", *((int16_t *)(pdm_cfg + 2*(0+4*index)))); + return 0; +} + int setResetDAC(int8_t value, int index) { if (value < 0 || value >= 2) return -1; diff --git a/src/lib/rp-daq-lib.h b/src/lib/rp-daq-lib.h index 649a6dcc..9dc8378f 100644 --- a/src/lib/rp-daq-lib.h +++ b/src/lib/rp-daq-lib.h @@ -143,6 +143,8 @@ extern uint32_t getXADCValue(int); extern float getXADCValueVolt(int); extern int setEnableDACAll(int8_t, int); extern int setEnableDAC(int8_t, int, int); +extern int setResyncDACAll(int8_t, int); +extern int setResyncDAC(int8_t, int, int); //extern int setResetDAC(int8_t, int); extern int setRampDownDAC(int8_t, int, int); extern int getRampDownDAC(int, int); From d82017459db92e6396a7e4f9b5a278463a5276a4 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:43:00 +0000 Subject: [PATCH 03/38] Init resync server --- src/server/control.c | 19 +++++++++++++++++++ src/server/daq_server_scpi.h | 2 ++ src/server/scpi_commands.c | 26 ++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/server/control.c b/src/server/control.c index abca9c2a..0ec9b880 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -46,6 +46,7 @@ sequenceData_t * allocSequence() { seq->enableLUT = NULL; seq->rampUp = NULL; seq->rampDown = NULL; + seq->resyncLUT = NULL; return seq; } @@ -66,6 +67,10 @@ void freeSequence(sequenceData_t *seqData) { freeRamping(seqData->rampDown); seqData->rampDown = NULL; } + if (seqData->resyncLUT != NULL) { + free(seqData->resyncLUT); + seqData->resyncLUT = NULL; + } } rampingData_t * allocRamping() { @@ -120,6 +125,15 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { return result; } +bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { + bool result = false; + if (seqData->resyncLUT != NULL) { + int localStep = seqStep % seqData->numStepsPerRepetition; + result = seqData->resyncLUT[localStep + channel]; + } + return result; +} + float getRampingValue(rampingData_t *rampData, int rampStep, int channel) { int localStep = rampStep % rampData->numStepsPerRepetition; return rampData->LUT[localStep * numSlowDACChan + channel]; @@ -216,6 +230,7 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { float val = 0.0; bool enable = true; bool rampDown = false; + bool resync = false; switch(interval) { case RAMPUP: @@ -224,6 +239,7 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { case REGULAR: val = getSequenceValue(activeSequence, localStep, channel); enable = getSequenceEnableValue(activeSequence, localStep, channel); + resync = getSequenceResyncValue(activeSequence, localStep, channel); break; case RAMPDOWN: val = getRampingValue(activeSequence->rampDown, localStep, channel); @@ -240,6 +256,9 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { printf("Could not set AO[%d] voltage.\n", channel); } setEnableDAC(enable, channel, currPDMIndex); + if (channel < 2) { + setResyncDAC(resync, channel, currPDMIndex); + } setRampDownDAC(rampDown, channel, currPDMIndex); } diff --git a/src/server/daq_server_scpi.h b/src/server/daq_server_scpi.h index 4fdf6f08..08e9adf2 100644 --- a/src/server/daq_server_scpi.h +++ b/src/server/daq_server_scpi.h @@ -107,6 +107,7 @@ typedef struct { int numStepsPerRepetition; // How many steps per repetition float* LUT; // LUT for value function pointer bool * enableLUT; + bool * resyncLUT; rampingData_t* rampUp; rampingData_t* rampDown; } sequenceData_t; @@ -131,6 +132,7 @@ extern sequenceInterval_t computeInterval(sequenceData_t *seqData, int step); extern bool isSequenceConfigurable(); extern float getSequenceValue(sequenceData_t *seqData, int seqStep, int channel); extern bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel); +extern bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel); extern float getRampingValue(rampingData_t *rampData, int rampStep, int channel); extern int getRampUpSteps(sequenceData_t *seqData); extern int getRampDownSteps(sequenceData_t *seqData); diff --git a/src/server/scpi_commands.c b/src/server/scpi_commands.c index 7629ba5b..6025297e 100644 --- a/src/server/scpi_commands.c +++ b/src/server/scpi_commands.c @@ -1056,6 +1056,31 @@ static scpi_result_t RP_DAC_SetEnableLUT(scpi_t * context) { } } +static scpi_result_t RP_DAC_SetResyncLUT(scpi_t * context) { + + readyConfigSequence(); + + if(configSeq->LUT != NULL && numSlowDACChan > 0 && isSequenceConfigurable()) { + if(configSeq->resyncLUT != NULL) { + free(configSeq->resyncLUT); + configSeq->resyncLUT = NULL; + } + + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; + printf("Allocating ressyncLUT\n"); + configSeq->resyncLUT = (bool *)calloc(numChan, configSeq->numStepsPerRepetition * sizeof(bool)); + + int n = readAll(newdatasockfd, configSeq->resyncLUT, numSlowDACChan * configSeq->numStepsPerRepetition * sizeof(bool)); + seqState = CONFIG; + if (n < 0) perror("ERROR reading from socket"); + return returnSCPIBool(context, true); + } + else { + return returnSCPIBool(context, false); + } + +} + static scpi_result_t RP_DAC_SetUpLUT(scpi_t * context) { readyConfigSequence(); @@ -1739,6 +1764,7 @@ const scpi_command_t scpi_commands[] = { {.pattern = "RP:DAC:SEQ:CHan?", .callback = RP_DAC_GetNumSlowDACChan,}, {.pattern = "RP:DAC:SEQ:LUT", .callback = RP_DAC_SetValueLUT,}, {.pattern = "RP:DAC:SEQ:LUT:ENaBle", .callback = RP_DAC_SetEnableLUT,}, + {.pattern = "RP:DAC:SEQ:LUT:ReSYNC", .callback = RP_DAC_SetResyncLUT,}, {.pattern = "RP:DAC:SEQ:LUT:UP", .callback = RP_DAC_SetUpLUT,}, {.pattern = "RP:DAC:SEQ:LUT:DOWN", .callback = RP_DAC_SetDownLUT,}, {.pattern = "RP:DAC:SEQ:SET", .callback = RP_DAC_SetSequence,}, From 268702b496b433daa4b314edcd1a86a3634859a9 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:43:11 +0000 Subject: [PATCH 04/38] Init resync julia client --- src/client/julia/src/Sequence.jl | 52 ++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/client/julia/src/Sequence.jl b/src/client/julia/src/Sequence.jl index db223879..25054eef 100644 --- a/src/client/julia/src/Sequence.jl +++ b/src/client/julia/src/Sequence.jl @@ -134,17 +134,19 @@ abstract type RampingSequence <: AbstractSequence end struct SimpleRampingSequence <: AbstractSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} rampUp::SequenceLUT rampDown::SequenceLUT - function SimpleRampingSequencee(lut::SequenceLUT, up::SequenceLUT, down::SequenceLUT, enable::Union{Array{Bool}, Nothing}=nothing) + function SimpleRampingSequencee(lut::SequenceLUT, up::SequenceLUT, down::SequenceLUT, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(values(lut)) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end - return new(SequenceLUT(lut, repetitions), enable, up, down) + return new(SequenceLUT(lut, repetitions), enable, resync, up, down) end end enableLUT(seq::SimpleRampingSequence) = seq.enable +resyncLUT(seq::SimpleRampingSequence) = seq.resync valueLUT(seq::SimpleRampingSequence) = seq.lut rampUpLUT(seq::SimpleRampingSequence) = nothing rampDownLUT(seq::SimpleRampingSequence) = nothing @@ -158,6 +160,7 @@ end struct HoldBorderRampingSequence <: RampingSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} rampUp::SequenceLUT rampDown::SequenceLUT @@ -170,13 +173,13 @@ struct HoldBorderRampingSequence <: RampingSequence - `lut`,`repetitions`,`enable` are used the same as for a `SimpleSequence` - `rampingSteps` is the number of steps the first and last value of the given sequence are repeated before the sequence is started """ - function HoldBorderRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function HoldBorderRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end up = SequenceLUT(lut[:, 1], rampingSteps) down = SequenceLUT(lut[:, end], rampingSteps) - return new(SequenceLUT(lut, repetitions), enable, up, down) + return new(SequenceLUT(lut, repetitions), enable, resync, up, down) end end @@ -190,6 +193,7 @@ function HoldBorderRampingSequence(rp::RedPitaya, lut, repetitions, enable=nothi end enableLUT(seq::HoldBorderRampingSequence) = seq.enable +resyncLUT(seq::HoldBorderRampingSequence) = seq.resync valueLUT(seq::HoldBorderRampingSequence) = seq.lut rampUpLUT(seq::HoldBorderRampingSequence) = seq.rampUp rampDownLUT(seq::HoldBorderRampingSequence) = seq.rampDown @@ -197,14 +201,15 @@ rampDownLUT(seq::HoldBorderRampingSequence) = seq.rampDown struct ConstantRampingSequence <: RampingSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} ramping::SequenceLUT - function ConstantRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingValue::Float32, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function ConstantRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingValue::Float32, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end rampingLut = SequenceLUT([rampingValue for i = 1:size(lut, 1)], rampingSteps) - return new(SequenceLUT(lut, repetitions), enable, rampingLut) + return new(SequenceLUT(lut, repetitions), enable, resync, rampingLut) end end ConstantRampingSequence(lut::Array{T}, repetitions::Integer, rampingValue::Real, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = ConstantRampingSequence(map(Float32, lut), repetitions, Float32(rampingValue), rampingSteps, enable) @@ -212,6 +217,7 @@ ConstantRampingSequence(lut::Vector{Float32}, repetitions::Integer, rampingValue ConstantRampingSequence(lut::Vector{T}, repetitions::Integer, rampingValue::Real, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = ConstantRampingSequence(reshape(lut, 1, :), repetitions, rampingValue, rampingSteps, enable) enableLUT(seq::ConstantRampingSequence) = seq.enable +resyncLUT(seq::ConstantRampingSequence) = seq.resync valueLUT(seq::ConstantRampingSequence) = seq.lut rampUpLUT(seq::ConstantRampingSequence) = seq.ramping rampDownLUT(seq::ConstantRampingSequence) = seq.ramping @@ -219,9 +225,10 @@ rampDownLUT(seq::ConstantRampingSequence) = seq.ramping struct StartUpSequence <: RampingSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} rampUp::SequenceLUT rampDown::SequenceLUT - function StartUpSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function StartUpSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end @@ -239,7 +246,7 @@ struct StartUpSequence <: RampingSequence end up = SequenceLUT(upLut, 1) down = SequenceLUT(lut[:, end], rampingSteps) - return new(SequenceLUT(lut, repetitions), enable, up, down) + return new(SequenceLUT(lut, repetitions), enable, resync, up, down) end end StartUpSequence(lut::Array{T}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = StartUpSequence(map(Float32, lut), repetitions, rampingSteps, startUpSteps, enable) @@ -247,6 +254,7 @@ StartUpSequence(lut::Array{T}, repetitions::Integer, rampingSteps::Integer, star StartUpSequence(lut::Vector{T}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = StartUpSequence(reshape(lut, 1, :), repetitions, rampingSteps, startUpSteps, enable) enableLUT(seq::StartUpSequence) = seq.enable +resyncLUT(seq::StartUpSequence) = seq.resync valueLUT(seq::StartUpSequence) = seq.lut rampUpLUT(seq::StartUpSequence) = seq.rampUp rampDownLUT(seq::StartUpSequence) = seq.rampDown @@ -269,10 +277,11 @@ Transmit the client-side representation `seq` to the server and append it to the """ function sequence!(rp::RedPitaya, seq::AbstractSequence) result = true - result &= valueLUT!(rp, valueLUT(seq)) - result &= enableLUT!(rp, enableLUT(seq)) - result &= rampUpLUT!(rp, rampUpLUT(seq)) - result &= rampDownLUT!(rp, rampDownLUT(seq)) + result &= valueLUT!(rp, seq) + result &= enableLUT!(rp, seq) + result &= resyncLUT!(rp, seq) + result &= rampUpLUT!(rp, seq) + result &= rampDownLUT!(rp, seq) result &= setSequence!(rp) return result end @@ -283,11 +292,13 @@ function transmitLUT!(rp::RedPitaya, lut::Array{Float32}, cmd::String, repetitio return parse(Bool, receive(rp)) end +valueLUT!(rp::RedPitaya, lut::AbstractSequence) = valueLUT!(rp, valueLUT(lut)) function valueLUT!(rp::RedPitaya, lut::SequenceLUT) lutFloat32 = map(Float32, values(lut)) return transmitLUT!(rp, lutFloat32, "RP:DAC:SEQ:LUT", repetitions(lut)) end +rampUpLUT!(rp::RedPitaya, lut::AbstractSequence) = rampUpLUT!(rp, rampUpLUT(lut)) function rampUpLUT!(rp::RedPitaya, lut::SequenceLUT) lutFloat32 = map(Float32, values(lut)) return transmitLUT!(rp, lutFloat32, "RP:DAC:SEQ:LUT:UP", repetitions(lut)) @@ -298,6 +309,7 @@ function rampUpLUT!(rp::RedPitaya, lut::Nothing) return true end +rampDownLUT!(rp::RedPitaya, lut::AbstractSequence) = rampDownLUT!(rp, rampDownLUT(lut)) function rampDownLUT!(rp::RedPitaya, lut::SequenceLUT) lutFloat32 = map(Float32, values(lut)) return transmitLUT!(rp, lutFloat32, "RP:DAC:SEQ:LUT:DOWN", repetitions(lut)) @@ -308,6 +320,7 @@ function rampDownLUT!(rp::RedPitaya, lut::Nothing) return true end +enableLUT!(rp::RedPitaya, lut::AbstractSequence) = enableLUT!(rp, enableLUT(lut)) function enableLUT!(rp::RedPitaya, lut::Array) lutBool = map(Bool, lut) send(rp, string("RP:DAC:SEQ:LUT:ENaBle")) @@ -322,6 +335,21 @@ function enableLUT!(rp::RedPitaya, lut::Nothing) return true end +resyncLUT!(rp::RedPitaya, lut::AbstractSequence) = resyncLUT!(rp, resyncLUT(lut)) +function resyncLUT!(rp::RedPitaya, lut::Array) + lutBool = map(Bool, lut) + send(rp, string("RP:DAC:SEQ:LUT:ReSYNC")) + @debug "Writing resync DAC LUT" + write(rp.dataSocket, lutBool) + reply = receive(rp) + return parse(Bool, reply) +end + +function resyncLUT!(rp::RedPitaya, lut::Nothing) + # NOP + return true +end + function seqTiming(seq::AbstractSequence) up = 0 if !isnothing(rampUpLUT(seq)) From 7b8d04e42773a6f995a32144e5c5eead13bdb968 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:54:25 +0000 Subject: [PATCH 05/38] Fix variable name in seq_data_int --- src/fpga/hdl/sequence_slice.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fpga/hdl/sequence_slice.v b/src/fpga/hdl/sequence_slice.v index 67b36e07..ab2e91a5 100644 --- a/src/fpga/hdl/sequence_slice.v +++ b/src/fpga/hdl/sequence_slice.v @@ -42,7 +42,7 @@ assign pdm_value_3[10:0] = seq_data_int[90:80]; // Flags assign enable_dac[1:0] = seq_data_int[97:96]; assign enable_pdm[3:0] = seq_data_int[101:98]; -assign resync_dac[1:0] = seq_data_init[31:30]; +assign resync_dac[1:0] = seq_data_int[31:30]; assign enable_dac_ramp_down[0] = seq_data_int[112]; assign enable_dac_ramp_down[1] = seq_data_int[113]; From 0457f85cf1d6d720f3f73e57605fe49db0ce0ac0 Mon Sep 17 00:00:00 2001 From: rp_local Date: Wed, 25 Sep 2024 16:05:18 +0000 Subject: [PATCH 06/38] Init working resync based on aresetn --- src/client/julia/Project.toml | 2 +- src/client/julia/src/Sequence.jl | 12 +++++---- src/fpga/bd/bd.tcl | 9 +++++-- src/fpga/bd/waveform_gen.tcl | 45 ++++++++++++++++++-------------- src/lib/rp-daq-lib.c | 5 ++-- src/server/control.c | 6 +++-- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/client/julia/Project.toml b/src/client/julia/Project.toml index 654c97b0..26393c4d 100644 --- a/src/client/julia/Project.toml +++ b/src/client/julia/Project.toml @@ -1,7 +1,7 @@ name = "RedPitayaDAQServer" uuid = "c544963a-496b-56d4-a5fe-f99a3f174c8f" authors = ["Tobias Knopp "] -version = "0.8.2" +version = "0.9.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/client/julia/src/Sequence.jl b/src/client/julia/src/Sequence.jl index 25054eef..7b197ed5 100644 --- a/src/client/julia/src/Sequence.jl +++ b/src/client/julia/src/Sequence.jl @@ -103,7 +103,8 @@ Struct representing a sequence in which the server directly takes the values fro """ struct SimpleSequence <: AbstractSequence lut::SequenceLUT - enable::Union{Array{Bool}, Nothing} + enable::Union{Matrix{Bool}, Nothing} + resync::Union{Matrix{Bool}, Nothing} """ SimpleSequence(lut, repetitions, enable=nothing) @@ -114,17 +115,18 @@ struct SimpleSequence <: AbstractSequence - `repetitions::Int32`: the number of times the sequence should be repeated - `emable::Union{Array{Bool}, Nothing}`: matrix containing enable flags """ - function SimpleSequence(lut::Array{Float32}, repetitions::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function SimpleSequence(lut::Matrix{Float32}, repetitions::Integer, enable::Union{Matrix{Bool}, Nothing}=nothing, resync::Union{Matrix{Bool}, Nothing} = nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end - return new(SequenceLUT(lut, repetitions), enable) + return new(SequenceLUT(lut, repetitions), enable, resync) end end -SimpleSequence(lut::Array{T}, repetitions::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = SimpleSequence(map(Float32, lut), repetitions, enable) -SimpleSequence(lut::Vector{T}, repetitions::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = SimpleSequence(reshape(lut, 1, :), repetitions, enable) +SimpleSequence(lut::Array{T}, repetitions::Integer, args...) where T <: Real = SimpleSequence(map(Float32, lut), repetitions, args...) +SimpleSequence(lut::Vector{T}, repetitions::Integer, args...) where T <: Real = SimpleSequence(reshape(lut, 1, :), repetitions, args...) enableLUT(seq::SimpleSequence) = seq.enable +resyncLUT(seq::SimpleSequence) = seq.resync valueLUT(seq::SimpleSequence) = seq.lut rampUpLUT(seq::SimpleSequence) = nothing rampDownLUT(seq::SimpleSequence) = nothing diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 206a1a32..e9ae2bab 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -402,6 +402,9 @@ proc create_hier_cell_waveform_awg1 { parentCell nameHier } { # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + set_property -dict [ list \ + CONFIG.IN0_WIDTH {48} \ + ] $xlconcat_0 # Create instance: xlconstant_0, and set properties set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] @@ -572,6 +575,9 @@ proc create_hier_cell_waveform_awg { parentCell nameHier } { # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + set_property -dict [ list \ + CONFIG.IN0_WIDTH {48} \ + ] $xlconcat_0 # Create instance: xlconstant_0, and set properties set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] @@ -3462,6 +3468,7 @@ proc create_root_design { parentCell } { # Restore current instance current_bd_instance $oldCurInst + validate_bd_design save_bd_design } # End of create_root_design() @@ -3474,5 +3481,3 @@ proc create_root_design { parentCell } { create_root_design "" -common::send_gid_msg -ssname BD::TCL -id 2053 -severity "WARNING" "This Tcl script was generated from a block design that has not been validated. It is possible that design <$design_name> may result in errors during validation." - diff --git a/src/fpga/bd/waveform_gen.tcl b/src/fpga/bd/waveform_gen.tcl index ac9b77b2..8b6070f9 100644 --- a/src/fpga/bd/waveform_gen.tcl +++ b/src/fpga/bd/waveform_gen.tcl @@ -127,8 +127,8 @@ pavel-demin:user:axis_variable:1.0\ xilinx.com:ip:dds_compiler:6.0\ xilinx.com:ip:mult_gen:12.0\ jbeuke:user:signal_generator:1.0\ +xilinx.com:ip:util_vector_logic:2.0\ xilinx.com:ip:xlconcat:2.1\ -xilinx.com:ip:xlconstant:1.1\ " set list_ips_missing "" @@ -210,7 +210,7 @@ proc create_root_design { parentCell } { # Create instance: axis_variable_A_channel_1, and set properties set axis_variable_A_channel_1 [ create_bd_cell -type ip -vlnv pavel-demin:user:axis_variable:1.0 axis_variable_A_channel_1 ] set_property -dict [ list \ - CONFIG.AXIS_TDATA_WIDTH {104} \ + CONFIG.AXIS_TDATA_WIDTH {96} \ ] $axis_variable_A_channel_1 # Create instance: dds_compiler_A_channel_1, and set properties @@ -220,6 +220,7 @@ proc create_root_design { parentCell } { CONFIG.DATA_Has_TLAST {Not_Required} \ CONFIG.DDS_Clock_Rate {125} \ CONFIG.Frequency_Resolution {4.440893e-7} \ + CONFIG.Has_ACLKEN {false} \ CONFIG.Has_ARESETn {true} \ CONFIG.Has_Phase_Out {true} \ CONFIG.Has_TREADY {false} \ @@ -235,11 +236,11 @@ proc create_root_design { parentCell } { CONFIG.POFF1 {0} \ CONFIG.Parameter_Entry {System_Parameters} \ CONFIG.PartsPresent {Phase_Generator_and_SIN_COS_LUT} \ - CONFIG.Phase_Increment {Streaming} \ + CONFIG.Phase_Increment {Programmable} \ CONFIG.Phase_Offset_Angles1 {0} \ CONFIG.Phase_Width {48} \ - CONFIG.Phase_offset {Streaming} \ - CONFIG.Resync {true} \ + CONFIG.Phase_offset {Programmable} \ + CONFIG.Resync {false} \ CONFIG.S_PHASE_Has_TUSER {Not_Required} \ CONFIG.Spurious_Free_Dynamic_Range {84} \ ] $dds_compiler_A_channel_1 @@ -264,8 +265,19 @@ proc create_root_design { parentCell } { CONFIG.CFG_DATA_WIDTH {48} \ ] $signal_generator_0 - # Create instance: xlconcat_0, and set properties - set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + # Create instance: util_vector_logic_0, and set properties + set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {not} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_notgate.png} \ + ] $util_vector_logic_0 + + # Create instance: util_vector_logic_1, and set properties + set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_1 # Create instance: xlconcat_A_channel_1, and set properties set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] @@ -273,35 +285,28 @@ proc create_root_design { parentCell } { CONFIG.IN0_WIDTH {48} \ CONFIG.IN1_WIDTH {48} \ CONFIG.IN2_WIDTH {8} \ - CONFIG.NUM_PORTS {3} \ + CONFIG.NUM_PORTS {2} \ ] $xlconcat_A_channel_1 - # Create instance: xlconstant_0, and set properties - set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] - set_property -dict [ list \ - CONFIG.CONST_VAL {0} \ - CONFIG.CONST_WIDTH {7} \ - ] $xlconstant_0 - # Create interface connections - connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_PHASE] + connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_CONFIG] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_DATA [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_DATA] [get_bd_intf_pins signal_generator_0/s_axis] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_PHASE [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_PHASE] [get_bd_intf_pins signal_generator_0/s_axis_phase] # Create port connections connect_bd_net -net amplitude_A_channel_1_slice1_Dout [get_bd_ports amplitude] [get_bd_pins mult_gen_0/A] + connect_bd_net -net aresetn_1 [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins signal_generator_0/aresetn] [get_bd_pins util_vector_logic_1/Op2] connect_bd_net -net clk_wiz_0_clk_internal [get_bd_ports aclk] [get_bd_pins axis_variable_A_channel_1/aclk] [get_bd_pins dds_compiler_A_channel_1/aclk] [get_bd_pins mult_gen_0/CLK] [get_bd_pins signal_generator_0/clk] connect_bd_net -net freq_1 [get_bd_ports freq] [get_bd_pins xlconcat_A_channel_1/In0] connect_bd_net -net mult_gen_0_P [get_bd_ports wave] [get_bd_pins mult_gen_0/P] connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] connect_bd_net -net phase_A_channel_1_slice1_Dout [get_bd_ports cfg_data] [get_bd_pins signal_generator_0/cfg_data] - connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins xlconcat_0/In0] - connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins signal_generator_0/aresetn] + connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins util_vector_logic_0/Op1] connect_bd_net -net signal_generator_0_m_axis_tdata [get_bd_pins mult_gen_0/B] [get_bd_pins signal_generator_0/m_axis_tdata] connect_bd_net -net signal_generator_0_m_axis_tvalid [get_bd_ports m_axis_data_tvalid_1] [get_bd_pins signal_generator_0/m_axis_tvalid] - connect_bd_net -net xlconcat_0_dout [get_bd_pins xlconcat_0/dout] [get_bd_pins xlconcat_A_channel_1/In2] + connect_bd_net -net util_vector_logic_0_Res [get_bd_pins util_vector_logic_0/Res] [get_bd_pins util_vector_logic_1/Op1] + connect_bd_net -net util_vector_logic_1_Res [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins util_vector_logic_1/Res] connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] - connect_bd_net -net xlconstant_0_dout [get_bd_pins xlconcat_0/In1] [get_bd_pins xlconstant_0/dout] # Create address segments diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 37f26941..0d555380 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -653,8 +653,8 @@ int setResyncDAC(int8_t value, int channel, int index) { return -1; int bitpos = 14 + channel; - // Reset bit is in the 2-th channel - int offset = 8 * index + 2; + // Reset bits are in the 2nd channel -> bitpos 31:30 + int offset = 8 * index + 1; // clear the bit *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); // set the bit @@ -1306,6 +1306,7 @@ void stopTx() { for(int d=0; d<5; d++) { setPDMAllValuesVolt(0.0, d); setEnableDACAll(1,d); + setResyncDACAll(0,d); } } diff --git a/src/server/control.c b/src/server/control.c index 0ec9b880..64c7abc8 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -102,9 +102,11 @@ void clearSequence() { setPDMAllValuesVolt(0.0, 2); setPDMAllValuesVolt(0.0, 3); - for(int d=0; d<4; d++) { + for(int d=0; d<6; d++) { setEnableDACAll(1,d); - } + setResyncDACAll(0,d); + } + } bool isSequenceConfigurable() { From 45d19c13ddb9268c8ae66b48e25c8cc1342b8b67 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Thu, 26 Sep 2024 07:17:33 +0200 Subject: [PATCH 07/38] fix multi-channel resync issues --- src/server/control.c | 3 ++- src/server/scpi_commands.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/server/control.c b/src/server/control.c index 64c7abc8..bfd08aed 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -129,9 +129,10 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { bool result = false; + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; if (seqData->resyncLUT != NULL) { int localStep = seqStep % seqData->numStepsPerRepetition; - result = seqData->resyncLUT[localStep + channel]; + result = seqData->resyncLUT[localStep * numChan + channel]; } return result; } diff --git a/src/server/scpi_commands.c b/src/server/scpi_commands.c index 6025297e..b7308745 100644 --- a/src/server/scpi_commands.c +++ b/src/server/scpi_commands.c @@ -1070,7 +1070,7 @@ static scpi_result_t RP_DAC_SetResyncLUT(scpi_t * context) { printf("Allocating ressyncLUT\n"); configSeq->resyncLUT = (bool *)calloc(numChan, configSeq->numStepsPerRepetition * sizeof(bool)); - int n = readAll(newdatasockfd, configSeq->resyncLUT, numSlowDACChan * configSeq->numStepsPerRepetition * sizeof(bool)); + int n = readAll(newdatasockfd, configSeq->resyncLUT, numChan * configSeq->numStepsPerRepetition * sizeof(bool)); seqState = CONFIG; if (n < 0) perror("ERROR reading from socket"); return returnSCPIBool(context, true); From cdb0ae9e8a21654a4c6fc5f7cbe971daa36779f1 Mon Sep 17 00:00:00 2001 From: rp_local Date: Thu, 26 Sep 2024 09:23:01 +0000 Subject: [PATCH 08/38] Move resync flag to bit 14 of each DAC channel --- src/fpga/hdl/sequence_slice.v | 5 +++-- src/lib/rp-daq-lib.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/fpga/hdl/sequence_slice.v b/src/fpga/hdl/sequence_slice.v index ab2e91a5..3ffc5840 100644 --- a/src/fpga/hdl/sequence_slice.v +++ b/src/fpga/hdl/sequence_slice.v @@ -42,8 +42,9 @@ assign pdm_value_3[10:0] = seq_data_int[90:80]; // Flags assign enable_dac[1:0] = seq_data_int[97:96]; assign enable_pdm[3:0] = seq_data_int[101:98]; -assign resync_dac[1:0] = seq_data_int[31:30]; +assign resync_dac[0] = seq_data_int[14]; +assign resync_dac[1] = seq_data_int[30]; assign enable_dac_ramp_down[0] = seq_data_int[112]; assign enable_dac_ramp_down[1] = seq_data_int[113]; -endmodule +endmodule \ No newline at end of file diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 0d555380..fe6eff16 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -652,9 +652,9 @@ int setResyncDAC(int8_t value, int channel, int index) { if (value < 0 || value >= 2) return -1; - int bitpos = 14 + channel; - // Reset bits are in the 2nd channel -> bitpos 31:30 - int offset = 8 * index + 1; + int bitpos = 14; + // Reset bits are in the 14th bit of the respective DAC channel -> 14 and 30 + int offset = 8 * index + channel; // clear the bit *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); // set the bit From 823c37e6624f212d832b1184ef0433d5d783bf33 Mon Sep 17 00:00:00 2001 From: rp_local Date: Thu, 26 Sep 2024 09:23:34 +0000 Subject: [PATCH 09/38] Restrict getSequenceResyncValue to DAC channel --- src/server/control.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/server/control.c b/src/server/control.c index bfd08aed..3e662510 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -129,8 +129,8 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { bool result = false; - int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; - if (seqData->resyncLUT != NULL) { + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; + if (seqData->resyncLUT != NULL && channel < numChan) { int localStep = seqStep % seqData->numStepsPerRepetition; result = seqData->resyncLUT[localStep * numChan + channel]; } @@ -215,6 +215,7 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { if (activeSequence == NULL) { setPDMValueVolt(0.0, channel, currPDMIndex); setEnableDAC(false, channel, currPDMIndex); + setResyncDAC(false, channel, currPDMIndex); setRampDownDAC(false, channel, currPDMIndex); return; } From b79123c0d24e173321b1cab3ca144b0c3ff86d51 Mon Sep 17 00:00:00 2001 From: rp_local Date: Fri, 29 Nov 2024 13:07:08 +0000 Subject: [PATCH 10/38] Init test of step counting with writepointer lowest bit --- src/fpga/hdl/sequence_stepper.v | 41 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/fpga/hdl/sequence_stepper.v b/src/fpga/hdl/sequence_stepper.v index 9a28dd9a..25754421 100644 --- a/src/fpga/hdl/sequence_stepper.v +++ b/src/fpga/hdl/sequence_stepper.v @@ -1,36 +1,45 @@ `timescale 1ns / 1ps module sequence_stepper( - input [63:0] writepointer, + input [63:0] writePointer, input [31:0] stepSize, input clk, input aresetn, - output [31:0] step_counter + output [31:0] seq_counter ); -reg [63:0] end_of_step, next_end_of_step; -reg [31:0] step_counter_reg, step_counter_next; +reg [31:0] stepSize_int; +reg [31:0] seq_counter_state; +reg [31:0] sample_counter; +reg wp_prev, wp_next; always @(posedge clk) begin + stepSize_int <= stepSize; + wp_next <= writePointer[0]; if (~aresetn) begin - step_counter_reg <= 0; - step_counter_next <= 0; - end_of_step <= stepSize; - next_end_of_step <= stepSize; + seq_counter_state <= 0; + sample_counter <= stepSize_int; + wp_prev <= 0; end else begin - step_counter_reg <= step_counter_next; - end_of_step <= next_end_of_step; - if (end_of_step < writepointer) begin - next_end_of_step <= end_of_step + stepSize; - step_counter_next <= step_counter_reg + 1; + wp_prev <= wp_next; + if (wp_prev != wp_next) begin + + if (sample_counter == 0) begin + sample_counter <= stepSize_int; + seq_counter_state <= seq_counter_state + 1; + end else begin + sample_counter <= sample_counter - 1; + seq_counter_state <= seq_counter_state; + end + end else begin - next_end_of_step <= next_end_of_step; - step_counter_next <= step_counter_reg; + sample_counter <= sample_counter; + seq_counter_state <= seq_counter_state; end end end -assign step_counter = step_counter_reg; +assign seq_counter = seq_counter_state; endmodule From 3bada952605943f4a7dfeb63b8732ed54d7c246a Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Sun, 1 Dec 2024 14:48:28 +0100 Subject: [PATCH 11/38] add sequenceIssue.jl --- src/examples/julia/sequenceIssue.jl | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/examples/julia/sequenceIssue.jl diff --git a/src/examples/julia/sequenceIssue.jl b/src/examples/julia/sequenceIssue.jl new file mode 100644 index 00000000..5d387cb8 --- /dev/null +++ b/src/examples/julia/sequenceIssue.jl @@ -0,0 +1,60 @@ +using RedPitayaDAQServer +using CairoMakie + +# obtain the URL of the RedPitaya +include("config.jl") + +rp = RedPitaya(URLs[1]) +serverMode!(rp, CONFIGURATION) + + +dec = 128 +base_frequency = 125000000 + +samples_per_step = 40 #30*16 +steps_per_frame = 4 +numSamples = steps_per_frame * samples_per_step + +decimation!(rp, dec) +samplesPerPeriod!(rp, 1) +periodsPerFrame!(rp, numSamples) +samplesPerStep!(rp, samples_per_step) +triggerMode!(rp, INTERNAL) + + +amplitudeDAC!(rp, 1, 1, 0.0) +amplitudeDAC!(rp, 2, 1, 0.0 ) + +clearSequence!(rp) + +# Climbing offset for first channel, fixed offset for second channel +seqChan!(rp, 6) +lutB = collect(ones(steps_per_frame)) +lutB[1:2:end] .= 0.0 +lut = collect(cat(-lutB,-lutB*0.3, 0*lutB,0*lutB,0*lutB,0*lutB,dims=2)') +#lut = collect(cat(-lutB,dims=2)')#,lutB,lutB,lutB,lutB,dims=2)') + +lutEnableDACA = ones(Bool, steps_per_frame) + +#enableLUT = collect( cat(lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) +enableLUT = collect( cat(lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) +#enableLUT = collect( cat(lutEnableDACA,dims=2)') #,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) + +seq = SimpleSequence(lut, 300, enableLUT) +sequence!(rp, seq) + +serverMode!(rp, ACQUISITION) +masterTrigger!(rp, true) + +uCurrentPeriod = readFrames(rp, 1, 3) + +masterTrigger!(rp, false) +serverMode!(rp, CONFIGURATION) + +plot = lines(vec(uCurrentPeriod[:,1,:,1]), label = "Rx1") +lines!(plot.axis, vec(uCurrentPeriod[:,2,:,1]), label = "Rx2") +lines!(plot.axis, vec(uCurrentPeriod[:,1,:,2]), label = "Rx1_2") +lines!(plot.axis, vec(uCurrentPeriod[:,2,:,2]), label = "Rx2_2") +axislegend(plot.axis) +save(joinpath(@__DIR__(), "images", "sequenceIssue.png"), plot) +plot \ No newline at end of file From f1130c45fc93992b4046f941dd88dee32ee45656 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Sun, 1 Dec 2024 17:38:51 +0100 Subject: [PATCH 12/38] fix sequence stepper issue --- src/fpga/bd/bd.tcl | 9 +++---- src/fpga/hdl/sequence_stepper.v | 42 +++++++++++++-------------------- src/lib/rp-daq-lib.c | 4 ++-- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index e9ae2bab..494b4cfb 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -2099,7 +2099,6 @@ proc create_hier_cell_sequencer { parentCell nameHier } { # Create pins create_bd_pin -dir I -type clk aclk - create_bd_pin -dir I -from 63 -to 0 adc_sts create_bd_pin -dir I -type rst aresetn create_bd_pin -dir I bram_aresetn create_bd_pin -dir I -from 31 -to 0 cfg_data @@ -2220,6 +2219,9 @@ proc create_hier_cell_sequencer { parentCell nameHier } { # Create instance: xlconstant_0, and set properties set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] + # Create instance: xlslice_0, and set properties + set xlslice_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_0 ] + # Create instance: zero_constant, and set properties set zero_constant [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 zero_constant ] set_property -dict [ list \ @@ -2240,7 +2242,6 @@ proc create_hier_cell_sequencer { parentCell nameHier } { # Create port connections connect_bd_net -net aclk_1 [get_bd_pins aclk] [get_bd_pins axi_bram_ctrl_0/s_axi_aclk] [get_bd_pins blk_mem_gen_0/clkb] [get_bd_pins sequence_slice_0/clk] [get_bd_pins sequence_stepper_0/clk] - connect_bd_net -net adc_sts_1 [get_bd_pins adc_sts] [get_bd_pins sequence_stepper_0/writepointer] connect_bd_net -net aresetn3_1 [get_bd_pins keep_alive_aresetn] [get_bd_pins util_vector_logic_0/Op2] connect_bd_net -net blk_mem_gen_0_doutb [get_bd_pins blk_mem_gen_0/doutb] [get_bd_pins sequence_slice_0/seq_data] connect_bd_net -net bram_aresetn_1 [get_bd_pins bram_aresetn] [get_bd_pins axi_bram_ctrl_0/s_axi_aresetn] @@ -2267,7 +2268,7 @@ proc create_hier_cell_sequencer { parentCell nameHier } { connect_bd_net -net xlconcat_0_dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconcat_1_dout [get_bd_pins oa_dac] [get_bd_pins xlconcat_1/dout] connect_bd_net -net xlconstant_0_dout [get_bd_pins blk_mem_gen_0/enb] [get_bd_pins xlconstant_0/dout] - connect_bd_net -net xlslice_1_Dout [get_bd_pins pdm_sts] [get_bd_pins bram_element_slice/Din] [get_bd_pins sequence_stepper_0/step_counter] + connect_bd_net -net xlslice_1_Dout [get_bd_pins pdm_sts] [get_bd_pins bram_element_slice/Din] [get_bd_pins sequence_stepper_0/step_counter] [get_bd_pins xlslice_0/Din] connect_bd_net -net zero_constant1_dout [get_bd_pins concat_element_addr/In0] [get_bd_pins zero_constant1/dout] connect_bd_net -net zero_constant_dout [get_bd_pins concat_element_addr/In2] [get_bd_pins zero_constant/dout] @@ -3436,7 +3437,7 @@ proc create_root_design { parentCell } { connect_bd_net -net util_vector_logic_0_Res [get_bd_pins clk_wiz_0/clk_in_sel] [get_bd_pins reset_manager_0/isMaster] [get_bd_pins util_vector_logic_0/Res] connect_bd_net -net write_to_ram_adc_out_A [get_bd_pins counter_trigger/adc0] [get_bd_pins write_to_ram/adc_out_A] connect_bd_net -net write_to_ram_adc_out_B [get_bd_pins counter_trigger/adc1] [get_bd_pins write_to_ram/adc_out_B] - connect_bd_net -net xlconcat_0_dout [get_bd_pins sequencer/adc_sts] [get_bd_pins system/adc_sts] [get_bd_pins write_to_ram/sts_data] + connect_bd_net -net xlconcat_0_dout [get_bd_pins system/adc_sts] [get_bd_pins write_to_ram/sts_data] connect_bd_net -net xlconcat_0_dout1 [get_bd_ports dac_pwm_o] [get_bd_pins sequencer/dout] connect_bd_net -net xlconcat_1_dout [get_bd_pins counter_trigger/counter_trigger_sts] [get_bd_pins system/counter_trigger_sts] connect_bd_net -net xlconstant_0_dout [get_bd_ports ext_DIO1_N] [get_bd_pins xlconstant_0/dout] diff --git a/src/fpga/hdl/sequence_stepper.v b/src/fpga/hdl/sequence_stepper.v index 25754421..2431364e 100644 --- a/src/fpga/hdl/sequence_stepper.v +++ b/src/fpga/hdl/sequence_stepper.v @@ -1,45 +1,37 @@ `timescale 1ns / 1ps module sequence_stepper( - input [63:0] writePointer, input [31:0] stepSize, input clk, input aresetn, - output [31:0] seq_counter + output [31:0] step_counter ); -reg [31:0] stepSize_int; -reg [31:0] seq_counter_state; -reg [31:0] sample_counter; -reg wp_prev, wp_next; +reg [63:0] step_counter_local, step_counter_local_next; +reg [31:0] step_counter_reg, step_counter_next; +reg [31:0] step_size_local; always @(posedge clk) begin - stepSize_int <= stepSize; - wp_next <= writePointer[0]; if (~aresetn) begin - seq_counter_state <= 0; - sample_counter <= stepSize_int; - wp_prev <= 0; + step_counter_reg <= 0; + step_counter_next <= 0; + step_counter_local <= 0; + step_counter_local_next <= 0; + step_size_local <= stepSize-1; end else begin - wp_prev <= wp_next; - if (wp_prev != wp_next) begin - - if (sample_counter == 0) begin - sample_counter <= stepSize_int; - seq_counter_state <= seq_counter_state + 1; - end else begin - sample_counter <= sample_counter - 1; - seq_counter_state <= seq_counter_state; - end - + step_counter_reg <= step_counter_next; + step_counter_local <= step_counter_local_next; + if (step_counter_local == step_size_local) begin + step_counter_local_next <= 0; + step_counter_next <= step_counter_reg + 1; end else begin - sample_counter <= sample_counter; - seq_counter_state <= seq_counter_state; + step_counter_local_next <= step_counter_local + 1; + step_counter_next <= step_counter_reg; end end end -assign seq_counter = seq_counter_state; +assign step_counter = step_counter_reg; endmodule diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index fe6eff16..2e3ecc12 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -777,11 +777,11 @@ int setPDMAllValuesVolt(float voltage, int channel) { int getSamplesPerStep() { int32_t value = *((int32_t *)(cfg + 4)); - return value; + return value*2/getDecimation(); } int setSamplesPerStep(int samples) { - *((int32_t *)(cfg + 4)) = samples; + *((int32_t *)(cfg + 4)) = samples/2*getDecimation(); return 0; } From d5e364e9230d7b101d87aeb5207cb4ba4d439ca9 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 14:53:27 +0100 Subject: [PATCH 13/38] first version of hbridge --- src/client/julia/src/SlowIO.jl | 40 +++ src/examples/julia/config.jl | 2 + src/examples/julia/sequenceIssue.jl | 17 +- src/fpga/bd/bd.tcl | 404 ++++++++++++++++++++++------ src/fpga/bd/hbridgewaveform.tcl | 357 ++++++++++++++++++++++++ src/fpga/build.tcl | 1 + src/fpga/hdl/hbridge_signalgen.v | 82 ++++++ 7 files changed, 817 insertions(+), 86 deletions(-) create mode 100644 src/fpga/bd/hbridgewaveform.tcl create mode 100644 src/fpga/hdl/hbridge_signalgen.v diff --git a/src/client/julia/src/SlowIO.jl b/src/client/julia/src/SlowIO.jl index f3c80011..26fcd3f4 100644 --- a/src/client/julia/src/SlowIO.jl +++ b/src/client/julia/src/SlowIO.jl @@ -182,3 +182,43 @@ end scpiCommand(::typeof(DIO), pin) = string("RP:DIO:", DIOPinToCommand(pin), "?") scpiReturn(::typeof(DIO)) = String parseReturn(::typeof(DIO), ret) = occursin("ON", ret) + + + + + + +export DIOHBridge! +""" +DIOHBridge!(rp::RedPitaya, pin::DIOPins, val::Bool) + +Set the value of DIOHBridge pin `pin` to the value `val`. +# Example +```julia +julia> DIOHBridge!(rp, DIO7_P, true) +true +``` +""" +function DIOHBridge!(rp::RedPitaya, pin, val) + return query(rp, scpiCommand(DIOHBridge!, pin, val), scpiReturn(DIOHBridge!)) +end +scpiCommand(::typeof(DIOHBridge!), pin::DIOPins, val::Bool) = string("RP:DIO:", DIOPinToCommand(pin), ":HBRIDGE ", (val ? "ON" : "OFF")) +scpiReturn(::typeof(DIOHBridge!)) = Bool + +export DIOHBridge +""" + DIOHBridge(rp::RedPitaya, pin::DIOPins) + +Get the value of DIOHBridge pin `pin`. +# Example +```julia +julia>DIOHBridge(rp, DIO7_P) +true +``` +""" +function DIOHBridge(rp::RedPitaya, pin) + return parseReturn(DIOHBridge, query(rp, scpiCommand(DIOHBridge, pin), scpiReturn(DIOHBridge))) +end +scpiCommand(::typeof(DIOHBridge), pin) = string("RP:DIO:", DIOPinToCommand(pin), ":HBRIDGE?") +scpiReturn(::typeof(DIOHBridge)) = String +parseReturn(::typeof(DIOHBridge), ret) = occursin("ON", ret) \ No newline at end of file diff --git a/src/examples/julia/config.jl b/src/examples/julia/config.jl index 5ec9b3a0..8d5f511a 100644 --- a/src/examples/julia/config.jl +++ b/src/examples/julia/config.jl @@ -1,3 +1,5 @@ # URLs= ["rp-f08ccb.local", "rp-f08caa.local"] URLs= ["192.168.2.22"]#, "192.168.2.17"] +URLs= ["192.168.178.65"]#, "192.168.178.95"] + mkpath("images") \ No newline at end of file diff --git a/src/examples/julia/sequenceIssue.jl b/src/examples/julia/sequenceIssue.jl index 5d387cb8..021d2a1a 100644 --- a/src/examples/julia/sequenceIssue.jl +++ b/src/examples/julia/sequenceIssue.jl @@ -11,7 +11,7 @@ serverMode!(rp, CONFIGURATION) dec = 128 base_frequency = 125000000 -samples_per_step = 40 #30*16 +samples_per_step = 4000 #30*16 steps_per_frame = 4 numSamples = steps_per_frame * samples_per_step @@ -21,9 +21,10 @@ periodsPerFrame!(rp, numSamples) samplesPerStep!(rp, samples_per_step) triggerMode!(rp, INTERNAL) - -amplitudeDAC!(rp, 1, 1, 0.0) -amplitudeDAC!(rp, 2, 1, 0.0 ) +frequencyDAC!(rp, 1, 1, base_frequency/samples_per_step/dec) +frequencyDAC!(rp, 2, 1, base_frequency/samples_per_step/dec) +amplitudeDAC!(rp, 1, 1, 0.2) +amplitudeDAC!(rp, 2, 1, 0.2 ) clearSequence!(rp) @@ -40,21 +41,21 @@ lutEnableDACA = ones(Bool, steps_per_frame) enableLUT = collect( cat(lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) #enableLUT = collect( cat(lutEnableDACA,dims=2)') #,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) -seq = SimpleSequence(lut, 300, enableLUT) +seq = SimpleSequence(lut, 2, enableLUT) sequence!(rp, seq) serverMode!(rp, ACQUISITION) masterTrigger!(rp, true) -uCurrentPeriod = readFrames(rp, 1, 3) +uCurrentPeriod = readFrames(rp, 1, 200) masterTrigger!(rp, false) serverMode!(rp, CONFIGURATION) plot = lines(vec(uCurrentPeriod[:,1,:,1]), label = "Rx1") lines!(plot.axis, vec(uCurrentPeriod[:,2,:,1]), label = "Rx2") -lines!(plot.axis, vec(uCurrentPeriod[:,1,:,2]), label = "Rx1_2") -lines!(plot.axis, vec(uCurrentPeriod[:,2,:,2]), label = "Rx2_2") +#lines!(plot.axis, vec(uCurrentPeriod[:,1,:,2]), label = "Rx1_2") +#lines!(plot.axis, vec(uCurrentPeriod[:,2,:,2]), label = "Rx2_2") axislegend(plot.axis) save(joinpath(@__DIR__(), "images", "sequenceIssue.png"), plot) plot \ No newline at end of file diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 494b4cfb..9576f109 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -47,7 +47,7 @@ if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { # The design that will be created by this Tcl script contains the following # block design container source references: -# signal_calib, signal_ramp, waveform_gen +# hbridgewaveform, signal_calib, signal_ramp, waveform_gen # Please add the sources before sourcing this Tcl script. @@ -227,7 +227,7 @@ wave_awg_composer\ # CHECK Block Design Container Sources ################################################################## set bCheckSources 1 -set list_bdc_active "signal_calib, signal_ramp, waveform_gen" +set list_bdc_active "hbridgewaveform, signal_calib, signal_ramp, waveform_gen" array set map_bdc_missing {} set map_bdc_missing(ACTIVE) "" @@ -235,6 +235,7 @@ set map_bdc_missing(BDC) "" if { $bCheckSources == 1 } { set list_check_srcs "\ +hbridgewaveform \ signal_calib \ signal_ramp \ waveform_gen \ @@ -885,16 +886,8 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { CONFIG.LOCK_PROPAGATE {0} \ ] $waveform_gen_2 - # Create instance: waveform_gen_3, and set properties - set waveform_gen_3 [ create_bd_cell -type container -reference waveform_gen waveform_gen_3 ] - set_property -dict [ list \ - CONFIG.ACTIVE_SIM_BD {waveform_gen.bd} \ - CONFIG.ACTIVE_SYNTH_BD {waveform_gen.bd} \ - CONFIG.ENABLE_DFX {0} \ - CONFIG.LIST_SIM_BD {waveform_gen.bd} \ - CONFIG.LIST_SYNTH_BD {waveform_gen.bd} \ - CONFIG.LOCK_PROPAGATE {0} \ - ] $waveform_gen_3 + # Create instance: xlconstant_0, and set properties + set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] # Create interface connections connect_bd_intf_net -intf_net awg_bram_1 [get_bd_intf_pins awg_bram] [get_bd_intf_pins waveform_awg1/S_AXI] @@ -902,12 +895,12 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { # Create port connections connect_bd_net -net Din_1 [get_bd_pins Din] [get_bd_pins signal_cfg_slice_0/cfg_data] connect_bd_net -net bram_aresetn_1 [get_bd_pins bram_aresetn] [get_bd_pins waveform_awg1/bram_aresetn] - connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp_0/aclk] [get_bd_pins waveform_awg1/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] [get_bd_pins waveform_gen_3/aclk] + connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp_0/aclk] [get_bd_pins waveform_awg1/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net enable_ramping_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp_0/enableRamping] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] - connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] - connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_pins aresetn] [get_bd_pins signal_ramp_0/aresetn] [get_bd_pins waveform_awg1/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] [get_bd_pins waveform_gen_3/aresetn] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] + connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_pins aresetn] [get_bd_pins signal_ramp_0/aresetn] [get_bd_pins waveform_awg1/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] @@ -925,10 +918,8 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { connect_bd_net -net signal_cfg_slice_0_comp_2_cfg [get_bd_pins signal_cfg_slice_0/comp_2_cfg] [get_bd_pins waveform_gen_2/cfg_data] connect_bd_net -net signal_cfg_slice_0_comp_2_freq [get_bd_pins signal_cfg_slice_0/comp_2_freq] [get_bd_pins waveform_gen_2/freq] connect_bd_net -net signal_cfg_slice_0_comp_2_phase [get_bd_pins signal_cfg_slice_0/comp_2_phase] [get_bd_pins waveform_gen_2/phase] - connect_bd_net -net signal_cfg_slice_0_comp_3_amp [get_bd_pins signal_cfg_slice_0/comp_3_amp] [get_bd_pins waveform_gen_3/amplitude] - connect_bd_net -net signal_cfg_slice_0_comp_3_cfg [get_bd_pins signal_cfg_slice_0/comp_3_cfg] [get_bd_pins waveform_gen_3/cfg_data] - connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg1/freq] [get_bd_pins waveform_gen_3/freq] - connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg1/phase] [get_bd_pins waveform_gen_3/phase] + connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg1/freq] + connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg1/phase] connect_bd_net -net signal_cfg_slice_0_offset [get_bd_pins signal_cfg_slice_0/offset] [get_bd_pins signal_composer_0/offset] connect_bd_net -net signal_cfg_slice_0_ramp_freq [get_bd_pins signal_cfg_slice_0/ramp_freq] [get_bd_pins signal_ramp_0/freq] connect_bd_net -net signal_composer_0_signal_out [get_bd_pins signal_composer_0/signal_out] [get_bd_pins signal_ramp_0/signal_in] @@ -943,7 +934,7 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { connect_bd_net -net waveform_gen_1_wave [get_bd_pins signal_composer_0/wave1] [get_bd_pins waveform_gen_1/wave] connect_bd_net -net waveform_gen_2_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid2] [get_bd_pins waveform_gen_2/m_axis_data_tvalid_1] connect_bd_net -net waveform_gen_2_wave [get_bd_pins signal_composer_0/wave2] [get_bd_pins waveform_gen_2/wave] - connect_bd_net -net waveform_gen_3_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid3] [get_bd_pins waveform_gen_3/m_axis_data_tvalid_1] + connect_bd_net -net xlconstant_0_dout [get_bd_pins signal_composer_0/valid3] [get_bd_pins xlconstant_0/dout] # Restore current instance current_bd_instance $oldCurInst @@ -1081,29 +1072,21 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { CONFIG.LOCK_PROPAGATE {0} \ ] $waveform_gen_2 - # Create instance: waveform_gen_3, and set properties - set waveform_gen_3 [ create_bd_cell -type container -reference waveform_gen waveform_gen_3 ] - set_property -dict [ list \ - CONFIG.ACTIVE_SIM_BD {waveform_gen.bd} \ - CONFIG.ACTIVE_SYNTH_BD {waveform_gen.bd} \ - CONFIG.ENABLE_DFX {0} \ - CONFIG.LIST_SIM_BD {waveform_gen.bd} \ - CONFIG.LIST_SYNTH_BD {waveform_gen.bd} \ - CONFIG.LOCK_PROPAGATE {0} \ - ] $waveform_gen_3 + # Create instance: xlconstant_0, and set properties + set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] # Create interface connections connect_bd_intf_net -intf_net awg_bram_1 [get_bd_intf_pins awg_bram] [get_bd_intf_pins waveform_awg/S_AXI] # Create port connections connect_bd_net -net Din_1 [get_bd_pins Din] [get_bd_pins signal_cfg_slice_0/cfg_data] - connect_bd_net -net aclk_1 [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp/aclk] [get_bd_pins waveform_awg/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] [get_bd_pins waveform_gen_3/aclk] - connect_bd_net -net aresetn_1 [get_bd_pins aresetn] [get_bd_pins signal_ramp/aresetn] [get_bd_pins waveform_awg/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] [get_bd_pins waveform_gen_3/aresetn] + connect_bd_net -net aclk_1 [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp/aclk] [get_bd_pins waveform_awg/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] + connect_bd_net -net aresetn_1 [get_bd_pins aresetn] [get_bd_pins signal_ramp/aresetn] [get_bd_pins waveform_awg/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] connect_bd_net -net bram_aresetn_1 [get_bd_pins bram_aresetn] [get_bd_pins waveform_awg/bram_aresetn] connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] connect_bd_net -net ramping_enable_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp/enableRamping] - connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] @@ -1121,10 +1104,8 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { connect_bd_net -net signal_cfg_slice_0_comp_2_cfg [get_bd_pins signal_cfg_slice_0/comp_2_cfg] [get_bd_pins waveform_gen_2/cfg_data] connect_bd_net -net signal_cfg_slice_0_comp_2_freq [get_bd_pins signal_cfg_slice_0/comp_2_freq] [get_bd_pins waveform_gen_2/freq] connect_bd_net -net signal_cfg_slice_0_comp_2_phase [get_bd_pins signal_cfg_slice_0/comp_2_phase] [get_bd_pins waveform_gen_2/phase] - connect_bd_net -net signal_cfg_slice_0_comp_3_amp [get_bd_pins signal_cfg_slice_0/comp_3_amp] [get_bd_pins waveform_gen_3/amplitude] - connect_bd_net -net signal_cfg_slice_0_comp_3_cfg [get_bd_pins signal_cfg_slice_0/comp_3_cfg] [get_bd_pins waveform_gen_3/cfg_data] - connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg/freq] [get_bd_pins waveform_gen_3/freq] - connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg/phase] [get_bd_pins waveform_gen_3/phase] + connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg/freq] + connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg/phase] connect_bd_net -net signal_cfg_slice_0_offset [get_bd_pins signal_cfg_slice_0/offset] [get_bd_pins signal_composer_0/offset] connect_bd_net -net signal_cfg_slice_0_ramp_freq [get_bd_pins signal_cfg_slice_0/ramp_freq] [get_bd_pins signal_ramp/freq] connect_bd_net -net signal_composer_0_signal_out [get_bd_pins signal_composer_0/signal_out] [get_bd_pins signal_ramp/signal_in] @@ -1139,7 +1120,7 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { connect_bd_net -net waveform_gen_1_wave [get_bd_pins signal_composer_0/wave1] [get_bd_pins waveform_gen_1/wave] connect_bd_net -net waveform_gen_2_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid2] [get_bd_pins waveform_gen_2/m_axis_data_tvalid_1] connect_bd_net -net waveform_gen_2_wave [get_bd_pins signal_composer_0/wave2] [get_bd_pins waveform_gen_2/wave] - connect_bd_net -net waveform_gen_3_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid3] [get_bd_pins waveform_gen_3/m_axis_data_tvalid_1] + connect_bd_net -net xlconstant_0_dout [get_bd_pins signal_composer_0/valid3] [get_bd_pins xlconstant_0/dout] # Restore current instance current_bd_instance $oldCurInst @@ -2696,9 +2677,12 @@ proc create_hier_cell_DIO { parentCell nameHier } { # Create interface pins # Create pins + create_bd_pin -dir I aresetn + create_bd_pin -dir I -from 1663 -to 0 cfg_dac create_bd_pin -dir I -from 95 -to 0 cfg_in create_bd_pin -dir I -type clk clk create_bd_pin -dir O -from 31 -to 0 dio_data_clocked + create_bd_pin -dir I -from 1 -to 0 enable_dac create_bd_pin -dir IO ext_DIO2_N create_bd_pin -dir IO ext_DIO3_N create_bd_pin -dir IO ext_DIO4_N @@ -2707,29 +2691,30 @@ proc create_hier_cell_DIO { parentCell nameHier } { create_bd_pin -dir IO ext_DIO6_P create_bd_pin -dir IO ext_DIO7_N create_bd_pin -dir IO ext_DIO7_P + create_bd_pin -dir I -from 1 -to 0 resync + + # Create instance: hbridgewaveform_0, and set properties + set hbridgewaveform_0 [ create_bd_cell -type container -reference hbridgewaveform hbridgewaveform_0 ] + set_property -dict [ list \ + CONFIG.ACTIVE_SIM_BD {hbridgewaveform.bd} \ + CONFIG.ACTIVE_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.ENABLE_DFX {0} \ + CONFIG.LIST_SIM_BD {hbridgewaveform.bd} \ + CONFIG.LIST_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.LOCK_PROPAGATE {0} \ + ] $hbridgewaveform_0 + + # Create instance: hbridgewaveform_1, and set properties + set hbridgewaveform_1 [ create_bd_cell -type container -reference hbridgewaveform hbridgewaveform_1 ] + set_property -dict [ list \ + CONFIG.ACTIVE_SIM_BD {hbridgewaveform.bd} \ + CONFIG.ACTIVE_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.ENABLE_DFX {0} \ + CONFIG.LIST_SIM_BD {hbridgewaveform.bd} \ + CONFIG.LIST_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.LOCK_PROPAGATE {0} \ + ] $hbridgewaveform_1 - # Create instance: rp_iobuf_0, and set properties - set block_name rp_iobuf - set block_cell_name rp_iobuf_0 - if { [catch {set rp_iobuf_0 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { - catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } elseif { $rp_iobuf_0 eq "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } - - # Create instance: rp_iobuf_1, and set properties - set block_name rp_iobuf - set block_cell_name rp_iobuf_1 - if { [catch {set rp_iobuf_1 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { - catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } elseif { $rp_iobuf_1 eq "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } - # Create instance: rp_iobuf_2, and set properties set block_name rp_iobuf set block_cell_name rp_iobuf_2 @@ -2796,6 +2781,92 @@ proc create_hier_cell_DIO { parentCell nameHier } { return 1 } + # Create instance: rp_iobuf_8, and set properties + set block_name rp_iobuf + set block_cell_name rp_iobuf_8 + if { [catch {set rp_iobuf_8 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { + catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } elseif { $rp_iobuf_8 eq "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } + + # Create instance: rp_iobuf_9, and set properties + set block_name rp_iobuf + set block_cell_name rp_iobuf_9 + if { [catch {set rp_iobuf_9 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { + catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } elseif { $rp_iobuf_9 eq "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } + + # Create instance: util_vector_logic_0, and set properties + set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {and} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_andgate.png} \ + ] $util_vector_logic_0 + + # Create instance: util_vector_logic_1, and set properties + set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_1 + + # Create instance: util_vector_logic_2, and set properties + set util_vector_logic_2 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_2 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_2 + + # Create instance: util_vector_logic_3, and set properties + set util_vector_logic_3 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_3 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_3 + + # Create instance: util_vector_logic_4, and set properties + set util_vector_logic_4 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_4 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_4 + + # Create instance: util_vector_logic_5, and set properties + set util_vector_logic_5 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_5 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_5 + + # Create instance: util_vector_logic_6, and set properties + set util_vector_logic_6 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_6 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {and} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_andgate.png} \ + ] $util_vector_logic_6 + + # Create instance: util_vector_logic_7, and set properties + set util_vector_logic_7 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_7 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_7 + # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] set_property -dict [ list \ @@ -2965,6 +3036,150 @@ proc create_hier_cell_DIO { parentCell nameHier } { CONFIG.DOUT_WIDTH {1} \ ] $xlslice_17 + # Create instance: xlslice_18, and set properties + set xlslice_18 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_18 ] + set_property -dict [ list \ + CONFIG.DIN_WIDTH {2} \ + ] $xlslice_18 + + # Create instance: xlslice_19, and set properties + set xlslice_19 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_19 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {175} \ + CONFIG.DIN_TO {128} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_19 + + # Create instance: xlslice_20, and set properties + set xlslice_20 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_20 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {239} \ + CONFIG.DIN_TO {192} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_20 + + # Create instance: xlslice_21, and set properties + set xlslice_21 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_21 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {127} \ + CONFIG.DIN_TO {112} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {16} \ + ] $xlslice_21 + + # Create instance: xlslice_22, and set properties + set xlslice_22 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_22 ] + set_property -dict [ list \ + CONFIG.DIN_WIDTH {2} \ + ] $xlslice_22 + + # Create instance: xlslice_23, and set properties + set xlslice_23 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_23 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {95} \ + CONFIG.DIN_TO {88} \ + CONFIG.DIN_WIDTH {96} \ + CONFIG.DOUT_WIDTH {8} \ + ] $xlslice_23 + + # Create instance: xlslice_24, and set properties + set xlslice_24 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_24 ] + set_property -dict [ list \ + CONFIG.DIN_WIDTH {8} \ + ] $xlslice_24 + + # Create instance: xlslice_25, and set properties + set xlslice_25 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_25 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {8} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_25 + + # Create instance: xlslice_26, and set properties + set xlslice_26 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_26 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {175} \ + CONFIG.DIN_TO {128} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_26 + + # Create instance: xlslice_27, and set properties + set xlslice_27 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_27 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {239} \ + CONFIG.DIN_TO {192} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_27 + + # Create instance: xlslice_28, and set properties + set xlslice_28 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_28 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {127} \ + CONFIG.DIN_TO {112} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {16} \ + ] $xlslice_28 + + # Create instance: xlslice_29, and set properties + set xlslice_29 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_29 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {2} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_29 + + # Create instance: xlslice_30, and set properties + set xlslice_30 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_30 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1663} \ + CONFIG.DIN_TO {832} \ + CONFIG.DIN_WIDTH {1664} \ + CONFIG.DOUT_WIDTH {832} \ + ] $xlslice_30 + + # Create instance: xlslice_31, and set properties + set xlslice_31 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_31 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {831} \ + CONFIG.DIN_TO {0} \ + CONFIG.DIN_WIDTH {1664} \ + CONFIG.DOUT_WIDTH {832} \ + ] $xlslice_31 + + # Create instance: xlslice_32, and set properties + set xlslice_32 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_32 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {2} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_32 + + # Create instance: xlslice_33, and set properties + set xlslice_33 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_33 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {2} \ + CONFIG.DIN_TO {2} \ + CONFIG.DIN_WIDTH {8} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_33 + + # Create instance: xlslice_34, and set properties + set xlslice_34 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_34 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {3} \ + CONFIG.DIN_TO {3} \ + CONFIG.DIN_WIDTH {8} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_34 + # Create port connections connect_bd_net -net Net [get_bd_pins ext_DIO6_P] [get_bd_pins rp_iobuf_2/val_tri] connect_bd_net -net Net1 [get_bd_pins ext_DIO6_N] [get_bd_pins rp_iobuf_3/val_tri] @@ -2972,38 +3187,71 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net Net3 [get_bd_pins ext_DIO4_N] [get_bd_pins rp_iobuf_5/val_tri] connect_bd_net -net Net4 [get_bd_pins ext_DIO3_N] [get_bd_pins rp_iobuf_6/val_tri] connect_bd_net -net Net5 [get_bd_pins ext_DIO2_N] [get_bd_pins rp_iobuf_7/val_tri] - connect_bd_net -net Net6 [get_bd_pins ext_DIO7_P] [get_bd_pins rp_iobuf_0/val_tri] - connect_bd_net -net Net7 [get_bd_pins ext_DIO7_N] [get_bd_pins rp_iobuf_1/val_tri] - connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins clk] [get_bd_pins rp_iobuf_0/clk] [get_bd_pins rp_iobuf_1/clk] [get_bd_pins rp_iobuf_2/clk] [get_bd_pins rp_iobuf_3/clk] [get_bd_pins rp_iobuf_4/clk] [get_bd_pins rp_iobuf_5/clk] [get_bd_pins rp_iobuf_6/clk] [get_bd_pins rp_iobuf_7/clk] - connect_bd_net -net rp_iobuf_0_val_in_clocked [get_bd_pins rp_iobuf_0/val_in_clocked] [get_bd_pins xlconcat_0/In0] - connect_bd_net -net rp_iobuf_1_val_in_clocked [get_bd_pins rp_iobuf_1/val_in_clocked] [get_bd_pins xlconcat_0/In1] + connect_bd_net -net Net6 [get_bd_pins ext_DIO7_P] [get_bd_pins rp_iobuf_8/val_tri] + connect_bd_net -net Net7 [get_bd_pins ext_DIO7_N] [get_bd_pins rp_iobuf_9/val_tri] + connect_bd_net -net aresetn_1 [get_bd_pins aresetn] [get_bd_pins hbridgewaveform_0/aresetn] [get_bd_pins hbridgewaveform_1/aresetn] + connect_bd_net -net cfg_dac_1 [get_bd_pins cfg_dac] [get_bd_pins xlslice_30/Din] [get_bd_pins xlslice_31/Din] + connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins clk] [get_bd_pins hbridgewaveform_0/aclk] [get_bd_pins hbridgewaveform_1/aclk] [get_bd_pins rp_iobuf_2/clk] [get_bd_pins rp_iobuf_3/clk] [get_bd_pins rp_iobuf_4/clk] [get_bd_pins rp_iobuf_5/clk] [get_bd_pins rp_iobuf_6/clk] [get_bd_pins rp_iobuf_7/clk] [get_bd_pins rp_iobuf_8/clk] [get_bd_pins rp_iobuf_9/clk] + connect_bd_net -net enable_dac_1 [get_bd_pins enable_dac] [get_bd_pins xlslice_18/Din] [get_bd_pins xlslice_32/Din] + connect_bd_net -net enable_dac_2 [get_bd_pins hbridgewaveform_1/enable_dac] [get_bd_pins util_vector_logic_6/Res] + connect_bd_net -net hbridgewaveform_0_H1out [get_bd_pins hbridgewaveform_0/H1out] [get_bd_pins util_vector_logic_2/Op2] + connect_bd_net -net hbridgewaveform_0_H2out [get_bd_pins hbridgewaveform_0/H2out] [get_bd_pins util_vector_logic_3/Op2] + connect_bd_net -net hbridgewaveform_1_H1out [get_bd_pins hbridgewaveform_1/H1out] [get_bd_pins util_vector_logic_4/Op2] + connect_bd_net -net hbridgewaveform_1_H2out [get_bd_pins hbridgewaveform_1/H2out] [get_bd_pins util_vector_logic_5/Op2] + connect_bd_net -net resync_1 [get_bd_pins resync] [get_bd_pins xlslice_22/Din] [get_bd_pins xlslice_29/Din] connect_bd_net -net rp_iobuf_2_val_in_clocked [get_bd_pins rp_iobuf_2/val_in_clocked] [get_bd_pins xlconcat_0/In2] connect_bd_net -net rp_iobuf_3_val_in_clocked [get_bd_pins rp_iobuf_3/val_in_clocked] [get_bd_pins xlconcat_0/In3] connect_bd_net -net rp_iobuf_4_val_in_clocked [get_bd_pins rp_iobuf_4/val_in_clocked] [get_bd_pins xlconcat_0/In4] connect_bd_net -net rp_iobuf_5_val_in_clocked [get_bd_pins rp_iobuf_5/val_in_clocked] [get_bd_pins xlconcat_0/In5] connect_bd_net -net rp_iobuf_6_val_in_clocked [get_bd_pins rp_iobuf_6/val_in_clocked] [get_bd_pins xlconcat_0/In6] connect_bd_net -net rp_iobuf_7_val_in_clocked [get_bd_pins rp_iobuf_7/val_in_clocked] [get_bd_pins xlconcat_0/In7] - connect_bd_net -net system_cfg_data1 [get_bd_pins cfg_in] [get_bd_pins xlslice_4/Din] [get_bd_pins xlslice_5/Din] + connect_bd_net -net rp_iobuf_8_val_in_clocked [get_bd_pins rp_iobuf_8/val_in_clocked] [get_bd_pins xlconcat_0/In0] + connect_bd_net -net rp_iobuf_9_val_in_clocked [get_bd_pins rp_iobuf_9/val_in_clocked] [get_bd_pins xlconcat_0/In1] + connect_bd_net -net system_cfg_data1 [get_bd_pins cfg_in] [get_bd_pins xlslice_23/Din] [get_bd_pins xlslice_4/Din] [get_bd_pins xlslice_5/Din] + connect_bd_net -net util_vector_logic_0_Res [get_bd_pins hbridgewaveform_0/enable_dac] [get_bd_pins util_vector_logic_0/Res] + connect_bd_net -net util_vector_logic_1_Res [get_bd_pins util_vector_logic_0/Op1] [get_bd_pins util_vector_logic_1/Res] + connect_bd_net -net util_vector_logic_2_Res [get_bd_pins rp_iobuf_8/val_out] [get_bd_pins util_vector_logic_2/Res] + connect_bd_net -net util_vector_logic_3_Res [get_bd_pins rp_iobuf_9/val_out] [get_bd_pins util_vector_logic_3/Res] + connect_bd_net -net util_vector_logic_4_Res [get_bd_pins rp_iobuf_2/val_out] [get_bd_pins util_vector_logic_4/Res] + connect_bd_net -net util_vector_logic_5_Res [get_bd_pins rp_iobuf_3/val_out] [get_bd_pins util_vector_logic_5/Res] + connect_bd_net -net util_vector_logic_7_Res [get_bd_pins util_vector_logic_6/Op1] [get_bd_pins util_vector_logic_7/Res] connect_bd_net -net xlconcat_0_dout2 [get_bd_pins dio_data_clocked] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconstant_1_dout [get_bd_pins xlconcat_0/In8] [get_bd_pins xlconstant_1/dout] - connect_bd_net -net xlslice_0_Dout [get_bd_pins rp_iobuf_0/val_out] [get_bd_pins xlslice_0/Dout] - connect_bd_net -net xlslice_10_Dout [get_bd_pins rp_iobuf_2/val_out] [get_bd_pins xlslice_10/Dout] - connect_bd_net -net xlslice_11_Dout [get_bd_pins rp_iobuf_3/val_out] [get_bd_pins xlslice_11/Dout] + connect_bd_net -net xlslice_0_Dout [get_bd_pins util_vector_logic_2/Op1] [get_bd_pins xlslice_0/Dout] + connect_bd_net -net xlslice_10_Dout [get_bd_pins util_vector_logic_4/Op1] [get_bd_pins xlslice_10/Dout] + connect_bd_net -net xlslice_11_Dout [get_bd_pins util_vector_logic_5/Op1] [get_bd_pins xlslice_11/Dout] connect_bd_net -net xlslice_12_Dout [get_bd_pins rp_iobuf_4/val_out] [get_bd_pins xlslice_12/Dout] connect_bd_net -net xlslice_13_Dout [get_bd_pins rp_iobuf_5/direction] [get_bd_pins xlslice_13/Dout] connect_bd_net -net xlslice_14_Dout [get_bd_pins rp_iobuf_6/direction] [get_bd_pins xlslice_14/Dout] connect_bd_net -net xlslice_15_Dout [get_bd_pins rp_iobuf_6/val_out] [get_bd_pins xlslice_15/Dout] connect_bd_net -net xlslice_16_Dout [get_bd_pins rp_iobuf_7/val_out] [get_bd_pins xlslice_16/Dout] connect_bd_net -net xlslice_17_Dout [get_bd_pins rp_iobuf_7/direction] [get_bd_pins xlslice_17/Dout] + connect_bd_net -net xlslice_18_Dout [get_bd_pins util_vector_logic_0/Op2] [get_bd_pins xlslice_18/Dout] + connect_bd_net -net xlslice_19_Dout [get_bd_pins hbridgewaveform_0/freq] [get_bd_pins xlslice_19/Dout] connect_bd_net -net xlslice_1_Dout [get_bd_pins rp_iobuf_2/direction] [get_bd_pins xlslice_1/Dout] + connect_bd_net -net xlslice_20_Dout [get_bd_pins hbridgewaveform_0/phase] [get_bd_pins xlslice_20/Dout] + connect_bd_net -net xlslice_21_Dout [get_bd_pins hbridgewaveform_0/pulswidth] [get_bd_pins xlslice_21/Dout] + connect_bd_net -net xlslice_22_Dout [get_bd_pins hbridgewaveform_0/resync] [get_bd_pins xlslice_22/Dout] + connect_bd_net -net xlslice_23_Dout [get_bd_pins xlslice_23/Dout] [get_bd_pins xlslice_24/Din] [get_bd_pins xlslice_25/Din] [get_bd_pins xlslice_33/Din] [get_bd_pins xlslice_34/Din] + connect_bd_net -net xlslice_24_Dout [get_bd_pins util_vector_logic_1/Op2] [get_bd_pins xlslice_24/Dout] + connect_bd_net -net xlslice_25_Dout [get_bd_pins util_vector_logic_1/Op1] [get_bd_pins xlslice_25/Dout] + connect_bd_net -net xlslice_26_Dout [get_bd_pins hbridgewaveform_1/phase] [get_bd_pins xlslice_26/Dout] + connect_bd_net -net xlslice_27_Dout [get_bd_pins hbridgewaveform_1/freq] [get_bd_pins xlslice_27/Dout] + connect_bd_net -net xlslice_28_Dout [get_bd_pins hbridgewaveform_1/pulswidth] [get_bd_pins xlslice_28/Dout] + connect_bd_net -net xlslice_29_Dout [get_bd_pins hbridgewaveform_1/resync] [get_bd_pins xlslice_29/Dout] connect_bd_net -net xlslice_2_Dout [get_bd_pins rp_iobuf_3/direction] [get_bd_pins xlslice_2/Dout] + connect_bd_net -net xlslice_30_Dout [get_bd_pins xlslice_26/Din] [get_bd_pins xlslice_27/Din] [get_bd_pins xlslice_28/Din] [get_bd_pins xlslice_30/Dout] + connect_bd_net -net xlslice_31_Dout [get_bd_pins xlslice_19/Din] [get_bd_pins xlslice_20/Din] [get_bd_pins xlslice_21/Din] [get_bd_pins xlslice_31/Dout] + connect_bd_net -net xlslice_32_Dout [get_bd_pins util_vector_logic_6/Op2] [get_bd_pins xlslice_32/Dout] + connect_bd_net -net xlslice_33_Dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlslice_33/Dout] + connect_bd_net -net xlslice_34_Dout [get_bd_pins util_vector_logic_7/Op2] [get_bd_pins xlslice_34/Dout] connect_bd_net -net xlslice_3_Dout [get_bd_pins rp_iobuf_4/direction] [get_bd_pins xlslice_3/Dout] connect_bd_net -net xlslice_4_Dout [get_bd_pins xlslice_0/Din] [get_bd_pins xlslice_10/Din] [get_bd_pins xlslice_11/Din] [get_bd_pins xlslice_12/Din] [get_bd_pins xlslice_15/Din] [get_bd_pins xlslice_16/Din] [get_bd_pins xlslice_4/Dout] [get_bd_pins xlslice_6/Din] [get_bd_pins xlslice_9/Din] connect_bd_net -net xlslice_5_Dout [get_bd_pins xlslice_1/Din] [get_bd_pins xlslice_13/Din] [get_bd_pins xlslice_14/Din] [get_bd_pins xlslice_17/Din] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] [get_bd_pins xlslice_5/Dout] [get_bd_pins xlslice_7/Din] [get_bd_pins xlslice_8/Din] connect_bd_net -net xlslice_6_Dout [get_bd_pins rp_iobuf_5/val_out] [get_bd_pins xlslice_6/Dout] - connect_bd_net -net xlslice_7_Dout [get_bd_pins rp_iobuf_0/direction] [get_bd_pins xlslice_7/Dout] - connect_bd_net -net xlslice_8_Dout [get_bd_pins rp_iobuf_1/direction] [get_bd_pins xlslice_8/Dout] - connect_bd_net -net xlslice_9_Dout [get_bd_pins rp_iobuf_1/val_out] [get_bd_pins xlslice_9/Dout] + connect_bd_net -net xlslice_7_Dout [get_bd_pins rp_iobuf_8/direction] [get_bd_pins xlslice_7/Dout] + connect_bd_net -net xlslice_8_Dout [get_bd_pins rp_iobuf_9/direction] [get_bd_pins xlslice_8/Dout] + connect_bd_net -net xlslice_9_Dout [get_bd_pins util_vector_logic_3/Op1] [get_bd_pins xlslice_9/Dout] # Restore current instance current_bd_instance $oldCurInst @@ -3369,8 +3617,8 @@ proc create_root_design { parentCell } { connect_bd_net -net Net3 [get_bd_ports ext_DIO3_P] [get_bd_pins reset_manager_0/instant_reset] connect_bd_net -net Net4 [get_bd_ports ext_DIO4_P] [get_bd_pins reset_manager_0/alive_signal] connect_bd_net -net Net5 [get_bd_ports ext_DIO5_P] [get_bd_pins reset_manager_0/master_trigger] - connect_bd_net -net Net6 [get_bd_ports ext_DIO7_P] [get_bd_pins DIO/ext_DIO7_P] - connect_bd_net -net Net7 [get_bd_ports ext_DIO7_N] [get_bd_pins DIO/ext_DIO7_N] + connect_bd_net -net Net6 [get_bd_ports ext_DIO7_N] [get_bd_pins DIO/ext_DIO7_N] + connect_bd_net -net Net7 [get_bd_ports ext_DIO7_P] [get_bd_pins DIO/ext_DIO7_P] connect_bd_net -net Net8 [get_bd_ports ext_DIO6_P] [get_bd_pins DIO/ext_DIO6_P] connect_bd_net -net Net9 [get_bd_ports ext_DIO6_N] [get_bd_pins DIO/ext_DIO6_N] connect_bd_net -net Net10 [get_bd_ports ext_DIO5_N] [get_bd_pins DIO/ext_DIO5_N] @@ -3407,7 +3655,7 @@ proc create_root_design { parentCell } { connect_bd_net -net pdm_oa_dac [get_bd_pins fourier_synth_standard/oa_dac] [get_bd_pins sequencer/oa_dac] connect_bd_net -net pdm_pdm_sts [get_bd_pins sequencer/pdm_sts] [get_bd_pins system/curr_pdm_values] connect_bd_net -net proc_sys_reset_bram_peripheral_aresetn [get_bd_pins fourier_synth_standard/bram_aresetn] [get_bd_pins proc_sys_reset_bram/peripheral_aresetn] [get_bd_pins sequencer/bram_aresetn] - connect_bd_net -net proc_sys_reset_fourier_synth_peripheral_aresetn [get_bd_pins fourier_synth_standard/aresetn] [get_bd_pins proc_sys_reset_fourier_synth/peripheral_aresetn] [get_bd_pins system/aresetn] + connect_bd_net -net proc_sys_reset_fourier_synth_peripheral_aresetn [get_bd_pins DIO/aresetn] [get_bd_pins fourier_synth_standard/aresetn] [get_bd_pins proc_sys_reset_fourier_synth/peripheral_aresetn] [get_bd_pins system/aresetn] connect_bd_net -net proc_sys_reset_pdm_peripheral_aresetn [get_bd_pins proc_sys_reset_pdm/peripheral_aresetn] [get_bd_pins sequencer/aresetn] connect_bd_net -net proc_sys_reset_write_to_ram_peripheral_aresetn [get_bd_pins proc_sys_reset_write_to_ram/peripheral_aresetn] [get_bd_pins write_to_ram/aresetn] connect_bd_net -net proc_sys_reset_xadc_peripheral_aresetn [get_bd_pins proc_sys_reset_xadc/peripheral_aresetn] [get_bd_pins xadc_wiz_0/s_axi_aresetn] @@ -3424,11 +3672,11 @@ proc create_root_design { parentCell } { connect_bd_net -net selectio_wiz_1_data_out_to_pins_p [get_bd_ports daisy_p_o] [get_bd_pins selectio_wiz_1/data_out_to_pins_p] connect_bd_net -net selectio_wiz_2_clk_out [get_bd_pins clk_wiz_1/clk_in1] [get_bd_pins selectio_wiz_2/clk_out] connect_bd_net -net selectio_wiz_2_data_in_to_device [get_bd_pins reset_manager_0/sata_trigger] [get_bd_pins selectio_wiz_2/data_in_to_device] - connect_bd_net -net sequencer_enable_dac [get_bd_pins fourier_synth_standard/enable_dac] [get_bd_pins sequencer/enable_dac] - connect_bd_net -net sequencer_resync_dac [get_bd_pins fourier_synth_standard/resync_dac] [get_bd_pins sequencer/resync_dac] + connect_bd_net -net sequencer_enable_dac [get_bd_pins DIO/enable_dac] [get_bd_pins fourier_synth_standard/enable_dac] [get_bd_pins sequencer/enable_dac] + connect_bd_net -net sequencer_resync_dac [get_bd_pins DIO/resync] [get_bd_pins fourier_synth_standard/resync_dac] [get_bd_pins sequencer/resync_dac] connect_bd_net -net sequencer_seq_ramp_down [get_bd_pins fourier_synth_standard/seq_ramp_down] [get_bd_pins sequencer/seq_ramp_down] connect_bd_net -net system_FCLK_RESET0_N [get_bd_pins system/FCLK_RESET0_N] [get_bd_pins util_vector_logic_1/Op1] - connect_bd_net -net system_cfg_data [get_bd_pins fourier_synth_standard/cfg_data] [get_bd_pins system/dac_cfg] + connect_bd_net -net system_cfg_data [get_bd_pins DIO/cfg_dac] [get_bd_pins fourier_synth_standard/cfg_data] [get_bd_pins system/dac_cfg] connect_bd_net -net system_cfg_data1 [get_bd_pins DIO/cfg_in] [get_bd_pins system/cfg_data] [get_bd_pins xlslice_1/Din] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] [get_bd_pins xlslice_6/Din] connect_bd_net -net system_counter_trigger_cfg [get_bd_pins counter_trigger/counter_trigger_cfg] [get_bd_pins system/counter_trigger_cfg] connect_bd_net -net system_peripheral_aresetn [get_bd_pins reset_manager_0/peripheral_aresetn] [get_bd_pins system/peripheral_aresetn] diff --git a/src/fpga/bd/hbridgewaveform.tcl b/src/fpga/bd/hbridgewaveform.tcl new file mode 100644 index 00000000..12a2d922 --- /dev/null +++ b/src/fpga/bd/hbridgewaveform.tcl @@ -0,0 +1,357 @@ + +################################################################ +# This is a generated script based on design: hbridgewaveform +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2021.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_gid_msg -ssname BD::TCL -id 2041 -severity "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source hbridgewaveform_script.tcl + + +# The design that will be created by this Tcl script contains the following +# module references: +# hbridge_signalgen + +# Please add the sources of those modules before sourcing this Tcl script. + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z010clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name hbridgewaveform + +# This script was generated for a remote BD. To create a non-remote design, +# change the variable to <0>. + +set run_remote_bd_flow 1 +if { $run_remote_bd_flow == 1 } { + # Set the reference directory for source file relative paths (by default + # the value is script directory path) + set origin_dir ./.julia/dev/RedPitayaDAQServer/src/fpga/bd + + # Use origin directory path location variable, if specified in the tcl shell + if { [info exists ::origin_dir_loc] } { + set origin_dir $::origin_dir_loc + } + + set str_bd_folder [file normalize ${origin_dir}] + set str_bd_filepath ${str_bd_folder}/${design_name}/${design_name}.bd + + # Check if remote design exists on disk + if { [file exists $str_bd_filepath ] == 1 } { + catch {common::send_gid_msg -ssname BD::TCL -id 2030 -severity "ERROR" "The remote BD file path <$str_bd_filepath> already exists!"} + common::send_gid_msg -ssname BD::TCL -id 2031 -severity "INFO" "To create a non-remote BD, change the variable to <0>." + common::send_gid_msg -ssname BD::TCL -id 2032 -severity "INFO" "Also make sure there is no design <$design_name> existing in your current project." + + return 1 + } + + # Check if design exists in memory + set list_existing_designs [get_bd_designs -quiet $design_name] + if { $list_existing_designs ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2033 -severity "ERROR" "The design <$design_name> already exists in this project! Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} + + common::send_gid_msg -ssname BD::TCL -id 2034 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." + + return 1 + } + + # Check if design exists on disk within project + set list_existing_designs [get_files -quiet */${design_name}.bd] + if { $list_existing_designs ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2035 -severity "ERROR" "The design <$design_name> already exists in this project at location: + $list_existing_designs"} + catch {common::send_gid_msg -ssname BD::TCL -id 2036 -severity "ERROR" "Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} + + common::send_gid_msg -ssname BD::TCL -id 2037 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." + + return 1 + } + + # Now can create the remote BD + # NOTE - usage of <-dir> will create <$str_bd_folder/$design_name/$design_name.bd> + create_bd_design -dir $str_bd_folder $design_name +} else { + + # Create regular design + if { [catch {create_bd_design $design_name} errmsg] } { + common::send_gid_msg -ssname BD::TCL -id 2038 -severity "INFO" "Please set a different value to variable ." + + return 1 + } +} + +current_bd_design $design_name + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +pavel-demin:user:axis_variable:1.0\ +xilinx.com:ip:dds_compiler:6.0\ +xilinx.com:ip:util_vector_logic:2.0\ +xilinx.com:ip:xlconcat:2.1\ +xilinx.com:ip:xlslice:1.0\ +" + + set list_ips_missing "" + common::send_gid_msg -ssname BD::TCL -id 2011 -severity "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2012 -severity "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +################################################################## +# CHECK Modules +################################################################## +set bCheckModules 1 +if { $bCheckModules == 1 } { + set list_check_mods "\ +hbridge_signalgen\ +" + + set list_mods_missing "" + common::send_gid_msg -ssname BD::TCL -id 2020 -severity "INFO" "Checking if the following modules exist in the project's sources: $list_check_mods ." + + foreach mod_vlnv $list_check_mods { + if { [can_resolve_reference $mod_vlnv] == 0 } { + lappend list_mods_missing $mod_vlnv + } + } + + if { $list_mods_missing ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2021 -severity "ERROR" "The following module(s) are not found in the project: $list_mods_missing" } + common::send_gid_msg -ssname BD::TCL -id 2022 -severity "INFO" "Please add source files for the missing module(s) above." + set bCheckIPsPassed 0 + } +} + +if { $bCheckIPsPassed != 1 } { + common::send_gid_msg -ssname BD::TCL -id 2023 -severity "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2090 -severity "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2091 -severity "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + + # Create ports + set H1out [ create_bd_port -dir O -type data H1out ] + set H2out [ create_bd_port -dir O -type data H2out ] + set aclk [ create_bd_port -dir I -type clk -freq_hz 125000000 aclk ] + set aresetn [ create_bd_port -dir I -type rst aresetn ] + set enable_dac [ create_bd_port -dir I enable_dac ] + set freq [ create_bd_port -dir I -from 47 -to 0 freq ] + set phase [ create_bd_port -dir I -from 47 -to 0 phase ] + set pulswidth [ create_bd_port -dir I -from 15 -to 0 pulswidth ] + set resync [ create_bd_port -dir I resync ] + + # Create instance: axis_variable_A_channel_1, and set properties + set axis_variable_A_channel_1 [ create_bd_cell -type ip -vlnv pavel-demin:user:axis_variable:1.0 axis_variable_A_channel_1 ] + set_property -dict [ list \ + CONFIG.AXIS_TDATA_WIDTH {96} \ + ] $axis_variable_A_channel_1 + + # Create instance: dds_compiler_A_channel_1, and set properties + set dds_compiler_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:dds_compiler:6.0 dds_compiler_A_channel_1 ] + set_property -dict [ list \ + CONFIG.Amplitude_Mode {Full_Range} \ + CONFIG.DATA_Has_TLAST {Not_Required} \ + CONFIG.DDS_Clock_Rate {125} \ + CONFIG.Frequency_Resolution {4.440893e-7} \ + CONFIG.Has_ACLKEN {false} \ + CONFIG.Has_ARESETn {true} \ + CONFIG.Has_Phase_Out {true} \ + CONFIG.Has_TREADY {false} \ + CONFIG.Latency {2} \ + CONFIG.Latency_Configuration {Auto} \ + CONFIG.M_DATA_Has_TUSER {Not_Required} \ + CONFIG.M_PHASE_Has_TUSER {Not_Required} \ + CONFIG.Noise_Shaping {None} \ + CONFIG.Output_Frequency1 {0} \ + CONFIG.Output_Selection {Sine} \ + CONFIG.Output_Width {3} \ + CONFIG.PINC1 {0} \ + CONFIG.POFF1 {0} \ + CONFIG.Parameter_Entry {Hardware_Parameters} \ + CONFIG.PartsPresent {Phase_Generator_only} \ + CONFIG.Phase_Increment {Programmable} \ + CONFIG.Phase_Offset_Angles1 {0} \ + CONFIG.Phase_Width {48} \ + CONFIG.Phase_offset {Programmable} \ + CONFIG.Resync {false} \ + CONFIG.S_PHASE_Has_TUSER {Not_Required} \ + CONFIG.Spurious_Free_Dynamic_Range {88} \ + ] $dds_compiler_A_channel_1 + + # Create instance: hbridge_signalgen_0_upgraded_ipi, and set properties + set block_name hbridge_signalgen + set block_cell_name hbridge_signalgen_0_upgraded_ipi + if { [catch {set hbridge_signalgen_0_upgraded_ipi [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { + catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } elseif { $hbridge_signalgen_0_upgraded_ipi eq "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } + set_property -dict [ list \ + CONFIG.AXIS_TDATA_PHASE_WIDTH {48} \ + CONFIG.CFG_DATA_WIDTH {14} \ + ] $hbridge_signalgen_0_upgraded_ipi + + # Create instance: util_vector_logic_0, and set properties + set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {not} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_notgate.png} \ + ] $util_vector_logic_0 + + # Create instance: util_vector_logic_1, and set properties + set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_1 + + # Create instance: xlconcat_A_channel_1, and set properties + set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] + set_property -dict [ list \ + CONFIG.IN0_WIDTH {48} \ + CONFIG.IN1_WIDTH {48} \ + CONFIG.IN2_WIDTH {8} \ + CONFIG.NUM_PORTS {2} \ + ] $xlconcat_A_channel_1 + + # Create instance: xlslice_0, and set properties + set xlslice_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_0 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {13} \ + CONFIG.DIN_WIDTH {16} \ + CONFIG.DOUT_WIDTH {14} \ + ] $xlslice_0 + + # Create interface connections + connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_CONFIG] + connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_PHASE [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_PHASE] [get_bd_intf_pins hbridge_signalgen_0_upgraded_ipi/s_axis_phase] + + # Create port connections + connect_bd_net -net aresetn_1 [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/aresetn] [get_bd_pins util_vector_logic_1/Op2] + connect_bd_net -net clk_wiz_0_clk_internal [get_bd_ports aclk] [get_bd_pins axis_variable_A_channel_1/aclk] [get_bd_pins dds_compiler_A_channel_1/aclk] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/clk] + connect_bd_net -net enable_dac_1 [get_bd_ports enable_dac] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/enable_dac] + connect_bd_net -net freq_1 [get_bd_ports freq] [get_bd_pins xlconcat_A_channel_1/In0] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H1 [get_bd_ports H1out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H1] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H2 [get_bd_ports H2out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H2] + connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] + connect_bd_net -net pulswidth_1 [get_bd_ports pulswidth] [get_bd_pins xlslice_0/Din] + connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins util_vector_logic_0/Op1] + connect_bd_net -net util_vector_logic_0_Res [get_bd_pins util_vector_logic_0/Res] [get_bd_pins util_vector_logic_1/Op1] + connect_bd_net -net util_vector_logic_1_Res [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins util_vector_logic_1/Res] + connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] + connect_bd_net -net xlslice_0_Dout [get_bd_pins hbridge_signalgen_0_upgraded_ipi/cfg_data] [get_bd_pins xlslice_0/Dout] + + # Create address segments + + + # Restore current instance + current_bd_instance $oldCurInst + + validate_bd_design + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/src/fpga/build.tcl b/src/fpga/build.tcl index 84a305a4..e2aded55 100644 --- a/src/fpga/build.tcl +++ b/src/fpga/build.tcl @@ -30,6 +30,7 @@ update_ip_catalog source src/fpga/bd/signal_calib.tcl source src/fpga/bd/signal_ramp.tcl source src/fpga/bd/waveform_gen.tcl +source src/fpga/bd/hbridgewaveform.tcl source src/fpga/bd/bd.tcl # Create HDL wrapper for blockdesign diff --git a/src/fpga/hdl/hbridge_signalgen.v b/src/fpga/hdl/hbridge_signalgen.v new file mode 100644 index 00000000..9fedc0c0 --- /dev/null +++ b/src/fpga/hdl/hbridge_signalgen.v @@ -0,0 +1,82 @@ +`timescale 1ns / 1ps + +module hbridge_signalgen # +( + parameter integer AXIS_TDATA_PHASE_WIDTH = 16, + parameter integer CFG_DATA_WIDTH = 16 +) +( + // DDS Input + input wire [AXIS_TDATA_PHASE_WIDTH-1:0] s_axis_tdata_phase, + input wire s_axis_tvalid_phase, + + input [CFG_DATA_WIDTH-1:0] cfg_data, + + + input clk, + input aresetn, + input enable_dac, + output H1, H2 +); + + reg signed [AXIS_TDATA_PHASE_WIDTH-1:0] phase; + reg signed [CFG_DATA_WIDTH-1:0] A; + reg h1, h2; + + + always @(posedge clk) + begin + A <= cfg_data>>1; + + if (~aresetn) + begin + h1 <= 0; + h2 <= 0; + phase <= 0; + end + else + begin + phase <= s_axis_tdata_phase >>> (AXIS_TDATA_PHASE_WIDTH - CFG_DATA_WIDTH); + //4096 = (1<<<(CFG_DATA_WIDTH-2)) + + if (enable_dac) + begin + if (phase < 4096-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 4096+A) + begin + h1 <= 0; + h2 <= 1; + end + else if (phase < 12288-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 12288+A) + begin + h1 <= 1; + h2 <= 0; + end + else + begin + h1 <= 0; + h2 <= 0; + end + end else begin + h1 <= 0; + h2 <= 0; + end + + end + + + end + +assign H1 = h1; +assign H2 = h2; + +endmodule \ No newline at end of file From 3f5d76122aa2ebea46d8f174c0ea4a7aebdb05c4 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 18:02:09 +0100 Subject: [PATCH 14/38] some fix remaining issues in BD --- src/fpga/bd/bd.tcl | 52 +++++--------------------------- src/fpga/bd/hbridgewaveform.tcl | 44 +++++++++++++++++++++++---- src/fpga/hdl/hbridge_signalgen.v | 50 +++++++++++++----------------- 3 files changed, 67 insertions(+), 79 deletions(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 9576f109..f85d8cfb 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -2803,22 +2803,6 @@ proc create_hier_cell_DIO { parentCell nameHier } { return 1 } - # Create instance: util_vector_logic_0, and set properties - set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {and} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_andgate.png} \ - ] $util_vector_logic_0 - - # Create instance: util_vector_logic_1, and set properties - set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {or} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_orgate.png} \ - ] $util_vector_logic_1 - # Create instance: util_vector_logic_2, and set properties set util_vector_logic_2 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_2 ] set_property -dict [ list \ @@ -2851,22 +2835,6 @@ proc create_hier_cell_DIO { parentCell nameHier } { CONFIG.LOGO_FILE {data/sym_orgate.png} \ ] $util_vector_logic_5 - # Create instance: util_vector_logic_6, and set properties - set util_vector_logic_6 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_6 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {and} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_andgate.png} \ - ] $util_vector_logic_6 - - # Create instance: util_vector_logic_7, and set properties - set util_vector_logic_7 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_7 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {or} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_orgate.png} \ - ] $util_vector_logic_7 - # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] set_property -dict [ list \ @@ -3193,7 +3161,6 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net cfg_dac_1 [get_bd_pins cfg_dac] [get_bd_pins xlslice_30/Din] [get_bd_pins xlslice_31/Din] connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins clk] [get_bd_pins hbridgewaveform_0/aclk] [get_bd_pins hbridgewaveform_1/aclk] [get_bd_pins rp_iobuf_2/clk] [get_bd_pins rp_iobuf_3/clk] [get_bd_pins rp_iobuf_4/clk] [get_bd_pins rp_iobuf_5/clk] [get_bd_pins rp_iobuf_6/clk] [get_bd_pins rp_iobuf_7/clk] [get_bd_pins rp_iobuf_8/clk] [get_bd_pins rp_iobuf_9/clk] connect_bd_net -net enable_dac_1 [get_bd_pins enable_dac] [get_bd_pins xlslice_18/Din] [get_bd_pins xlslice_32/Din] - connect_bd_net -net enable_dac_2 [get_bd_pins hbridgewaveform_1/enable_dac] [get_bd_pins util_vector_logic_6/Res] connect_bd_net -net hbridgewaveform_0_H1out [get_bd_pins hbridgewaveform_0/H1out] [get_bd_pins util_vector_logic_2/Op2] connect_bd_net -net hbridgewaveform_0_H2out [get_bd_pins hbridgewaveform_0/H2out] [get_bd_pins util_vector_logic_3/Op2] connect_bd_net -net hbridgewaveform_1_H1out [get_bd_pins hbridgewaveform_1/H1out] [get_bd_pins util_vector_logic_4/Op2] @@ -3208,13 +3175,10 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net rp_iobuf_8_val_in_clocked [get_bd_pins rp_iobuf_8/val_in_clocked] [get_bd_pins xlconcat_0/In0] connect_bd_net -net rp_iobuf_9_val_in_clocked [get_bd_pins rp_iobuf_9/val_in_clocked] [get_bd_pins xlconcat_0/In1] connect_bd_net -net system_cfg_data1 [get_bd_pins cfg_in] [get_bd_pins xlslice_23/Din] [get_bd_pins xlslice_4/Din] [get_bd_pins xlslice_5/Din] - connect_bd_net -net util_vector_logic_0_Res [get_bd_pins hbridgewaveform_0/enable_dac] [get_bd_pins util_vector_logic_0/Res] - connect_bd_net -net util_vector_logic_1_Res [get_bd_pins util_vector_logic_0/Op1] [get_bd_pins util_vector_logic_1/Res] connect_bd_net -net util_vector_logic_2_Res [get_bd_pins rp_iobuf_8/val_out] [get_bd_pins util_vector_logic_2/Res] connect_bd_net -net util_vector_logic_3_Res [get_bd_pins rp_iobuf_9/val_out] [get_bd_pins util_vector_logic_3/Res] connect_bd_net -net util_vector_logic_4_Res [get_bd_pins rp_iobuf_2/val_out] [get_bd_pins util_vector_logic_4/Res] connect_bd_net -net util_vector_logic_5_Res [get_bd_pins rp_iobuf_3/val_out] [get_bd_pins util_vector_logic_5/Res] - connect_bd_net -net util_vector_logic_7_Res [get_bd_pins util_vector_logic_6/Op1] [get_bd_pins util_vector_logic_7/Res] connect_bd_net -net xlconcat_0_dout2 [get_bd_pins dio_data_clocked] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconstant_1_dout [get_bd_pins xlconcat_0/In8] [get_bd_pins xlconstant_1/dout] connect_bd_net -net xlslice_0_Dout [get_bd_pins util_vector_logic_2/Op1] [get_bd_pins xlslice_0/Dout] @@ -3226,25 +3190,25 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net xlslice_15_Dout [get_bd_pins rp_iobuf_6/val_out] [get_bd_pins xlslice_15/Dout] connect_bd_net -net xlslice_16_Dout [get_bd_pins rp_iobuf_7/val_out] [get_bd_pins xlslice_16/Dout] connect_bd_net -net xlslice_17_Dout [get_bd_pins rp_iobuf_7/direction] [get_bd_pins xlslice_17/Dout] - connect_bd_net -net xlslice_18_Dout [get_bd_pins util_vector_logic_0/Op2] [get_bd_pins xlslice_18/Dout] + connect_bd_net -net xlslice_18_Dout [get_bd_pins hbridgewaveform_0/enable_All] [get_bd_pins xlslice_18/Dout] connect_bd_net -net xlslice_19_Dout [get_bd_pins hbridgewaveform_0/freq] [get_bd_pins xlslice_19/Dout] connect_bd_net -net xlslice_1_Dout [get_bd_pins rp_iobuf_2/direction] [get_bd_pins xlslice_1/Dout] connect_bd_net -net xlslice_20_Dout [get_bd_pins hbridgewaveform_0/phase] [get_bd_pins xlslice_20/Dout] connect_bd_net -net xlslice_21_Dout [get_bd_pins hbridgewaveform_0/pulswidth] [get_bd_pins xlslice_21/Dout] connect_bd_net -net xlslice_22_Dout [get_bd_pins hbridgewaveform_0/resync] [get_bd_pins xlslice_22/Dout] connect_bd_net -net xlslice_23_Dout [get_bd_pins xlslice_23/Dout] [get_bd_pins xlslice_24/Din] [get_bd_pins xlslice_25/Din] [get_bd_pins xlslice_33/Din] [get_bd_pins xlslice_34/Din] - connect_bd_net -net xlslice_24_Dout [get_bd_pins util_vector_logic_1/Op2] [get_bd_pins xlslice_24/Dout] - connect_bd_net -net xlslice_25_Dout [get_bd_pins util_vector_logic_1/Op1] [get_bd_pins xlslice_25/Dout] - connect_bd_net -net xlslice_26_Dout [get_bd_pins hbridgewaveform_1/phase] [get_bd_pins xlslice_26/Dout] - connect_bd_net -net xlslice_27_Dout [get_bd_pins hbridgewaveform_1/freq] [get_bd_pins xlslice_27/Dout] + connect_bd_net -net xlslice_24_Dout [get_bd_pins hbridgewaveform_0/enable_H1] [get_bd_pins xlslice_24/Dout] + connect_bd_net -net xlslice_25_Dout [get_bd_pins hbridgewaveform_0/enable_H2] [get_bd_pins xlslice_25/Dout] + connect_bd_net -net xlslice_26_Dout [get_bd_pins hbridgewaveform_1/freq] [get_bd_pins xlslice_26/Dout] + connect_bd_net -net xlslice_27_Dout [get_bd_pins hbridgewaveform_1/phase] [get_bd_pins xlslice_27/Dout] connect_bd_net -net xlslice_28_Dout [get_bd_pins hbridgewaveform_1/pulswidth] [get_bd_pins xlslice_28/Dout] connect_bd_net -net xlslice_29_Dout [get_bd_pins hbridgewaveform_1/resync] [get_bd_pins xlslice_29/Dout] connect_bd_net -net xlslice_2_Dout [get_bd_pins rp_iobuf_3/direction] [get_bd_pins xlslice_2/Dout] connect_bd_net -net xlslice_30_Dout [get_bd_pins xlslice_26/Din] [get_bd_pins xlslice_27/Din] [get_bd_pins xlslice_28/Din] [get_bd_pins xlslice_30/Dout] connect_bd_net -net xlslice_31_Dout [get_bd_pins xlslice_19/Din] [get_bd_pins xlslice_20/Din] [get_bd_pins xlslice_21/Din] [get_bd_pins xlslice_31/Dout] - connect_bd_net -net xlslice_32_Dout [get_bd_pins util_vector_logic_6/Op2] [get_bd_pins xlslice_32/Dout] - connect_bd_net -net xlslice_33_Dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlslice_33/Dout] - connect_bd_net -net xlslice_34_Dout [get_bd_pins util_vector_logic_7/Op2] [get_bd_pins xlslice_34/Dout] + connect_bd_net -net xlslice_32_Dout [get_bd_pins hbridgewaveform_1/enable_All] [get_bd_pins xlslice_32/Dout] + connect_bd_net -net xlslice_33_Dout [get_bd_pins hbridgewaveform_1/enable_H1] [get_bd_pins xlslice_33/Dout] + connect_bd_net -net xlslice_34_Dout [get_bd_pins hbridgewaveform_1/enable_H2] [get_bd_pins xlslice_34/Dout] connect_bd_net -net xlslice_3_Dout [get_bd_pins rp_iobuf_4/direction] [get_bd_pins xlslice_3/Dout] connect_bd_net -net xlslice_4_Dout [get_bd_pins xlslice_0/Din] [get_bd_pins xlslice_10/Din] [get_bd_pins xlslice_11/Din] [get_bd_pins xlslice_12/Din] [get_bd_pins xlslice_15/Din] [get_bd_pins xlslice_16/Din] [get_bd_pins xlslice_4/Dout] [get_bd_pins xlslice_6/Din] [get_bd_pins xlslice_9/Din] connect_bd_net -net xlslice_5_Dout [get_bd_pins xlslice_1/Din] [get_bd_pins xlslice_13/Din] [get_bd_pins xlslice_14/Din] [get_bd_pins xlslice_17/Din] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] [get_bd_pins xlslice_5/Dout] [get_bd_pins xlslice_7/Din] [get_bd_pins xlslice_8/Din] diff --git a/src/fpga/bd/hbridgewaveform.tcl b/src/fpga/bd/hbridgewaveform.tcl index 12a2d922..d2f98ab8 100644 --- a/src/fpga/bd/hbridgewaveform.tcl +++ b/src/fpga/bd/hbridgewaveform.tcl @@ -223,11 +223,13 @@ proc create_root_design { parentCell } { # Create interface ports # Create ports - set H1out [ create_bd_port -dir O -type data H1out ] - set H2out [ create_bd_port -dir O -type data H2out ] + set H1out [ create_bd_port -dir O -from 0 -to 0 -type data H1out ] + set H2out [ create_bd_port -dir O -from 0 -to 0 -type data H2out ] set aclk [ create_bd_port -dir I -type clk -freq_hz 125000000 aclk ] set aresetn [ create_bd_port -dir I -type rst aresetn ] - set enable_dac [ create_bd_port -dir I enable_dac ] + set enable_All [ create_bd_port -dir I enable_All ] + set enable_H1 [ create_bd_port -dir I -type data enable_H1 ] + set enable_H2 [ create_bd_port -dir I -type data enable_H2 ] set freq [ create_bd_port -dir I -from 47 -to 0 freq ] set phase [ create_bd_port -dir I -from 47 -to 0 phase ] set pulswidth [ create_bd_port -dir I -from 15 -to 0 pulswidth ] @@ -300,6 +302,30 @@ proc create_root_design { parentCell } { CONFIG.C_SIZE {1} \ ] $util_vector_logic_1 + # Create instance: util_vector_logic_2, and set properties + set util_vector_logic_2 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_2 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_2 + + # Create instance: util_vector_logic_3, and set properties + set util_vector_logic_3 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_3 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_3 + + # Create instance: util_vector_logic_4, and set properties + set util_vector_logic_4 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_4 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_4 + + # Create instance: util_vector_logic_5, and set properties + set util_vector_logic_5 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_5 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_5 + # Create instance: xlconcat_A_channel_1, and set properties set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] set_property -dict [ list \ @@ -324,15 +350,21 @@ proc create_root_design { parentCell } { # Create port connections connect_bd_net -net aresetn_1 [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/aresetn] [get_bd_pins util_vector_logic_1/Op2] connect_bd_net -net clk_wiz_0_clk_internal [get_bd_ports aclk] [get_bd_pins axis_variable_A_channel_1/aclk] [get_bd_pins dds_compiler_A_channel_1/aclk] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/clk] - connect_bd_net -net enable_dac_1 [get_bd_ports enable_dac] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/enable_dac] + connect_bd_net -net enable_All_1 [get_bd_ports enable_All] [get_bd_pins util_vector_logic_4/Op1] [get_bd_pins util_vector_logic_5/Op1] + connect_bd_net -net enable_H1_1 [get_bd_ports enable_H1] [get_bd_pins util_vector_logic_2/Op1] + connect_bd_net -net enable_H2_1 [get_bd_ports enable_H2] [get_bd_pins util_vector_logic_3/Op1] connect_bd_net -net freq_1 [get_bd_ports freq] [get_bd_pins xlconcat_A_channel_1/In0] - connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H1 [get_bd_ports H1out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H1] - connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H2 [get_bd_ports H2out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H2] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H1 [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H1] [get_bd_pins util_vector_logic_2/Op2] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H2 [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H2] [get_bd_pins util_vector_logic_3/Op2] connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] connect_bd_net -net pulswidth_1 [get_bd_ports pulswidth] [get_bd_pins xlslice_0/Din] connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins util_vector_logic_0/Op1] connect_bd_net -net util_vector_logic_0_Res [get_bd_pins util_vector_logic_0/Res] [get_bd_pins util_vector_logic_1/Op1] connect_bd_net -net util_vector_logic_1_Res [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins util_vector_logic_1/Res] + connect_bd_net -net util_vector_logic_2_Res [get_bd_pins util_vector_logic_2/Res] [get_bd_pins util_vector_logic_4/Op2] + connect_bd_net -net util_vector_logic_3_Res [get_bd_pins util_vector_logic_3/Res] [get_bd_pins util_vector_logic_5/Op2] + connect_bd_net -net util_vector_logic_4_Res [get_bd_ports H1out] [get_bd_pins util_vector_logic_4/Res] + connect_bd_net -net util_vector_logic_5_Res [get_bd_ports H2out] [get_bd_pins util_vector_logic_5/Res] connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] connect_bd_net -net xlslice_0_Dout [get_bd_pins hbridge_signalgen_0_upgraded_ipi/cfg_data] [get_bd_pins xlslice_0/Dout] diff --git a/src/fpga/hdl/hbridge_signalgen.v b/src/fpga/hdl/hbridge_signalgen.v index 9fedc0c0..9b5e56eb 100644 --- a/src/fpga/hdl/hbridge_signalgen.v +++ b/src/fpga/hdl/hbridge_signalgen.v @@ -15,7 +15,6 @@ module hbridge_signalgen # input clk, input aresetn, - input enable_dac, output H1, H2 ); @@ -39,41 +38,34 @@ module hbridge_signalgen # phase <= s_axis_tdata_phase >>> (AXIS_TDATA_PHASE_WIDTH - CFG_DATA_WIDTH); //4096 = (1<<<(CFG_DATA_WIDTH-2)) - if (enable_dac) + if (phase < 4096-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 4096+A) + begin + h1 <= 0; + h2 <= 1; + end + else if (phase < 12288-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 12288+A) + begin + h1 <= 1; + h2 <= 0; + end + else begin - if (phase < 4096-A) - begin - h1 <= 0; - h2 <= 0; - end - else if (phase < 4096+A) - begin - h1 <= 0; - h2 <= 1; - end - else if (phase < 12288-A) - begin - h1 <= 0; - h2 <= 0; - end - else if (phase < 12288+A) - begin - h1 <= 1; - h2 <= 0; - end - else - begin - h1 <= 0; - h2 <= 0; - end - end else begin h1 <= 0; h2 <= 0; end end - end assign H1 = h1; From 7d28e35e107e7c1fef9dc374a8374f3321ab2da7 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 19:45:49 +0100 Subject: [PATCH 15/38] update bd --- src/fpga/bd/hbridgewaveform.tcl | 96 +++++++++++++++++---------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/src/fpga/bd/hbridgewaveform.tcl b/src/fpga/bd/hbridgewaveform.tcl index d2f98ab8..5e6adbc8 100644 --- a/src/fpga/bd/hbridgewaveform.tcl +++ b/src/fpga/bd/hbridgewaveform.tcl @@ -58,68 +58,70 @@ if { $list_projs eq "" } { variable design_name set design_name hbridgewaveform -# This script was generated for a remote BD. To create a non-remote design, -# change the variable to <0>. - -set run_remote_bd_flow 1 -if { $run_remote_bd_flow == 1 } { - # Set the reference directory for source file relative paths (by default - # the value is script directory path) - set origin_dir ./.julia/dev/RedPitayaDAQServer/src/fpga/bd - - # Use origin directory path location variable, if specified in the tcl shell - if { [info exists ::origin_dir_loc] } { - set origin_dir $::origin_dir_loc - } +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name - set str_bd_folder [file normalize ${origin_dir}] - set str_bd_filepath ${str_bd_folder}/${design_name}/${design_name}.bd +# Creating design if needed +set errMsg "" +set nRet 0 - # Check if remote design exists on disk - if { [file exists $str_bd_filepath ] == 1 } { - catch {common::send_gid_msg -ssname BD::TCL -id 2030 -severity "ERROR" "The remote BD file path <$str_bd_filepath> already exists!"} - common::send_gid_msg -ssname BD::TCL -id 2031 -severity "INFO" "To create a non-remote BD, change the variable to <0>." - common::send_gid_msg -ssname BD::TCL -id 2032 -severity "INFO" "Also make sure there is no design <$design_name> existing in your current project." +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] - return 1 - } +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set - # Check if design exists in memory - set list_existing_designs [get_bd_designs -quiet $design_name] - if { $list_existing_designs ne "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2033 -severity "ERROR" "The design <$design_name> already exists in this project! Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} + set errMsg "Please set the variable to a non-empty value." + set nRet 1 - common::send_gid_msg -ssname BD::TCL -id 2034 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. - return 1 - } + if { $cur_design ne $design_name } { + common::send_gid_msg -ssname BD::TCL -id 2001 -severity "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_gid_msg -ssname BD::TCL -id 2002 -severity "INFO" "Constructing design in IPI design <$cur_design>..." - # Check if design exists on disk within project - set list_existing_designs [get_files -quiet */${design_name}.bd] - if { $list_existing_designs ne "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2035 -severity "ERROR" "The design <$design_name> already exists in this project at location: - $list_existing_designs"} - catch {common::send_gid_msg -ssname BD::TCL -id 2036 -severity "ERROR" "Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. - common::send_gid_msg -ssname BD::TCL -id 2037 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. - return 1 - } + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 - # Now can create the remote BD - # NOTE - usage of <-dir> will create <$str_bd_folder/$design_name/$design_name.bd> - create_bd_design -dir $str_bd_folder $design_name } else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. - # Create regular design - if { [catch {create_bd_design $design_name} errmsg] } { - common::send_gid_msg -ssname BD::TCL -id 2038 -severity "INFO" "Please set a different value to variable ." + common::send_gid_msg -ssname BD::TCL -id 2003 -severity "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_gid_msg -ssname BD::TCL -id 2004 -severity "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name - return 1 - } } -current_bd_design $design_name +common::send_gid_msg -ssname BD::TCL -id 2005 -severity "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_gid_msg -ssname BD::TCL -id 2006 -severity "ERROR" $errMsg} + return $nRet +} set bCheckIPsPassed 1 ################################################################## From 691afb933fba9fee5896ea3829c7d1128fb320af Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 21:01:02 +0100 Subject: [PATCH 16/38] server changes for hbridge --- src/lib/rp-daq-lib.c | 32 +++++++++++++++++- src/lib/rp-daq-lib.h | 2 ++ src/server/control.c | 2 +- src/server/scpi_commands.c | 66 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 2e3ecc12..821cb013 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -653,7 +653,7 @@ int setResyncDAC(int8_t value, int channel, int index) { return -1; int bitpos = 14; - // Reset bits are in the 14th bit of the respective DAC channel -> 14 and 30 + // Reset bits are in the 14th bit of the respective DAC channel -> 14 and 30 int offset = 8 * index + channel; // clear the bit *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); @@ -1225,6 +1225,36 @@ char* getPinFromInternalPINNumber(const uint32_t pinNumber) { } } +int getDIOHBridge(const char* pin) { + int pinInternal = getInternalPINNumber(pin); + if(pinInternal < 0) { + return -3; + } + + uint32_t register_value = *((uint8_t *)(cfg + 11)); + register_value = ((register_value & (0x1 << (pinInternal))) >> (pinInternal)); + + return register_value; +} + +int setDIOHBridge(const char* pin, int value) { + int pinInternal = getInternalPINNumber(pin); + if(pinInternal < 0) { + return -3; + } + + if(value == DIO_OUT) { + *((uint8_t *)(cfg + 11)) &= ~(0x1 << (pinInternal)); + } else if(value == DIO_IN) { + *((uint8_t *)(cfg + 11)) |= (0x1 << (pinInternal)); + } else { + return -1; + } + + return 0; +} + + int getDIODirection(const char* pin) { int pinInternal = getInternalPINNumber(pin); if(pinInternal < 0) { diff --git a/src/lib/rp-daq-lib.h b/src/lib/rp-daq-lib.h index 9dc8378f..e608591b 100644 --- a/src/lib/rp-daq-lib.h +++ b/src/lib/rp-daq-lib.h @@ -174,6 +174,8 @@ extern int getDIODirection(const char*); extern int setDIODirection(const char*, int); extern int setDIO(const char*, int); extern int getDIO(const char*); +extern int getDIOHBridge(const char*); +extern int setDIOHBridge(const char*, int); extern int setTriggerMode(int); extern int getTriggerMode(); extern int setTriggerPropagation(int); diff --git a/src/server/control.c b/src/server/control.c index 3e662510..d0e86c8c 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -129,7 +129,7 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { bool result = false; - int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; if (seqData->resyncLUT != NULL && channel < numChan) { int localStep = seqStep % seqData->numStepsPerRepetition; result = seqData->resyncLUT[localStep * numChan + channel]; diff --git a/src/server/scpi_commands.c b/src/server/scpi_commands.c index b7308745..dd31c1f1 100644 --- a/src/server/scpi_commands.c +++ b/src/server/scpi_commands.c @@ -722,6 +722,68 @@ static scpi_result_t RP_DIO_GetDIOOutputP(scpi_t * context) { return RP_DIO_GetDIOOutput(context, true); } + + + +static scpi_result_t RP_DIO_SetDIOHBridge(scpi_t * context, bool pinSide) { + int32_t numbers[1]; + SCPI_CommandNumbers(context, numbers, 1, 1); + int pin_number = numbers[0]; + char pin[8]; + pinSide ? sprintf(pin, "DIO%d_P", pin_number) : sprintf(pin, "DIO%d_N", pin_number); + + int32_t DIO_pin_output_selection; + if (!SCPI_ParamChoice(context, onoff_modes, &DIO_pin_output_selection, TRUE)) { + return returnSCPIBool(context, false); + } + + int result = setDIOHBridge(pin, DIO_pin_output_selection); + if (result < 0) { + return returnSCPIBool(context, false); + } + + return returnSCPIBool(context, true); +} + +static scpi_result_t RP_DIO_SetDIOHBridgeN(scpi_t * context) { + return RP_DIO_SetDIOHBridge(context, false); +} + +static scpi_result_t RP_DIO_SetDIOHBridgeP(scpi_t * context) { + return RP_DIO_SetDIOHBridge(context, true); +} + +static scpi_result_t RP_DIO_GetDIOHBridge(scpi_t * context, bool pinSide) { + int32_t numbers[1]; + SCPI_CommandNumbers(context, numbers, 1, 1); + int pin_number = numbers[0]; + char pin[8]; + pinSide ? sprintf(pin, "DIO%d_P", pin_number) : sprintf(pin, "DIO%d_N", pin_number); + + int result = getDIOHBridge(pin); + + if (result < 0) { + return returnSCPIBool(context, false); + } + + const char* name; + SCPI_ChoiceToName(onoff_modes, result, &name); + SCPI_ResultText(context, name); + + return SCPI_RES_OK; +} + +static scpi_result_t RP_DIO_GetDIOHBridgeN(scpi_t * context) { + return RP_DIO_GetDIOHBridge(context, false); +} + +static scpi_result_t RP_DIO_GetDIOHBridgeP(scpi_t * context) { + return RP_DIO_GetDIOHBridge(context, true); +} + + + + static scpi_result_t RP_GetWatchdogMode(scpi_t * context) { const char * name; @@ -1791,6 +1853,10 @@ const scpi_command_t scpi_commands[] = { {.pattern = "RP:DIO:Pin#:SideP", .callback = RP_DIO_SetDIOOutputP,}, {.pattern = "RP:DIO:Pin#:SideN?", .callback = RP_DIO_GetDIOOutputN,}, {.pattern = "RP:DIO:Pin#:SideP?", .callback = RP_DIO_GetDIOOutputP,}, + {.pattern = "RP:DIO:Pin#:SideN:HBridge", .callback = RP_DIO_SetDIOHBridgeN,}, + {.pattern = "RP:DIO:Pin#:SideP:HBridge", .callback = RP_DIO_SetDIOHBridgeP,}, + {.pattern = "RP:DIO:Pin#:SideN:HBridge?", .callback = RP_DIO_GetDIOHBridgeN,}, + {.pattern = "RP:DIO:Pin#:SideP:HBridge?", .callback = RP_DIO_GetDIOHBridgeP,}, {.pattern = "RP:WatchDogMode", .callback = RP_SetWatchdogMode,}, {.pattern = "RP:WatchDogMode?", .callback = RP_GetWatchdogMode,}, {.pattern = "RP:TRIGger:ALiVe", .callback = RP_SetKeepAliveReset,}, From 7b1528439a4a49761057744079301e7f8312b759 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 21:02:21 +0100 Subject: [PATCH 17/38] change version to 10 --- src/fpga/bd/bd.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index f85d8cfb..d6049ccc 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -1567,7 +1567,7 @@ proc create_hier_cell_system_1 { parentCell nameHier } { # Create instance: image_version, and set properties set image_version [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 image_version ] set_property -dict [ list \ - CONFIG.CONST_VAL {9} \ + CONFIG.CONST_VAL {10} \ CONFIG.CONST_WIDTH {32} \ ] $image_version From 0828b19f33a62cd2213475bdda93854be79799e2 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:42:18 +0000 Subject: [PATCH 18/38] Init Resync FPGA image --- src/fpga/bd/bd.tcl | 41 ++++++++++++++++++++++++++++++----- src/fpga/bd/waveform_gen.tcl | 26 ++++++++++++++++++---- src/fpga/hdl/sequence_slice.v | 2 ++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 8e2e13fc..206a1a32 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -796,6 +796,7 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { create_bd_pin -dir O -from 0 -to 0 m_axis_data_tvalid_1 create_bd_pin -dir I -from 15 -to 0 offset create_bd_pin -dir O -from 1 -to 0 ramp_state_1 + create_bd_pin -dir I resync_dac create_bd_pin -dir I start_ramp_down # Create instance: signal_calib_0, and set properties @@ -899,10 +900,11 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net enable_ramping_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp_0/enableRamping] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_pins aresetn] [get_bd_pins signal_ramp_0/aresetn] [get_bd_pins waveform_awg1/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] [get_bd_pins waveform_gen_3/aresetn] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] - connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_calib_0/calib_limit_lower] [get_bd_pins signal_cfg_slice_0/calib_limit_lower] - connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_calib_0/calib_limit_upper] [get_bd_pins signal_cfg_slice_0/calib_limit_upper] + connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] + connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] connect_bd_net -net signal_cfg_slice_0_calib_offset [get_bd_pins signal_calib_0/calib_offset] [get_bd_pins signal_cfg_slice_0/calib_offset] connect_bd_net -net signal_cfg_slice_0_calib_scale [get_bd_pins signal_calib_0/calib_scale] [get_bd_pins signal_cfg_slice_0/calib_scale] connect_bd_net -net signal_cfg_slice_0_comp_0_amp [get_bd_pins signal_cfg_slice_0/comp_0_amp] [get_bd_pins waveform_gen_0/amplitude] @@ -990,6 +992,7 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { create_bd_pin -dir O -from 0 -to 0 m_axis_data_tvalid_1 create_bd_pin -dir I -from 15 -to 0 offset create_bd_pin -dir O -from 1 -to 0 ramp_state_0 + create_bd_pin -dir I resync_dac create_bd_pin -dir I start_ramp_down # Create instance: signal_calib_0, and set properties @@ -1094,9 +1097,10 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] connect_bd_net -net ramping_enable_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp/enableRamping] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] - connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_calib_0/calib_limit_lower] [get_bd_pins signal_cfg_slice_0/calib_limit_lower] - connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_calib_0/calib_limit_upper] [get_bd_pins signal_cfg_slice_0/calib_limit_upper] + connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] + connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] connect_bd_net -net signal_cfg_slice_0_calib_offset [get_bd_pins signal_calib_0/calib_offset] [get_bd_pins signal_cfg_slice_0/calib_offset] connect_bd_net -net signal_cfg_slice_0_calib_scale [get_bd_pins signal_calib_0/calib_scale] [get_bd_pins signal_cfg_slice_0/calib_scale] connect_bd_net -net signal_cfg_slice_0_comp_0_amp [get_bd_pins signal_cfg_slice_0/comp_0_amp] [get_bd_pins waveform_gen_0/amplitude] @@ -1576,7 +1580,7 @@ proc create_hier_cell_system_1 { parentCell nameHier } { # Create instance: image_version, and set properties set image_version [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 image_version ] set_property -dict [ list \ - CONFIG.CONST_VAL {8} \ + CONFIG.CONST_VAL {9} \ CONFIG.CONST_WIDTH {32} \ ] $image_version @@ -2099,6 +2103,7 @@ proc create_hier_cell_sequencer { parentCell nameHier } { create_bd_pin -dir I -type rst keep_alive_aresetn create_bd_pin -dir O -from 31 -to 0 oa_dac create_bd_pin -dir O -from 31 -to 0 pdm_sts + create_bd_pin -dir O -from 1 -to 0 resync_dac create_bd_pin -dir O -from 1 -to 0 seq_ramp_down # Create instance: axi_bram_ctrl_0, and set properties @@ -2251,6 +2256,7 @@ proc create_hier_cell_sequencer { parentCell nameHier } { connect_bd_net -net sequence_slice_0_pdm_value_1 [get_bd_pins pdm_2/din] [get_bd_pins sequence_slice_0/pdm_value_1] connect_bd_net -net sequence_slice_0_pdm_value_2 [get_bd_pins pdm_3/din] [get_bd_pins sequence_slice_0/pdm_value_2] connect_bd_net -net sequence_slice_0_pdm_value_3 [get_bd_pins pdm_4/din] [get_bd_pins sequence_slice_0/pdm_value_3] + connect_bd_net -net sequence_slice_0_resync_dac [get_bd_pins resync_dac] [get_bd_pins sequence_slice_0/resync_dac] connect_bd_net -net util_vector_logic_7_Res [get_bd_pins dout] [get_bd_pins util_vector_logic_7/Res] connect_bd_net -net xlconcat_0_dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconcat_1_dout [get_bd_pins oa_dac] [get_bd_pins xlconcat_1/dout] @@ -2313,6 +2319,7 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { create_bd_pin -dir I -from 31 -to 0 oa_dac create_bd_pin -dir O -from 1 -to 0 ramp_state_0 create_bd_pin -dir O -from 1 -to 0 ramp_state_1 + create_bd_pin -dir I -from 1 -to 0 resync_dac create_bd_pin -dir I -from 1 -to 0 seq_ramp_down create_bd_pin -dir I -from 1 -to 0 start_ramp_down create_bd_pin -dir O -from 31 -to 0 synth_tdata @@ -2405,6 +2412,23 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { CONFIG.DOUT_WIDTH {1} \ ] $xlslice_5 + # Create instance: xlslice_6, and set properties + set xlslice_6 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_6 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {0} \ + CONFIG.DIN_TO {0} \ + CONFIG.DIN_WIDTH {2} \ + ] $xlslice_6 + + # Create instance: xlslice_7, and set properties + set xlslice_7 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_7 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {2} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_7 + # Create interface connections connect_bd_intf_net -intf_net awg_0_bram_1 [get_bd_intf_pins awg_0_bram] [get_bd_intf_pins signal_compose/awg_bram] connect_bd_intf_net -intf_net awg_1_bram_1 [get_bd_intf_pins awg_1_bram] [get_bd_intf_pins signal_compose1/awg_bram] @@ -2422,6 +2446,7 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { connect_bd_net -net enable_ramping_slice_0_start_ramp_down_0 [get_bd_pins enable_ramping_slice_0/start_ramp_down_0] [get_bd_pins signal_compose/start_ramp_down] connect_bd_net -net enable_ramping_slice_0_start_ramp_down_1 [get_bd_pins enable_ramping_slice_0/start_ramp_down_1] [get_bd_pins signal_compose1/start_ramp_down] connect_bd_net -net oa_dac_1 [get_bd_pins oa_dac] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins xlslice_6/Din] [get_bd_pins xlslice_7/Din] connect_bd_net -net seq_ramp_down_1 [get_bd_pins seq_ramp_down] [get_bd_pins enable_ramping_slice_0/seq_ramp_down] connect_bd_net -net signal_compose1_S [get_bd_pins signal_compose1/S] [get_bd_pins xlconcat_2/In1] connect_bd_net -net signal_compose1_m_axis_data_tvalid_1 [get_bd_pins signal_compose1/m_axis_data_tvalid_1] [get_bd_pins util_vector_logic_1/Op2] @@ -2438,6 +2463,8 @@ proc create_hier_cell_fourier_synth_standard { parentCell nameHier } { connect_bd_net -net xlslice_3_Dout [get_bd_pins signal_compose/offset] [get_bd_pins xlslice_3/Dout] connect_bd_net -net xlslice_4_Dout [get_bd_pins signal_compose/disable_dac] [get_bd_pins xlslice_4/Dout] connect_bd_net -net xlslice_5_Dout [get_bd_pins signal_compose1/disable_dac] [get_bd_pins xlslice_5/Dout] + connect_bd_net -net xlslice_6_Dout [get_bd_pins signal_compose/resync_dac] [get_bd_pins xlslice_6/Dout] + connect_bd_net -net xlslice_7_Dout [get_bd_pins signal_compose1/resync_dac] [get_bd_pins xlslice_7/Dout] # Restore current instance current_bd_instance $oldCurInst @@ -3391,6 +3418,7 @@ proc create_root_design { parentCell } { connect_bd_net -net selectio_wiz_2_clk_out [get_bd_pins clk_wiz_1/clk_in1] [get_bd_pins selectio_wiz_2/clk_out] connect_bd_net -net selectio_wiz_2_data_in_to_device [get_bd_pins reset_manager_0/sata_trigger] [get_bd_pins selectio_wiz_2/data_in_to_device] connect_bd_net -net sequencer_enable_dac [get_bd_pins fourier_synth_standard/enable_dac] [get_bd_pins sequencer/enable_dac] + connect_bd_net -net sequencer_resync_dac [get_bd_pins fourier_synth_standard/resync_dac] [get_bd_pins sequencer/resync_dac] connect_bd_net -net sequencer_seq_ramp_down [get_bd_pins fourier_synth_standard/seq_ramp_down] [get_bd_pins sequencer/seq_ramp_down] connect_bd_net -net system_FCLK_RESET0_N [get_bd_pins system/FCLK_RESET0_N] [get_bd_pins util_vector_logic_1/Op1] connect_bd_net -net system_cfg_data [get_bd_pins fourier_synth_standard/cfg_data] [get_bd_pins system/dac_cfg] @@ -3434,7 +3462,6 @@ proc create_root_design { parentCell } { # Restore current instance current_bd_instance $oldCurInst - validate_bd_design save_bd_design } # End of create_root_design() @@ -3447,3 +3474,5 @@ proc create_root_design { parentCell } { create_root_design "" +common::send_gid_msg -ssname BD::TCL -id 2053 -severity "WARNING" "This Tcl script was generated from a block design that has not been validated. It is possible that design <$design_name> may result in errors during validation." + diff --git a/src/fpga/bd/waveform_gen.tcl b/src/fpga/bd/waveform_gen.tcl index f56db04a..ac9b77b2 100644 --- a/src/fpga/bd/waveform_gen.tcl +++ b/src/fpga/bd/waveform_gen.tcl @@ -128,6 +128,7 @@ xilinx.com:ip:dds_compiler:6.0\ xilinx.com:ip:mult_gen:12.0\ jbeuke:user:signal_generator:1.0\ xilinx.com:ip:xlconcat:2.1\ +xilinx.com:ip:xlconstant:1.1\ " set list_ips_missing "" @@ -203,12 +204,13 @@ proc create_root_design { parentCell } { set freq [ create_bd_port -dir I -from 47 -to 0 freq ] set m_axis_data_tvalid_1 [ create_bd_port -dir O m_axis_data_tvalid_1 ] set phase [ create_bd_port -dir I -from 47 -to 0 phase ] + set resync [ create_bd_port -dir I resync ] set wave [ create_bd_port -dir O -from 15 -to 0 -type data wave ] # Create instance: axis_variable_A_channel_1, and set properties set axis_variable_A_channel_1 [ create_bd_cell -type ip -vlnv pavel-demin:user:axis_variable:1.0 axis_variable_A_channel_1 ] set_property -dict [ list \ - CONFIG.AXIS_TDATA_WIDTH {96} \ + CONFIG.AXIS_TDATA_WIDTH {104} \ ] $axis_variable_A_channel_1 # Create instance: dds_compiler_A_channel_1, and set properties @@ -233,10 +235,11 @@ proc create_root_design { parentCell } { CONFIG.POFF1 {0} \ CONFIG.Parameter_Entry {System_Parameters} \ CONFIG.PartsPresent {Phase_Generator_and_SIN_COS_LUT} \ - CONFIG.Phase_Increment {Programmable} \ + CONFIG.Phase_Increment {Streaming} \ CONFIG.Phase_Offset_Angles1 {0} \ CONFIG.Phase_Width {48} \ - CONFIG.Phase_offset {Programmable} \ + CONFIG.Phase_offset {Streaming} \ + CONFIG.Resync {true} \ CONFIG.S_PHASE_Has_TUSER {Not_Required} \ CONFIG.Spurious_Free_Dynamic_Range {84} \ ] $dds_compiler_A_channel_1 @@ -261,15 +264,27 @@ proc create_root_design { parentCell } { CONFIG.CFG_DATA_WIDTH {48} \ ] $signal_generator_0 + # Create instance: xlconcat_0, and set properties + set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + # Create instance: xlconcat_A_channel_1, and set properties set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] set_property -dict [ list \ CONFIG.IN0_WIDTH {48} \ CONFIG.IN1_WIDTH {48} \ + CONFIG.IN2_WIDTH {8} \ + CONFIG.NUM_PORTS {3} \ ] $xlconcat_A_channel_1 + # Create instance: xlconstant_0, and set properties + set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] + set_property -dict [ list \ + CONFIG.CONST_VAL {0} \ + CONFIG.CONST_WIDTH {7} \ + ] $xlconstant_0 + # Create interface connections - connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_CONFIG] + connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_PHASE] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_DATA [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_DATA] [get_bd_intf_pins signal_generator_0/s_axis] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_PHASE [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_PHASE] [get_bd_intf_pins signal_generator_0/s_axis_phase] @@ -280,10 +295,13 @@ proc create_root_design { parentCell } { connect_bd_net -net mult_gen_0_P [get_bd_ports wave] [get_bd_pins mult_gen_0/P] connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] connect_bd_net -net phase_A_channel_1_slice1_Dout [get_bd_ports cfg_data] [get_bd_pins signal_generator_0/cfg_data] + connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins xlconcat_0/In0] connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins signal_generator_0/aresetn] connect_bd_net -net signal_generator_0_m_axis_tdata [get_bd_pins mult_gen_0/B] [get_bd_pins signal_generator_0/m_axis_tdata] connect_bd_net -net signal_generator_0_m_axis_tvalid [get_bd_ports m_axis_data_tvalid_1] [get_bd_pins signal_generator_0/m_axis_tvalid] + connect_bd_net -net xlconcat_0_dout [get_bd_pins xlconcat_0/dout] [get_bd_pins xlconcat_A_channel_1/In2] connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] + connect_bd_net -net xlconstant_0_dout [get_bd_pins xlconcat_0/In1] [get_bd_pins xlconstant_0/dout] # Create address segments diff --git a/src/fpga/hdl/sequence_slice.v b/src/fpga/hdl/sequence_slice.v index 7e3f15f8..67b36e07 100644 --- a/src/fpga/hdl/sequence_slice.v +++ b/src/fpga/hdl/sequence_slice.v @@ -11,6 +11,7 @@ module sequence_slice( output [10:0] pdm_value_2, output [10:0] pdm_value_3, output [1:0] enable_dac, + output [1:0] resync_dac, output [3:0] enable_pdm, output [1:0] enable_dac_ramp_down ); @@ -41,6 +42,7 @@ assign pdm_value_3[10:0] = seq_data_int[90:80]; // Flags assign enable_dac[1:0] = seq_data_int[97:96]; assign enable_pdm[3:0] = seq_data_int[101:98]; +assign resync_dac[1:0] = seq_data_init[31:30]; assign enable_dac_ramp_down[0] = seq_data_int[112]; assign enable_dac_ramp_down[1] = seq_data_int[113]; From 49de96b9e3c9fbe7e6719344a39cefb9882df322 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:42:44 +0000 Subject: [PATCH 19/38] Init resync rp-lib --- src/lib/rp-daq-lib.c | 26 ++++++++++++++++++++++++++ src/lib/rp-daq-lib.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index c588f7ac..9c495034 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -637,6 +637,32 @@ int setEnableDAC(int8_t value, int channel, int index) { return 0; } +int setResyncDACAll(int8_t value, int channel) { + for(int i=0; i= 2) { + return -2; + } + + if (value < 0 || value >= 2) + return -1; + + int bitpos = 14 + channel; + // Reset bit is in the 2-th channel + int offset = 8 * index + 2; + // clear the bit + *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); + // set the bit + *((int16_t *)(pdm_cfg + offset)) |= (value << bitpos); + //printf("%d reset pdm\n", *((int16_t *)(pdm_cfg + 2*(0+4*index)))); + return 0; +} + int setResetDAC(int8_t value, int index) { if (value < 0 || value >= 2) return -1; diff --git a/src/lib/rp-daq-lib.h b/src/lib/rp-daq-lib.h index 691bd70c..f7cf6bcc 100644 --- a/src/lib/rp-daq-lib.h +++ b/src/lib/rp-daq-lib.h @@ -143,6 +143,8 @@ extern uint32_t getXADCValue(int); extern float getXADCValueVolt(int); extern int setEnableDACAll(int8_t, int); extern int setEnableDAC(int8_t, int, int); +extern int setResyncDACAll(int8_t, int); +extern int setResyncDAC(int8_t, int, int); //extern int setResetDAC(int8_t, int); extern int setRampDownDAC(int8_t, int, int); extern int setRampDownDACAll(int8_t, int); From 48635989f31157c56103c7db9a1c364025647cd9 Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:43:00 +0000 Subject: [PATCH 20/38] Init resync server --- src/server/control.c | 19 +++++++++++++++++++ src/server/daq_server_scpi.h | 2 ++ src/server/scpi_commands.c | 26 ++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/server/control.c b/src/server/control.c index 05ef096a..07868075 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -46,6 +46,7 @@ sequenceData_t * allocSequence() { seq->enableLUT = NULL; seq->rampUp = NULL; seq->rampDown = NULL; + seq->resyncLUT = NULL; return seq; } @@ -66,6 +67,10 @@ void freeSequence(sequenceData_t *seqData) { freeRamping(seqData->rampDown); seqData->rampDown = NULL; } + if (seqData->resyncLUT != NULL) { + free(seqData->resyncLUT); + seqData->resyncLUT = NULL; + } } rampingData_t * allocRamping() { @@ -123,6 +128,15 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { return result; } +bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { + bool result = false; + if (seqData->resyncLUT != NULL) { + int localStep = seqStep % seqData->numStepsPerRepetition; + result = seqData->resyncLUT[localStep + channel]; + } + return result; +} + float getRampingValue(rampingData_t *rampData, int rampStep, int channel) { int localStep = rampStep % rampData->numStepsPerRepetition; return rampData->LUT[localStep * numSlowDACChan + channel]; @@ -219,6 +233,7 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { float val = 0.0; bool enable = true; bool rampDown = false; + bool resync = false; switch(interval) { case RAMPUP: @@ -227,6 +242,7 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { case REGULAR: val = getSequenceValue(activeSequence, localStep, channel); enable = getSequenceEnableValue(activeSequence, localStep, channel); + resync = getSequenceResyncValue(activeSequence, localStep, channel); break; case RAMPDOWN: val = getRampingValue(activeSequence->rampDown, localStep, channel); @@ -243,6 +259,9 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { printf("Could not set AO[%d] voltage.\n", channel); } setEnableDAC(enable, channel, currPDMIndex); + if (channel < 2) { + setResyncDAC(resync, channel, currPDMIndex); + } setRampDownDAC(rampDown, channel, currPDMIndex); } diff --git a/src/server/daq_server_scpi.h b/src/server/daq_server_scpi.h index 4fdf6f08..08e9adf2 100644 --- a/src/server/daq_server_scpi.h +++ b/src/server/daq_server_scpi.h @@ -107,6 +107,7 @@ typedef struct { int numStepsPerRepetition; // How many steps per repetition float* LUT; // LUT for value function pointer bool * enableLUT; + bool * resyncLUT; rampingData_t* rampUp; rampingData_t* rampDown; } sequenceData_t; @@ -131,6 +132,7 @@ extern sequenceInterval_t computeInterval(sequenceData_t *seqData, int step); extern bool isSequenceConfigurable(); extern float getSequenceValue(sequenceData_t *seqData, int seqStep, int channel); extern bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel); +extern bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel); extern float getRampingValue(rampingData_t *rampData, int rampStep, int channel); extern int getRampUpSteps(sequenceData_t *seqData); extern int getRampDownSteps(sequenceData_t *seqData); diff --git a/src/server/scpi_commands.c b/src/server/scpi_commands.c index 7629ba5b..6025297e 100644 --- a/src/server/scpi_commands.c +++ b/src/server/scpi_commands.c @@ -1056,6 +1056,31 @@ static scpi_result_t RP_DAC_SetEnableLUT(scpi_t * context) { } } +static scpi_result_t RP_DAC_SetResyncLUT(scpi_t * context) { + + readyConfigSequence(); + + if(configSeq->LUT != NULL && numSlowDACChan > 0 && isSequenceConfigurable()) { + if(configSeq->resyncLUT != NULL) { + free(configSeq->resyncLUT); + configSeq->resyncLUT = NULL; + } + + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; + printf("Allocating ressyncLUT\n"); + configSeq->resyncLUT = (bool *)calloc(numChan, configSeq->numStepsPerRepetition * sizeof(bool)); + + int n = readAll(newdatasockfd, configSeq->resyncLUT, numSlowDACChan * configSeq->numStepsPerRepetition * sizeof(bool)); + seqState = CONFIG; + if (n < 0) perror("ERROR reading from socket"); + return returnSCPIBool(context, true); + } + else { + return returnSCPIBool(context, false); + } + +} + static scpi_result_t RP_DAC_SetUpLUT(scpi_t * context) { readyConfigSequence(); @@ -1739,6 +1764,7 @@ const scpi_command_t scpi_commands[] = { {.pattern = "RP:DAC:SEQ:CHan?", .callback = RP_DAC_GetNumSlowDACChan,}, {.pattern = "RP:DAC:SEQ:LUT", .callback = RP_DAC_SetValueLUT,}, {.pattern = "RP:DAC:SEQ:LUT:ENaBle", .callback = RP_DAC_SetEnableLUT,}, + {.pattern = "RP:DAC:SEQ:LUT:ReSYNC", .callback = RP_DAC_SetResyncLUT,}, {.pattern = "RP:DAC:SEQ:LUT:UP", .callback = RP_DAC_SetUpLUT,}, {.pattern = "RP:DAC:SEQ:LUT:DOWN", .callback = RP_DAC_SetDownLUT,}, {.pattern = "RP:DAC:SEQ:SET", .callback = RP_DAC_SetSequence,}, From e2685b2daeeea02bf081abef4d62f8d4ea71f96c Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:43:11 +0000 Subject: [PATCH 21/38] Init resync julia client --- src/client/julia/src/Sequence.jl | 52 ++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/client/julia/src/Sequence.jl b/src/client/julia/src/Sequence.jl index db223879..25054eef 100644 --- a/src/client/julia/src/Sequence.jl +++ b/src/client/julia/src/Sequence.jl @@ -134,17 +134,19 @@ abstract type RampingSequence <: AbstractSequence end struct SimpleRampingSequence <: AbstractSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} rampUp::SequenceLUT rampDown::SequenceLUT - function SimpleRampingSequencee(lut::SequenceLUT, up::SequenceLUT, down::SequenceLUT, enable::Union{Array{Bool}, Nothing}=nothing) + function SimpleRampingSequencee(lut::SequenceLUT, up::SequenceLUT, down::SequenceLUT, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(values(lut)) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end - return new(SequenceLUT(lut, repetitions), enable, up, down) + return new(SequenceLUT(lut, repetitions), enable, resync, up, down) end end enableLUT(seq::SimpleRampingSequence) = seq.enable +resyncLUT(seq::SimpleRampingSequence) = seq.resync valueLUT(seq::SimpleRampingSequence) = seq.lut rampUpLUT(seq::SimpleRampingSequence) = nothing rampDownLUT(seq::SimpleRampingSequence) = nothing @@ -158,6 +160,7 @@ end struct HoldBorderRampingSequence <: RampingSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} rampUp::SequenceLUT rampDown::SequenceLUT @@ -170,13 +173,13 @@ struct HoldBorderRampingSequence <: RampingSequence - `lut`,`repetitions`,`enable` are used the same as for a `SimpleSequence` - `rampingSteps` is the number of steps the first and last value of the given sequence are repeated before the sequence is started """ - function HoldBorderRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function HoldBorderRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end up = SequenceLUT(lut[:, 1], rampingSteps) down = SequenceLUT(lut[:, end], rampingSteps) - return new(SequenceLUT(lut, repetitions), enable, up, down) + return new(SequenceLUT(lut, repetitions), enable, resync, up, down) end end @@ -190,6 +193,7 @@ function HoldBorderRampingSequence(rp::RedPitaya, lut, repetitions, enable=nothi end enableLUT(seq::HoldBorderRampingSequence) = seq.enable +resyncLUT(seq::HoldBorderRampingSequence) = seq.resync valueLUT(seq::HoldBorderRampingSequence) = seq.lut rampUpLUT(seq::HoldBorderRampingSequence) = seq.rampUp rampDownLUT(seq::HoldBorderRampingSequence) = seq.rampDown @@ -197,14 +201,15 @@ rampDownLUT(seq::HoldBorderRampingSequence) = seq.rampDown struct ConstantRampingSequence <: RampingSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} ramping::SequenceLUT - function ConstantRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingValue::Float32, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function ConstantRampingSequence(lut::Array{Float32}, repetitions::Integer, rampingValue::Float32, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end rampingLut = SequenceLUT([rampingValue for i = 1:size(lut, 1)], rampingSteps) - return new(SequenceLUT(lut, repetitions), enable, rampingLut) + return new(SequenceLUT(lut, repetitions), enable, resync, rampingLut) end end ConstantRampingSequence(lut::Array{T}, repetitions::Integer, rampingValue::Real, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = ConstantRampingSequence(map(Float32, lut), repetitions, Float32(rampingValue), rampingSteps, enable) @@ -212,6 +217,7 @@ ConstantRampingSequence(lut::Vector{Float32}, repetitions::Integer, rampingValue ConstantRampingSequence(lut::Vector{T}, repetitions::Integer, rampingValue::Real, rampingSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = ConstantRampingSequence(reshape(lut, 1, :), repetitions, rampingValue, rampingSteps, enable) enableLUT(seq::ConstantRampingSequence) = seq.enable +resyncLUT(seq::ConstantRampingSequence) = seq.resync valueLUT(seq::ConstantRampingSequence) = seq.lut rampUpLUT(seq::ConstantRampingSequence) = seq.ramping rampDownLUT(seq::ConstantRampingSequence) = seq.ramping @@ -219,9 +225,10 @@ rampDownLUT(seq::ConstantRampingSequence) = seq.ramping struct StartUpSequence <: RampingSequence lut::SequenceLUT enable::Union{Array{Bool}, Nothing} + resync::Union{Array{Bool}, Nothing} rampUp::SequenceLUT rampDown::SequenceLUT - function StartUpSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function StartUpSequence(lut::Array{Float32}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing, resync::Union{Array{Bool}, Nothing}=nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end @@ -239,7 +246,7 @@ struct StartUpSequence <: RampingSequence end up = SequenceLUT(upLut, 1) down = SequenceLUT(lut[:, end], rampingSteps) - return new(SequenceLUT(lut, repetitions), enable, up, down) + return new(SequenceLUT(lut, repetitions), enable, resync, up, down) end end StartUpSequence(lut::Array{T}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = StartUpSequence(map(Float32, lut), repetitions, rampingSteps, startUpSteps, enable) @@ -247,6 +254,7 @@ StartUpSequence(lut::Array{T}, repetitions::Integer, rampingSteps::Integer, star StartUpSequence(lut::Vector{T}, repetitions::Integer, rampingSteps::Integer, startUpSteps::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = StartUpSequence(reshape(lut, 1, :), repetitions, rampingSteps, startUpSteps, enable) enableLUT(seq::StartUpSequence) = seq.enable +resyncLUT(seq::StartUpSequence) = seq.resync valueLUT(seq::StartUpSequence) = seq.lut rampUpLUT(seq::StartUpSequence) = seq.rampUp rampDownLUT(seq::StartUpSequence) = seq.rampDown @@ -269,10 +277,11 @@ Transmit the client-side representation `seq` to the server and append it to the """ function sequence!(rp::RedPitaya, seq::AbstractSequence) result = true - result &= valueLUT!(rp, valueLUT(seq)) - result &= enableLUT!(rp, enableLUT(seq)) - result &= rampUpLUT!(rp, rampUpLUT(seq)) - result &= rampDownLUT!(rp, rampDownLUT(seq)) + result &= valueLUT!(rp, seq) + result &= enableLUT!(rp, seq) + result &= resyncLUT!(rp, seq) + result &= rampUpLUT!(rp, seq) + result &= rampDownLUT!(rp, seq) result &= setSequence!(rp) return result end @@ -283,11 +292,13 @@ function transmitLUT!(rp::RedPitaya, lut::Array{Float32}, cmd::String, repetitio return parse(Bool, receive(rp)) end +valueLUT!(rp::RedPitaya, lut::AbstractSequence) = valueLUT!(rp, valueLUT(lut)) function valueLUT!(rp::RedPitaya, lut::SequenceLUT) lutFloat32 = map(Float32, values(lut)) return transmitLUT!(rp, lutFloat32, "RP:DAC:SEQ:LUT", repetitions(lut)) end +rampUpLUT!(rp::RedPitaya, lut::AbstractSequence) = rampUpLUT!(rp, rampUpLUT(lut)) function rampUpLUT!(rp::RedPitaya, lut::SequenceLUT) lutFloat32 = map(Float32, values(lut)) return transmitLUT!(rp, lutFloat32, "RP:DAC:SEQ:LUT:UP", repetitions(lut)) @@ -298,6 +309,7 @@ function rampUpLUT!(rp::RedPitaya, lut::Nothing) return true end +rampDownLUT!(rp::RedPitaya, lut::AbstractSequence) = rampDownLUT!(rp, rampDownLUT(lut)) function rampDownLUT!(rp::RedPitaya, lut::SequenceLUT) lutFloat32 = map(Float32, values(lut)) return transmitLUT!(rp, lutFloat32, "RP:DAC:SEQ:LUT:DOWN", repetitions(lut)) @@ -308,6 +320,7 @@ function rampDownLUT!(rp::RedPitaya, lut::Nothing) return true end +enableLUT!(rp::RedPitaya, lut::AbstractSequence) = enableLUT!(rp, enableLUT(lut)) function enableLUT!(rp::RedPitaya, lut::Array) lutBool = map(Bool, lut) send(rp, string("RP:DAC:SEQ:LUT:ENaBle")) @@ -322,6 +335,21 @@ function enableLUT!(rp::RedPitaya, lut::Nothing) return true end +resyncLUT!(rp::RedPitaya, lut::AbstractSequence) = resyncLUT!(rp, resyncLUT(lut)) +function resyncLUT!(rp::RedPitaya, lut::Array) + lutBool = map(Bool, lut) + send(rp, string("RP:DAC:SEQ:LUT:ReSYNC")) + @debug "Writing resync DAC LUT" + write(rp.dataSocket, lutBool) + reply = receive(rp) + return parse(Bool, reply) +end + +function resyncLUT!(rp::RedPitaya, lut::Nothing) + # NOP + return true +end + function seqTiming(seq::AbstractSequence) up = 0 if !isnothing(rampUpLUT(seq)) From b78f39db2fda4f91ae771cb76fae63a59b37429e Mon Sep 17 00:00:00 2001 From: rp_local Date: Tue, 24 Sep 2024 15:54:25 +0000 Subject: [PATCH 22/38] Fix variable name in seq_data_int --- src/fpga/hdl/sequence_slice.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fpga/hdl/sequence_slice.v b/src/fpga/hdl/sequence_slice.v index 67b36e07..ab2e91a5 100644 --- a/src/fpga/hdl/sequence_slice.v +++ b/src/fpga/hdl/sequence_slice.v @@ -42,7 +42,7 @@ assign pdm_value_3[10:0] = seq_data_int[90:80]; // Flags assign enable_dac[1:0] = seq_data_int[97:96]; assign enable_pdm[3:0] = seq_data_int[101:98]; -assign resync_dac[1:0] = seq_data_init[31:30]; +assign resync_dac[1:0] = seq_data_int[31:30]; assign enable_dac_ramp_down[0] = seq_data_int[112]; assign enable_dac_ramp_down[1] = seq_data_int[113]; From 06353ea3d1c2a61ffad5d0e25c0b9571a309b867 Mon Sep 17 00:00:00 2001 From: rp_local Date: Wed, 25 Sep 2024 16:05:18 +0000 Subject: [PATCH 23/38] Init working resync based on aresetn --- src/client/julia/Project.toml | 2 +- src/client/julia/src/Sequence.jl | 12 +++++---- src/fpga/bd/bd.tcl | 9 +++++-- src/fpga/bd/waveform_gen.tcl | 45 ++++++++++++++++++-------------- src/lib/rp-daq-lib.c | 5 ++-- src/server/control.c | 1 + 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/client/julia/Project.toml b/src/client/julia/Project.toml index 654c97b0..26393c4d 100644 --- a/src/client/julia/Project.toml +++ b/src/client/julia/Project.toml @@ -1,7 +1,7 @@ name = "RedPitayaDAQServer" uuid = "c544963a-496b-56d4-a5fe-f99a3f174c8f" authors = ["Tobias Knopp "] -version = "0.8.2" +version = "0.9.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/client/julia/src/Sequence.jl b/src/client/julia/src/Sequence.jl index 25054eef..7b197ed5 100644 --- a/src/client/julia/src/Sequence.jl +++ b/src/client/julia/src/Sequence.jl @@ -103,7 +103,8 @@ Struct representing a sequence in which the server directly takes the values fro """ struct SimpleSequence <: AbstractSequence lut::SequenceLUT - enable::Union{Array{Bool}, Nothing} + enable::Union{Matrix{Bool}, Nothing} + resync::Union{Matrix{Bool}, Nothing} """ SimpleSequence(lut, repetitions, enable=nothing) @@ -114,17 +115,18 @@ struct SimpleSequence <: AbstractSequence - `repetitions::Int32`: the number of times the sequence should be repeated - `emable::Union{Array{Bool}, Nothing}`: matrix containing enable flags """ - function SimpleSequence(lut::Array{Float32}, repetitions::Integer, enable::Union{Array{Bool}, Nothing}=nothing) + function SimpleSequence(lut::Matrix{Float32}, repetitions::Integer, enable::Union{Matrix{Bool}, Nothing}=nothing, resync::Union{Matrix{Bool}, Nothing} = nothing) if !isnothing(enable) && size(lut) != size(enable) throw(DimensionMismatch("Size of enable LUT does not match size of value LUT")) end - return new(SequenceLUT(lut, repetitions), enable) + return new(SequenceLUT(lut, repetitions), enable, resync) end end -SimpleSequence(lut::Array{T}, repetitions::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = SimpleSequence(map(Float32, lut), repetitions, enable) -SimpleSequence(lut::Vector{T}, repetitions::Integer, enable::Union{Array{Bool}, Nothing}=nothing) where T <: Real = SimpleSequence(reshape(lut, 1, :), repetitions, enable) +SimpleSequence(lut::Array{T}, repetitions::Integer, args...) where T <: Real = SimpleSequence(map(Float32, lut), repetitions, args...) +SimpleSequence(lut::Vector{T}, repetitions::Integer, args...) where T <: Real = SimpleSequence(reshape(lut, 1, :), repetitions, args...) enableLUT(seq::SimpleSequence) = seq.enable +resyncLUT(seq::SimpleSequence) = seq.resync valueLUT(seq::SimpleSequence) = seq.lut rampUpLUT(seq::SimpleSequence) = nothing rampDownLUT(seq::SimpleSequence) = nothing diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 206a1a32..e9ae2bab 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -402,6 +402,9 @@ proc create_hier_cell_waveform_awg1 { parentCell nameHier } { # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + set_property -dict [ list \ + CONFIG.IN0_WIDTH {48} \ + ] $xlconcat_0 # Create instance: xlconstant_0, and set properties set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] @@ -572,6 +575,9 @@ proc create_hier_cell_waveform_awg { parentCell nameHier } { # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + set_property -dict [ list \ + CONFIG.IN0_WIDTH {48} \ + ] $xlconcat_0 # Create instance: xlconstant_0, and set properties set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] @@ -3462,6 +3468,7 @@ proc create_root_design { parentCell } { # Restore current instance current_bd_instance $oldCurInst + validate_bd_design save_bd_design } # End of create_root_design() @@ -3474,5 +3481,3 @@ proc create_root_design { parentCell } { create_root_design "" -common::send_gid_msg -ssname BD::TCL -id 2053 -severity "WARNING" "This Tcl script was generated from a block design that has not been validated. It is possible that design <$design_name> may result in errors during validation." - diff --git a/src/fpga/bd/waveform_gen.tcl b/src/fpga/bd/waveform_gen.tcl index ac9b77b2..8b6070f9 100644 --- a/src/fpga/bd/waveform_gen.tcl +++ b/src/fpga/bd/waveform_gen.tcl @@ -127,8 +127,8 @@ pavel-demin:user:axis_variable:1.0\ xilinx.com:ip:dds_compiler:6.0\ xilinx.com:ip:mult_gen:12.0\ jbeuke:user:signal_generator:1.0\ +xilinx.com:ip:util_vector_logic:2.0\ xilinx.com:ip:xlconcat:2.1\ -xilinx.com:ip:xlconstant:1.1\ " set list_ips_missing "" @@ -210,7 +210,7 @@ proc create_root_design { parentCell } { # Create instance: axis_variable_A_channel_1, and set properties set axis_variable_A_channel_1 [ create_bd_cell -type ip -vlnv pavel-demin:user:axis_variable:1.0 axis_variable_A_channel_1 ] set_property -dict [ list \ - CONFIG.AXIS_TDATA_WIDTH {104} \ + CONFIG.AXIS_TDATA_WIDTH {96} \ ] $axis_variable_A_channel_1 # Create instance: dds_compiler_A_channel_1, and set properties @@ -220,6 +220,7 @@ proc create_root_design { parentCell } { CONFIG.DATA_Has_TLAST {Not_Required} \ CONFIG.DDS_Clock_Rate {125} \ CONFIG.Frequency_Resolution {4.440893e-7} \ + CONFIG.Has_ACLKEN {false} \ CONFIG.Has_ARESETn {true} \ CONFIG.Has_Phase_Out {true} \ CONFIG.Has_TREADY {false} \ @@ -235,11 +236,11 @@ proc create_root_design { parentCell } { CONFIG.POFF1 {0} \ CONFIG.Parameter_Entry {System_Parameters} \ CONFIG.PartsPresent {Phase_Generator_and_SIN_COS_LUT} \ - CONFIG.Phase_Increment {Streaming} \ + CONFIG.Phase_Increment {Programmable} \ CONFIG.Phase_Offset_Angles1 {0} \ CONFIG.Phase_Width {48} \ - CONFIG.Phase_offset {Streaming} \ - CONFIG.Resync {true} \ + CONFIG.Phase_offset {Programmable} \ + CONFIG.Resync {false} \ CONFIG.S_PHASE_Has_TUSER {Not_Required} \ CONFIG.Spurious_Free_Dynamic_Range {84} \ ] $dds_compiler_A_channel_1 @@ -264,8 +265,19 @@ proc create_root_design { parentCell } { CONFIG.CFG_DATA_WIDTH {48} \ ] $signal_generator_0 - # Create instance: xlconcat_0, and set properties - set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + # Create instance: util_vector_logic_0, and set properties + set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {not} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_notgate.png} \ + ] $util_vector_logic_0 + + # Create instance: util_vector_logic_1, and set properties + set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_1 # Create instance: xlconcat_A_channel_1, and set properties set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] @@ -273,35 +285,28 @@ proc create_root_design { parentCell } { CONFIG.IN0_WIDTH {48} \ CONFIG.IN1_WIDTH {48} \ CONFIG.IN2_WIDTH {8} \ - CONFIG.NUM_PORTS {3} \ + CONFIG.NUM_PORTS {2} \ ] $xlconcat_A_channel_1 - # Create instance: xlconstant_0, and set properties - set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] - set_property -dict [ list \ - CONFIG.CONST_VAL {0} \ - CONFIG.CONST_WIDTH {7} \ - ] $xlconstant_0 - # Create interface connections - connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_PHASE] + connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_CONFIG] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_DATA [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_DATA] [get_bd_intf_pins signal_generator_0/s_axis] connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_PHASE [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_PHASE] [get_bd_intf_pins signal_generator_0/s_axis_phase] # Create port connections connect_bd_net -net amplitude_A_channel_1_slice1_Dout [get_bd_ports amplitude] [get_bd_pins mult_gen_0/A] + connect_bd_net -net aresetn_1 [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins signal_generator_0/aresetn] [get_bd_pins util_vector_logic_1/Op2] connect_bd_net -net clk_wiz_0_clk_internal [get_bd_ports aclk] [get_bd_pins axis_variable_A_channel_1/aclk] [get_bd_pins dds_compiler_A_channel_1/aclk] [get_bd_pins mult_gen_0/CLK] [get_bd_pins signal_generator_0/clk] connect_bd_net -net freq_1 [get_bd_ports freq] [get_bd_pins xlconcat_A_channel_1/In0] connect_bd_net -net mult_gen_0_P [get_bd_ports wave] [get_bd_pins mult_gen_0/P] connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] connect_bd_net -net phase_A_channel_1_slice1_Dout [get_bd_ports cfg_data] [get_bd_pins signal_generator_0/cfg_data] - connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins xlconcat_0/In0] - connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins signal_generator_0/aresetn] + connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins util_vector_logic_0/Op1] connect_bd_net -net signal_generator_0_m_axis_tdata [get_bd_pins mult_gen_0/B] [get_bd_pins signal_generator_0/m_axis_tdata] connect_bd_net -net signal_generator_0_m_axis_tvalid [get_bd_ports m_axis_data_tvalid_1] [get_bd_pins signal_generator_0/m_axis_tvalid] - connect_bd_net -net xlconcat_0_dout [get_bd_pins xlconcat_0/dout] [get_bd_pins xlconcat_A_channel_1/In2] + connect_bd_net -net util_vector_logic_0_Res [get_bd_pins util_vector_logic_0/Res] [get_bd_pins util_vector_logic_1/Op1] + connect_bd_net -net util_vector_logic_1_Res [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins util_vector_logic_1/Res] connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] - connect_bd_net -net xlconstant_0_dout [get_bd_pins xlconcat_0/In1] [get_bd_pins xlconstant_0/dout] # Create address segments diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 9c495034..842cc84b 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -653,8 +653,8 @@ int setResyncDAC(int8_t value, int channel, int index) { return -1; int bitpos = 14 + channel; - // Reset bit is in the 2-th channel - int offset = 8 * index + 2; + // Reset bits are in the 2nd channel -> bitpos 31:30 + int offset = 8 * index + 1; // clear the bit *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); // set the bit @@ -1313,6 +1313,7 @@ void stopTx() { for(int d=0; d<5; d++) { setPDMAllValuesVolt(0.0, d); setEnableDACAll(1,d); + setResyncDACAll(0,d); } } diff --git a/src/server/control.c b/src/server/control.c index 07868075..db92500b 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -104,6 +104,7 @@ void clearSequence() { for(int d=0; d<6; d++) { setEnableDACAll(1,d); + setResyncDACAll(0,d); } for(int d=0; d<2; d++) { setRampDownDACAll(false,d); From a2c090141c3fb16a2042bda990464e842723e704 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Thu, 26 Sep 2024 07:17:33 +0200 Subject: [PATCH 24/38] fix multi-channel resync issues --- src/server/control.c | 3 ++- src/server/scpi_commands.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/server/control.c b/src/server/control.c index db92500b..8762ba41 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -131,9 +131,10 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { bool result = false; + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; if (seqData->resyncLUT != NULL) { int localStep = seqStep % seqData->numStepsPerRepetition; - result = seqData->resyncLUT[localStep + channel]; + result = seqData->resyncLUT[localStep * numChan + channel]; } return result; } diff --git a/src/server/scpi_commands.c b/src/server/scpi_commands.c index 6025297e..b7308745 100644 --- a/src/server/scpi_commands.c +++ b/src/server/scpi_commands.c @@ -1070,7 +1070,7 @@ static scpi_result_t RP_DAC_SetResyncLUT(scpi_t * context) { printf("Allocating ressyncLUT\n"); configSeq->resyncLUT = (bool *)calloc(numChan, configSeq->numStepsPerRepetition * sizeof(bool)); - int n = readAll(newdatasockfd, configSeq->resyncLUT, numSlowDACChan * configSeq->numStepsPerRepetition * sizeof(bool)); + int n = readAll(newdatasockfd, configSeq->resyncLUT, numChan * configSeq->numStepsPerRepetition * sizeof(bool)); seqState = CONFIG; if (n < 0) perror("ERROR reading from socket"); return returnSCPIBool(context, true); From 14ab693086acfc1fc343de68b98b3942cb69ac4b Mon Sep 17 00:00:00 2001 From: rp_local Date: Thu, 26 Sep 2024 09:23:01 +0000 Subject: [PATCH 25/38] Move resync flag to bit 14 of each DAC channel --- src/fpga/hdl/sequence_slice.v | 5 +++-- src/lib/rp-daq-lib.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/fpga/hdl/sequence_slice.v b/src/fpga/hdl/sequence_slice.v index ab2e91a5..3ffc5840 100644 --- a/src/fpga/hdl/sequence_slice.v +++ b/src/fpga/hdl/sequence_slice.v @@ -42,8 +42,9 @@ assign pdm_value_3[10:0] = seq_data_int[90:80]; // Flags assign enable_dac[1:0] = seq_data_int[97:96]; assign enable_pdm[3:0] = seq_data_int[101:98]; -assign resync_dac[1:0] = seq_data_int[31:30]; +assign resync_dac[0] = seq_data_int[14]; +assign resync_dac[1] = seq_data_int[30]; assign enable_dac_ramp_down[0] = seq_data_int[112]; assign enable_dac_ramp_down[1] = seq_data_int[113]; -endmodule +endmodule \ No newline at end of file diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 842cc84b..28f85cf0 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -652,9 +652,9 @@ int setResyncDAC(int8_t value, int channel, int index) { if (value < 0 || value >= 2) return -1; - int bitpos = 14 + channel; - // Reset bits are in the 2nd channel -> bitpos 31:30 - int offset = 8 * index + 1; + int bitpos = 14; + // Reset bits are in the 14th bit of the respective DAC channel -> 14 and 30 + int offset = 8 * index + channel; // clear the bit *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); // set the bit From 5d4f42d492d13c7f08795e1cc7f95f72dff9e694 Mon Sep 17 00:00:00 2001 From: rp_local Date: Thu, 26 Sep 2024 09:23:34 +0000 Subject: [PATCH 26/38] Restrict getSequenceResyncValue to DAC channel --- src/server/control.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/server/control.c b/src/server/control.c index 8762ba41..1b6b422c 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -131,8 +131,8 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { bool result = false; - int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; - if (seqData->resyncLUT != NULL) { + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; + if (seqData->resyncLUT != NULL && channel < numChan) { int localStep = seqStep % seqData->numStepsPerRepetition; result = seqData->resyncLUT[localStep * numChan + channel]; } @@ -217,6 +217,7 @@ static void setLUTValuesFor(int futureStep, int channel, int currPDMIndex) { if (activeSequence == NULL) { setPDMValueVolt(0.0, channel, currPDMIndex); setEnableDAC(false, channel, currPDMIndex); + setResyncDAC(false, channel, currPDMIndex); setRampDownDAC(false, channel, currPDMIndex); return; } From 3c627929cfd1d1b57e0ec554157fc64a41593672 Mon Sep 17 00:00:00 2001 From: rp_local Date: Fri, 29 Nov 2024 13:07:08 +0000 Subject: [PATCH 27/38] Init test of step counting with writepointer lowest bit --- src/fpga/hdl/sequence_stepper.v | 41 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/fpga/hdl/sequence_stepper.v b/src/fpga/hdl/sequence_stepper.v index 9a28dd9a..25754421 100644 --- a/src/fpga/hdl/sequence_stepper.v +++ b/src/fpga/hdl/sequence_stepper.v @@ -1,36 +1,45 @@ `timescale 1ns / 1ps module sequence_stepper( - input [63:0] writepointer, + input [63:0] writePointer, input [31:0] stepSize, input clk, input aresetn, - output [31:0] step_counter + output [31:0] seq_counter ); -reg [63:0] end_of_step, next_end_of_step; -reg [31:0] step_counter_reg, step_counter_next; +reg [31:0] stepSize_int; +reg [31:0] seq_counter_state; +reg [31:0] sample_counter; +reg wp_prev, wp_next; always @(posedge clk) begin + stepSize_int <= stepSize; + wp_next <= writePointer[0]; if (~aresetn) begin - step_counter_reg <= 0; - step_counter_next <= 0; - end_of_step <= stepSize; - next_end_of_step <= stepSize; + seq_counter_state <= 0; + sample_counter <= stepSize_int; + wp_prev <= 0; end else begin - step_counter_reg <= step_counter_next; - end_of_step <= next_end_of_step; - if (end_of_step < writepointer) begin - next_end_of_step <= end_of_step + stepSize; - step_counter_next <= step_counter_reg + 1; + wp_prev <= wp_next; + if (wp_prev != wp_next) begin + + if (sample_counter == 0) begin + sample_counter <= stepSize_int; + seq_counter_state <= seq_counter_state + 1; + end else begin + sample_counter <= sample_counter - 1; + seq_counter_state <= seq_counter_state; + end + end else begin - next_end_of_step <= next_end_of_step; - step_counter_next <= step_counter_reg; + sample_counter <= sample_counter; + seq_counter_state <= seq_counter_state; end end end -assign step_counter = step_counter_reg; +assign seq_counter = seq_counter_state; endmodule From b7a82592def6c8f64d7df9a9576c00b19382fa90 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Sun, 1 Dec 2024 14:48:28 +0100 Subject: [PATCH 28/38] add sequenceIssue.jl --- src/examples/julia/sequenceIssue.jl | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/examples/julia/sequenceIssue.jl diff --git a/src/examples/julia/sequenceIssue.jl b/src/examples/julia/sequenceIssue.jl new file mode 100644 index 00000000..5d387cb8 --- /dev/null +++ b/src/examples/julia/sequenceIssue.jl @@ -0,0 +1,60 @@ +using RedPitayaDAQServer +using CairoMakie + +# obtain the URL of the RedPitaya +include("config.jl") + +rp = RedPitaya(URLs[1]) +serverMode!(rp, CONFIGURATION) + + +dec = 128 +base_frequency = 125000000 + +samples_per_step = 40 #30*16 +steps_per_frame = 4 +numSamples = steps_per_frame * samples_per_step + +decimation!(rp, dec) +samplesPerPeriod!(rp, 1) +periodsPerFrame!(rp, numSamples) +samplesPerStep!(rp, samples_per_step) +triggerMode!(rp, INTERNAL) + + +amplitudeDAC!(rp, 1, 1, 0.0) +amplitudeDAC!(rp, 2, 1, 0.0 ) + +clearSequence!(rp) + +# Climbing offset for first channel, fixed offset for second channel +seqChan!(rp, 6) +lutB = collect(ones(steps_per_frame)) +lutB[1:2:end] .= 0.0 +lut = collect(cat(-lutB,-lutB*0.3, 0*lutB,0*lutB,0*lutB,0*lutB,dims=2)') +#lut = collect(cat(-lutB,dims=2)')#,lutB,lutB,lutB,lutB,dims=2)') + +lutEnableDACA = ones(Bool, steps_per_frame) + +#enableLUT = collect( cat(lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) +enableLUT = collect( cat(lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) +#enableLUT = collect( cat(lutEnableDACA,dims=2)') #,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) + +seq = SimpleSequence(lut, 300, enableLUT) +sequence!(rp, seq) + +serverMode!(rp, ACQUISITION) +masterTrigger!(rp, true) + +uCurrentPeriod = readFrames(rp, 1, 3) + +masterTrigger!(rp, false) +serverMode!(rp, CONFIGURATION) + +plot = lines(vec(uCurrentPeriod[:,1,:,1]), label = "Rx1") +lines!(plot.axis, vec(uCurrentPeriod[:,2,:,1]), label = "Rx2") +lines!(plot.axis, vec(uCurrentPeriod[:,1,:,2]), label = "Rx1_2") +lines!(plot.axis, vec(uCurrentPeriod[:,2,:,2]), label = "Rx2_2") +axislegend(plot.axis) +save(joinpath(@__DIR__(), "images", "sequenceIssue.png"), plot) +plot \ No newline at end of file From 731826b5bab6776b1669eb4466088f7bd532de3f Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Sun, 1 Dec 2024 17:38:51 +0100 Subject: [PATCH 29/38] fix sequence stepper issue --- src/fpga/bd/bd.tcl | 9 +++---- src/fpga/hdl/sequence_stepper.v | 42 +++++++++++++-------------------- src/lib/rp-daq-lib.c | 4 ++-- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index e9ae2bab..494b4cfb 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -2099,7 +2099,6 @@ proc create_hier_cell_sequencer { parentCell nameHier } { # Create pins create_bd_pin -dir I -type clk aclk - create_bd_pin -dir I -from 63 -to 0 adc_sts create_bd_pin -dir I -type rst aresetn create_bd_pin -dir I bram_aresetn create_bd_pin -dir I -from 31 -to 0 cfg_data @@ -2220,6 +2219,9 @@ proc create_hier_cell_sequencer { parentCell nameHier } { # Create instance: xlconstant_0, and set properties set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] + # Create instance: xlslice_0, and set properties + set xlslice_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_0 ] + # Create instance: zero_constant, and set properties set zero_constant [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 zero_constant ] set_property -dict [ list \ @@ -2240,7 +2242,6 @@ proc create_hier_cell_sequencer { parentCell nameHier } { # Create port connections connect_bd_net -net aclk_1 [get_bd_pins aclk] [get_bd_pins axi_bram_ctrl_0/s_axi_aclk] [get_bd_pins blk_mem_gen_0/clkb] [get_bd_pins sequence_slice_0/clk] [get_bd_pins sequence_stepper_0/clk] - connect_bd_net -net adc_sts_1 [get_bd_pins adc_sts] [get_bd_pins sequence_stepper_0/writepointer] connect_bd_net -net aresetn3_1 [get_bd_pins keep_alive_aresetn] [get_bd_pins util_vector_logic_0/Op2] connect_bd_net -net blk_mem_gen_0_doutb [get_bd_pins blk_mem_gen_0/doutb] [get_bd_pins sequence_slice_0/seq_data] connect_bd_net -net bram_aresetn_1 [get_bd_pins bram_aresetn] [get_bd_pins axi_bram_ctrl_0/s_axi_aresetn] @@ -2267,7 +2268,7 @@ proc create_hier_cell_sequencer { parentCell nameHier } { connect_bd_net -net xlconcat_0_dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconcat_1_dout [get_bd_pins oa_dac] [get_bd_pins xlconcat_1/dout] connect_bd_net -net xlconstant_0_dout [get_bd_pins blk_mem_gen_0/enb] [get_bd_pins xlconstant_0/dout] - connect_bd_net -net xlslice_1_Dout [get_bd_pins pdm_sts] [get_bd_pins bram_element_slice/Din] [get_bd_pins sequence_stepper_0/step_counter] + connect_bd_net -net xlslice_1_Dout [get_bd_pins pdm_sts] [get_bd_pins bram_element_slice/Din] [get_bd_pins sequence_stepper_0/step_counter] [get_bd_pins xlslice_0/Din] connect_bd_net -net zero_constant1_dout [get_bd_pins concat_element_addr/In0] [get_bd_pins zero_constant1/dout] connect_bd_net -net zero_constant_dout [get_bd_pins concat_element_addr/In2] [get_bd_pins zero_constant/dout] @@ -3436,7 +3437,7 @@ proc create_root_design { parentCell } { connect_bd_net -net util_vector_logic_0_Res [get_bd_pins clk_wiz_0/clk_in_sel] [get_bd_pins reset_manager_0/isMaster] [get_bd_pins util_vector_logic_0/Res] connect_bd_net -net write_to_ram_adc_out_A [get_bd_pins counter_trigger/adc0] [get_bd_pins write_to_ram/adc_out_A] connect_bd_net -net write_to_ram_adc_out_B [get_bd_pins counter_trigger/adc1] [get_bd_pins write_to_ram/adc_out_B] - connect_bd_net -net xlconcat_0_dout [get_bd_pins sequencer/adc_sts] [get_bd_pins system/adc_sts] [get_bd_pins write_to_ram/sts_data] + connect_bd_net -net xlconcat_0_dout [get_bd_pins system/adc_sts] [get_bd_pins write_to_ram/sts_data] connect_bd_net -net xlconcat_0_dout1 [get_bd_ports dac_pwm_o] [get_bd_pins sequencer/dout] connect_bd_net -net xlconcat_1_dout [get_bd_pins counter_trigger/counter_trigger_sts] [get_bd_pins system/counter_trigger_sts] connect_bd_net -net xlconstant_0_dout [get_bd_ports ext_DIO1_N] [get_bd_pins xlconstant_0/dout] diff --git a/src/fpga/hdl/sequence_stepper.v b/src/fpga/hdl/sequence_stepper.v index 25754421..2431364e 100644 --- a/src/fpga/hdl/sequence_stepper.v +++ b/src/fpga/hdl/sequence_stepper.v @@ -1,45 +1,37 @@ `timescale 1ns / 1ps module sequence_stepper( - input [63:0] writePointer, input [31:0] stepSize, input clk, input aresetn, - output [31:0] seq_counter + output [31:0] step_counter ); -reg [31:0] stepSize_int; -reg [31:0] seq_counter_state; -reg [31:0] sample_counter; -reg wp_prev, wp_next; +reg [63:0] step_counter_local, step_counter_local_next; +reg [31:0] step_counter_reg, step_counter_next; +reg [31:0] step_size_local; always @(posedge clk) begin - stepSize_int <= stepSize; - wp_next <= writePointer[0]; if (~aresetn) begin - seq_counter_state <= 0; - sample_counter <= stepSize_int; - wp_prev <= 0; + step_counter_reg <= 0; + step_counter_next <= 0; + step_counter_local <= 0; + step_counter_local_next <= 0; + step_size_local <= stepSize-1; end else begin - wp_prev <= wp_next; - if (wp_prev != wp_next) begin - - if (sample_counter == 0) begin - sample_counter <= stepSize_int; - seq_counter_state <= seq_counter_state + 1; - end else begin - sample_counter <= sample_counter - 1; - seq_counter_state <= seq_counter_state; - end - + step_counter_reg <= step_counter_next; + step_counter_local <= step_counter_local_next; + if (step_counter_local == step_size_local) begin + step_counter_local_next <= 0; + step_counter_next <= step_counter_reg + 1; end else begin - sample_counter <= sample_counter; - seq_counter_state <= seq_counter_state; + step_counter_local_next <= step_counter_local + 1; + step_counter_next <= step_counter_reg; end end end -assign seq_counter = seq_counter_state; +assign step_counter = step_counter_reg; endmodule diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 28f85cf0..3cef3572 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -784,11 +784,11 @@ int setPDMAllValuesVolt(float voltage, int channel) { int getSamplesPerStep() { int32_t value = *((int32_t *)(cfg + 4)); - return value; + return value*2/getDecimation(); } int setSamplesPerStep(int samples) { - *((int32_t *)(cfg + 4)) = samples; + *((int32_t *)(cfg + 4)) = samples/2*getDecimation(); return 0; } From cc911a91095dcea37f71d85a01f8ac0f0df9d71b Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 14:53:27 +0100 Subject: [PATCH 30/38] first version of hbridge --- src/client/julia/src/SlowIO.jl | 40 +++ src/examples/julia/config.jl | 1 + src/examples/julia/sequenceIssue.jl | 17 +- src/fpga/bd/bd.tcl | 404 ++++++++++++++++++++++------ src/fpga/bd/hbridgewaveform.tcl | 357 ++++++++++++++++++++++++ src/fpga/build.tcl | 1 + src/fpga/hdl/hbridge_signalgen.v | 82 ++++++ 7 files changed, 816 insertions(+), 86 deletions(-) create mode 100644 src/fpga/bd/hbridgewaveform.tcl create mode 100644 src/fpga/hdl/hbridge_signalgen.v diff --git a/src/client/julia/src/SlowIO.jl b/src/client/julia/src/SlowIO.jl index f3c80011..26fcd3f4 100644 --- a/src/client/julia/src/SlowIO.jl +++ b/src/client/julia/src/SlowIO.jl @@ -182,3 +182,43 @@ end scpiCommand(::typeof(DIO), pin) = string("RP:DIO:", DIOPinToCommand(pin), "?") scpiReturn(::typeof(DIO)) = String parseReturn(::typeof(DIO), ret) = occursin("ON", ret) + + + + + + +export DIOHBridge! +""" +DIOHBridge!(rp::RedPitaya, pin::DIOPins, val::Bool) + +Set the value of DIOHBridge pin `pin` to the value `val`. +# Example +```julia +julia> DIOHBridge!(rp, DIO7_P, true) +true +``` +""" +function DIOHBridge!(rp::RedPitaya, pin, val) + return query(rp, scpiCommand(DIOHBridge!, pin, val), scpiReturn(DIOHBridge!)) +end +scpiCommand(::typeof(DIOHBridge!), pin::DIOPins, val::Bool) = string("RP:DIO:", DIOPinToCommand(pin), ":HBRIDGE ", (val ? "ON" : "OFF")) +scpiReturn(::typeof(DIOHBridge!)) = Bool + +export DIOHBridge +""" + DIOHBridge(rp::RedPitaya, pin::DIOPins) + +Get the value of DIOHBridge pin `pin`. +# Example +```julia +julia>DIOHBridge(rp, DIO7_P) +true +``` +""" +function DIOHBridge(rp::RedPitaya, pin) + return parseReturn(DIOHBridge, query(rp, scpiCommand(DIOHBridge, pin), scpiReturn(DIOHBridge))) +end +scpiCommand(::typeof(DIOHBridge), pin) = string("RP:DIO:", DIOPinToCommand(pin), ":HBRIDGE?") +scpiReturn(::typeof(DIOHBridge)) = String +parseReturn(::typeof(DIOHBridge), ret) = occursin("ON", ret) \ No newline at end of file diff --git a/src/examples/julia/config.jl b/src/examples/julia/config.jl index ec096412..6e2da7e9 100644 --- a/src/examples/julia/config.jl +++ b/src/examples/julia/config.jl @@ -1,3 +1,4 @@ # URLs= ["rp-f08ccb.local", "rp-f08caa.local"] URLs= ["192.168.1.100"]#, "192.168.2.17"] +# URLs= ["192.168.178.65"]#, "192.168.178.95"] mkpath("images") \ No newline at end of file diff --git a/src/examples/julia/sequenceIssue.jl b/src/examples/julia/sequenceIssue.jl index 5d387cb8..021d2a1a 100644 --- a/src/examples/julia/sequenceIssue.jl +++ b/src/examples/julia/sequenceIssue.jl @@ -11,7 +11,7 @@ serverMode!(rp, CONFIGURATION) dec = 128 base_frequency = 125000000 -samples_per_step = 40 #30*16 +samples_per_step = 4000 #30*16 steps_per_frame = 4 numSamples = steps_per_frame * samples_per_step @@ -21,9 +21,10 @@ periodsPerFrame!(rp, numSamples) samplesPerStep!(rp, samples_per_step) triggerMode!(rp, INTERNAL) - -amplitudeDAC!(rp, 1, 1, 0.0) -amplitudeDAC!(rp, 2, 1, 0.0 ) +frequencyDAC!(rp, 1, 1, base_frequency/samples_per_step/dec) +frequencyDAC!(rp, 2, 1, base_frequency/samples_per_step/dec) +amplitudeDAC!(rp, 1, 1, 0.2) +amplitudeDAC!(rp, 2, 1, 0.2 ) clearSequence!(rp) @@ -40,21 +41,21 @@ lutEnableDACA = ones(Bool, steps_per_frame) enableLUT = collect( cat(lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) #enableLUT = collect( cat(lutEnableDACA,dims=2)') #,lutEnableDACA,lutEnableDACA,lutEnableDACA,lutEnableDACA,dims=2)' ) -seq = SimpleSequence(lut, 300, enableLUT) +seq = SimpleSequence(lut, 2, enableLUT) sequence!(rp, seq) serverMode!(rp, ACQUISITION) masterTrigger!(rp, true) -uCurrentPeriod = readFrames(rp, 1, 3) +uCurrentPeriod = readFrames(rp, 1, 200) masterTrigger!(rp, false) serverMode!(rp, CONFIGURATION) plot = lines(vec(uCurrentPeriod[:,1,:,1]), label = "Rx1") lines!(plot.axis, vec(uCurrentPeriod[:,2,:,1]), label = "Rx2") -lines!(plot.axis, vec(uCurrentPeriod[:,1,:,2]), label = "Rx1_2") -lines!(plot.axis, vec(uCurrentPeriod[:,2,:,2]), label = "Rx2_2") +#lines!(plot.axis, vec(uCurrentPeriod[:,1,:,2]), label = "Rx1_2") +#lines!(plot.axis, vec(uCurrentPeriod[:,2,:,2]), label = "Rx2_2") axislegend(plot.axis) save(joinpath(@__DIR__(), "images", "sequenceIssue.png"), plot) plot \ No newline at end of file diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 494b4cfb..9576f109 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -47,7 +47,7 @@ if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { # The design that will be created by this Tcl script contains the following # block design container source references: -# signal_calib, signal_ramp, waveform_gen +# hbridgewaveform, signal_calib, signal_ramp, waveform_gen # Please add the sources before sourcing this Tcl script. @@ -227,7 +227,7 @@ wave_awg_composer\ # CHECK Block Design Container Sources ################################################################## set bCheckSources 1 -set list_bdc_active "signal_calib, signal_ramp, waveform_gen" +set list_bdc_active "hbridgewaveform, signal_calib, signal_ramp, waveform_gen" array set map_bdc_missing {} set map_bdc_missing(ACTIVE) "" @@ -235,6 +235,7 @@ set map_bdc_missing(BDC) "" if { $bCheckSources == 1 } { set list_check_srcs "\ +hbridgewaveform \ signal_calib \ signal_ramp \ waveform_gen \ @@ -885,16 +886,8 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { CONFIG.LOCK_PROPAGATE {0} \ ] $waveform_gen_2 - # Create instance: waveform_gen_3, and set properties - set waveform_gen_3 [ create_bd_cell -type container -reference waveform_gen waveform_gen_3 ] - set_property -dict [ list \ - CONFIG.ACTIVE_SIM_BD {waveform_gen.bd} \ - CONFIG.ACTIVE_SYNTH_BD {waveform_gen.bd} \ - CONFIG.ENABLE_DFX {0} \ - CONFIG.LIST_SIM_BD {waveform_gen.bd} \ - CONFIG.LIST_SYNTH_BD {waveform_gen.bd} \ - CONFIG.LOCK_PROPAGATE {0} \ - ] $waveform_gen_3 + # Create instance: xlconstant_0, and set properties + set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] # Create interface connections connect_bd_intf_net -intf_net awg_bram_1 [get_bd_intf_pins awg_bram] [get_bd_intf_pins waveform_awg1/S_AXI] @@ -902,12 +895,12 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { # Create port connections connect_bd_net -net Din_1 [get_bd_pins Din] [get_bd_pins signal_cfg_slice_0/cfg_data] connect_bd_net -net bram_aresetn_1 [get_bd_pins bram_aresetn] [get_bd_pins waveform_awg1/bram_aresetn] - connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp_0/aclk] [get_bd_pins waveform_awg1/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] [get_bd_pins waveform_gen_3/aclk] + connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp_0/aclk] [get_bd_pins waveform_awg1/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net enable_ramping_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp_0/enableRamping] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] - connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] - connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_pins aresetn] [get_bd_pins signal_ramp_0/aresetn] [get_bd_pins waveform_awg1/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] [get_bd_pins waveform_gen_3/aresetn] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] + connect_bd_net -net rst_ps7_0_125M_peripheral_aresetn [get_bd_pins aresetn] [get_bd_pins signal_ramp_0/aresetn] [get_bd_pins waveform_awg1/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] @@ -925,10 +918,8 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { connect_bd_net -net signal_cfg_slice_0_comp_2_cfg [get_bd_pins signal_cfg_slice_0/comp_2_cfg] [get_bd_pins waveform_gen_2/cfg_data] connect_bd_net -net signal_cfg_slice_0_comp_2_freq [get_bd_pins signal_cfg_slice_0/comp_2_freq] [get_bd_pins waveform_gen_2/freq] connect_bd_net -net signal_cfg_slice_0_comp_2_phase [get_bd_pins signal_cfg_slice_0/comp_2_phase] [get_bd_pins waveform_gen_2/phase] - connect_bd_net -net signal_cfg_slice_0_comp_3_amp [get_bd_pins signal_cfg_slice_0/comp_3_amp] [get_bd_pins waveform_gen_3/amplitude] - connect_bd_net -net signal_cfg_slice_0_comp_3_cfg [get_bd_pins signal_cfg_slice_0/comp_3_cfg] [get_bd_pins waveform_gen_3/cfg_data] - connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg1/freq] [get_bd_pins waveform_gen_3/freq] - connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg1/phase] [get_bd_pins waveform_gen_3/phase] + connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg1/freq] + connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg1/phase] connect_bd_net -net signal_cfg_slice_0_offset [get_bd_pins signal_cfg_slice_0/offset] [get_bd_pins signal_composer_0/offset] connect_bd_net -net signal_cfg_slice_0_ramp_freq [get_bd_pins signal_cfg_slice_0/ramp_freq] [get_bd_pins signal_ramp_0/freq] connect_bd_net -net signal_composer_0_signal_out [get_bd_pins signal_composer_0/signal_out] [get_bd_pins signal_ramp_0/signal_in] @@ -943,7 +934,7 @@ proc create_hier_cell_signal_compose1 { parentCell nameHier } { connect_bd_net -net waveform_gen_1_wave [get_bd_pins signal_composer_0/wave1] [get_bd_pins waveform_gen_1/wave] connect_bd_net -net waveform_gen_2_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid2] [get_bd_pins waveform_gen_2/m_axis_data_tvalid_1] connect_bd_net -net waveform_gen_2_wave [get_bd_pins signal_composer_0/wave2] [get_bd_pins waveform_gen_2/wave] - connect_bd_net -net waveform_gen_3_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid3] [get_bd_pins waveform_gen_3/m_axis_data_tvalid_1] + connect_bd_net -net xlconstant_0_dout [get_bd_pins signal_composer_0/valid3] [get_bd_pins xlconstant_0/dout] # Restore current instance current_bd_instance $oldCurInst @@ -1081,29 +1072,21 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { CONFIG.LOCK_PROPAGATE {0} \ ] $waveform_gen_2 - # Create instance: waveform_gen_3, and set properties - set waveform_gen_3 [ create_bd_cell -type container -reference waveform_gen waveform_gen_3 ] - set_property -dict [ list \ - CONFIG.ACTIVE_SIM_BD {waveform_gen.bd} \ - CONFIG.ACTIVE_SYNTH_BD {waveform_gen.bd} \ - CONFIG.ENABLE_DFX {0} \ - CONFIG.LIST_SIM_BD {waveform_gen.bd} \ - CONFIG.LIST_SYNTH_BD {waveform_gen.bd} \ - CONFIG.LOCK_PROPAGATE {0} \ - ] $waveform_gen_3 + # Create instance: xlconstant_0, and set properties + set xlconstant_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 ] # Create interface connections connect_bd_intf_net -intf_net awg_bram_1 [get_bd_intf_pins awg_bram] [get_bd_intf_pins waveform_awg/S_AXI] # Create port connections connect_bd_net -net Din_1 [get_bd_pins Din] [get_bd_pins signal_cfg_slice_0/cfg_data] - connect_bd_net -net aclk_1 [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp/aclk] [get_bd_pins waveform_awg/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] [get_bd_pins waveform_gen_3/aclk] - connect_bd_net -net aresetn_1 [get_bd_pins aresetn] [get_bd_pins signal_ramp/aresetn] [get_bd_pins waveform_awg/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] [get_bd_pins waveform_gen_3/aresetn] + connect_bd_net -net aclk_1 [get_bd_pins aclk] [get_bd_pins signal_calib_0/aclk] [get_bd_pins signal_composer_0/clk] [get_bd_pins signal_ramp/aclk] [get_bd_pins waveform_awg/aclk] [get_bd_pins waveform_gen_0/aclk] [get_bd_pins waveform_gen_1/aclk] [get_bd_pins waveform_gen_2/aclk] + connect_bd_net -net aresetn_1 [get_bd_pins aresetn] [get_bd_pins signal_ramp/aresetn] [get_bd_pins waveform_awg/aresetn] [get_bd_pins waveform_gen_0/aresetn] [get_bd_pins waveform_gen_1/aresetn] [get_bd_pins waveform_gen_2/aresetn] connect_bd_net -net bram_aresetn_1 [get_bd_pins bram_aresetn] [get_bd_pins waveform_awg/bram_aresetn] connect_bd_net -net disable_dac_1 [get_bd_pins disable_dac] [get_bd_pins signal_composer_0/disable_dac] connect_bd_net -net offset_1 [get_bd_pins offset] [get_bd_pins signal_composer_0/seq] connect_bd_net -net ramping_enable_1 [get_bd_pins enable_ramping] [get_bd_pins signal_ramp/enableRamping] - connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] [get_bd_pins waveform_gen_3/resync] + connect_bd_net -net resync_dac_1 [get_bd_pins resync_dac] [get_bd_pins waveform_gen_0/resync] [get_bd_pins waveform_gen_1/resync] [get_bd_pins waveform_gen_2/resync] connect_bd_net -net signal_calib_0_signal_out [get_bd_pins S] [get_bd_pins signal_calib_0/signal_out] connect_bd_net -net signal_cfg_slice_0_calib_limit_lower [get_bd_pins signal_cfg_slice_0/calib_limit_lower] connect_bd_net -net signal_cfg_slice_0_calib_limit_upper [get_bd_pins signal_cfg_slice_0/calib_limit_upper] @@ -1121,10 +1104,8 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { connect_bd_net -net signal_cfg_slice_0_comp_2_cfg [get_bd_pins signal_cfg_slice_0/comp_2_cfg] [get_bd_pins waveform_gen_2/cfg_data] connect_bd_net -net signal_cfg_slice_0_comp_2_freq [get_bd_pins signal_cfg_slice_0/comp_2_freq] [get_bd_pins waveform_gen_2/freq] connect_bd_net -net signal_cfg_slice_0_comp_2_phase [get_bd_pins signal_cfg_slice_0/comp_2_phase] [get_bd_pins waveform_gen_2/phase] - connect_bd_net -net signal_cfg_slice_0_comp_3_amp [get_bd_pins signal_cfg_slice_0/comp_3_amp] [get_bd_pins waveform_gen_3/amplitude] - connect_bd_net -net signal_cfg_slice_0_comp_3_cfg [get_bd_pins signal_cfg_slice_0/comp_3_cfg] [get_bd_pins waveform_gen_3/cfg_data] - connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg/freq] [get_bd_pins waveform_gen_3/freq] - connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg/phase] [get_bd_pins waveform_gen_3/phase] + connect_bd_net -net signal_cfg_slice_0_comp_3_freq [get_bd_pins signal_cfg_slice_0/comp_3_freq] [get_bd_pins waveform_awg/freq] + connect_bd_net -net signal_cfg_slice_0_comp_3_phase [get_bd_pins signal_cfg_slice_0/comp_3_phase] [get_bd_pins waveform_awg/phase] connect_bd_net -net signal_cfg_slice_0_offset [get_bd_pins signal_cfg_slice_0/offset] [get_bd_pins signal_composer_0/offset] connect_bd_net -net signal_cfg_slice_0_ramp_freq [get_bd_pins signal_cfg_slice_0/ramp_freq] [get_bd_pins signal_ramp/freq] connect_bd_net -net signal_composer_0_signal_out [get_bd_pins signal_composer_0/signal_out] [get_bd_pins signal_ramp/signal_in] @@ -1139,7 +1120,7 @@ proc create_hier_cell_signal_compose { parentCell nameHier } { connect_bd_net -net waveform_gen_1_wave [get_bd_pins signal_composer_0/wave1] [get_bd_pins waveform_gen_1/wave] connect_bd_net -net waveform_gen_2_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid2] [get_bd_pins waveform_gen_2/m_axis_data_tvalid_1] connect_bd_net -net waveform_gen_2_wave [get_bd_pins signal_composer_0/wave2] [get_bd_pins waveform_gen_2/wave] - connect_bd_net -net waveform_gen_3_m_axis_data_tvalid_1 [get_bd_pins signal_composer_0/valid3] [get_bd_pins waveform_gen_3/m_axis_data_tvalid_1] + connect_bd_net -net xlconstant_0_dout [get_bd_pins signal_composer_0/valid3] [get_bd_pins xlconstant_0/dout] # Restore current instance current_bd_instance $oldCurInst @@ -2696,9 +2677,12 @@ proc create_hier_cell_DIO { parentCell nameHier } { # Create interface pins # Create pins + create_bd_pin -dir I aresetn + create_bd_pin -dir I -from 1663 -to 0 cfg_dac create_bd_pin -dir I -from 95 -to 0 cfg_in create_bd_pin -dir I -type clk clk create_bd_pin -dir O -from 31 -to 0 dio_data_clocked + create_bd_pin -dir I -from 1 -to 0 enable_dac create_bd_pin -dir IO ext_DIO2_N create_bd_pin -dir IO ext_DIO3_N create_bd_pin -dir IO ext_DIO4_N @@ -2707,29 +2691,30 @@ proc create_hier_cell_DIO { parentCell nameHier } { create_bd_pin -dir IO ext_DIO6_P create_bd_pin -dir IO ext_DIO7_N create_bd_pin -dir IO ext_DIO7_P + create_bd_pin -dir I -from 1 -to 0 resync + + # Create instance: hbridgewaveform_0, and set properties + set hbridgewaveform_0 [ create_bd_cell -type container -reference hbridgewaveform hbridgewaveform_0 ] + set_property -dict [ list \ + CONFIG.ACTIVE_SIM_BD {hbridgewaveform.bd} \ + CONFIG.ACTIVE_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.ENABLE_DFX {0} \ + CONFIG.LIST_SIM_BD {hbridgewaveform.bd} \ + CONFIG.LIST_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.LOCK_PROPAGATE {0} \ + ] $hbridgewaveform_0 + + # Create instance: hbridgewaveform_1, and set properties + set hbridgewaveform_1 [ create_bd_cell -type container -reference hbridgewaveform hbridgewaveform_1 ] + set_property -dict [ list \ + CONFIG.ACTIVE_SIM_BD {hbridgewaveform.bd} \ + CONFIG.ACTIVE_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.ENABLE_DFX {0} \ + CONFIG.LIST_SIM_BD {hbridgewaveform.bd} \ + CONFIG.LIST_SYNTH_BD {hbridgewaveform.bd} \ + CONFIG.LOCK_PROPAGATE {0} \ + ] $hbridgewaveform_1 - # Create instance: rp_iobuf_0, and set properties - set block_name rp_iobuf - set block_cell_name rp_iobuf_0 - if { [catch {set rp_iobuf_0 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { - catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } elseif { $rp_iobuf_0 eq "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } - - # Create instance: rp_iobuf_1, and set properties - set block_name rp_iobuf - set block_cell_name rp_iobuf_1 - if { [catch {set rp_iobuf_1 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { - catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } elseif { $rp_iobuf_1 eq "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} - return 1 - } - # Create instance: rp_iobuf_2, and set properties set block_name rp_iobuf set block_cell_name rp_iobuf_2 @@ -2796,6 +2781,92 @@ proc create_hier_cell_DIO { parentCell nameHier } { return 1 } + # Create instance: rp_iobuf_8, and set properties + set block_name rp_iobuf + set block_cell_name rp_iobuf_8 + if { [catch {set rp_iobuf_8 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { + catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } elseif { $rp_iobuf_8 eq "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } + + # Create instance: rp_iobuf_9, and set properties + set block_name rp_iobuf + set block_cell_name rp_iobuf_9 + if { [catch {set rp_iobuf_9 [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { + catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } elseif { $rp_iobuf_9 eq "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } + + # Create instance: util_vector_logic_0, and set properties + set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {and} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_andgate.png} \ + ] $util_vector_logic_0 + + # Create instance: util_vector_logic_1, and set properties + set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_1 + + # Create instance: util_vector_logic_2, and set properties + set util_vector_logic_2 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_2 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_2 + + # Create instance: util_vector_logic_3, and set properties + set util_vector_logic_3 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_3 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_3 + + # Create instance: util_vector_logic_4, and set properties + set util_vector_logic_4 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_4 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_4 + + # Create instance: util_vector_logic_5, and set properties + set util_vector_logic_5 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_5 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_5 + + # Create instance: util_vector_logic_6, and set properties + set util_vector_logic_6 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_6 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {and} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_andgate.png} \ + ] $util_vector_logic_6 + + # Create instance: util_vector_logic_7, and set properties + set util_vector_logic_7 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_7 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {or} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_orgate.png} \ + ] $util_vector_logic_7 + # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] set_property -dict [ list \ @@ -2965,6 +3036,150 @@ proc create_hier_cell_DIO { parentCell nameHier } { CONFIG.DOUT_WIDTH {1} \ ] $xlslice_17 + # Create instance: xlslice_18, and set properties + set xlslice_18 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_18 ] + set_property -dict [ list \ + CONFIG.DIN_WIDTH {2} \ + ] $xlslice_18 + + # Create instance: xlslice_19, and set properties + set xlslice_19 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_19 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {175} \ + CONFIG.DIN_TO {128} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_19 + + # Create instance: xlslice_20, and set properties + set xlslice_20 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_20 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {239} \ + CONFIG.DIN_TO {192} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_20 + + # Create instance: xlslice_21, and set properties + set xlslice_21 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_21 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {127} \ + CONFIG.DIN_TO {112} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {16} \ + ] $xlslice_21 + + # Create instance: xlslice_22, and set properties + set xlslice_22 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_22 ] + set_property -dict [ list \ + CONFIG.DIN_WIDTH {2} \ + ] $xlslice_22 + + # Create instance: xlslice_23, and set properties + set xlslice_23 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_23 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {95} \ + CONFIG.DIN_TO {88} \ + CONFIG.DIN_WIDTH {96} \ + CONFIG.DOUT_WIDTH {8} \ + ] $xlslice_23 + + # Create instance: xlslice_24, and set properties + set xlslice_24 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_24 ] + set_property -dict [ list \ + CONFIG.DIN_WIDTH {8} \ + ] $xlslice_24 + + # Create instance: xlslice_25, and set properties + set xlslice_25 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_25 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {8} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_25 + + # Create instance: xlslice_26, and set properties + set xlslice_26 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_26 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {175} \ + CONFIG.DIN_TO {128} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_26 + + # Create instance: xlslice_27, and set properties + set xlslice_27 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_27 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {239} \ + CONFIG.DIN_TO {192} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {48} \ + ] $xlslice_27 + + # Create instance: xlslice_28, and set properties + set xlslice_28 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_28 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {127} \ + CONFIG.DIN_TO {112} \ + CONFIG.DIN_WIDTH {832} \ + CONFIG.DOUT_WIDTH {16} \ + ] $xlslice_28 + + # Create instance: xlslice_29, and set properties + set xlslice_29 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_29 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {2} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_29 + + # Create instance: xlslice_30, and set properties + set xlslice_30 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_30 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1663} \ + CONFIG.DIN_TO {832} \ + CONFIG.DIN_WIDTH {1664} \ + CONFIG.DOUT_WIDTH {832} \ + ] $xlslice_30 + + # Create instance: xlslice_31, and set properties + set xlslice_31 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_31 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {831} \ + CONFIG.DIN_TO {0} \ + CONFIG.DIN_WIDTH {1664} \ + CONFIG.DOUT_WIDTH {832} \ + ] $xlslice_31 + + # Create instance: xlslice_32, and set properties + set xlslice_32 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_32 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {1} \ + CONFIG.DIN_TO {1} \ + CONFIG.DIN_WIDTH {2} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_32 + + # Create instance: xlslice_33, and set properties + set xlslice_33 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_33 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {2} \ + CONFIG.DIN_TO {2} \ + CONFIG.DIN_WIDTH {8} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_33 + + # Create instance: xlslice_34, and set properties + set xlslice_34 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_34 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {3} \ + CONFIG.DIN_TO {3} \ + CONFIG.DIN_WIDTH {8} \ + CONFIG.DOUT_WIDTH {1} \ + ] $xlslice_34 + # Create port connections connect_bd_net -net Net [get_bd_pins ext_DIO6_P] [get_bd_pins rp_iobuf_2/val_tri] connect_bd_net -net Net1 [get_bd_pins ext_DIO6_N] [get_bd_pins rp_iobuf_3/val_tri] @@ -2972,38 +3187,71 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net Net3 [get_bd_pins ext_DIO4_N] [get_bd_pins rp_iobuf_5/val_tri] connect_bd_net -net Net4 [get_bd_pins ext_DIO3_N] [get_bd_pins rp_iobuf_6/val_tri] connect_bd_net -net Net5 [get_bd_pins ext_DIO2_N] [get_bd_pins rp_iobuf_7/val_tri] - connect_bd_net -net Net6 [get_bd_pins ext_DIO7_P] [get_bd_pins rp_iobuf_0/val_tri] - connect_bd_net -net Net7 [get_bd_pins ext_DIO7_N] [get_bd_pins rp_iobuf_1/val_tri] - connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins clk] [get_bd_pins rp_iobuf_0/clk] [get_bd_pins rp_iobuf_1/clk] [get_bd_pins rp_iobuf_2/clk] [get_bd_pins rp_iobuf_3/clk] [get_bd_pins rp_iobuf_4/clk] [get_bd_pins rp_iobuf_5/clk] [get_bd_pins rp_iobuf_6/clk] [get_bd_pins rp_iobuf_7/clk] - connect_bd_net -net rp_iobuf_0_val_in_clocked [get_bd_pins rp_iobuf_0/val_in_clocked] [get_bd_pins xlconcat_0/In0] - connect_bd_net -net rp_iobuf_1_val_in_clocked [get_bd_pins rp_iobuf_1/val_in_clocked] [get_bd_pins xlconcat_0/In1] + connect_bd_net -net Net6 [get_bd_pins ext_DIO7_P] [get_bd_pins rp_iobuf_8/val_tri] + connect_bd_net -net Net7 [get_bd_pins ext_DIO7_N] [get_bd_pins rp_iobuf_9/val_tri] + connect_bd_net -net aresetn_1 [get_bd_pins aresetn] [get_bd_pins hbridgewaveform_0/aresetn] [get_bd_pins hbridgewaveform_1/aresetn] + connect_bd_net -net cfg_dac_1 [get_bd_pins cfg_dac] [get_bd_pins xlslice_30/Din] [get_bd_pins xlslice_31/Din] + connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins clk] [get_bd_pins hbridgewaveform_0/aclk] [get_bd_pins hbridgewaveform_1/aclk] [get_bd_pins rp_iobuf_2/clk] [get_bd_pins rp_iobuf_3/clk] [get_bd_pins rp_iobuf_4/clk] [get_bd_pins rp_iobuf_5/clk] [get_bd_pins rp_iobuf_6/clk] [get_bd_pins rp_iobuf_7/clk] [get_bd_pins rp_iobuf_8/clk] [get_bd_pins rp_iobuf_9/clk] + connect_bd_net -net enable_dac_1 [get_bd_pins enable_dac] [get_bd_pins xlslice_18/Din] [get_bd_pins xlslice_32/Din] + connect_bd_net -net enable_dac_2 [get_bd_pins hbridgewaveform_1/enable_dac] [get_bd_pins util_vector_logic_6/Res] + connect_bd_net -net hbridgewaveform_0_H1out [get_bd_pins hbridgewaveform_0/H1out] [get_bd_pins util_vector_logic_2/Op2] + connect_bd_net -net hbridgewaveform_0_H2out [get_bd_pins hbridgewaveform_0/H2out] [get_bd_pins util_vector_logic_3/Op2] + connect_bd_net -net hbridgewaveform_1_H1out [get_bd_pins hbridgewaveform_1/H1out] [get_bd_pins util_vector_logic_4/Op2] + connect_bd_net -net hbridgewaveform_1_H2out [get_bd_pins hbridgewaveform_1/H2out] [get_bd_pins util_vector_logic_5/Op2] + connect_bd_net -net resync_1 [get_bd_pins resync] [get_bd_pins xlslice_22/Din] [get_bd_pins xlslice_29/Din] connect_bd_net -net rp_iobuf_2_val_in_clocked [get_bd_pins rp_iobuf_2/val_in_clocked] [get_bd_pins xlconcat_0/In2] connect_bd_net -net rp_iobuf_3_val_in_clocked [get_bd_pins rp_iobuf_3/val_in_clocked] [get_bd_pins xlconcat_0/In3] connect_bd_net -net rp_iobuf_4_val_in_clocked [get_bd_pins rp_iobuf_4/val_in_clocked] [get_bd_pins xlconcat_0/In4] connect_bd_net -net rp_iobuf_5_val_in_clocked [get_bd_pins rp_iobuf_5/val_in_clocked] [get_bd_pins xlconcat_0/In5] connect_bd_net -net rp_iobuf_6_val_in_clocked [get_bd_pins rp_iobuf_6/val_in_clocked] [get_bd_pins xlconcat_0/In6] connect_bd_net -net rp_iobuf_7_val_in_clocked [get_bd_pins rp_iobuf_7/val_in_clocked] [get_bd_pins xlconcat_0/In7] - connect_bd_net -net system_cfg_data1 [get_bd_pins cfg_in] [get_bd_pins xlslice_4/Din] [get_bd_pins xlslice_5/Din] + connect_bd_net -net rp_iobuf_8_val_in_clocked [get_bd_pins rp_iobuf_8/val_in_clocked] [get_bd_pins xlconcat_0/In0] + connect_bd_net -net rp_iobuf_9_val_in_clocked [get_bd_pins rp_iobuf_9/val_in_clocked] [get_bd_pins xlconcat_0/In1] + connect_bd_net -net system_cfg_data1 [get_bd_pins cfg_in] [get_bd_pins xlslice_23/Din] [get_bd_pins xlslice_4/Din] [get_bd_pins xlslice_5/Din] + connect_bd_net -net util_vector_logic_0_Res [get_bd_pins hbridgewaveform_0/enable_dac] [get_bd_pins util_vector_logic_0/Res] + connect_bd_net -net util_vector_logic_1_Res [get_bd_pins util_vector_logic_0/Op1] [get_bd_pins util_vector_logic_1/Res] + connect_bd_net -net util_vector_logic_2_Res [get_bd_pins rp_iobuf_8/val_out] [get_bd_pins util_vector_logic_2/Res] + connect_bd_net -net util_vector_logic_3_Res [get_bd_pins rp_iobuf_9/val_out] [get_bd_pins util_vector_logic_3/Res] + connect_bd_net -net util_vector_logic_4_Res [get_bd_pins rp_iobuf_2/val_out] [get_bd_pins util_vector_logic_4/Res] + connect_bd_net -net util_vector_logic_5_Res [get_bd_pins rp_iobuf_3/val_out] [get_bd_pins util_vector_logic_5/Res] + connect_bd_net -net util_vector_logic_7_Res [get_bd_pins util_vector_logic_6/Op1] [get_bd_pins util_vector_logic_7/Res] connect_bd_net -net xlconcat_0_dout2 [get_bd_pins dio_data_clocked] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconstant_1_dout [get_bd_pins xlconcat_0/In8] [get_bd_pins xlconstant_1/dout] - connect_bd_net -net xlslice_0_Dout [get_bd_pins rp_iobuf_0/val_out] [get_bd_pins xlslice_0/Dout] - connect_bd_net -net xlslice_10_Dout [get_bd_pins rp_iobuf_2/val_out] [get_bd_pins xlslice_10/Dout] - connect_bd_net -net xlslice_11_Dout [get_bd_pins rp_iobuf_3/val_out] [get_bd_pins xlslice_11/Dout] + connect_bd_net -net xlslice_0_Dout [get_bd_pins util_vector_logic_2/Op1] [get_bd_pins xlslice_0/Dout] + connect_bd_net -net xlslice_10_Dout [get_bd_pins util_vector_logic_4/Op1] [get_bd_pins xlslice_10/Dout] + connect_bd_net -net xlslice_11_Dout [get_bd_pins util_vector_logic_5/Op1] [get_bd_pins xlslice_11/Dout] connect_bd_net -net xlslice_12_Dout [get_bd_pins rp_iobuf_4/val_out] [get_bd_pins xlslice_12/Dout] connect_bd_net -net xlslice_13_Dout [get_bd_pins rp_iobuf_5/direction] [get_bd_pins xlslice_13/Dout] connect_bd_net -net xlslice_14_Dout [get_bd_pins rp_iobuf_6/direction] [get_bd_pins xlslice_14/Dout] connect_bd_net -net xlslice_15_Dout [get_bd_pins rp_iobuf_6/val_out] [get_bd_pins xlslice_15/Dout] connect_bd_net -net xlslice_16_Dout [get_bd_pins rp_iobuf_7/val_out] [get_bd_pins xlslice_16/Dout] connect_bd_net -net xlslice_17_Dout [get_bd_pins rp_iobuf_7/direction] [get_bd_pins xlslice_17/Dout] + connect_bd_net -net xlslice_18_Dout [get_bd_pins util_vector_logic_0/Op2] [get_bd_pins xlslice_18/Dout] + connect_bd_net -net xlslice_19_Dout [get_bd_pins hbridgewaveform_0/freq] [get_bd_pins xlslice_19/Dout] connect_bd_net -net xlslice_1_Dout [get_bd_pins rp_iobuf_2/direction] [get_bd_pins xlslice_1/Dout] + connect_bd_net -net xlslice_20_Dout [get_bd_pins hbridgewaveform_0/phase] [get_bd_pins xlslice_20/Dout] + connect_bd_net -net xlslice_21_Dout [get_bd_pins hbridgewaveform_0/pulswidth] [get_bd_pins xlslice_21/Dout] + connect_bd_net -net xlslice_22_Dout [get_bd_pins hbridgewaveform_0/resync] [get_bd_pins xlslice_22/Dout] + connect_bd_net -net xlslice_23_Dout [get_bd_pins xlslice_23/Dout] [get_bd_pins xlslice_24/Din] [get_bd_pins xlslice_25/Din] [get_bd_pins xlslice_33/Din] [get_bd_pins xlslice_34/Din] + connect_bd_net -net xlslice_24_Dout [get_bd_pins util_vector_logic_1/Op2] [get_bd_pins xlslice_24/Dout] + connect_bd_net -net xlslice_25_Dout [get_bd_pins util_vector_logic_1/Op1] [get_bd_pins xlslice_25/Dout] + connect_bd_net -net xlslice_26_Dout [get_bd_pins hbridgewaveform_1/phase] [get_bd_pins xlslice_26/Dout] + connect_bd_net -net xlslice_27_Dout [get_bd_pins hbridgewaveform_1/freq] [get_bd_pins xlslice_27/Dout] + connect_bd_net -net xlslice_28_Dout [get_bd_pins hbridgewaveform_1/pulswidth] [get_bd_pins xlslice_28/Dout] + connect_bd_net -net xlslice_29_Dout [get_bd_pins hbridgewaveform_1/resync] [get_bd_pins xlslice_29/Dout] connect_bd_net -net xlslice_2_Dout [get_bd_pins rp_iobuf_3/direction] [get_bd_pins xlslice_2/Dout] + connect_bd_net -net xlslice_30_Dout [get_bd_pins xlslice_26/Din] [get_bd_pins xlslice_27/Din] [get_bd_pins xlslice_28/Din] [get_bd_pins xlslice_30/Dout] + connect_bd_net -net xlslice_31_Dout [get_bd_pins xlslice_19/Din] [get_bd_pins xlslice_20/Din] [get_bd_pins xlslice_21/Din] [get_bd_pins xlslice_31/Dout] + connect_bd_net -net xlslice_32_Dout [get_bd_pins util_vector_logic_6/Op2] [get_bd_pins xlslice_32/Dout] + connect_bd_net -net xlslice_33_Dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlslice_33/Dout] + connect_bd_net -net xlslice_34_Dout [get_bd_pins util_vector_logic_7/Op2] [get_bd_pins xlslice_34/Dout] connect_bd_net -net xlslice_3_Dout [get_bd_pins rp_iobuf_4/direction] [get_bd_pins xlslice_3/Dout] connect_bd_net -net xlslice_4_Dout [get_bd_pins xlslice_0/Din] [get_bd_pins xlslice_10/Din] [get_bd_pins xlslice_11/Din] [get_bd_pins xlslice_12/Din] [get_bd_pins xlslice_15/Din] [get_bd_pins xlslice_16/Din] [get_bd_pins xlslice_4/Dout] [get_bd_pins xlslice_6/Din] [get_bd_pins xlslice_9/Din] connect_bd_net -net xlslice_5_Dout [get_bd_pins xlslice_1/Din] [get_bd_pins xlslice_13/Din] [get_bd_pins xlslice_14/Din] [get_bd_pins xlslice_17/Din] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] [get_bd_pins xlslice_5/Dout] [get_bd_pins xlslice_7/Din] [get_bd_pins xlslice_8/Din] connect_bd_net -net xlslice_6_Dout [get_bd_pins rp_iobuf_5/val_out] [get_bd_pins xlslice_6/Dout] - connect_bd_net -net xlslice_7_Dout [get_bd_pins rp_iobuf_0/direction] [get_bd_pins xlslice_7/Dout] - connect_bd_net -net xlslice_8_Dout [get_bd_pins rp_iobuf_1/direction] [get_bd_pins xlslice_8/Dout] - connect_bd_net -net xlslice_9_Dout [get_bd_pins rp_iobuf_1/val_out] [get_bd_pins xlslice_9/Dout] + connect_bd_net -net xlslice_7_Dout [get_bd_pins rp_iobuf_8/direction] [get_bd_pins xlslice_7/Dout] + connect_bd_net -net xlslice_8_Dout [get_bd_pins rp_iobuf_9/direction] [get_bd_pins xlslice_8/Dout] + connect_bd_net -net xlslice_9_Dout [get_bd_pins util_vector_logic_3/Op1] [get_bd_pins xlslice_9/Dout] # Restore current instance current_bd_instance $oldCurInst @@ -3369,8 +3617,8 @@ proc create_root_design { parentCell } { connect_bd_net -net Net3 [get_bd_ports ext_DIO3_P] [get_bd_pins reset_manager_0/instant_reset] connect_bd_net -net Net4 [get_bd_ports ext_DIO4_P] [get_bd_pins reset_manager_0/alive_signal] connect_bd_net -net Net5 [get_bd_ports ext_DIO5_P] [get_bd_pins reset_manager_0/master_trigger] - connect_bd_net -net Net6 [get_bd_ports ext_DIO7_P] [get_bd_pins DIO/ext_DIO7_P] - connect_bd_net -net Net7 [get_bd_ports ext_DIO7_N] [get_bd_pins DIO/ext_DIO7_N] + connect_bd_net -net Net6 [get_bd_ports ext_DIO7_N] [get_bd_pins DIO/ext_DIO7_N] + connect_bd_net -net Net7 [get_bd_ports ext_DIO7_P] [get_bd_pins DIO/ext_DIO7_P] connect_bd_net -net Net8 [get_bd_ports ext_DIO6_P] [get_bd_pins DIO/ext_DIO6_P] connect_bd_net -net Net9 [get_bd_ports ext_DIO6_N] [get_bd_pins DIO/ext_DIO6_N] connect_bd_net -net Net10 [get_bd_ports ext_DIO5_N] [get_bd_pins DIO/ext_DIO5_N] @@ -3407,7 +3655,7 @@ proc create_root_design { parentCell } { connect_bd_net -net pdm_oa_dac [get_bd_pins fourier_synth_standard/oa_dac] [get_bd_pins sequencer/oa_dac] connect_bd_net -net pdm_pdm_sts [get_bd_pins sequencer/pdm_sts] [get_bd_pins system/curr_pdm_values] connect_bd_net -net proc_sys_reset_bram_peripheral_aresetn [get_bd_pins fourier_synth_standard/bram_aresetn] [get_bd_pins proc_sys_reset_bram/peripheral_aresetn] [get_bd_pins sequencer/bram_aresetn] - connect_bd_net -net proc_sys_reset_fourier_synth_peripheral_aresetn [get_bd_pins fourier_synth_standard/aresetn] [get_bd_pins proc_sys_reset_fourier_synth/peripheral_aresetn] [get_bd_pins system/aresetn] + connect_bd_net -net proc_sys_reset_fourier_synth_peripheral_aresetn [get_bd_pins DIO/aresetn] [get_bd_pins fourier_synth_standard/aresetn] [get_bd_pins proc_sys_reset_fourier_synth/peripheral_aresetn] [get_bd_pins system/aresetn] connect_bd_net -net proc_sys_reset_pdm_peripheral_aresetn [get_bd_pins proc_sys_reset_pdm/peripheral_aresetn] [get_bd_pins sequencer/aresetn] connect_bd_net -net proc_sys_reset_write_to_ram_peripheral_aresetn [get_bd_pins proc_sys_reset_write_to_ram/peripheral_aresetn] [get_bd_pins write_to_ram/aresetn] connect_bd_net -net proc_sys_reset_xadc_peripheral_aresetn [get_bd_pins proc_sys_reset_xadc/peripheral_aresetn] [get_bd_pins xadc_wiz_0/s_axi_aresetn] @@ -3424,11 +3672,11 @@ proc create_root_design { parentCell } { connect_bd_net -net selectio_wiz_1_data_out_to_pins_p [get_bd_ports daisy_p_o] [get_bd_pins selectio_wiz_1/data_out_to_pins_p] connect_bd_net -net selectio_wiz_2_clk_out [get_bd_pins clk_wiz_1/clk_in1] [get_bd_pins selectio_wiz_2/clk_out] connect_bd_net -net selectio_wiz_2_data_in_to_device [get_bd_pins reset_manager_0/sata_trigger] [get_bd_pins selectio_wiz_2/data_in_to_device] - connect_bd_net -net sequencer_enable_dac [get_bd_pins fourier_synth_standard/enable_dac] [get_bd_pins sequencer/enable_dac] - connect_bd_net -net sequencer_resync_dac [get_bd_pins fourier_synth_standard/resync_dac] [get_bd_pins sequencer/resync_dac] + connect_bd_net -net sequencer_enable_dac [get_bd_pins DIO/enable_dac] [get_bd_pins fourier_synth_standard/enable_dac] [get_bd_pins sequencer/enable_dac] + connect_bd_net -net sequencer_resync_dac [get_bd_pins DIO/resync] [get_bd_pins fourier_synth_standard/resync_dac] [get_bd_pins sequencer/resync_dac] connect_bd_net -net sequencer_seq_ramp_down [get_bd_pins fourier_synth_standard/seq_ramp_down] [get_bd_pins sequencer/seq_ramp_down] connect_bd_net -net system_FCLK_RESET0_N [get_bd_pins system/FCLK_RESET0_N] [get_bd_pins util_vector_logic_1/Op1] - connect_bd_net -net system_cfg_data [get_bd_pins fourier_synth_standard/cfg_data] [get_bd_pins system/dac_cfg] + connect_bd_net -net system_cfg_data [get_bd_pins DIO/cfg_dac] [get_bd_pins fourier_synth_standard/cfg_data] [get_bd_pins system/dac_cfg] connect_bd_net -net system_cfg_data1 [get_bd_pins DIO/cfg_in] [get_bd_pins system/cfg_data] [get_bd_pins xlslice_1/Din] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] [get_bd_pins xlslice_6/Din] connect_bd_net -net system_counter_trigger_cfg [get_bd_pins counter_trigger/counter_trigger_cfg] [get_bd_pins system/counter_trigger_cfg] connect_bd_net -net system_peripheral_aresetn [get_bd_pins reset_manager_0/peripheral_aresetn] [get_bd_pins system/peripheral_aresetn] diff --git a/src/fpga/bd/hbridgewaveform.tcl b/src/fpga/bd/hbridgewaveform.tcl new file mode 100644 index 00000000..12a2d922 --- /dev/null +++ b/src/fpga/bd/hbridgewaveform.tcl @@ -0,0 +1,357 @@ + +################################################################ +# This is a generated script based on design: hbridgewaveform +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2021.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_gid_msg -ssname BD::TCL -id 2041 -severity "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source hbridgewaveform_script.tcl + + +# The design that will be created by this Tcl script contains the following +# module references: +# hbridge_signalgen + +# Please add the sources of those modules before sourcing this Tcl script. + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z010clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name hbridgewaveform + +# This script was generated for a remote BD. To create a non-remote design, +# change the variable to <0>. + +set run_remote_bd_flow 1 +if { $run_remote_bd_flow == 1 } { + # Set the reference directory for source file relative paths (by default + # the value is script directory path) + set origin_dir ./.julia/dev/RedPitayaDAQServer/src/fpga/bd + + # Use origin directory path location variable, if specified in the tcl shell + if { [info exists ::origin_dir_loc] } { + set origin_dir $::origin_dir_loc + } + + set str_bd_folder [file normalize ${origin_dir}] + set str_bd_filepath ${str_bd_folder}/${design_name}/${design_name}.bd + + # Check if remote design exists on disk + if { [file exists $str_bd_filepath ] == 1 } { + catch {common::send_gid_msg -ssname BD::TCL -id 2030 -severity "ERROR" "The remote BD file path <$str_bd_filepath> already exists!"} + common::send_gid_msg -ssname BD::TCL -id 2031 -severity "INFO" "To create a non-remote BD, change the variable to <0>." + common::send_gid_msg -ssname BD::TCL -id 2032 -severity "INFO" "Also make sure there is no design <$design_name> existing in your current project." + + return 1 + } + + # Check if design exists in memory + set list_existing_designs [get_bd_designs -quiet $design_name] + if { $list_existing_designs ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2033 -severity "ERROR" "The design <$design_name> already exists in this project! Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} + + common::send_gid_msg -ssname BD::TCL -id 2034 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." + + return 1 + } + + # Check if design exists on disk within project + set list_existing_designs [get_files -quiet */${design_name}.bd] + if { $list_existing_designs ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2035 -severity "ERROR" "The design <$design_name> already exists in this project at location: + $list_existing_designs"} + catch {common::send_gid_msg -ssname BD::TCL -id 2036 -severity "ERROR" "Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} + + common::send_gid_msg -ssname BD::TCL -id 2037 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." + + return 1 + } + + # Now can create the remote BD + # NOTE - usage of <-dir> will create <$str_bd_folder/$design_name/$design_name.bd> + create_bd_design -dir $str_bd_folder $design_name +} else { + + # Create regular design + if { [catch {create_bd_design $design_name} errmsg] } { + common::send_gid_msg -ssname BD::TCL -id 2038 -severity "INFO" "Please set a different value to variable ." + + return 1 + } +} + +current_bd_design $design_name + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +pavel-demin:user:axis_variable:1.0\ +xilinx.com:ip:dds_compiler:6.0\ +xilinx.com:ip:util_vector_logic:2.0\ +xilinx.com:ip:xlconcat:2.1\ +xilinx.com:ip:xlslice:1.0\ +" + + set list_ips_missing "" + common::send_gid_msg -ssname BD::TCL -id 2011 -severity "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2012 -severity "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +################################################################## +# CHECK Modules +################################################################## +set bCheckModules 1 +if { $bCheckModules == 1 } { + set list_check_mods "\ +hbridge_signalgen\ +" + + set list_mods_missing "" + common::send_gid_msg -ssname BD::TCL -id 2020 -severity "INFO" "Checking if the following modules exist in the project's sources: $list_check_mods ." + + foreach mod_vlnv $list_check_mods { + if { [can_resolve_reference $mod_vlnv] == 0 } { + lappend list_mods_missing $mod_vlnv + } + } + + if { $list_mods_missing ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2021 -severity "ERROR" "The following module(s) are not found in the project: $list_mods_missing" } + common::send_gid_msg -ssname BD::TCL -id 2022 -severity "INFO" "Please add source files for the missing module(s) above." + set bCheckIPsPassed 0 + } +} + +if { $bCheckIPsPassed != 1 } { + common::send_gid_msg -ssname BD::TCL -id 2023 -severity "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2090 -severity "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2091 -severity "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + + # Create ports + set H1out [ create_bd_port -dir O -type data H1out ] + set H2out [ create_bd_port -dir O -type data H2out ] + set aclk [ create_bd_port -dir I -type clk -freq_hz 125000000 aclk ] + set aresetn [ create_bd_port -dir I -type rst aresetn ] + set enable_dac [ create_bd_port -dir I enable_dac ] + set freq [ create_bd_port -dir I -from 47 -to 0 freq ] + set phase [ create_bd_port -dir I -from 47 -to 0 phase ] + set pulswidth [ create_bd_port -dir I -from 15 -to 0 pulswidth ] + set resync [ create_bd_port -dir I resync ] + + # Create instance: axis_variable_A_channel_1, and set properties + set axis_variable_A_channel_1 [ create_bd_cell -type ip -vlnv pavel-demin:user:axis_variable:1.0 axis_variable_A_channel_1 ] + set_property -dict [ list \ + CONFIG.AXIS_TDATA_WIDTH {96} \ + ] $axis_variable_A_channel_1 + + # Create instance: dds_compiler_A_channel_1, and set properties + set dds_compiler_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:dds_compiler:6.0 dds_compiler_A_channel_1 ] + set_property -dict [ list \ + CONFIG.Amplitude_Mode {Full_Range} \ + CONFIG.DATA_Has_TLAST {Not_Required} \ + CONFIG.DDS_Clock_Rate {125} \ + CONFIG.Frequency_Resolution {4.440893e-7} \ + CONFIG.Has_ACLKEN {false} \ + CONFIG.Has_ARESETn {true} \ + CONFIG.Has_Phase_Out {true} \ + CONFIG.Has_TREADY {false} \ + CONFIG.Latency {2} \ + CONFIG.Latency_Configuration {Auto} \ + CONFIG.M_DATA_Has_TUSER {Not_Required} \ + CONFIG.M_PHASE_Has_TUSER {Not_Required} \ + CONFIG.Noise_Shaping {None} \ + CONFIG.Output_Frequency1 {0} \ + CONFIG.Output_Selection {Sine} \ + CONFIG.Output_Width {3} \ + CONFIG.PINC1 {0} \ + CONFIG.POFF1 {0} \ + CONFIG.Parameter_Entry {Hardware_Parameters} \ + CONFIG.PartsPresent {Phase_Generator_only} \ + CONFIG.Phase_Increment {Programmable} \ + CONFIG.Phase_Offset_Angles1 {0} \ + CONFIG.Phase_Width {48} \ + CONFIG.Phase_offset {Programmable} \ + CONFIG.Resync {false} \ + CONFIG.S_PHASE_Has_TUSER {Not_Required} \ + CONFIG.Spurious_Free_Dynamic_Range {88} \ + ] $dds_compiler_A_channel_1 + + # Create instance: hbridge_signalgen_0_upgraded_ipi, and set properties + set block_name hbridge_signalgen + set block_cell_name hbridge_signalgen_0_upgraded_ipi + if { [catch {set hbridge_signalgen_0_upgraded_ipi [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } { + catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } elseif { $hbridge_signalgen_0_upgraded_ipi eq "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."} + return 1 + } + set_property -dict [ list \ + CONFIG.AXIS_TDATA_PHASE_WIDTH {48} \ + CONFIG.CFG_DATA_WIDTH {14} \ + ] $hbridge_signalgen_0_upgraded_ipi + + # Create instance: util_vector_logic_0, and set properties + set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] + set_property -dict [ list \ + CONFIG.C_OPERATION {not} \ + CONFIG.C_SIZE {1} \ + CONFIG.LOGO_FILE {data/sym_notgate.png} \ + ] $util_vector_logic_0 + + # Create instance: util_vector_logic_1, and set properties + set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_1 + + # Create instance: xlconcat_A_channel_1, and set properties + set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] + set_property -dict [ list \ + CONFIG.IN0_WIDTH {48} \ + CONFIG.IN1_WIDTH {48} \ + CONFIG.IN2_WIDTH {8} \ + CONFIG.NUM_PORTS {2} \ + ] $xlconcat_A_channel_1 + + # Create instance: xlslice_0, and set properties + set xlslice_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_0 ] + set_property -dict [ list \ + CONFIG.DIN_FROM {13} \ + CONFIG.DIN_WIDTH {16} \ + CONFIG.DOUT_WIDTH {14} \ + ] $xlslice_0 + + # Create interface connections + connect_bd_intf_net -intf_net axis_variable_A_channel_1_M_AXIS [get_bd_intf_pins axis_variable_A_channel_1/M_AXIS] [get_bd_intf_pins dds_compiler_A_channel_1/S_AXIS_CONFIG] + connect_bd_intf_net -intf_net dds_compiler_A_channel_1_M_AXIS_PHASE [get_bd_intf_pins dds_compiler_A_channel_1/M_AXIS_PHASE] [get_bd_intf_pins hbridge_signalgen_0_upgraded_ipi/s_axis_phase] + + # Create port connections + connect_bd_net -net aresetn_1 [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/aresetn] [get_bd_pins util_vector_logic_1/Op2] + connect_bd_net -net clk_wiz_0_clk_internal [get_bd_ports aclk] [get_bd_pins axis_variable_A_channel_1/aclk] [get_bd_pins dds_compiler_A_channel_1/aclk] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/clk] + connect_bd_net -net enable_dac_1 [get_bd_ports enable_dac] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/enable_dac] + connect_bd_net -net freq_1 [get_bd_ports freq] [get_bd_pins xlconcat_A_channel_1/In0] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H1 [get_bd_ports H1out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H1] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H2 [get_bd_ports H2out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H2] + connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] + connect_bd_net -net pulswidth_1 [get_bd_ports pulswidth] [get_bd_pins xlslice_0/Din] + connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins util_vector_logic_0/Op1] + connect_bd_net -net util_vector_logic_0_Res [get_bd_pins util_vector_logic_0/Res] [get_bd_pins util_vector_logic_1/Op1] + connect_bd_net -net util_vector_logic_1_Res [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins util_vector_logic_1/Res] + connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] + connect_bd_net -net xlslice_0_Dout [get_bd_pins hbridge_signalgen_0_upgraded_ipi/cfg_data] [get_bd_pins xlslice_0/Dout] + + # Create address segments + + + # Restore current instance + current_bd_instance $oldCurInst + + validate_bd_design + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/src/fpga/build.tcl b/src/fpga/build.tcl index 84a305a4..e2aded55 100644 --- a/src/fpga/build.tcl +++ b/src/fpga/build.tcl @@ -30,6 +30,7 @@ update_ip_catalog source src/fpga/bd/signal_calib.tcl source src/fpga/bd/signal_ramp.tcl source src/fpga/bd/waveform_gen.tcl +source src/fpga/bd/hbridgewaveform.tcl source src/fpga/bd/bd.tcl # Create HDL wrapper for blockdesign diff --git a/src/fpga/hdl/hbridge_signalgen.v b/src/fpga/hdl/hbridge_signalgen.v new file mode 100644 index 00000000..9fedc0c0 --- /dev/null +++ b/src/fpga/hdl/hbridge_signalgen.v @@ -0,0 +1,82 @@ +`timescale 1ns / 1ps + +module hbridge_signalgen # +( + parameter integer AXIS_TDATA_PHASE_WIDTH = 16, + parameter integer CFG_DATA_WIDTH = 16 +) +( + // DDS Input + input wire [AXIS_TDATA_PHASE_WIDTH-1:0] s_axis_tdata_phase, + input wire s_axis_tvalid_phase, + + input [CFG_DATA_WIDTH-1:0] cfg_data, + + + input clk, + input aresetn, + input enable_dac, + output H1, H2 +); + + reg signed [AXIS_TDATA_PHASE_WIDTH-1:0] phase; + reg signed [CFG_DATA_WIDTH-1:0] A; + reg h1, h2; + + + always @(posedge clk) + begin + A <= cfg_data>>1; + + if (~aresetn) + begin + h1 <= 0; + h2 <= 0; + phase <= 0; + end + else + begin + phase <= s_axis_tdata_phase >>> (AXIS_TDATA_PHASE_WIDTH - CFG_DATA_WIDTH); + //4096 = (1<<<(CFG_DATA_WIDTH-2)) + + if (enable_dac) + begin + if (phase < 4096-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 4096+A) + begin + h1 <= 0; + h2 <= 1; + end + else if (phase < 12288-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 12288+A) + begin + h1 <= 1; + h2 <= 0; + end + else + begin + h1 <= 0; + h2 <= 0; + end + end else begin + h1 <= 0; + h2 <= 0; + end + + end + + + end + +assign H1 = h1; +assign H2 = h2; + +endmodule \ No newline at end of file From c2088de8e9f31ca66794ca7f2312b98faaaabefc Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 18:02:09 +0100 Subject: [PATCH 31/38] some fix remaining issues in BD --- src/fpga/bd/bd.tcl | 52 +++++--------------------------- src/fpga/bd/hbridgewaveform.tcl | 44 +++++++++++++++++++++++---- src/fpga/hdl/hbridge_signalgen.v | 50 +++++++++++++----------------- 3 files changed, 67 insertions(+), 79 deletions(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index 9576f109..f85d8cfb 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -2803,22 +2803,6 @@ proc create_hier_cell_DIO { parentCell nameHier } { return 1 } - # Create instance: util_vector_logic_0, and set properties - set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {and} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_andgate.png} \ - ] $util_vector_logic_0 - - # Create instance: util_vector_logic_1, and set properties - set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {or} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_orgate.png} \ - ] $util_vector_logic_1 - # Create instance: util_vector_logic_2, and set properties set util_vector_logic_2 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_2 ] set_property -dict [ list \ @@ -2851,22 +2835,6 @@ proc create_hier_cell_DIO { parentCell nameHier } { CONFIG.LOGO_FILE {data/sym_orgate.png} \ ] $util_vector_logic_5 - # Create instance: util_vector_logic_6, and set properties - set util_vector_logic_6 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_6 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {and} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_andgate.png} \ - ] $util_vector_logic_6 - - # Create instance: util_vector_logic_7, and set properties - set util_vector_logic_7 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_7 ] - set_property -dict [ list \ - CONFIG.C_OPERATION {or} \ - CONFIG.C_SIZE {1} \ - CONFIG.LOGO_FILE {data/sym_orgate.png} \ - ] $util_vector_logic_7 - # Create instance: xlconcat_0, and set properties set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] set_property -dict [ list \ @@ -3193,7 +3161,6 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net cfg_dac_1 [get_bd_pins cfg_dac] [get_bd_pins xlslice_30/Din] [get_bd_pins xlslice_31/Din] connect_bd_net -net clk_wiz_0_clk_internal [get_bd_pins clk] [get_bd_pins hbridgewaveform_0/aclk] [get_bd_pins hbridgewaveform_1/aclk] [get_bd_pins rp_iobuf_2/clk] [get_bd_pins rp_iobuf_3/clk] [get_bd_pins rp_iobuf_4/clk] [get_bd_pins rp_iobuf_5/clk] [get_bd_pins rp_iobuf_6/clk] [get_bd_pins rp_iobuf_7/clk] [get_bd_pins rp_iobuf_8/clk] [get_bd_pins rp_iobuf_9/clk] connect_bd_net -net enable_dac_1 [get_bd_pins enable_dac] [get_bd_pins xlslice_18/Din] [get_bd_pins xlslice_32/Din] - connect_bd_net -net enable_dac_2 [get_bd_pins hbridgewaveform_1/enable_dac] [get_bd_pins util_vector_logic_6/Res] connect_bd_net -net hbridgewaveform_0_H1out [get_bd_pins hbridgewaveform_0/H1out] [get_bd_pins util_vector_logic_2/Op2] connect_bd_net -net hbridgewaveform_0_H2out [get_bd_pins hbridgewaveform_0/H2out] [get_bd_pins util_vector_logic_3/Op2] connect_bd_net -net hbridgewaveform_1_H1out [get_bd_pins hbridgewaveform_1/H1out] [get_bd_pins util_vector_logic_4/Op2] @@ -3208,13 +3175,10 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net rp_iobuf_8_val_in_clocked [get_bd_pins rp_iobuf_8/val_in_clocked] [get_bd_pins xlconcat_0/In0] connect_bd_net -net rp_iobuf_9_val_in_clocked [get_bd_pins rp_iobuf_9/val_in_clocked] [get_bd_pins xlconcat_0/In1] connect_bd_net -net system_cfg_data1 [get_bd_pins cfg_in] [get_bd_pins xlslice_23/Din] [get_bd_pins xlslice_4/Din] [get_bd_pins xlslice_5/Din] - connect_bd_net -net util_vector_logic_0_Res [get_bd_pins hbridgewaveform_0/enable_dac] [get_bd_pins util_vector_logic_0/Res] - connect_bd_net -net util_vector_logic_1_Res [get_bd_pins util_vector_logic_0/Op1] [get_bd_pins util_vector_logic_1/Res] connect_bd_net -net util_vector_logic_2_Res [get_bd_pins rp_iobuf_8/val_out] [get_bd_pins util_vector_logic_2/Res] connect_bd_net -net util_vector_logic_3_Res [get_bd_pins rp_iobuf_9/val_out] [get_bd_pins util_vector_logic_3/Res] connect_bd_net -net util_vector_logic_4_Res [get_bd_pins rp_iobuf_2/val_out] [get_bd_pins util_vector_logic_4/Res] connect_bd_net -net util_vector_logic_5_Res [get_bd_pins rp_iobuf_3/val_out] [get_bd_pins util_vector_logic_5/Res] - connect_bd_net -net util_vector_logic_7_Res [get_bd_pins util_vector_logic_6/Op1] [get_bd_pins util_vector_logic_7/Res] connect_bd_net -net xlconcat_0_dout2 [get_bd_pins dio_data_clocked] [get_bd_pins xlconcat_0/dout] connect_bd_net -net xlconstant_1_dout [get_bd_pins xlconcat_0/In8] [get_bd_pins xlconstant_1/dout] connect_bd_net -net xlslice_0_Dout [get_bd_pins util_vector_logic_2/Op1] [get_bd_pins xlslice_0/Dout] @@ -3226,25 +3190,25 @@ proc create_hier_cell_DIO { parentCell nameHier } { connect_bd_net -net xlslice_15_Dout [get_bd_pins rp_iobuf_6/val_out] [get_bd_pins xlslice_15/Dout] connect_bd_net -net xlslice_16_Dout [get_bd_pins rp_iobuf_7/val_out] [get_bd_pins xlslice_16/Dout] connect_bd_net -net xlslice_17_Dout [get_bd_pins rp_iobuf_7/direction] [get_bd_pins xlslice_17/Dout] - connect_bd_net -net xlslice_18_Dout [get_bd_pins util_vector_logic_0/Op2] [get_bd_pins xlslice_18/Dout] + connect_bd_net -net xlslice_18_Dout [get_bd_pins hbridgewaveform_0/enable_All] [get_bd_pins xlslice_18/Dout] connect_bd_net -net xlslice_19_Dout [get_bd_pins hbridgewaveform_0/freq] [get_bd_pins xlslice_19/Dout] connect_bd_net -net xlslice_1_Dout [get_bd_pins rp_iobuf_2/direction] [get_bd_pins xlslice_1/Dout] connect_bd_net -net xlslice_20_Dout [get_bd_pins hbridgewaveform_0/phase] [get_bd_pins xlslice_20/Dout] connect_bd_net -net xlslice_21_Dout [get_bd_pins hbridgewaveform_0/pulswidth] [get_bd_pins xlslice_21/Dout] connect_bd_net -net xlslice_22_Dout [get_bd_pins hbridgewaveform_0/resync] [get_bd_pins xlslice_22/Dout] connect_bd_net -net xlslice_23_Dout [get_bd_pins xlslice_23/Dout] [get_bd_pins xlslice_24/Din] [get_bd_pins xlslice_25/Din] [get_bd_pins xlslice_33/Din] [get_bd_pins xlslice_34/Din] - connect_bd_net -net xlslice_24_Dout [get_bd_pins util_vector_logic_1/Op2] [get_bd_pins xlslice_24/Dout] - connect_bd_net -net xlslice_25_Dout [get_bd_pins util_vector_logic_1/Op1] [get_bd_pins xlslice_25/Dout] - connect_bd_net -net xlslice_26_Dout [get_bd_pins hbridgewaveform_1/phase] [get_bd_pins xlslice_26/Dout] - connect_bd_net -net xlslice_27_Dout [get_bd_pins hbridgewaveform_1/freq] [get_bd_pins xlslice_27/Dout] + connect_bd_net -net xlslice_24_Dout [get_bd_pins hbridgewaveform_0/enable_H1] [get_bd_pins xlslice_24/Dout] + connect_bd_net -net xlslice_25_Dout [get_bd_pins hbridgewaveform_0/enable_H2] [get_bd_pins xlslice_25/Dout] + connect_bd_net -net xlslice_26_Dout [get_bd_pins hbridgewaveform_1/freq] [get_bd_pins xlslice_26/Dout] + connect_bd_net -net xlslice_27_Dout [get_bd_pins hbridgewaveform_1/phase] [get_bd_pins xlslice_27/Dout] connect_bd_net -net xlslice_28_Dout [get_bd_pins hbridgewaveform_1/pulswidth] [get_bd_pins xlslice_28/Dout] connect_bd_net -net xlslice_29_Dout [get_bd_pins hbridgewaveform_1/resync] [get_bd_pins xlslice_29/Dout] connect_bd_net -net xlslice_2_Dout [get_bd_pins rp_iobuf_3/direction] [get_bd_pins xlslice_2/Dout] connect_bd_net -net xlslice_30_Dout [get_bd_pins xlslice_26/Din] [get_bd_pins xlslice_27/Din] [get_bd_pins xlslice_28/Din] [get_bd_pins xlslice_30/Dout] connect_bd_net -net xlslice_31_Dout [get_bd_pins xlslice_19/Din] [get_bd_pins xlslice_20/Din] [get_bd_pins xlslice_21/Din] [get_bd_pins xlslice_31/Dout] - connect_bd_net -net xlslice_32_Dout [get_bd_pins util_vector_logic_6/Op2] [get_bd_pins xlslice_32/Dout] - connect_bd_net -net xlslice_33_Dout [get_bd_pins util_vector_logic_7/Op1] [get_bd_pins xlslice_33/Dout] - connect_bd_net -net xlslice_34_Dout [get_bd_pins util_vector_logic_7/Op2] [get_bd_pins xlslice_34/Dout] + connect_bd_net -net xlslice_32_Dout [get_bd_pins hbridgewaveform_1/enable_All] [get_bd_pins xlslice_32/Dout] + connect_bd_net -net xlslice_33_Dout [get_bd_pins hbridgewaveform_1/enable_H1] [get_bd_pins xlslice_33/Dout] + connect_bd_net -net xlslice_34_Dout [get_bd_pins hbridgewaveform_1/enable_H2] [get_bd_pins xlslice_34/Dout] connect_bd_net -net xlslice_3_Dout [get_bd_pins rp_iobuf_4/direction] [get_bd_pins xlslice_3/Dout] connect_bd_net -net xlslice_4_Dout [get_bd_pins xlslice_0/Din] [get_bd_pins xlslice_10/Din] [get_bd_pins xlslice_11/Din] [get_bd_pins xlslice_12/Din] [get_bd_pins xlslice_15/Din] [get_bd_pins xlslice_16/Din] [get_bd_pins xlslice_4/Dout] [get_bd_pins xlslice_6/Din] [get_bd_pins xlslice_9/Din] connect_bd_net -net xlslice_5_Dout [get_bd_pins xlslice_1/Din] [get_bd_pins xlslice_13/Din] [get_bd_pins xlslice_14/Din] [get_bd_pins xlslice_17/Din] [get_bd_pins xlslice_2/Din] [get_bd_pins xlslice_3/Din] [get_bd_pins xlslice_5/Dout] [get_bd_pins xlslice_7/Din] [get_bd_pins xlslice_8/Din] diff --git a/src/fpga/bd/hbridgewaveform.tcl b/src/fpga/bd/hbridgewaveform.tcl index 12a2d922..d2f98ab8 100644 --- a/src/fpga/bd/hbridgewaveform.tcl +++ b/src/fpga/bd/hbridgewaveform.tcl @@ -223,11 +223,13 @@ proc create_root_design { parentCell } { # Create interface ports # Create ports - set H1out [ create_bd_port -dir O -type data H1out ] - set H2out [ create_bd_port -dir O -type data H2out ] + set H1out [ create_bd_port -dir O -from 0 -to 0 -type data H1out ] + set H2out [ create_bd_port -dir O -from 0 -to 0 -type data H2out ] set aclk [ create_bd_port -dir I -type clk -freq_hz 125000000 aclk ] set aresetn [ create_bd_port -dir I -type rst aresetn ] - set enable_dac [ create_bd_port -dir I enable_dac ] + set enable_All [ create_bd_port -dir I enable_All ] + set enable_H1 [ create_bd_port -dir I -type data enable_H1 ] + set enable_H2 [ create_bd_port -dir I -type data enable_H2 ] set freq [ create_bd_port -dir I -from 47 -to 0 freq ] set phase [ create_bd_port -dir I -from 47 -to 0 phase ] set pulswidth [ create_bd_port -dir I -from 15 -to 0 pulswidth ] @@ -300,6 +302,30 @@ proc create_root_design { parentCell } { CONFIG.C_SIZE {1} \ ] $util_vector_logic_1 + # Create instance: util_vector_logic_2, and set properties + set util_vector_logic_2 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_2 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_2 + + # Create instance: util_vector_logic_3, and set properties + set util_vector_logic_3 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_3 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_3 + + # Create instance: util_vector_logic_4, and set properties + set util_vector_logic_4 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_4 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_4 + + # Create instance: util_vector_logic_5, and set properties + set util_vector_logic_5 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_5 ] + set_property -dict [ list \ + CONFIG.C_SIZE {1} \ + ] $util_vector_logic_5 + # Create instance: xlconcat_A_channel_1, and set properties set xlconcat_A_channel_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_A_channel_1 ] set_property -dict [ list \ @@ -324,15 +350,21 @@ proc create_root_design { parentCell } { # Create port connections connect_bd_net -net aresetn_1 [get_bd_ports aresetn] [get_bd_pins axis_variable_A_channel_1/aresetn] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/aresetn] [get_bd_pins util_vector_logic_1/Op2] connect_bd_net -net clk_wiz_0_clk_internal [get_bd_ports aclk] [get_bd_pins axis_variable_A_channel_1/aclk] [get_bd_pins dds_compiler_A_channel_1/aclk] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/clk] - connect_bd_net -net enable_dac_1 [get_bd_ports enable_dac] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/enable_dac] + connect_bd_net -net enable_All_1 [get_bd_ports enable_All] [get_bd_pins util_vector_logic_4/Op1] [get_bd_pins util_vector_logic_5/Op1] + connect_bd_net -net enable_H1_1 [get_bd_ports enable_H1] [get_bd_pins util_vector_logic_2/Op1] + connect_bd_net -net enable_H2_1 [get_bd_ports enable_H2] [get_bd_pins util_vector_logic_3/Op1] connect_bd_net -net freq_1 [get_bd_ports freq] [get_bd_pins xlconcat_A_channel_1/In0] - connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H1 [get_bd_ports H1out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H1] - connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H2 [get_bd_ports H2out] [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H2] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H1 [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H1] [get_bd_pins util_vector_logic_2/Op2] + connect_bd_net -net hbridge_signalgen_0_upgraded_ipi_H2 [get_bd_pins hbridge_signalgen_0_upgraded_ipi/H2] [get_bd_pins util_vector_logic_3/Op2] connect_bd_net -net phase_1 [get_bd_ports phase] [get_bd_pins xlconcat_A_channel_1/In1] connect_bd_net -net pulswidth_1 [get_bd_ports pulswidth] [get_bd_pins xlslice_0/Din] connect_bd_net -net resync_1 [get_bd_ports resync] [get_bd_pins util_vector_logic_0/Op1] connect_bd_net -net util_vector_logic_0_Res [get_bd_pins util_vector_logic_0/Res] [get_bd_pins util_vector_logic_1/Op1] connect_bd_net -net util_vector_logic_1_Res [get_bd_pins dds_compiler_A_channel_1/aresetn] [get_bd_pins util_vector_logic_1/Res] + connect_bd_net -net util_vector_logic_2_Res [get_bd_pins util_vector_logic_2/Res] [get_bd_pins util_vector_logic_4/Op2] + connect_bd_net -net util_vector_logic_3_Res [get_bd_pins util_vector_logic_3/Res] [get_bd_pins util_vector_logic_5/Op2] + connect_bd_net -net util_vector_logic_4_Res [get_bd_ports H1out] [get_bd_pins util_vector_logic_4/Res] + connect_bd_net -net util_vector_logic_5_Res [get_bd_ports H2out] [get_bd_pins util_vector_logic_5/Res] connect_bd_net -net xlconcat_A_channel_1_dout [get_bd_pins axis_variable_A_channel_1/cfg_data] [get_bd_pins xlconcat_A_channel_1/dout] connect_bd_net -net xlslice_0_Dout [get_bd_pins hbridge_signalgen_0_upgraded_ipi/cfg_data] [get_bd_pins xlslice_0/Dout] diff --git a/src/fpga/hdl/hbridge_signalgen.v b/src/fpga/hdl/hbridge_signalgen.v index 9fedc0c0..9b5e56eb 100644 --- a/src/fpga/hdl/hbridge_signalgen.v +++ b/src/fpga/hdl/hbridge_signalgen.v @@ -15,7 +15,6 @@ module hbridge_signalgen # input clk, input aresetn, - input enable_dac, output H1, H2 ); @@ -39,41 +38,34 @@ module hbridge_signalgen # phase <= s_axis_tdata_phase >>> (AXIS_TDATA_PHASE_WIDTH - CFG_DATA_WIDTH); //4096 = (1<<<(CFG_DATA_WIDTH-2)) - if (enable_dac) + if (phase < 4096-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 4096+A) + begin + h1 <= 0; + h2 <= 1; + end + else if (phase < 12288-A) + begin + h1 <= 0; + h2 <= 0; + end + else if (phase < 12288+A) + begin + h1 <= 1; + h2 <= 0; + end + else begin - if (phase < 4096-A) - begin - h1 <= 0; - h2 <= 0; - end - else if (phase < 4096+A) - begin - h1 <= 0; - h2 <= 1; - end - else if (phase < 12288-A) - begin - h1 <= 0; - h2 <= 0; - end - else if (phase < 12288+A) - begin - h1 <= 1; - h2 <= 0; - end - else - begin - h1 <= 0; - h2 <= 0; - end - end else begin h1 <= 0; h2 <= 0; end end - end assign H1 = h1; From 1503123deae17aa64ec287d22ac789c51c1c75f3 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 19:45:49 +0100 Subject: [PATCH 32/38] update bd --- src/fpga/bd/hbridgewaveform.tcl | 96 +++++++++++++++++---------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/src/fpga/bd/hbridgewaveform.tcl b/src/fpga/bd/hbridgewaveform.tcl index d2f98ab8..5e6adbc8 100644 --- a/src/fpga/bd/hbridgewaveform.tcl +++ b/src/fpga/bd/hbridgewaveform.tcl @@ -58,68 +58,70 @@ if { $list_projs eq "" } { variable design_name set design_name hbridgewaveform -# This script was generated for a remote BD. To create a non-remote design, -# change the variable to <0>. - -set run_remote_bd_flow 1 -if { $run_remote_bd_flow == 1 } { - # Set the reference directory for source file relative paths (by default - # the value is script directory path) - set origin_dir ./.julia/dev/RedPitayaDAQServer/src/fpga/bd - - # Use origin directory path location variable, if specified in the tcl shell - if { [info exists ::origin_dir_loc] } { - set origin_dir $::origin_dir_loc - } +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name - set str_bd_folder [file normalize ${origin_dir}] - set str_bd_filepath ${str_bd_folder}/${design_name}/${design_name}.bd +# Creating design if needed +set errMsg "" +set nRet 0 - # Check if remote design exists on disk - if { [file exists $str_bd_filepath ] == 1 } { - catch {common::send_gid_msg -ssname BD::TCL -id 2030 -severity "ERROR" "The remote BD file path <$str_bd_filepath> already exists!"} - common::send_gid_msg -ssname BD::TCL -id 2031 -severity "INFO" "To create a non-remote BD, change the variable to <0>." - common::send_gid_msg -ssname BD::TCL -id 2032 -severity "INFO" "Also make sure there is no design <$design_name> existing in your current project." +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] - return 1 - } +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set - # Check if design exists in memory - set list_existing_designs [get_bd_designs -quiet $design_name] - if { $list_existing_designs ne "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2033 -severity "ERROR" "The design <$design_name> already exists in this project! Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} + set errMsg "Please set the variable to a non-empty value." + set nRet 1 - common::send_gid_msg -ssname BD::TCL -id 2034 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. - return 1 - } + if { $cur_design ne $design_name } { + common::send_gid_msg -ssname BD::TCL -id 2001 -severity "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_gid_msg -ssname BD::TCL -id 2002 -severity "INFO" "Constructing design in IPI design <$cur_design>..." - # Check if design exists on disk within project - set list_existing_designs [get_files -quiet */${design_name}.bd] - if { $list_existing_designs ne "" } { - catch {common::send_gid_msg -ssname BD::TCL -id 2035 -severity "ERROR" "The design <$design_name> already exists in this project at location: - $list_existing_designs"} - catch {common::send_gid_msg -ssname BD::TCL -id 2036 -severity "ERROR" "Will not create the remote BD <$design_name> at the folder <$str_bd_folder>."} +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. - common::send_gid_msg -ssname BD::TCL -id 2037 -severity "INFO" "To create a non-remote BD, change the variable to <0> or please set a different value to variable ." + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. - return 1 - } + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 - # Now can create the remote BD - # NOTE - usage of <-dir> will create <$str_bd_folder/$design_name/$design_name.bd> - create_bd_design -dir $str_bd_folder $design_name } else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. - # Create regular design - if { [catch {create_bd_design $design_name} errmsg] } { - common::send_gid_msg -ssname BD::TCL -id 2038 -severity "INFO" "Please set a different value to variable ." + common::send_gid_msg -ssname BD::TCL -id 2003 -severity "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_gid_msg -ssname BD::TCL -id 2004 -severity "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name - return 1 - } } -current_bd_design $design_name +common::send_gid_msg -ssname BD::TCL -id 2005 -severity "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_gid_msg -ssname BD::TCL -id 2006 -severity "ERROR" $errMsg} + return $nRet +} set bCheckIPsPassed 1 ################################################################## From 03b55110f28ea140e716470f9b465af61eaa8da7 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 21:01:02 +0100 Subject: [PATCH 33/38] server changes for hbridge --- src/lib/rp-daq-lib.c | 32 +++++++++++++++++- src/lib/rp-daq-lib.h | 2 ++ src/server/control.c | 2 +- src/server/scpi_commands.c | 66 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 3cef3572..5393cac2 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -653,7 +653,7 @@ int setResyncDAC(int8_t value, int channel, int index) { return -1; int bitpos = 14; - // Reset bits are in the 14th bit of the respective DAC channel -> 14 and 30 + // Reset bits are in the 14th bit of the respective DAC channel -> 14 and 30 int offset = 8 * index + channel; // clear the bit *((int16_t *)(pdm_cfg + offset)) &= ~(1u << bitpos); @@ -1232,6 +1232,36 @@ char* getPinFromInternalPINNumber(const uint32_t pinNumber) { } } +int getDIOHBridge(const char* pin) { + int pinInternal = getInternalPINNumber(pin); + if(pinInternal < 0) { + return -3; + } + + uint32_t register_value = *((uint8_t *)(cfg + 11)); + register_value = ((register_value & (0x1 << (pinInternal))) >> (pinInternal)); + + return register_value; +} + +int setDIOHBridge(const char* pin, int value) { + int pinInternal = getInternalPINNumber(pin); + if(pinInternal < 0) { + return -3; + } + + if(value == DIO_OUT) { + *((uint8_t *)(cfg + 11)) &= ~(0x1 << (pinInternal)); + } else if(value == DIO_IN) { + *((uint8_t *)(cfg + 11)) |= (0x1 << (pinInternal)); + } else { + return -1; + } + + return 0; +} + + int getDIODirection(const char* pin) { int pinInternal = getInternalPINNumber(pin); if(pinInternal < 0) { diff --git a/src/lib/rp-daq-lib.h b/src/lib/rp-daq-lib.h index f7cf6bcc..74628671 100644 --- a/src/lib/rp-daq-lib.h +++ b/src/lib/rp-daq-lib.h @@ -175,6 +175,8 @@ extern int getDIODirection(const char*); extern int setDIODirection(const char*, int); extern int setDIO(const char*, int); extern int getDIO(const char*); +extern int getDIOHBridge(const char*); +extern int setDIOHBridge(const char*, int); extern int setTriggerMode(int); extern int getTriggerMode(); extern int setTriggerPropagation(int); diff --git a/src/server/control.c b/src/server/control.c index 1b6b422c..4b95eca7 100644 --- a/src/server/control.c +++ b/src/server/control.c @@ -131,7 +131,7 @@ bool getSequenceEnableValue(sequenceData_t *seqData, int seqStep, int channel) { bool getSequenceResyncValue(sequenceData_t *seqData, int seqStep, int channel) { bool result = false; - int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; + int numChan = numSlowDACChan > 2 ? 2 : numSlowDACChan; if (seqData->resyncLUT != NULL && channel < numChan) { int localStep = seqStep % seqData->numStepsPerRepetition; result = seqData->resyncLUT[localStep * numChan + channel]; diff --git a/src/server/scpi_commands.c b/src/server/scpi_commands.c index b7308745..dd31c1f1 100644 --- a/src/server/scpi_commands.c +++ b/src/server/scpi_commands.c @@ -722,6 +722,68 @@ static scpi_result_t RP_DIO_GetDIOOutputP(scpi_t * context) { return RP_DIO_GetDIOOutput(context, true); } + + + +static scpi_result_t RP_DIO_SetDIOHBridge(scpi_t * context, bool pinSide) { + int32_t numbers[1]; + SCPI_CommandNumbers(context, numbers, 1, 1); + int pin_number = numbers[0]; + char pin[8]; + pinSide ? sprintf(pin, "DIO%d_P", pin_number) : sprintf(pin, "DIO%d_N", pin_number); + + int32_t DIO_pin_output_selection; + if (!SCPI_ParamChoice(context, onoff_modes, &DIO_pin_output_selection, TRUE)) { + return returnSCPIBool(context, false); + } + + int result = setDIOHBridge(pin, DIO_pin_output_selection); + if (result < 0) { + return returnSCPIBool(context, false); + } + + return returnSCPIBool(context, true); +} + +static scpi_result_t RP_DIO_SetDIOHBridgeN(scpi_t * context) { + return RP_DIO_SetDIOHBridge(context, false); +} + +static scpi_result_t RP_DIO_SetDIOHBridgeP(scpi_t * context) { + return RP_DIO_SetDIOHBridge(context, true); +} + +static scpi_result_t RP_DIO_GetDIOHBridge(scpi_t * context, bool pinSide) { + int32_t numbers[1]; + SCPI_CommandNumbers(context, numbers, 1, 1); + int pin_number = numbers[0]; + char pin[8]; + pinSide ? sprintf(pin, "DIO%d_P", pin_number) : sprintf(pin, "DIO%d_N", pin_number); + + int result = getDIOHBridge(pin); + + if (result < 0) { + return returnSCPIBool(context, false); + } + + const char* name; + SCPI_ChoiceToName(onoff_modes, result, &name); + SCPI_ResultText(context, name); + + return SCPI_RES_OK; +} + +static scpi_result_t RP_DIO_GetDIOHBridgeN(scpi_t * context) { + return RP_DIO_GetDIOHBridge(context, false); +} + +static scpi_result_t RP_DIO_GetDIOHBridgeP(scpi_t * context) { + return RP_DIO_GetDIOHBridge(context, true); +} + + + + static scpi_result_t RP_GetWatchdogMode(scpi_t * context) { const char * name; @@ -1791,6 +1853,10 @@ const scpi_command_t scpi_commands[] = { {.pattern = "RP:DIO:Pin#:SideP", .callback = RP_DIO_SetDIOOutputP,}, {.pattern = "RP:DIO:Pin#:SideN?", .callback = RP_DIO_GetDIOOutputN,}, {.pattern = "RP:DIO:Pin#:SideP?", .callback = RP_DIO_GetDIOOutputP,}, + {.pattern = "RP:DIO:Pin#:SideN:HBridge", .callback = RP_DIO_SetDIOHBridgeN,}, + {.pattern = "RP:DIO:Pin#:SideP:HBridge", .callback = RP_DIO_SetDIOHBridgeP,}, + {.pattern = "RP:DIO:Pin#:SideN:HBridge?", .callback = RP_DIO_GetDIOHBridgeN,}, + {.pattern = "RP:DIO:Pin#:SideP:HBridge?", .callback = RP_DIO_GetDIOHBridgeP,}, {.pattern = "RP:WatchDogMode", .callback = RP_SetWatchdogMode,}, {.pattern = "RP:WatchDogMode?", .callback = RP_GetWatchdogMode,}, {.pattern = "RP:TRIGger:ALiVe", .callback = RP_SetKeepAliveReset,}, From 8d4f9ebc782befc5531676146606fe27d8dd7186 Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Fri, 6 Dec 2024 21:02:21 +0100 Subject: [PATCH 34/38] change version to 10 --- src/fpga/bd/bd.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fpga/bd/bd.tcl b/src/fpga/bd/bd.tcl index f85d8cfb..d6049ccc 100644 --- a/src/fpga/bd/bd.tcl +++ b/src/fpga/bd/bd.tcl @@ -1567,7 +1567,7 @@ proc create_hier_cell_system_1 { parentCell nameHier } { # Create instance: image_version, and set properties set image_version [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 image_version ] set_property -dict [ list \ - CONFIG.CONST_VAL {9} \ + CONFIG.CONST_VAL {10} \ CONFIG.CONST_WIDTH {32} \ ] $image_version From 3f89cc151bdc7cd8766aa8034085d2dbd4f3d4be Mon Sep 17 00:00:00 2001 From: root Date: Mon, 9 Dec 2024 21:06:52 +0000 Subject: [PATCH 35/38] fix issue with sequence stepper --- src/lib/rp-daq-lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/rp-daq-lib.c b/src/lib/rp-daq-lib.c index 5393cac2..d84335f0 100644 --- a/src/lib/rp-daq-lib.c +++ b/src/lib/rp-daq-lib.c @@ -784,11 +784,11 @@ int setPDMAllValuesVolt(float voltage, int channel) { int getSamplesPerStep() { int32_t value = *((int32_t *)(cfg + 4)); - return value*2/getDecimation(); + return value/getDecimation(); } int setSamplesPerStep(int samples) { - *((int32_t *)(cfg + 4)) = samples/2*getDecimation(); + *((int32_t *)(cfg + 4)) = samples*getDecimation(); return 0; } From 5b565917e17d0e39a28b7ee717487c56e934f89d Mon Sep 17 00:00:00 2001 From: Tobias Knopp Date: Mon, 9 Dec 2024 22:08:10 +0100 Subject: [PATCH 36/38] fix sequence stepper issue --- src/fpga/hdl/sequence_stepper.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fpga/hdl/sequence_stepper.v b/src/fpga/hdl/sequence_stepper.v index 2431364e..4c1a77dc 100644 --- a/src/fpga/hdl/sequence_stepper.v +++ b/src/fpga/hdl/sequence_stepper.v @@ -18,7 +18,7 @@ begin step_counter_next <= 0; step_counter_local <= 0; step_counter_local_next <= 0; - step_size_local <= stepSize-1; + step_size_local <= (stepSize>>1)-1; end else begin step_counter_reg <= step_counter_next; step_counter_local <= step_counter_local_next; From cefe2378c7851cc3c6e6efa88470be36a194f2d0 Mon Sep 17 00:00:00 2001 From: nHackel Date: Fri, 13 Dec 2024 14:29:49 +0100 Subject: [PATCH 37/38] Add resync example and docs --- docs/make.jl | 3 +- docs/src/assets/resync.png | Bin 0 -> 124857 bytes docs/src/examples/resync.md | 21 ++++++++++ docs/src/generation.md | 2 +- docs/src/scpi.md | 1 + src/examples/julia/resync.jl | 78 +++++++++++++++++++++++++++++++++++ 6 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 docs/src/assets/resync.png create mode 100644 docs/src/examples/resync.md create mode 100644 src/examples/julia/resync.jl diff --git a/docs/make.jl b/docs/make.jl index 085f2756..5e4a0765 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -23,7 +23,8 @@ makedocs( "Sequence Ramping" => "examples/seqRamping.md", "Cluster" => "examples/cluster.md", "Batch" => "examples/batch.md", - "Continous Signal Acquisition" => "examples/producerConsumer.md"], + "Continous Signal Acquisition" => "examples/producerConsumer.md", + "Resync" => "examples/resync.md",], "FPGA Development" => "fpga.md", "Development Tips" => "devtips.md", #"Getting Started" => "overview.md", diff --git a/docs/src/assets/resync.png b/docs/src/assets/resync.png new file mode 100644 index 0000000000000000000000000000000000000000..85296d1419f13bfa6922542847bb1b7254e9f74c GIT binary patch literal 124857 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 z zwrD|$624ZVgek}@@q#dI7`L4RA4(oBobDCuRQnZCW@MUPsukI(FaPLGs-oL=?o z&u5?RYd(Xxwc9x<5ZDgvO3m0+yEqqv(s2RTlM&*(R*1i@*8O!;pT%z|a!QgV58Gl1 z3@vP`a;sRGCU7Kxk!}`?rPEnCmI-3v`h!*m(*X%aiy&P<^(zP6Qjgj`4tIQ&hi;WP z?MbCpCbEQxpy-G#LlQFLp9*tdktaXwX6DHkT{b!V3y@4fVZrUezy7d`r`8P^5Wv}`k16*Fb{6DDUc=? zK=XMc=>75FBsBsvJ_x;eo^~0at2Qaht*G=fC&VdU7=#`c;2Uy=rIp8h%O>?!gh{}@ zp$jYFvS#?Cj3`(@PDWB}D|e7C9YE*PP@LJ%QjbexyBgE2BCM5;N7JzAb}lG4iBYI* zqiYW4-_i3!Zp;k<4Kt!&ps1Ti$8K%fC!Df=d{vr3m{SnGdx{TDomHyX+ZU-rBbdX3 zYOa4PQH4?!CC--~`pT-BoMuPl;!VnM}38vWSL&D%L^wRSH`oF{9XAN^| zQROH)*y5P#l7h$n=-d(~i7t&;D&}ut-LTvgUB_KNlYVT1vilArYop1t6PEq_* zGSqE_er8lwuM##O)Go_%ZcKW*$>zJwfEo--DXJS|x~9!H^y%c}02L1si_zXva+mx! zx0>%&Y#KezR#O~To}t&pA3h^>;n~dg8WB%8d9~`7cB}n>|AiS*(-8l^Z~!8^fq&?y>XRsaj$2Z5edBEAbtrmyIRY_ z3R*~c-$$2f25#hun*$|f+N`hiL^dUH*io4eO>sS_eIoVP;6jp(*-18JgMULRv(q%? zc9Fe(&Ed8LNJ3-BZV&a3>~OW6jVQCSFPV|p>_(mg%eazPtbp3wg=&_#LWD^&-^qm7 z+0L-o_Mq$kv;Yjv-~LEMmuNi(G}z-;%q5ZII_FeVzT2}|b7(u3C}V;yR-l|!{$QiW z>T}oE*9ZBU?wAy!t?paBps%kGOX#}U`MK?F4g3PR#D zCYljJ!;A08QrhLSma>*4LLbp7OLf-#dP>vkym62G6dbgNuzT)g9~LvQ7mk!;j|VtX z?Z+d;VO`_La3(N?5rZb2I$NLxu%l6OD#T5cE&^XAlk9#`i0P~f%KQ{t^N(XA5&yIhjd&(A5Tu=3y3oP3NiZ5s9sId*b446|Eu z*IaFX?I|$>(>KxXPM1spfK*{Yq`o_(Bj5KJIT(YWJ*p z-Ok5VLyL-~<0YX9$?1L=wzM*~?L4~ds}fDQ`lb7?d%!o%%IO|y8$t4z;MEwULIF7! z71chMwg_26hUE1$Mk3NB;MsG6^kF=P?YCi{@0X_F(cnTb-$+OrolDo+jlw1^i+8I7 z|Lg>a$$p_n4E_7Qwe_!@E65Q*4Tgpobp9)(O+s}ucUAU`ZGCFyisO{cl)>5j!9bJ7 zz&xnu6PnXPwJqNCIe1e+JIjeHPLhFo5giMCa4||Ez;*gyOq2!9I{E7 zq|!=>T1Pih2U1vm?|zp3&seSik7Y}Fuym#L!bXL%K^v9T!&^RsZz z)Yi}oJ}|mQSsnPfAaXrkyPnoyNs0WwQX(<h2re)&VaoQQ9mH*z1}ZteP;=%9Fo@8~5ja-t#PpG0vID*?is(V;fV< zrj9ZvLe#=YRv$F}N;HuhbPZnGx4-Ij*1-NG z;4?Ljzj;;mu~waFAjwG4IG8~;Cv4%i(YugVTsy_!+m~~jsU(Y;X}`3HoKM}K+F-k0 z5fc6BQZ&>UT1FdV^_iMCRLX(%M#&?C*T!|VSoa@~gO;IO$S(rFv)3$tGla5W(6 zd%6t7TMDS8q-11L_f3fxKYHG$Fmc(ABjfZKng`P%QzMI9H&?u`F-%MDG&DW0;yht2 zg&u2|akrTpBF1irc}Bv&FPha7xcYPUF-x-&Kge?p8$l`zr{J?o#~U9DI)hzVxz;_QZ_UicD@ph6;XUq>&Q8LD?wja~zSyYN>O#^<_FRL~W|i7J0%xjO znUcPf#qSqce|40(;Tu=%`9TcUl;{sKlOVzwIl{rqrbO z*ceL=_)+JvB|Jyd9g9-5E3}pV)rM)v`TIh=`gyR;IEyyQ%L5GDHw7|2zBun}owip` zmgouIgsW>WNSbUD5-$iA6u=FZj5$*#)AETzlA9fi0vZdUn-}~tiIYuO06HWz>sr?gV34J}$v5I$Wp=qNVLjT|+RpVxR$MIwTBUOnCFTDmS z;GyN=mCjKKanof-6knE-d?J;v$fXnS?%Tq3XUdk9-Gf<-E6-QO`TF!XYnr*>rq})O zqgOO|Ho0S+)1zlJ(OQ}`5Ip{EvngB<^q-z*{ATeR&!gSmJ$$e5nQX)i*1HCc27Wq1 zV<-{$C_%(WDv_y&j4*k9UERgWNizLO;qyshefQ1eL}9lL4eIvS+$!{>nt!p`->HQz zv)&_9NSYWd<--LoO8Fy|OCYD*7fF0$qJYrL`?k|Mn%&(p>!HYTv%jpy6)Y&Sbz zWd!$c$|+@DiAT5@jnIu*;)b%iC%3rqFWu2|+V~-G*O2I2Vu^VCC&F9tmwKOsa9`yr zlAb?jC6CO9Q#EfOUHazjdO&;!`UFMsm`hy23SF%7ipCPWOyij|2q>N8ouow~Y{J*$ zOmWIGCuGBOj&i+r#64HhUcgIDiHQwcpo%c1P4$9pQLqpZGSp#~3l{)8HT~;THUt<< zd;xEdBIj0Cb^;5@3H)La%Bq^AtqW#5!mI!GJR9?)4U>^GB8S>Gw6J-$XyVnp^&qSBDe(+Pd#el35{^schH^x$p#~{o$vEC%h56u3RQn1`LJ`Lj&qP$gbAclRcqoJ@glFj*> zmdz_*EI-_#cu(py{08>9+(}<(NS6ecJudq`fmR0xcWpMI&p;2YWGw-!E(iL&N1q`y ziiz*Le_Q-x*JMHqmn>)RQHPYB@ni*zctS@UdBFoqX8tIJMMZC^xX~v5 z5aTwO|GeJZ5@@zPt?bia5uB-!T+dgod8bn^nX~fk_bUYAE8cRW6?`$tEY?-&!JW8w zKGdI^zDVa22KeW`Bq;!oap3g`(Z7qWXAB5!^7!8eK<^5AkobGIlqwZ4AR1sG{rvEr@h{Ka+IZK0xvlj(lZuYk|6pe9^E{~j<)AC zM_HKBGfkFNe*LP>raonrS~&@nA^tUuTlCeKQ6t@jL`?jTXH=&uq!q@EoM98a>MdW- z@wCLR0n6ZD_w6j+1?3}1qmRurd;1lHF-o3XsS?=)#1^EX|0EQ79bvmblv}cJYUibk zA#p@Zo(Uhm#cj%;Pt(f?xwut9XDe$rXNyp1g-IZx@m}R6EH-(9E@GXyp^lTbB56hz z?8m65w`ZNhOHovy#+Q9j{~(-=Fszk(A8u&sYwm`CZ6q4h9G!S#L!%p@+K`~(vl5VR z>$w^JrnFqGLUBv>f8~<+I&a@7|IVYdr|5oD&;Ff$hqXmwG+xAr@la4c@Vf@(zvl7i z8xgx0Nw(ZUy?pxSV96{YpNocA&$)u7d&{kVB~*T zA{CimT6X#7y%T6MgRa?ds)1~Ex2_1sglk9+W}KGM8gS5L+eTv@l1o3fhIYx1(^QS8 z7v0!3nhGAYYDG#+tVf#un*I})w;g~&KgVp_nWUOSJ3($)0>Y{;MuhH?{IT`dW;CqM|2yFZ~uLNifL zfmq$Se_wUOh&Z@REmaXtRw!e8@KG7oCO~*WKy{8>Vrv6&X>>_|F)=-8po!3x+rR%NSort=3h^ znSJPP6#P9Jy?ck+{hen~n+99Y{ZAmRtw7E}UWnUiDowUu{d{ZWPbuf;flSvsZf`H36!hjlH z>a+ZbCt$mN9(+~eA|HKJu#HcsK45?0GsDHFjZna&en3TTrD7*3J{r5e<`m=aHBo|= zr>3%t@zb%2qR;(Fn;>Pth0mc&@m+5enu>xSIEY|KH;cx$I~ALRlL^I`xt3GNsc7$W zwz+8ab$_{Pt(=X;%IQA%#cOV{MA8e+)dY7bYht_?Q=B!{6K3lW$F3!F>nLt+zIpL$ z_Xhpp*AVl++GfZ!y}25~n#<<1e<>G|_TkPNBvR=nR04ev)v%=%Ik8~dpquWOa|iwG zFnA%0g(W<#0%hSQLOmx89=Bu)r8jbsgVA+;ZF;7N9{9U7(Y59QschSBD`f<`kGM9G z>OzL?vU$n7&F*1e!!!4ajAy1~1}<)^8V{$He;NxFK+bt<`6a6y53GojvC3CU;i__l=GdOfZxi%estZKtCGvF8G7tuc zRcj=o&!MuP!PdPx6D{@ET#L45WDsFyG@o1*t71hK73S9a{Yy-&zM)yUBPr!2gSLt9 zFPXR5aqk7rw{<*TJ)uD82ai%SE-iYYX5AcAI&I3%c_VZUkBFZwlTLX;ty!!NyiR+`P>PqW|~ zoU;=Em1sFuO9&%jH0j?z^|oP2V!!WKor_{-YN$XV_Ya)T{z|kU5SN|5Pv?}TP7tWL zGSGB=$Kza%uLr><#1Xmpm~HL-PQh49B(rjOj#iz3WZ=YiTmE?Zl~pjNtvgY%kgRT* zLRWq|iQO`InrcA|>n6T5VL=$H>bLho=o`w9r%kd`jR_cK{Xg}xe)jt{ojDY*VQUS! zI5KarhehMnE-Wkn8Jz2Eo(K{qIRv7w&jrAuQ(S#dt0wMdKq?0aq@SM=7m8L6+bAp~F1vY2wzQBn+~Hld)|wNT$?#OK4v61uI9#D_95e zKgDBVN@B4cd_NmPxfb?AT_W$Ajdb^CPwu9Z_0+62HM;LTPlnso(a~-+2VoxADL#;{ zDT^la)@e7{s0#h1r6AMc@DC^^&xWJ%u*9$WB_1|z4|ClQxn@(~zWm4g>s8eHyX+H^ujR8m z%!v_sPhTxQZ%>q=iA>p|&MmYY_H&a^?&wr$Q+No=n&$Is)W=sQViBIa8sY4x$;2Y; zk*8UpTipE-E?^HG(Y)f|CPNqxh<%HZ{I;3;H{=tVaogy)21#6~kihHMH%}MtA%CXcJbQtoDpWfsyf=7TK zPZQ?FoKsC!ak8?yJ!B?#%uMyxQ!w%^&y)ynM#&$KYToA zdqWEL$MGXLvr-}sXZ9m8of;E1DyW!E2%R1tbb8W)+D z_(|nrL)zyPPy2loefU_(#P`rc4xD$D0(gQt>QE)oFS%(SV6d%?vIsLDiH43K*;mxW z-ntmCpj5cg0rEL(tmu#=4c%-MRukx)z;24Eh+tc4mv`tWX(T(X$Hej{WZUnK`NlA< ze;`qbFjGiqM5Wo9l{AAh0&3~h*R{;=#obxf)d?r{=x!_s0k*wYs(-`6ka#m%VP2;T1> z%ga7X8bU8GJ;3?~02^X`?{6pjq|=we;$?*c1?tS3Jcj>A*;j@|8FlRr9n#(1Al=;z zQqm>eAq@_VbcZw&0!kyLD2O;PbR!ZnTOa*3SsZi=>vjk@e?mcJ1hWw(LGSJ>ikw#q6xYmuY{P$Nc z?r~vZVPIEHhVA~Cs55~DuALPtLT$ATQ6U!}$Wv+dWJRRe>57TdNcIx-Q`)9864Olv zEMMLgm4gZbGQL~En*kZ31nJu&1VFzp0%Z`$o6=IGOKDI;`3p9@MX||Mo%hUjr?<(KGoCXKgV&B3Kwa*l1=ta*vW>(W9$BfW4&PD0}M9R5P`A{@Nsu4OeU@dXY=!iw+b4{J9BPoEBVdNFJ zhaP5Lc3}8aec+>*5V3(aE+LlXr8_s46YJodU%73XOJ zB_^4}f$VqXgKAAOr$K{WXH*dgZ7!GCY{BHTdN3Pi&i(?82h zs;h-6AKBvsnJMcbvpY0{A1+8=T5AmvFwv!11#Q1uH~y~$@Wx<_unYsyIbX%FfeA?w zdRPU@TX$*)2NT&n`8*OY*Z4LZG8tAtnjiJdTZg+Wicm1^UB?Y%M{g8kVmEoB(#s)1l?4p@-f8kOiWX3vRHoxG>GH& zasKdei)Ybryo3-jJysE-;1tdhdS!iME#YW4Vj4F^D|AiUi-_I0YFLt;o+&ZYllzmJ z^hF2vHJf|BmC;Xf$eeV;P1mf>-Zn*>vnj&BYBwcQ33TL!t8j_!rWRZg!oPPpd*Fqj zCgG6>d!@jrD;r)AO_MJ=#UpW|AB6DikTjdctCSVsC zN3s4nQ5uoxzw#O-Divy$T7OGbK^-=C;M;Sb!v6~=gZriOC<0yaZLhgf<*Q+6X`rKR zbGxbf7qbFpbPk~p!Ul?^!oOfQ^Ubj*gw{6hR(kl5xF905&olqVbU8jteu2QVn)p$C z13uxSz$KEfC2t6jBSmZ&2HpkS5~IKcU?k52Y^TUQW3-!tw}f-x140^c+I%qyU-R{? zd`I(bJeJ;e6l8au)ba+_REyn5D-{a!5K5 z2)|2;>JESkDYqZqH=7*Hmr(Df6x9S#rB+N$uY?5`A)#Dq*;+!u)tRR36fGqPospO! z5}cYHTOi|zuRfF%a2ic<1{o(w9wk9x`!L3VuFkOxP|^Ib2i<9o9cqkTI^>KV3%#ti z!NQ6WBYI?6L5#ZOCS;V5uKT4c0ci@=y>hGyw~aeuSXwf#Wo z$8Y?pUI#A*C~j1KCS^syg*E-(U(=x;E}( zY$~N%K4l8}vQ40!!*c`PWYxc3p0?9{*GpIO#bQzH9Zt+zANs}ZEG)nYsnNGjG7hI zB-%E)BHW2NyHNo-bc4eI^3*SiQx{{{fvb|p?#3WPwoEq48OQYrjyMs=m!$L+RyJ%H zZXnH%me>&$wv=D_yf~?(Xj-yI#*I3aLp8dRlx&)|TPX3j=}1|zv^))b8fDtQnX9`5 zHT$sBKUq`M@h~^Dv6%`N8U8W2;*pRyUEO==`Kvvr&aaMi=`Jm{zXnv^*0F}4p{{e= z4EanH71s*kJ9RNJ@1K*R@4jC9E2&nP@1q}`k=**p&VIOqDFhECQbZy8nM}|K7R$`c zuD(^vpKvjA7W6qsxOoXlSXY zp3_5EzDR=ITwhd;?`MuzK2b59MjR728r{Zr04k<0W(>|sblM4LP{pjYOXs$HLP zm(jWIrTX~D>s6%9=pL8!lE;&V?=vM&>_7VW5HdHpczkrs>t9B7oBLlZ0Qz_Rpls$) z^-=!KS>?(zE=^Qaw@3nYX8*-3lb^I;u9$}>@#1`hmgjnz)mC~8=$XqP{l{WM`=jk$ zm<;ah=|}2Y*w#=*7&hIM8c94;dADn{pANCDPFK`3vWc|cM}<5zK%x(gAe>dhK;o-J zYm?)7`a^z&8jBBSRkWVwp#3Do7LFXzXrFB=LWXkcM<_^#H0hq8_1hhS9BZ5;3GD_P^KaLO$&eKJnds>gX`?DI%^`JFYWUs6FXUTD=j?C$ns zAX%T@GS%4}2^KNfE7}#?P)WB7nbeKEln;QbaAbUO-xS>w`po+hD`6VPGMZ2*{Uv#V~To1t&#j%_W)0FfDOkY#^)G+7=)~Dh+8;0WQ z5;2*5no6%!ciai{NExSku`%(6>Q0eeMEgp_x8vaySp2rQxS2&9Xb?lOz*}{ay7AKP z0t|vTJTJ|^UuYh~3&GJPJH7F_?qZhZI}?+iB*f92R)|m9cyY=G+7FG;5@K@HydBGz zVmf#+%6?0)ZaBYU6C-sMFw})|&(e)E&_mLvaXUg|Rrtbv))ht+#N_uzjV@xcyM|Jz z-i8-?F->a)_@F@y5X;ZMmI|CJl`ZSvHxIr!G7Ykix`FBze+GtR> zOsMOzb2q8_y7hdePi{!WK6HB90$deW;#KLoWkt1tE6@k2&T<F>`GY8chaS zr?rt#9xIfgZYgjbK56YzC!(zAf!jhgJd&I)f85an&!)HK=l?P;@SvmX-GWqadBAU3iH>SbH**Se@*jKq z6e1OMrVO=|o<%g0<$E-ZPykz+l9i4zgMX-@KhO$!3-xW*IB>WrIt+38-5DC2;WoOp zzrP5Ilu3M@Fi^5%B}&i$C7-sh)v-J^N3rM#X-{YL>ikrI){t#O6+rfhn2)Lg~g>Owd)kn*^(V&l;-G3i=X zewi8J-3Sa?cD?sQ#U;fV&ogqyyln{3`s0&EZHv_VYHTL7DX(x+&1JqS=QT=T9JON_ zE-p6_SB_`ovSrcm3FP!Ws^gVApo)$6o}|pytqFJw;{tEq>gfp_dZR3kUNI~+L=O)4 zsd#VO)mrrZ{(+)=qKEtA2CN{u!jEqp#mmDcN~r!$V69kRI_pi2TRbZkF-m@(vGe)bY4h`}hfOgBn!T<>6;s&{^cXv1Qb0w<}^=^Dd_p4iG%xE&CQzZFFqM_ zO|cL|nhO{smQgjC+{pz%f+8=j#ZjQXc?4l#Do_48@PS(P;?Nt)HJ)HFt%b0k%57Zt zK~!>P*`2@NK^N*SoRV}S(HRiYjTnX(=0k<`)8=^co%#sjU1vdR*K2ETPWQ7?`<^9K zonQ;E7Qa8xM?kzbZcon0;qdQOpDIQwU7hA3kgVExTonAKC4WEbyF$*%e48C3o>yjy zd{aO{b^&-(05V0==5CtI#oV7xwFy)j^h<6? z6fq&LZf*@=l>zc2Puk>A4+E8UKcp%v4`D*7&(cfPze7*{C7@mcU%`JvG~Vq3<{&cCQA1Kqb&* z9dYTf+Ek&AFUJ%3YXy9)vrZ-CtG}x_Q+B;1wcTk46&BXv2c2x3-7R@8uB2M0 z+}HTB3E3^S&G8lB%w@G%#Z#8uk~lSFrii+mWA4$mmMV4hJAfsXUar$|lxj2l_?u3l z_{wR0Cc6$*?8>!K7%QH3c&AIGBR^*P9xq*!^k=m1;qe)_UecI27p>$(8RZ!#l*;AQ z?$l?EMRo{InppfC8P1<{?=&Ar%0TDX72VI^ADlsG_9)m>g{rZQXQs!oDyt5VP+Vs* z98-pDCApI?^HBSBzOEgknoh=_xVEg5mv*Qa0eQmw)=SXb`>9QQvLYW!+uE57Jm?NsRta5Pl>U6tpMicZ z|LAF`pZs1si`cQZ`;lvzXK`W8_zFM^inQ3B(dWb{U}a9!NaumXyIhdTB+_Tp9tt#w6@#-i}j)m_NsJ;O0fHgUpI|1nl42aBK6#FmM zsc3hu?d$5v6&s*%Gi`T&_|&OV<59jk8}5{JKux))H6{f8Z;?iwJ7Dm)T`*U!ZwtqX6qtBc@*2C;~dVl8S#YKf)^;3?l2I390T`Gi5=j>(J ze1gf=S?f_o24VEX0A_BXOKjUWx3imRfBoZ#lT=N%Oii|yp9#>LoF7oBR6IIYDa(9M z$zp@E*))91&JQ=RCQqtoBGf36@nzLJj zI|hingCWgs9F?mZ71c9YnvchXkgEFn%x)}5o=k10e*{RK@oSI8|>-|AA>e=O{ppsOXFRRpo}uU0$gfjLY3E$lRUI z0`;-5DB?XcQ2FY{VORqpNHo)FV>`H`Srth(FguKimGp@AVZnm5P}hqTN>ap@*3__% zB_<|ve%;zGQ(n@2puRfEo>HE0{|2h}tm>{F9(1Q-M@FNxI)!VfidC(xqBMA$yU~GN*W5p>=(ptFEAyHPU%Xc+D=S0(Ru04H2=S8_ z8%Z+S^u?{j+xC;pfG+D@ZLckQ_dtLXI9k8bHj8`nv)6=+k8_5Gl-vE~}v@^zPrWk~r$pR{4ZUrzO zr;quD?L7H2(orGp38=cr5$P;}VO(TbC=s0TupUieo?yKASO*AyMttxzQ)xQS7dkbQ z9AQM3gQ=JT86mA9RIvc*3cM+3+>;41p}>zyh_NT}hKUFnqSTnEI_VYP9zy_u5aAL) z-Z0VREGn5Jnw?cJLDf>3BO%f;l4rO8iSQ@2P0Y(-bIb&yPOEXGm2@1)fVRJZatEPN zbUkLh2#&cM$FQIxH0Mtv3s*bma5ECJFRlaDc0~j;j=r0TO9LYVAw5(&LWUo`oPH)<1G(C!h$G>fXjr;>GJS1BzS#_aZPBWo~A6aj>|1`+#mER7@g! zd~$8XLX_bU2rkgyOvDv>J~nM;@f4HC32x2eE@YEc5kp-K&&M!fTdVuWXD-+C^d6Ek zXs*4hnrDORnE;3Fl%zjKY@SO5NprcdV>+2JO(|p7$*R%EWWM`$v0aWDk?h)LFkum9 za&e$MKy%@qR_>@VKuapE-_Q0_bn7!^rc>mbli7)4Qx~nj3bzUB1znBU2n+(%@(v^P z;f=(cmEb;IUo|clHlyLmB2*z_hoe*~V$f_uf=lfq=*^|1zBz?e*ISWIwpVXI;^qWc zig+mObbVs~TK06lGB$(ZgQixvt-6hhorAJs0}b_O-!H$d1c~8Y?{!U;HIhEXPDN1t z1{M5q=~Eou_=1XS`uk)0+-E+6b*3#Loup~~4FLUUb+=ZMVP3-9rU+EV1NO7zqyHHzP=ix_A_Qq|r$=0(B- z3gF1sJhf=}brSr~sQqr4O)W0Bkx(I{{4o7zg$e129+=4U*wfqP_8J2TymChPZ(bw& zF zHxli=@ZSg*+(@E7^K?!nKlU}*VR`|%Is;Ne6H53NKyC6t2HX;eO@L}X!h7fRdgh^# z{UE|}GR*fI=)ZtfHaRy3n}7c4j{xW?KnZ9vy;Z|0n}HRh=SY%0rOZ~Wx;ZRLgxv&V zn6tQuzWbJ~T(EG#JH6dyHFILSB%UWyCJw{IBHAcGS*($eoV$A=i_|gou|25%YYApB zSl2!-)^IXt6)(%~TFpQieJUK4|1V*nZ2w2^1yLqJH;Dv7Ql7x8ysR3yJn;W{!YP@W zesGC3FN!UWtIp>$)==VLkDar~4T*DNR!C1zpT-HMVG+|!Y#7;dM1yFFfdhdMoliuQ zZoy%d03&9ji^n-Ndu-l9XgAdUBjW3z)Yz!6XqkOesl>mQS?y%UkJ5M_w$<&eWF?RC zg*HL>WlepQD=K|tJAd4D*8R)5bFBKIbiOlXp41l0dP&{~7~h~J(2!ZrbPNjt(*0r! zUWkLmFF-)&8Vn(jyverN>HaLh_AkD- zQ(hk1R5xS+ft^qDOc`MD0unV8T@3qa;!_F28EZ{tP0l{J#C7uHB16oDf1bst;}z

JwS>45 z%jE(E!qohXLbzy@u!zSxCmXGYkgI*1UpdzT({oN+6`Zpn$P;<0V9<^;NLy}R4RQCM zNIbs;RdVasUSp^sF!isFdEwGOUibTU{t&g!+c@cS`DrYLWLZTRfE;HrPJPmf`W#y^V*TM&`w}+S`&UZ8$RkAg4!5E)BtBEG&+R)kM}hm%eqmTmAsG%t;}r_eEWo_VtItItXU&wI{9o}*7!WD5=E;J9AcQ|X)1}% zAN~#qoo4xqA9--0U!a&C{+ZQt;UNDq2(sM48pD><+dX7z2sxS=EZv95ZOIxjh#c>bvsnfF6M)N^i%>0`7-P~nbV zC8s$d2uDGNZX3Stq}Eh)@=)qTHKU_Q)TP8E?r>6eZtRG&r1lR(FIa$)kY8pI8qQOI z#55+%ndo{SGGt|W^+t{^gKWKFMt^lqTukofSmb!E= zrDoL5juh*byxZ5<`7J4t9FD=BHd%KuGr00RX*e*MIptA~Xort`qg?g+ANL9@sref| z%O#VANfM#07Yv8#DoB?NNZ&-)e|VT+u^{nW3z`459d((+*?2<@KNl&gZSEJ~xL~1~ zVUVkh&+poMDKI$4MR=lYP57EwuyXmOOfsb!be5xw?4-6(1n1{z{Ov4(zOZ9-Dp9J_ z6hXFbj+GTkL?esqh5p9$YzW)kO5RjW#x#Wym9-q&Le&6SyE=4I>vqR+lauxB)&kAz zBD4=s7CV#DUbtrQtZKwbU(WUPJ|dquYP+Lw-}(|@A@qemf3o);D>E|`vy{uA$C^y& zI`dMMvGXV%9ehG#zB$X$?%gPrk=p`}|IQ5WHgpB$1RfSPGf!DojT=oIOGlansbnnb zlV(>j7el8S-@L?fwG=D0dyA1pX? z`snHt*y?yR^f}LeMMK$?Mwq4SgX>YWAB2IKvEEE$J+pG;2xlI20h}se;1{zFQzI>3 zGha_Se+vpBNPHZ^DeY(+gT!E^Us4j*fC1q(k!+bcTK$6yIT~uZ)ua#KjtYZ_e|tCJ zM$w_ej>qG($ys>hxIOR!CR!}+-?i||VZQQ-n5N?i%5c=t%$R1_vZ#_};-kYE%K7z# zKi{z;Qdl%I)seh=xypAsbcdLT3R!K@oEIaXllF-Y`NYahp$QJ7Du^{p&Q~GFrCeiV z%2;z7fZA!N+UPQsx-t(lR?%$vCW~N8p|++}Mzxc;tO=pSrNG+Yx}noAVfKg*uJ5q6 zD`}eWCvYzG@t!Vywht_4fRDA_y1Pr6{pC_zEwgpP!%pTl7Bh@h)=Xwg%T2@kq5P*~ zoR7+ znwZJ4|1*-^Q#D+?S}R?8eCoQxt>MOUY5?fppc@q|bz&{%n)jb9smKbk_lwicAm-gS zGqJzfc2NjQ{}ZR+-Svr>;f^S)M`_EUlHSV-0#xh@teBq_Mka8HJrQ)`b|$br7FX(* zjW<-^dJHKPJ1Xc%gZ@|*to`0PY!635YdX!}H?*8PTQ4VgwxaWATu z+ta3G{DZ4?tzi%@Eul$lxmUM}s^R9)K;snWdtJeCh9pJR>APqTrfwC@0BXDU1S8xn z8-6!?EHo?KaGt1D$4A*~{jsIp6$uDVo-Apg^r$;GSHSw00yWimgf?Lz(ust|| zl*v_tzHn}CRRuY(<;;ZHay49pz4$KeA3p1BrPtPo>RQ+J z*KZZXs{2KJnhORd#&Rmklp=~oUuxAvI|1ucY9%0uMRdZ@iiPZBaMZB}H52(>Gqz5q z>=CtSmD9qx34POTtGzxphOb^$M$H*hw2qR*Or@@3cd09>THZdmtA|>vqPGTOeUhZj;ca|gt5vBO)kQ0S!a~Oiw6Dy zwW!roPHaz5vShqi9ZrONy^6dIr$%a?+qf4P<3bur^6DIRedB_WmJ3ycGOVBHTj5@( zH{bP}vm-4h2lgHkVPekoyp+L&^)kcHy7>ibte$g}d(W@YqW8TnC(r0fu3#s@6(>W1 z>812>5=IuuKdF_}4_<@OIMXx)s*kud=2=7&nvVPw_M&)|S!^T7Qi!&$WA_0W%!5$> zM!JC|8Nn3!v%Wv|HfGbIChkzhIn}PpNx|Cf4rH2tOl@S>*gmn@tsVn+k?8Xmp z)b3KIXbA|k^&620*}$Gb9C*ei@{5D)u5=~+vQ(AExeD2TQ9#QNsyDbtsP$^8F$L_6Tq+*wpOd+x7 zv0cH$O&|M&(8o1~LZt4L;^A{5PojaQa`_FabsigUYU6Wh6@`y7czLGnRnx9Owaw#$ zuz%FN8WsdWInA$iLG=VGH1f9l(3eElY}%WdMNKVDu%_!YsFz%;y1k}lxDIKE?vY#h zX-&D#!LHzFLJ3PPCHO&7z6x5>dOj$M*b(j6*S9%0m3V$@g9OA;HU$l|^c_B`f(8&w zjjDI0t1$ zq10jil#s6M$kzRNF2Wv#b}I{kP>j05eI)uXWkcpCzZ%(Vc%Aiq2 zHR?)lC8b~SW#Y4~p}r2&{IA@CBg%h%Rbm;_N4I7939m&*HS9&CIh}1`2VRHHMu-Z0 z6*c)rHoSS(m*z{|f7pxc7`Cs(?ZtWZ^9XR>d0)hEf2ZmV7GjskF!EPf+n8&7WRN42 zKv|jfD)GG+s%o={=cLmiIno=xYA=-Z^m02pALRwi!ONdST>&;nrt2>OkGkJAiMo`- zxlKX1PH2Eh^p$l#A5%zJ@hE90--0;e>~*i4Na18e<{NAcj_R!|GT4(ZI9BXxqP2pV z@koxyW0oe5S|QH1@aZPKr)1=h$a(59B8<~?7LJe`?(-ix=EO-Q3>%3e!%s7>XjXOe zUOz!p{AU8A88AB7q!w)Y%kd!TPlb!2+_p&{AQ2Mi6rNv02YHSX)%3>trutbGgusT& zX0LNITqVhVpH&`Vlku9C^2r(tO%g)g_Q|AS>J+EA)3lj{zDkCQ&9tW)XZPz*`L*i{evEM|JusA770voi^N>2Bvw;__FN=0+2%ndFzkhk z)Mb@f7!=^lPv)vK(lH@XoTOJD85?UgI`HnJZQCLQcP9xc-;u~51TtQ!urMM0HMssj zY3lus>C{x#u5~Ns-oWW{*kAL^VVQF3)4Fqk%OKT z3JI`*_c@MWW+qnns2&e6y-IgbSwRrS2`*G7%b|-awhmY*U-@z{#uAcu#$+THtmH2y zL6sHt!0`UygKNtBO8azuzget|Wfv7vn@oA}OKr?tPcF0aaSW^9pPdT8D5wt|#JYt6 z95HxK`)9|BUGPlkp0x!Txmh)T3}8zd@0tcn(9)90&N;Z5-#yxn?-!E3J zEKm1Ra3Nfe6Z?1xS9gdU*$dBfQhy&^XsfJ=P9Pa=Qm8(e3|zF!W)#SnhM|cUdLO&k z^;pqp`!d(1_hywj8N64JS5{S5*)*-Uz0|GCux*|*F+n!(?;|TErsCP~?HM0%O4fuD z>D3e)%&E)5>(OuNWIAHY$--B2Ow~v|SS5KF-O$7dRawA+saO{cqRbNQ>kb;wntgzO z$_>)sU?y#C9oj9ru_~c9*?8~i0=B8>dx<%jmnESGUJWi|TU6YAqpvrS;F*8h*^XNH zK3u$J%hJx3KawpHx7QtTR%NO^Ze?9ysyy0{vDbxbg}4WPEF88L&`6(S?NWPVLD{Vp zDLF1L$Wr#U>{NJ99tfE-_1tojZRBDKE#TzvFsX=%L_N31##39*M49I)o_EFyxQSa^ zi#S!{@}i&+)w>i}=|Q0nB=Uj84{_8})r`@_M+^A^P&v;x#3y*2i19$#5d8oyC?B}Q zmQwEVs)VGq+uSTDf)#(7^8*F`9t$_>@92^?MBG7-pipHD>%n!aNhMGP;0>E0`c26 zT<_0*h`0r)@6tTSMKv(j%#I#2!R{?}Zu__P>xT!pz`ZTVuIM~V3byHa66iBmsGm;(i*!Zx>t=X&%_1(3l zPu4qm?}T5kPu2X(o#|vfC*^i*gkhEokeN-IT!SkIlY1_A)_=V=vh7d+n%+58t%9R< z8`)GDu$b?!p;qB~67}>n(CYDy-!1-OT3Su)>*D`;$_-k#9;M0I+`QW0=s|LO+e|fQ zmn{P~eb@B?zl#Xz4f{(hGV^d;2=grs^?O_g|MEy;8)Y(Y{5SXr>JQ2Xc2&!Pba{}8 z*H1$PO-#B*9q@^o$HtSNDuPQrw+R+Vs8UgXrvA)I6#UVJ52a`6os-D*lVz)v#Kq^n z6U#uu3-7klJn_E~e<5Bt19KUOj}|N_*7IB9*=&sFPs1-n>Mw#E?7(sQ90;TZ#&+K*ViJP(37j6V(~6Ys z1*8gt=Z(KoF*(H zfMBX)Hpp8GOCpYSa_dP@VHd)W7sLPcB{W9Aw=U-@TutLM;%c`+lnf{Ym8cxfiiB}?}l+4S24(Su7#7}|} z)DbcE50D5+lVTyC;^YzIyc418>LziJGw@LiW~$r5qdi#dmrLPK5!T zI&K0-?RJgL(OxNnsQV`@RVO+gwN!4fUN?3R1Rs72oWjbHBz~^)w`C5(i%uD#%4dXF z2~fBTv=|o^0zN@u+0XWuiz5BMEQ2%Q{^~~%E~Qlhun4R-tkpw%0hGvT=}?(A%n|^32SLS=CA*ID7s>W{ z*X)fQdMPB~xQJKILedvhst(Z(t|Kb(F)WZRood2_ud$yYvn6`4pS134+fy~Bgv~>B z9SO_2rZgMW-YdvwUPk!79im76p~XH9&=Kb#!P;YoD_c3ML2_%=mG7i2OS{^)|KKq0 zXCQbVsM~8)de)L0eRARj`DDgoWnbX!J?P5R-dK4$7k_^^M43*`h1R@xQz-(Pl) zP1XhMw@c_#O>Z+jEcOjlX37-y=hc`AoV^X&)M4ur)vgFbI?-G$h1=#0o7) zJ2*h~{Picb9C1k?wv2@L9|80TB7~90b+)DquZHpM`u-O^4 zfRa}#B zra{Hg%zCTCRU8O6cR~xUaHiIae(V1JYtR6R5Ywb`XO#02G>Ir;@RN?qGynP>$0L_% z=>&IbysuN$VG1PHQfAFzcOBG(|mX14FTBJOA70a<&*3dqp`%hvyW?E6PkiQU%W{9 zx3jMgC=S^|o#E-qJUkYSA6BOAqT+)41BMquU14f&_lC8v$!1g^5zPB_75p@$x0wF0 zyS4oCeN)QMB^UZIcb)#Wq}>gpTqAtPhfLc^Y}MndsLPSS(1{%Uo@gxfAd{+zX~lhC zJGuiWhxz?xQCC|G7a5B0ND~YI+`^9M5_~P_X_+%H*`ad5)zPxcxaXY|BH8KJ>MzFoXvZMOm6zlr;qc&Pv8Mej?MdW;u^ zUnn4*ce%`Vbbm|@&(sd-vd zuz9^7+B-esXJwLteM{Sg5`ErzJ!LdYX;M<$4G?m=q!o$ai#!Z|&aBLt)#>6w>h*UM zGy&b2yppqjs+SW~97V7aku8-vV;95XZ)u7*={rzhNfEPTSdluf8NJ-wA#Z+>_4!a1 zhpu&?_*_!hHzGq8njI{a73E;p93BK4HZ0|L)|-@)(OkH1j24 z#NU$NlMbhP&+racE*PI+LKK;7RpU{S?it48hf7K_2vY|=Vg7oz*H{UAl|1tqr@79_ zx0%2oWOuHQgB2rBw+b_1wywn2o#A}qHG2r&m(4arl*_pZZM`x_CMDH+KZr()WGFX?=cO@dsn4Y!_CZ4Y zGzBXfePX(Mh944P+r%YU-elia)a&*d{!TG3vl|y`6=_U%6A?%WuSKM9`9`$FcGNFk zcL|_riqKp{pe+9>Db(;9jJxxvLomC>+kK$&dM)EHxp`|X#7~Ft4fE2(quQ+Lp+PrN zBojnRj0c&SmH3NefYKhfbYgG%_nTaf0$TlW37oc&`$a7XvU}+*zGzRTU|71BhxX!3 zb*x>+kt|+)In6=Mx1&pESnv)6C=hjk z5m!23)m{ts&075LYNjzfn4M2XpERct9^Zdd2#4X||1MzgYGKYRy83WAYaAO99)-uf zT4bY1*sfplM<(WK&W!`*+ZZ+e@Rf1yrvW?+T78#(DW%Xq6of``tjpnvt2S6_;uYBS z#hEAw8UupQI6QEio?JfX43)EKr={OItkxhL{p%VlXC%D)z4@5)iTe~<_*a{;S2u|z z-@I2fbZE~)cJbqG?)~ho{q?8!H+i^Jou|-WxSRi=cyxE!`QG#2cH^e`msGslvyY&w zJiz{Bq^L{bA*N9>YCeKdJLwxz+(&)#TxmB^R_s_n-|+IiT9Z3I7-PnWv<^+mUG&EG zH7s1D{cXm>a{N!WsumOJ8yw@}{rIr;AX9fwSw_pHl+#A`(GgP|YY#DnjpeGoV{d}0 zWpt!9>o_b)dOmEZLqlAn=K>3@DkZiMk=IxvD5XepC|jEb8CL@Hg0Wp*RPRt{ni2nA`exTYx4-Th`EI)J%9Ug z4x}WvQ&y=+@Nf6$H*a_k@lBPj?gtVZqdTuFmF|@^VIbaL6ZNg$G-F<1tUoAJsVn(gTXYqp_#d+1yHH9(gSiG=zMe_@P~U zUJAJ32{qmFURqSXt1B~|>kF=}xYiEPZmlfoNWl%F6^*}hIIH91G_q)QDMS5NC7A{B zG>6gj%~-Ajx@zNO&aq43Yn zriA5G4+H=bP*ru=)p@*eL~W{kA3P5Z+{avezH1ptxnf}<`|eBEd}cF8`)Tigb-qn~ z0srlupXQWwf_L@Ls$S+tW+B3cJrW|<;kf^_U^ie&&+2-aU9>KLbh@ed)7t|ubvKiS z&xmt1a>OoJvQm7(ZpjN;6|W|9W{kl-e&hryxujgOnf<2uc2}qZT5LyQA@gOwJj4B_ zuQhf9F+#vuqlN6pvyP687jT)}deDtG`2`Of0w3A#XkoO5$7&(KIsXtaCSe}*|mk~`5yX#pFKio|m+A_~= zaL3!lM8i23KAP6ZaWJ@(zudYla5fWLr5bc*#3I!={60NxXl_p3QT~MZf$GcmM4r(1mttk?f z>Z)b!zxkH@TE2dMKkS;Wx*zfJn0=^%5^Avn#Ww>0HB~L|lBy9V>?qH}6g1&=U-;}@ z$o*iCrRmLs)(aS@nS=ICguyZqpD^Z*%sKr;5?vB+)h?wYsxI9OR(HKA}iITw&6 zC<~`ZIr{xt*=rg9w{+S00x(Mc^G@I?_n>$@s4Cz1pUHTbl@lCq>HSWmJn{S6(;Hb{yNEZ+6#rQ^|6faj;zC;C?bNoju-P8Rtu;k#P0ff+ne6YAey}=N zh)ToLUnm+H%3TlY6#LJZTHSol4bh$le-jf7n34C>fo`%Z^XipT1rYue{5j4CL1w!OkTrB?Z2}NK!0u6G%q_nn@bK#;@3YTGp7$4? zp<_QMCm9o0x3;Rr1v*4Z*7qL_e8IPz6>kuEaj;NX5*7rWE2)6J0ml~E%6G;IJp%*r zn~Y)W%=DC}J8NBbX)>*Wr;g*~_qUsJ4W=!s1koEC8^MQPU)+Amgt7ptiuT@uuCeh8 zFm{!CoE!c+#nOR5VK`2)6eb-8$o?5|$M0q7_~j@%+!g_J5Lm(Sbru1ivZ?l`*QN1? zRhuQ@OQ*;G`onM4HZo*OQaZxjVeB2iBoT0+LzV(J@7CGnBo=*xo?;(zObNdLiw$Bgu=<&<66FnxmZYOU2B7X%jeI8=M?*RP;S z74o~1`_u3c%$aKaN+9m|1{C!}H}ahx@P3+X z2&u=O+0ebEuhftSyH^SPW8nNqeY#_3dwH-3o`&MwS>TxtWaJ*asR5Mje)!w%BgHKY zxvMU5&&^b+gZN%s;Ndn7T=7o9DFyl;Z1?I1IjG1>PD#2W^{Sce_?%!ottM zC)!ztYJwq_odu3^uRBkR4gtyR5ef>*T8DC5+2_M5U|0R7q9Qg#O$O+2p4t5GF#qts z10;t=8wy%lT5h8{@p>@KOotpQx*$|t0Ntp+1a&TFsZ^%{Pwr_+3F@YReKfU4=e6Ul zr^T!>@JahQ9@fgA3nmji;=xdB1YvLb4_u4Azx+|Hk6HRaPCC2KkvnML<<%we-pIWD zcqX?3RBW4o6mvt!A8zT$kN&$x?4>)WC#&_>(Vm-P->$V-h`MIaJ32y&4~t$b1%fpm z0?cyFJ43E9=tJa7ay~twlfIaOk5MSXP_1FA!X-{us#Z>2>DrfKZ0WiHzY@I zQ5_v)5c-%!LMz6Z?^=m{Nz`s5LTL#0%$oP0%T%56?VUrUcy(|w|l8h$-H8nM%qUdW} z`hro%4Cs&9Sv4c}wP68FGqp6j(7*ei@M*-;3krg6&bH+Z4h)R=RRwVLjf{+*K3%>P zY<9xl65PoZIz38V8Kg-UjtEW&Ab<*nLfHp>2TU$dI zd%iNxe+v&+RO~*fvg&{lG75`}U(H&D`@eWGCA@zwcx!$ROlO1Hq@;kG(&9Rk;N9IF ziHeAr*l7i8X*aMNLcze}$5Dbdg2=;>cmuT5FuRf_Hj_l1LP845I1u&_yr1S%Mt`>Xvh%@!#z}T=ZcCh&me#_c z4*%v%y*VW%CGbby%LgllDuEtX_8#Rsy@dZ$+_nEhnYM9RT1GNXLuDI8%8aRq z%BzuQC&@8#7*t`+yb>4*hHC^o}SKNge=dxa_Ata z8_F$sXOZyCjDSdeTYh&5lPnoc@LBa0|TuaXPXBH-GN_W$y!ju7m<8@eZ#{K&s>sN0?r%t>Q&X~(tY=; zs^|@`vd^PyUVIc?ArGj=p<&4;I}3Rbs10|@-WYj45qj++`@o30lDz*GRR6_(6v%a! z_su9ODq2}unx8sFp-_&$8^)%b?K_jQaG^6V(VpQY z*$5DeB+h8+=LX%lu_Abt*qu~K>7K*C^K`D?Fqt<5k~2g&HB09BBe{D zG=RCsjapx}$|i8#t3lR7d}M@?Pbw1vKQciMTYc}|TWFMH%Z}X4hx`tgceQ>zs&*S# zBGc22$H%9~?MU!ofBm(vz`!XmJdQgT@lZNl%Hu@_2hTt3B7%T;;DrnM z1qIiq%h~=EO6#!U@#7cub3voG_Wph0a~03}m9b>lXsjvI@$#j$o!z1?NlI2u?t8z^ zk?6m_eaNsYGL7DVOtnZR<8?|7lB+YpwZSx@A#r(SP)aCoC@Lz-p}eM{Au1rC?D6A`m$?SY%F6ZaQjg7OySynsTe2)| zZGolL+193e-~c5$T_(#(feA2i7J5QCIn`3Sc8mC5$6lIM>@k=0>%2#|zi$I&1Z&p7 zz+iTV$W=F!@XHzq9WFszG5GKH#Ey-RclbXF?&2BfCh96U4QGpxbU$!GVGM@p#d{*M-S& zzos=(%X_CGTNoYn2A$^@5nkeSI$d5~o{Td!9r4w_2;!ci)kWXWNhv8o!NE5~f3++w zEC4{I0&XvZYRz7mlO&RbRyr$ZoW_&eZL$Jm{{H@MRn9bP?#fQd7-M2(RaMkdugl`% zVhf+|nDOATnAp}oPm|0Xb#XXgTgyH;CZQMG9Verrw*3^DoHJto_@V27s&<;i+WI=w zI)8;_gR_GGx3iN|@0&NFSe(N3UuKP9b3$x4Bql@ygFTq!YjR03J`ikSqxCpNM~=Ai z9`ZA6#HW&zKh^B?x#Lj2t+~KyH}k!;GrF12*NiQ&)rsU!g%5+;ZTn(IGvt)?hd66r z-w%ME01hU*jvYGGNMt{!r=+IpsCa{+eh6I!LO3*pyL_uTdSR{(iDg)_+`?&biBa<| z=a@Z87|b7ab-U>NM~@z{fF-P{si~l-n4NP@BNoj1QNHbHwsvGhgebzr(eX7947`3P zhlYlV%n7k)EG!b;36oBV=%#ZY`qbEh-2D6t`nkXX-GByrSLyCjCH?*6Y6&DDCE=w&Fex`FjWmlp42BTfRo!jbvMPE!QpUr#l+)AM)AeZ)-wgv+IkerA&^R?s@v!h2&I8}cgrAilrQq5*1m;Cu)Lw* z>sObid#9!XX*Z>&VUPV0)olsee|Y=*`2-IR1>2s{@fS6^~)|yokbej)o+X z?*8_h)^Mi8h&r!Bzbod%P1WbSk(9B(M%||O`wkp%(ap4FXL#p;1~7?4dfnTrm-+>? zZK1}fa>fx&BEFQ7@%%`JXmzsK(9m#p`j$<;5%~Y8Up$;@XlTsN(_-&JRy3JQDQc8) z2L5h|VCt%j^7`5uqvfq461N5DhBr4F(Bn{~!dC#SunKDhzYf27v;6csx&Ap?ymz%n z!@V>6!2Ykj+P{B)y>_=1)|1oVYm{$SXdGt>(VWdHP>cL`boPO*#mtU=ckLRrLK{ozx=Ma*#-smn;pf@6Z}M7gB2a|lp( zKZP3uM)b`<$Gn~Z-@5LVXahsTIBahzn~lqCgW`~8b=c(PZ0zb%pC|Y~;B#15n6`rS zmC3_Mk4R+Fhw1vJ(_m`_D>*jBBqz$^Vu?BxVK%})3ri_Nx3!gsIqmu72&I#)6QOAq zzx7hVF0kMa^B2vXzh1aa5#|*aAJEe~R~KC9!AYgl0Vl$bs{Kp`87OJaSIWu^WLgv3 zb6b7WEws2?F62J;_V%+)fe(!PB=Sm!f{$=yi*B2Bifqc>nsEkZ8 z$#E4Ano(Rj)Hmm^Jbi|s;xx6jC5tt_tUA1|a=u_~y{%%*1&6L*PVc3H&bX_q>q-cf zIt`cwr3bj3*TMTg3H9t7Dk^5c94k@r-Z}7O1bhqfIu#`)^hOxN3LbASK0WcjF^1Qcf5xP? mX_5aq5EK7S8uS1Bm`HBQHF_ literal 0 HcmV?d00001 diff --git a/docs/src/examples/resync.md b/docs/src/examples/resync.md new file mode 100644 index 00000000..63aa636f --- /dev/null +++ b/docs/src/examples/resync.md @@ -0,0 +1,21 @@ +# Resync Example + +In this example we add a resync signal to a [sequence](sequence.md) to create a signal that resynchronizes phase and frequency of the DACs after every frame. This can be used to change the frequency and phase of a signal during measurement. While the resynchronization is synchronous due to the sequences, the actual new frequency and phase information is asynchronous as they are transmitted via SCPI. + +The example constructs a sequence with no offset and the very last step has the resync flag enabled. Note that during the resync-step the DAC outputs zero. + +## Julia Client + +This and all other examples are located in the ```examples``` [directory](https://github.com/tknopp/RedPitayaDAQServer/tree/master/src/examples/julia) + +````@eval +# Adapted from https://github.com/JuliaDocs/Documenter.jl/issues/499 +using Markdown +Markdown.parse(""" +```julia +$(open(f->read(f, String), "../../../src/examples/julia/resync.jl")) +``` +""") +```` + +![Resync Example Results](../assets/resync.png) diff --git a/docs/src/generation.md b/docs/src/generation.md index d57cfce4..e9b785a4 100644 --- a/docs/src/generation.md +++ b/docs/src/generation.md @@ -25,7 +25,7 @@ As the LUT used by the FPGA image is small in comparison with the main memory an Comparable to the sample transmission of the acquisition, this updating of the LUT is also a process with timing uncertainty as it is affected by the scheduling and execution of the RedPitayas CPU. While during the sample transmission samples could be lost because they were overwritten, in the signal generation wrong signals could be output because the server was too slow in updating the values. Here, the server tracks similar performance metrics and also features a status flag `lostSteps` for exactly this case. In its current implementation a safe step rate is at 12 kHz. -Sequences and their steps also have additional features. A step can be marked such that during its duration the signal is set to 0. Furthermore, a step can be marked such that it triggers the ramp down. To make this easier to manage the server actually manages three sequences, that can be set individually: A ramp up, regular and ramp down sequence. The ramp up sequence is moved to the FPGA LUT at the acquisition start, followed by the regular sequence. Afterwards the ramp down sequence is started and during its execution the ramp down flag is set. +Sequences and their steps also have additional features. A step can be marked such that during its duration the signal is set to 0. Furthermore, a step can be marked such that it triggers the ramp down. To make this easier to manage the server actually manages three sequences, that can be set individually: A ramp up, regular and ramp down sequence. The ramp up sequence is moved to the FPGA LUT at the acquisition start, followed by the regular sequence. Afterwards the ramp down sequence is started and during its execution the ramp down flag is set. Steps can also be marked to resync the fast DACs. During a resync, the signals are set to 0 and afterwards start again with their set phase and frequency. This can be used to change frequency and phase during measurements and s.t. the new phase and frequency is synchronous to the steps. ## Calibration Similar to the signal acquisition, there are also calibration scale ``c_{i, scale}`` and offset ``c_{i, offset}`` values for the signal generation. These are stored in the EEPROM of the RedPitaya and can be updated by a client. The calibration values are always applied, even when the master trigger is off. diff --git a/docs/src/scpi.md b/docs/src/scpi.md index 9af44dbd..3ca6c1d2 100644 --- a/docs/src/scpi.md +++ b/docs/src/scpi.md @@ -53,6 +53,7 @@ During an active trigger the buffer is periodically updated by the server. If th | RP:DAC:SEQ:CHan? | | Return the number of sequence channel | | | | RP:DAC:SEQ:LUT | steps, repetitions | Instruct the server to receive a LUT over the data socket | C | RP:DAC:SEQ:LUT 10,2 | | RP:DAC:SEQ:LUT:ENaBle | | Instruct the server to receive an enable LUT over the data socket of the same shape as the regular LUT| C | | +| RP:DAC:SEQ:LUT:ReSYNC | | Instruct the server to receive a resync LUT over the data socket of the same shape as the regular LUT| C | | | RP:DAC:SEQ:LUT:UP | steps, repetitions | Instruct the server to receive a ramp up LUT over the data socket | C | | | RP:DAC:SEQ:LUT:DOWN | steps, repetitions | Instruct the server to receive a ramp down LUT over the data socket | C | | | RP:DAC:SEQ:CLEAR | | Clear the set sequence values from the FPGA buffer | C | | diff --git a/src/examples/julia/resync.jl b/src/examples/julia/resync.jl new file mode 100644 index 00000000..9759d411 --- /dev/null +++ b/src/examples/julia/resync.jl @@ -0,0 +1,78 @@ +using RedPitayaDAQServer +using CairoMakie + +# obtain the URL of the RedPitaya +include("config.jl") + +rp = RedPitaya(URLs[1]) +serverMode!(rp, CONFIGURATION) + +dec = 32 +modulus = 124800 +base_frequency = 125000000 +periods_per_step = 5 +samples_per_period = div(modulus, dec) +periods_per_frame = 50 +frame_period = dec*samples_per_period*periods_per_frame / base_frequency +steps_per_frame = div(50, periods_per_step) + +decimation!(rp, dec) +samplesPerPeriod!(rp, samples_per_period) +periodsPerFrame!(rp, periods_per_frame) + +for i in 1:2 + frequencyDAC!(rp, i, 1, base_frequency / modulus) + signalTypeDAC!(rp, i, 1, "SINE") + amplitudeDAC!(rp, i, 1, 0.2) + phaseDAC!(rp, i, 1, 0) +end +triggerMode!(rp, INTERNAL) + +# Sequence Configuration +clearSequence!(rp) +stepsPerFrame!(rp, steps_per_frame) +seqChan!(rp, 2) +lut = reshape(fill(0.0f0, steps_per_frame), 1, :) +lut = repeat(lut, outer = 2) +enable = collect(fill(true, steps_per_frame)) +enable = reshape(enable, 1, :) +enable = repeat(enable, outer = 2) +# In the last step of each frame we resync the DACs +resync = vcat(fill(false, steps_per_frame - 1), [true]) +resync = reshape(resync, 1, :) +resync = repeat(resync, outer = 2) +seq = SimpleSequence(lut, 2, enable, resync) +sequence!(rp, seq) + +samples_per_frame = samples_per_period * periods_per_frame +target = samples_per_frame * 0.3 # After a third of a frame we want to switch frequency + +serverMode!(rp, ACQUISITION) +masterTrigger!(rp, true) + +# Wait until we reach the target sample +curr = currentWP(rp) +while curr < target + # NOP + global curr = currentWP(rp) + sleep(0.01) +end + +# Update the phase and frequency of the second channel +frequencyDAC!(rp, 2, 1, base_frequency / (2*modulus)) +phaseDAC!(rp, 2, 1, pi) + +data = readFrames(rp, 0, 2) + +masterTrigger!(rp, false) +serverMode!(rp, CONFIGURATION) + + +fig = Figure() +lines(fig[1, 1], vec(data[:, 2, :, 1]), axis = (ylabel = "First Frame", title = "All Periods")) +lines(fig[1, 2], vec(data[:, 2, 1:5, 1]), axis = (ylabel = "First Frame", title = "First Periods")) +lines(fig[2, 1], vec(data[:, 2, :, 2]), axis = (ylabel = "Second Frame",)) +lines(fig[2, 2], vec(data[:, 2, 1:5, 2]), axis = (ylabel = "Second Frame",)) + +save(joinpath(@__DIR__(), "images", "resync.png"), fig) +fig \ No newline at end of file From 34a932c1e76a1717d8c4d8dc838d3eca5fab70f0 Mon Sep 17 00:00:00 2001 From: nHackel Date: Fri, 13 Dec 2024 14:30:16 +0100 Subject: [PATCH 38/38] Update Julia version to match 0.10 FPGA image --- src/client/julia/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/julia/Project.toml b/src/client/julia/Project.toml index 26393c4d..8637f193 100644 --- a/src/client/julia/Project.toml +++ b/src/client/julia/Project.toml @@ -1,7 +1,7 @@ name = "RedPitayaDAQServer" uuid = "c544963a-496b-56d4-a5fe-f99a3f174c8f" authors = ["Tobias Knopp "] -version = "0.9.0" +version = "0.10.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"