Add support for 4-input Red Pitaya
This commit is contained in:
		
							parent
							
								
									6016d2d706
								
							
						
					
					
						commit
						6a39840821
					
				|  | @ -4,11 +4,14 @@ redpitaya_puzzlefw.xsa | |||
| vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ip | ||||
| vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ipshared | ||||
| vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/puzzlefw.bda | ||||
| vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ui | ||||
| vivado/redpitaya_puzzlefw.gen | ||||
| vivado/redpitaya_puzzlefw.cache | ||||
| vivado/redpitaya_puzzlefw.hw | ||||
| vivado/redpitaya_puzzlefw.ip_user_files | ||||
| vivado/redpitaya_puzzlefw.runs | ||||
| vivado/output | ||||
| vivado/output_4ch | ||||
| vivado/.Xil | ||||
| vivado/NONE | ||||
| vivado/*.html | ||||
|  |  | |||
|  | @ -0,0 +1,35 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -e | ||||
| set -o pipefail | ||||
| 
 | ||||
| . script_env | ||||
| setup_vivado | ||||
| 
 | ||||
| rm -f puzzlefw_top_4ch.bit.bin redpitaya_puzzlefw_4ch.xsa | ||||
| 
 | ||||
| rm -rf vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ip | ||||
| rm -rf vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ipshared | ||||
| rm -rf vivado/redpitaya_puzzlefw.gen | ||||
| rm -rf vivado/output_4ch | ||||
| 
 | ||||
| mkdir -p vivado/output_4ch | ||||
| 
 | ||||
| ( cd vivado | ||||
|   stdbuf -oL vivado -mode batch -source nonproject_4ch.tcl | tee output_4ch/build_log.txt | ||||
|   ) | ||||
| 
 | ||||
| cat >vivado/output_4ch/bitstream.bif <<EOF | ||||
| all: | ||||
| { | ||||
| 	puzzlefw_top_4ch.bit | ||||
| } | ||||
| EOF | ||||
| 
 | ||||
| ( cd vivado/output_4ch | ||||
|   bootgen -image bitstream.bif -arch zynq -process_bitstream bin | ||||
|   ) | ||||
| 
 | ||||
| cp -a vivado/output_4ch/puzzlefw_top_4ch.bit.bin . | ||||
| cp -a vivado/output_4ch/redpitaya_puzzlefw_4ch.xsa . | ||||
| 
 | ||||
|  | @ -0,0 +1,240 @@ | |||
| # | ||||
| # $Id: red_pitaya_4adc.xdc 961 2014-01-21 11:40:39Z matej.oblak $ | ||||
| # | ||||
| # @brief Red Pitaya location constraints. | ||||
| # | ||||
| # @Author Matej Oblak | ||||
| # | ||||
| # (c) Red Pitaya  http://www.redpitaya.com | ||||
| # | ||||
| # Modified by Joris van Rantwijk for PuzzleFW. | ||||
| # | ||||
| 
 | ||||
| ############################################################################ | ||||
| # IO constraints                                                           # | ||||
| ############################################################################ | ||||
| 
 | ||||
| 
 | ||||
| ############################################################################ | ||||
| # Clock constraints                                                        # | ||||
| ############################################################################ | ||||
| 
 | ||||
| # ADC data | ||||
| set_property IOSTANDARD LVCMOS18 [get_ports {adc_dat_i[*][*]}] | ||||
| set_property IOB        TRUE     [get_ports {adc_dat_i[*][*]}] | ||||
| 
 | ||||
| # ADC 0 data | ||||
| set_property PACKAGE_PIN Y17     [get_ports {adc_dat_i[0][0]}] | ||||
| set_property PACKAGE_PIN Y16     [get_ports {adc_dat_i[0][1]}] | ||||
| set_property PACKAGE_PIN W14     [get_ports {adc_dat_i[0][2]}] | ||||
| set_property PACKAGE_PIN Y14     [get_ports {adc_dat_i[0][3]}] | ||||
| set_property PACKAGE_PIN V12     [get_ports {adc_dat_i[0][4]}] | ||||
| set_property PACKAGE_PIN W13     [get_ports {adc_dat_i[0][5]}] | ||||
| set_property PACKAGE_PIN V13     [get_ports {adc_dat_i[0][6]}] | ||||
| 
 | ||||
| # ADC 1 data | ||||
| set_property PACKAGE_PIN W15     [get_ports {adc_dat_i[1][0]}] | ||||
| set_property PACKAGE_PIN W16     [get_ports {adc_dat_i[1][1]}] | ||||
| set_property PACKAGE_PIN V15     [get_ports {adc_dat_i[1][2]}] | ||||
| set_property PACKAGE_PIN V16     [get_ports {adc_dat_i[1][3]}] | ||||
| set_property PACKAGE_PIN Y19     [get_ports {adc_dat_i[1][4]}] | ||||
| set_property PACKAGE_PIN W18     [get_ports {adc_dat_i[1][5]}] | ||||
| set_property PACKAGE_PIN Y18     [get_ports {adc_dat_i[1][6]}] | ||||
| 
 | ||||
| # ADC 2 data | ||||
| set_property PACKAGE_PIN W20     [get_ports {adc_dat_i[2][0]}] | ||||
| set_property PACKAGE_PIN W19     [get_ports {adc_dat_i[2][1]}] | ||||
| set_property PACKAGE_PIN V17     [get_ports {adc_dat_i[2][2]}] | ||||
| set_property PACKAGE_PIN V18     [get_ports {adc_dat_i[2][3]}] | ||||
| set_property PACKAGE_PIN U17     [get_ports {adc_dat_i[2][4]}] | ||||
| set_property PACKAGE_PIN T16     [get_ports {adc_dat_i[2][5]}] | ||||
| set_property PACKAGE_PIN T17     [get_ports {adc_dat_i[2][6]}] | ||||
| 
 | ||||
| # ADC 3 data | ||||
| set_property PACKAGE_PIN R19     [get_ports {adc_dat_i[3][0]}] | ||||
| set_property PACKAGE_PIN R17     [get_ports {adc_dat_i[3][1]}] | ||||
| set_property PACKAGE_PIN T15     [get_ports {adc_dat_i[3][2]}] | ||||
| set_property PACKAGE_PIN R16     [get_ports {adc_dat_i[3][3]}] | ||||
| set_property PACKAGE_PIN T20     [get_ports {adc_dat_i[3][4]}] | ||||
| set_property PACKAGE_PIN U20     [get_ports {adc_dat_i[3][5]}] | ||||
| set_property PACKAGE_PIN V20     [get_ports {adc_dat_i[3][6]}] | ||||
| 
 | ||||
| set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports {adc_clk_i[*][*]}] | ||||
| 
 | ||||
| set_property PACKAGE_PIN U18           [get_ports {adc_clk_i[0][1]}] | ||||
| set_property PACKAGE_PIN U19           [get_ports {adc_clk_i[0][0]}] | ||||
| set_property PACKAGE_PIN N20           [get_ports {adc_clk_i[1][1]}] | ||||
| set_property PACKAGE_PIN P20           [get_ports {adc_clk_i[1][0]}] | ||||
| 
 | ||||
| # Output ADC clock | ||||
| # set_property IOSTANDARD LVCMOS18 [get_ports {adc_clk_o[*]}] | ||||
| # set_property SLEW       FAST     [get_ports {adc_clk_o[*]}] | ||||
| # set_property DRIVE      8        [get_ports {adc_clk_o[*]}] | ||||
| # #set_property IOB        TRUE     [get_ports {adc_clk_o[*]}] | ||||
| 
 | ||||
| # set_property PACKAGE_PIN N20 [get_ports {adc_clk_o[0]}] | ||||
| # set_property PACKAGE_PIN P20 [get_ports {adc_clk_o[1]}] | ||||
| 
 | ||||
| # SPI interface | ||||
| set_property IOSTANDARD  LVCMOS18 [get_ports spi_*_o] | ||||
| set_property SLEW        FAST     [get_ports spi_*_o] | ||||
| set_property DRIVE       8        [get_ports spi_*_o] | ||||
| 
 | ||||
| set_property PACKAGE_PIN P15      [get_ports spi_csa_o] | ||||
| set_property PACKAGE_PIN P16      [get_ports spi_csb_o] | ||||
| set_property PACKAGE_PIN P18      [get_ports spi_clk_o] | ||||
| set_property PACKAGE_PIN N17      [get_ports spi_mosi_o] | ||||
| 
 | ||||
| ### PWM DAC | ||||
| set_property IOSTANDARD LVCMOS18 [get_ports {dac_pwm_o[*]}] | ||||
| set_property SLEW FAST           [get_ports {dac_pwm_o[*]}] | ||||
| set_property DRIVE 12            [get_ports {dac_pwm_o[*]}] | ||||
| set_property IOB TRUE            [get_ports {dac_pwm_o[*]}] | ||||
| 
 | ||||
| set_property PACKAGE_PIN T10 [get_ports {dac_pwm_o[0]}] | ||||
| set_property PACKAGE_PIN T11 [get_ports {dac_pwm_o[1]}] | ||||
| set_property PACKAGE_PIN T19 [get_ports {dac_pwm_o[2]}] | ||||
| set_property PACKAGE_PIN T14 [get_ports {dac_pwm_o[3]}] | ||||
| 
 | ||||
| ### XADC | ||||
| #set_property IOSTANDARD LVCMOS33 [get_ports {vinp_i[*]}] | ||||
| #set_property IOSTANDARD LVCMOS33 [get_ports {vinn_i[*]}] | ||||
| ##AD0 | ||||
| #set_property PACKAGE_PIN C20 [get_ports {vinp_i[1]}] | ||||
| #set_property PACKAGE_PIN B20 [get_ports {vinn_i[1]}] | ||||
| ##AD1 | ||||
| #set_property PACKAGE_PIN E17 [get_ports {vinp_i[2]}] | ||||
| #set_property PACKAGE_PIN D18 [get_ports {vinn_i[2]}] | ||||
| ##AD8 | ||||
| #set_property PACKAGE_PIN B19 [get_ports {vinp_i[0]}] | ||||
| #set_property PACKAGE_PIN A20 [get_ports {vinn_i[0]}] | ||||
| ##AD9 | ||||
| #set_property PACKAGE_PIN E18 [get_ports {vinp_i[3]}] | ||||
| #set_property PACKAGE_PIN E19 [get_ports {vinn_i[3]}] | ||||
| ##V_0 | ||||
| #set_property PACKAGE_PIN K9  [get_ports {vinp_i[4]}] | ||||
| #set_property PACKAGE_PIN L10 [get_ports {vinn_i[4]}] | ||||
| 
 | ||||
| ### Expansion connector | ||||
| set_property IOSTANDARD LVCMOS33 [get_ports {exp_p_io[*]}] | ||||
| set_property IOSTANDARD LVCMOS33 [get_ports {exp_n_io[*]}] | ||||
| set_property SLEW       FAST     [get_ports {exp_p_io[*]}] | ||||
| set_property SLEW       FAST     [get_ports {exp_n_io[*]}] | ||||
| set_property DRIVE      8        [get_ports {exp_p_io[*]}] | ||||
| set_property DRIVE      8        [get_ports {exp_n_io[*]}] | ||||
| 
 | ||||
| set_property PACKAGE_PIN G17 [get_ports {exp_p_io[0]}] | ||||
| set_property PACKAGE_PIN G18 [get_ports {exp_n_io[0]}] | ||||
| set_property PACKAGE_PIN H16 [get_ports {exp_p_io[1]}] | ||||
| set_property PACKAGE_PIN H17 [get_ports {exp_n_io[1]}] | ||||
| set_property PACKAGE_PIN J18 [get_ports {exp_p_io[2]}] | ||||
| set_property PACKAGE_PIN H18 [get_ports {exp_n_io[2]}] | ||||
| set_property PACKAGE_PIN K17 [get_ports {exp_p_io[3]}] | ||||
| set_property PACKAGE_PIN K18 [get_ports {exp_n_io[3]}] | ||||
| set_property PACKAGE_PIN L14 [get_ports {exp_p_io[4]}] | ||||
| set_property PACKAGE_PIN L15 [get_ports {exp_n_io[4]}] | ||||
| set_property PACKAGE_PIN L16 [get_ports {exp_p_io[5]}] | ||||
| set_property PACKAGE_PIN L17 [get_ports {exp_n_io[5]}] | ||||
| set_property PACKAGE_PIN K16 [get_ports {exp_p_io[6]}] | ||||
| set_property PACKAGE_PIN J16 [get_ports {exp_n_io[6]}] | ||||
| set_property PACKAGE_PIN M14 [get_ports {exp_p_io[7]}] | ||||
| set_property PACKAGE_PIN M15 [get_ports {exp_n_io[7]}] | ||||
| set_property PACKAGE_PIN Y9  [get_ports {exp_p_io[8]}] | ||||
| set_property PACKAGE_PIN Y8  [get_ports {exp_n_io[8]}] | ||||
| set_property PACKAGE_PIN Y12 [get_ports {exp_p_io[9]}] | ||||
| set_property PACKAGE_PIN Y13 [get_ports {exp_n_io[9]}] | ||||
| set_property PACKAGE_PIN Y7  [get_ports {exp_p_io[10]}] | ||||
| set_property PACKAGE_PIN Y6  [get_ports {exp_n_io[10]}] | ||||
| 
 | ||||
| # Pull down digital inputs. | ||||
| set_property PULLDOWN TRUE [get_ports {exp_p_io[0]}] | ||||
| set_property PULLDOWN TRUE [get_ports {exp_n_io[0]}] | ||||
| set_property PULLDOWN TRUE [get_ports {exp_p_io[1]}] | ||||
| set_property PULLDOWN TRUE [get_ports {exp_n_io[1]}] | ||||
| 
 | ||||
| ### PLL | ||||
| #set_property IOSTANDARD LVCMOS33 [get_ports pll_*] | ||||
| #set_property PACKAGE_PIN J15 [get_ports pll_hi_o] | ||||
| #set_property PACKAGE_PIN K14 [get_ports pll_lo_o] | ||||
| 
 | ||||
| ### SATA connector | ||||
| #set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports {daisy_p_o[*]}] | ||||
| #set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports {daisy_n_o[*]}] | ||||
| #set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports {daisy_p_i[*]}] | ||||
| #set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports {daisy_n_i[*]}] | ||||
| # | ||||
| #set_property PACKAGE_PIN T12 [get_ports {daisy_p_o[0]}] | ||||
| #set_property PACKAGE_PIN U12 [get_ports {daisy_n_o[0]}] | ||||
| #set_property PACKAGE_PIN U14 [get_ports {daisy_p_o[1]}] | ||||
| #set_property PACKAGE_PIN U15 [get_ports {daisy_n_o[1]}] | ||||
| #set_property PACKAGE_PIN P14 [get_ports {daisy_p_i[0]}] | ||||
| #set_property PACKAGE_PIN R14 [get_ports {daisy_n_i[0]}] | ||||
| #set_property PACKAGE_PIN N18 [get_ports {daisy_p_i[1]}] | ||||
| #set_property PACKAGE_PIN P19 [get_ports {daisy_n_i[1]}] | ||||
| 
 | ||||
| ### LED | ||||
| set_property IOSTANDARD LVCMOS33 [get_ports {led_o[*]}] | ||||
| set_property SLEW       SLOW     [get_ports {led_o[*]}] | ||||
| set_property DRIVE      4        [get_ports {led_o[*]}] | ||||
| 
 | ||||
| set_property PACKAGE_PIN F16     [get_ports {led_o[0]}] | ||||
| set_property PACKAGE_PIN F17     [get_ports {led_o[1]}] | ||||
| set_property PACKAGE_PIN G19     [get_ports {led_o[2]}] | ||||
| set_property PACKAGE_PIN G15     [get_ports {led_o[3]}] | ||||
| set_property PACKAGE_PIN G14     [get_ports {led_o[4]}] | ||||
| set_property PACKAGE_PIN F20     [get_ports {led_o[5]}] | ||||
| set_property PACKAGE_PIN G20     [get_ports {led_o[6]}] | ||||
| set_property PACKAGE_PIN H20     [get_ports {led_o[7]}] | ||||
| 
 | ||||
| ############################################################################ | ||||
| # Clock constraints                                                        # | ||||
| ############################################################################ | ||||
| 
 | ||||
| #NET "adc_clk" TNM_NET = "adc_clk"; | ||||
| #TIMESPEC TS_adc_clk = PERIOD "adc_clk" 125 MHz; | ||||
| 
 | ||||
| 
 | ||||
| create_clock -period 8.000 -name adc_clk_01 [get_ports {adc_clk_i[0][1]}] | ||||
| create_clock -period 8.000 -name adc_clk_23 [get_ports {adc_clk_i[1][1]}] | ||||
| create_clock -period 4.000 -name rx_clk [get_ports {daisy_p_i[1]}] | ||||
| 
 | ||||
| # Add clock uncertainty for robust timing. | ||||
| set_clock_uncertainty 0.2 [get_clocks adc_clk_01] | ||||
| set_clock_uncertainty 0.2 [get_clocks adc_clk_23] | ||||
| 
 | ||||
| # ADC data input timing. | ||||
| # The LTC2145 datasheet says CLKOUT-to-DATA = minimum 0, maximum 0.6 ns. | ||||
| # We add 0.1 ns margin. | ||||
| set_input_delay -clock adc_clk_01 -min -0.1 [get_ports {adc_dat_i[0][*] adc_dat_i[1][*]}] | ||||
| set_input_delay -clock adc_clk_01 -max  0.7 [get_ports {adc_dat_i[0][*] adc_dat_i[1][*]}] | ||||
| set_input_delay -clock adc_clk_23 -min -0.1 [get_ports {adc_dat_i[2][*] adc_dat_i[3][*]}] | ||||
| set_input_delay -clock adc_clk_23 -max  0.7 [get_ports {adc_dat_i[2][*] adc_dat_i[3][*]}] | ||||
| 
 | ||||
| # The two ADC clocks may not be perfectly aligned. | ||||
| # Specify max delay on inter-clock paths to deal with this. | ||||
| set_min_delay -from [get_clocks adc_clk_23] -to [get_clocks adc_clk_01] 1.6 | ||||
| set_max_delay -from [get_clocks adc_clk_23] -to [get_clocks adc_clk_01] 6.4 | ||||
| 
 | ||||
| # TODO -- specify input delay for digital inputs | ||||
| 
 | ||||
| # Delay to LEDs does not matter; just set a long max delay. | ||||
| set_max_delay -to [get_ports {led_o[*]}] 20.0 | ||||
| 
 | ||||
| #set_false_path -from [get_clocks par_clk] -to [get_clocks pll_adc_clk_0] | ||||
| #set_false_path -from [get_clocks pll_adc_clk_0] -to [get_clocks par_clk] | ||||
| #set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks adc_clk_01] | ||||
| #set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks adc_clk_23] | ||||
| #set_false_path -from [get_clocks adc_clk_01] -to [get_clocks pll_ser_clk] | ||||
| #set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks par_clk] | ||||
| #set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks pll_adc_clk_0] | ||||
| #set_false_path -from [get_clocks pll_adc_clk_0] -to [get_clocks clk_fpga_0] | ||||
| #set_false_path -from [get_clocks pll_adc_clk_0] -to [get_clocks pll_adc_10mhz] | ||||
| #set_false_path -from [get_clocks pll_adc_10mhz] -to [get_clocks pll_adc_clk_0] | ||||
| #set_false_path -from [get_clocks adc_clk_23] -to [get_clocks pll_adc_clk_0] | ||||
| 
 | ||||
| ############################################################################ | ||||
| # Bit file settings                                                        # | ||||
| ############################################################################ | ||||
| 
 | ||||
| set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] | ||||
| 
 | ||||
|  | @ -0,0 +1,118 @@ | |||
| -- | ||||
| --  Capture ADC sample data from FPGA input ports. | ||||
| -- | ||||
| --  The ADC sends one 14-bit sample per clock cycle. | ||||
| --  These 14 bits are transferred through 7 DDR signals. | ||||
| -- | ||||
| --  Joris van Rantwijk 2024 | ||||
| -- | ||||
| 
 | ||||
| library ieee; | ||||
| use ieee.std_logic_1164.all; | ||||
| use ieee.numeric_std.all; | ||||
| 
 | ||||
| library unisim; | ||||
| use unisim.vcomponents.all; | ||||
| 
 | ||||
| use work.puzzlefw_pkg.all; | ||||
| 
 | ||||
| 
 | ||||
| entity adc_capture_ddr is | ||||
| 
 | ||||
|     port ( | ||||
|         -- Source-synchronous clock for capturing data. | ||||
|         clk_capture:        in  std_logic; | ||||
| 
 | ||||
|         -- Clock for intermediate register stage. | ||||
|         clk_intermediate:   in  std_logic; | ||||
| 
 | ||||
|         -- System clock for data output. | ||||
|         -- This clock is approximately phase aligned with the capture clock. | ||||
|         clk_handoff:        in  std_logic; | ||||
| 
 | ||||
|         -- Input signals, DDR. | ||||
|         in_data:            in  std_logic_vector(6 downto 0); | ||||
| 
 | ||||
|         -- Output sample stream. | ||||
|         -- Produces one new ADC sample per clock cycle. | ||||
|         out_data:           out adc_data_type | ||||
|     ); | ||||
| 
 | ||||
| end entity; | ||||
| 
 | ||||
| architecture arch of adc_capture_ddr is | ||||
| 
 | ||||
|     signal s_data_delayed:  std_logic_vector(6 downto 0); | ||||
|     signal s_data_iddr:     std_logic_vector(adc_data_bits - 1 downto 0); | ||||
|     signal s_data_staged:   std_logic_vector(adc_data_bits - 1 downto 0); | ||||
|     signal r_out_data:      std_logic_vector(adc_data_bits - 1 downto 0); | ||||
| 
 | ||||
| begin | ||||
| 
 | ||||
|     gen_bit_capture: for i in 0 to 6 generate | ||||
| 
 | ||||
|         -- Delay input signal. | ||||
|         -- Delay by 30 / (32 * 2 * 200 MHz) = 2.34 ns. | ||||
|         inst_idelay: IDELAYE2 | ||||
|             generic map ( | ||||
|                 DELAY_SRC       => "IDATAIN", | ||||
|                 HIGH_PERFORMANCE_MODE => "FALSE", | ||||
|                 IDELAY_TYPE     => "FIXED", | ||||
|                 IDELAY_VALUE    => 30, | ||||
|                 REFCLK_FREQUENCY => 200.0, | ||||
|                 SIGNAL_PATTERN  => "DATA" ) | ||||
|             port map ( | ||||
|                 CNTVALUEOUT => open, | ||||
|                 DATAOUT     => s_data_delayed(i), | ||||
|                 C           => '0', | ||||
|                 CE          => '0', | ||||
|                 CINVCTRL    => '0', | ||||
|                 CNTVALUEIN  => (others => '0'), | ||||
|                 DATAIN      => '0', | ||||
|                 IDATAIN     => in_data(i), | ||||
|                 INC         => '0', | ||||
|                 LD          => '0', | ||||
|                 LDPIPEEN    => '0', | ||||
|                 REGRST      => '0' ); | ||||
| 
 | ||||
|         -- DDR input register. | ||||
|         inst_iddr: IDDR | ||||
|             generic map ( | ||||
|                 DDR_CLK_EDGE    => "SAME_EDGE_PIPELINED" ) | ||||
|             port map ( | ||||
|                 Q1          => s_data_iddr(2*i), | ||||
|                 Q2          => s_data_iddr(2*i+1), | ||||
|                 C           => clk_capture, | ||||
|                 CE          => '1', | ||||
|                 D           => s_data_delayed(i), | ||||
|                 R           => '0', | ||||
|                 S           => '0' ); | ||||
| 
 | ||||
|     end generate; | ||||
| 
 | ||||
|     -- | ||||
|     -- Re-capture samples on intermediate clock. | ||||
|     -- | ||||
|     gen_ffpair: for i in 0 to adc_data_bits - 1 generate | ||||
|         inst_ffpair: entity work.ffpair | ||||
|             port map ( | ||||
|                 clk1        => clk_capture, | ||||
|                 clk2        => clk_intermediate, | ||||
|                 di          => s_data_iddr(i), | ||||
|                 do          => s_data_staged(i) ); | ||||
|     end generate; | ||||
| 
 | ||||
|     -- | ||||
|     -- Re-capture samples on system clock. | ||||
|     -- | ||||
|     process (clk_handoff) is | ||||
|     begin | ||||
|         if rising_edge(clk_handoff) then | ||||
|             r_out_data <= s_data_staged; | ||||
|         end if; | ||||
|     end process; | ||||
| 
 | ||||
|     -- Drive output ports. | ||||
|     out_data <= r_out_data; | ||||
| 
 | ||||
| end architecture; | ||||
|  | @ -0,0 +1,51 @@ | |||
| -- | ||||
| --  Pair of flip-flops located in adjacent slices. | ||||
| -- | ||||
| 
 | ||||
| library ieee; | ||||
| use ieee.std_logic_1164.all; | ||||
| 
 | ||||
| entity ffpair is | ||||
| 
 | ||||
|     port ( | ||||
|         -- Clocks. | ||||
|         clk1:       in  std_logic; | ||||
|         clk2:       in  std_logic; | ||||
| 
 | ||||
|         -- Input data, synchronous to "clk1". | ||||
|         di:         in  std_logic; | ||||
| 
 | ||||
|         -- Output data, synchronous to "clk2"; | ||||
|         do:         out std_logic | ||||
|     ); | ||||
| 
 | ||||
| end entity; | ||||
| 
 | ||||
| architecture rtl of ffpair is | ||||
| 
 | ||||
|     signal reg1: std_logic; | ||||
|     signal reg2: std_logic; | ||||
| 
 | ||||
|     attribute RLOC: string; | ||||
|     attribute RLOC of reg1: signal is "X0Y0"; | ||||
|     attribute RLOC of reg2: signal is "X1Y0"; | ||||
| 
 | ||||
| begin | ||||
| 
 | ||||
|     process (clk1) is | ||||
|     begin | ||||
|         if rising_edge(clk1) then | ||||
|             reg1 <= di; | ||||
|         end if; | ||||
|     end process; | ||||
| 
 | ||||
|     process (clk2) is | ||||
|     begin | ||||
|         if rising_edge(clk2) then | ||||
|             reg2 <= reg1; | ||||
|         end if; | ||||
|     end process; | ||||
| 
 | ||||
|     do <= reg2; | ||||
| 
 | ||||
| end architecture; | ||||
|  | @ -38,6 +38,8 @@ package puzzlefw_pkg is | |||
| 
 | ||||
|     -- ADC input port type. | ||||
|     type adc_data_input_type is array(0 to 1) of std_logic_vector(15 downto 0); | ||||
|     type adc_data_input_type_4ch is array(0 to 3) of std_logic_vector(6 downto 0); | ||||
|     type adc_clock_input_type_4ch is array(0 to 1) of std_logic_vector(1 downto 0); | ||||
| 
 | ||||
|     -- Register addresses. | ||||
|     constant reg_addr_mask:         std_logic_vector(31 downto 0) := x"0010fffc"; | ||||
|  |  | |||
|  | @ -0,0 +1,709 @@ | |||
| -- | ||||
| --  Top-level FPGA design for Red Pitaya PuzzleFW firmware, | ||||
| --  variant for 4 input channels. | ||||
| -- | ||||
| --  Joris van Rantwijk 2024 | ||||
| -- | ||||
| 
 | ||||
| library ieee; | ||||
| use ieee.std_logic_1164.all; | ||||
| use ieee.std_logic_misc.all; | ||||
| use ieee.numeric_std.all; | ||||
| 
 | ||||
| library unisim; | ||||
| use unisim.vcomponents.all; | ||||
| 
 | ||||
| library xpm; | ||||
| use xpm.vcomponents.all; | ||||
| 
 | ||||
| use work.puzzlefw_pkg.all; | ||||
| 
 | ||||
| 
 | ||||
| entity puzzlefw_top_4ch is | ||||
| 
 | ||||
|     port ( | ||||
|         -- Ports directly connected to ARM/PS. | ||||
|         DDR_0_addr:         inout std_logic_vector(14 downto 0); | ||||
|         DDR_0_ba:           inout std_logic_vector(2 downto 0); | ||||
|         DDR_0_cas_n:        inout std_logic; | ||||
|         DDR_0_ck_n:         inout std_logic; | ||||
|         DDR_0_ck_p:         inout std_logic; | ||||
|         DDR_0_cke:          inout std_logic; | ||||
|         DDR_0_cs_n:         inout std_logic; | ||||
|         DDR_0_dm:           inout std_logic_vector(3 downto 0); | ||||
|         DDR_0_dq:           inout std_logic_vector(31 downto 0); | ||||
|         DDR_0_dqs_n:        inout std_logic_vector(3 downto 0); | ||||
|         DDR_0_dqs_p:        inout std_logic_vector(3 downto 0); | ||||
|         DDR_0_odt:          inout std_logic; | ||||
|         DDR_0_ras_n:        inout std_logic; | ||||
|         DDR_0_reset_n:      inout std_logic; | ||||
|         DDR_0_we_n:         inout std_logic; | ||||
|         FIXED_IO_0_ddr_vrn: inout std_logic; | ||||
|         FIXED_IO_0_ddr_vrp: inout std_logic; | ||||
|         FIXED_IO_0_mio:     inout std_logic_vector(53 downto 0); | ||||
|         FIXED_IO_0_ps_clk:  inout std_logic; | ||||
|         FIXED_IO_0_ps_porb: inout std_logic; | ||||
|         FIXED_IO_0_ps_srstb: inout std_logic; | ||||
| 
 | ||||
|         -- Ports controlled by FPGA. | ||||
|         adc_dat_i:          in  adc_data_input_type_4ch;            -- ADC data | ||||
|         adc_clk_i:          in  adc_clock_input_type_4ch;           -- ADC clock 1=pos, 0=neg | ||||
|         spi_csa_o:          out std_logic;                          -- SPI interface to ADC | ||||
|         spi_csb_o:          out std_logic; | ||||
|         spi_clk_o:          out std_logic; | ||||
|         spi_mosi_o:         out std_logic; | ||||
|         dac_pwm_o:          out std_logic_vector(3 downto 0);       -- PWM DAC | ||||
|         exp_p_io:           inout std_logic_vector(10 downto 0);    -- extension I/O pos | ||||
|         exp_n_io:           inout std_logic_vector(10 downto 0);    -- extension I/O neg | ||||
|         led_o:              out std_logic_vector(7 downto 0)        -- LEDs | ||||
|     ); | ||||
| 
 | ||||
| end puzzlefw_top_4ch; | ||||
| 
 | ||||
| architecture arch of puzzlefw_top_4ch is | ||||
| 
 | ||||
|     -- Main 125 MHz clock, derived from ADC A clock input port. | ||||
|     signal clk_adc:         std_logic; | ||||
| 
 | ||||
|     -- Auxiliary clock from FCLK0. | ||||
|     signal clk_fclk200:     std_logic; | ||||
| 
 | ||||
|     -- Reset signals. | ||||
|     signal s_ext_reset_n:   std_logic;  -- reset signal from GPIO, active low | ||||
|     signal s_pll_reset:     std_logic;  -- reset signal for PLL | ||||
|     signal s_pll_locked:    std_logic;  -- PLL locked status | ||||
|     signal s_reset:         std_logic;  -- main reset, synchronized to clk_adc | ||||
|     signal r_reset_done:    std_logic;  -- reset status report via GPIO | ||||
| 
 | ||||
|     -- Internal clock signals. | ||||
|     signal s_adc_clk_ibuf:  std_logic_vector(1 downto 0); | ||||
|     signal clk_adc_capture: std_logic_vector(1 downto 0); | ||||
|     signal s_pll_clkfbout:  std_logic; | ||||
|     signal s_pll_clkfbin:   std_logic; | ||||
|     signal s_pll_clkout:    std_logic; | ||||
| 
 | ||||
|     -- Blinking LED. | ||||
|     signal r_adcclk_cnt:    unsigned(25 downto 0); | ||||
|     signal r_adcclk_led:    std_logic; | ||||
| 
 | ||||
|     -- Internal GPIO and SPI signals from PS. | ||||
|     signal s_gpio_in:       std_logic_vector(23 downto 0); | ||||
|     signal s_gpio_out:      std_logic_vector(23 downto 0); | ||||
|     signal s_spi_sclk_o:    std_logic; | ||||
|     signal s_spi_sclk_t:    std_logic; | ||||
|     signal s_spi_mosi_o:    std_logic; | ||||
|     signal s_spi_mosi_t:    std_logic; | ||||
|     signal s_spi_ss_o:      std_logic_vector(1 downto 0); | ||||
|     signal s_spi_ss_t:      std_logic; | ||||
| 
 | ||||
|     -- APB bus for register access. | ||||
|     signal s_apb_paddr:     std_logic_vector(31 downto 0); | ||||
|     signal s_apb_penable:   std_logic; | ||||
|     signal s_apb_prdata:    std_logic_vector(31 downto 0); | ||||
|     signal s_apb_pready:    std_logic; | ||||
|     signal s_apb_psel:      std_logic; | ||||
|     signal s_apb_pslverr:   std_logic; | ||||
|     signal s_apb_pwdata:    std_logic_vector(31 downto 0); | ||||
|     signal s_apb_pwrite:    std_logic; | ||||
| 
 | ||||
|     -- AXI bus for DMA. | ||||
|     signal s_axi_awid:      std_logic_vector(5 downto 0); | ||||
|     signal s_axi_awaddr:    std_logic_vector(31 downto 0); | ||||
|     signal s_axi_awlen:     std_logic_vector(3 downto 0); | ||||
|     signal s_axi_awsize:    std_logic_vector(2 downto 0); | ||||
|     signal s_axi_awburst:   std_logic_vector(1 downto 0); | ||||
|     signal s_axi_awlock:    std_logic_vector(1 downto 0); | ||||
|     signal s_axi_awcache:   std_logic_vector(3 downto 0); | ||||
|     signal s_axi_awprot:    std_logic_vector(2 downto 0); | ||||
|     signal s_axi_awqos:     std_logic_vector(3 downto 0); | ||||
|     signal s_axi_awvalid:   std_logic; | ||||
|     signal s_axi_awready:   std_logic; | ||||
|     signal s_axi_wid:       std_logic_vector(5 downto 0); | ||||
|     signal s_axi_wdata:     std_logic_vector(63 downto 0); | ||||
|     signal s_axi_wstrb:     std_logic_vector(7 downto 0); | ||||
|     signal s_axi_wlast:     std_logic; | ||||
|     signal s_axi_wvalid:    std_logic; | ||||
|     signal s_axi_wready:    std_logic; | ||||
|     signal s_axi_bid:       std_logic_vector(5 downto 0); | ||||
|     signal s_axi_bresp:     std_logic_vector(1 downto 0); | ||||
|     signal s_axi_bvalid:    std_logic; | ||||
|     signal s_axi_bready:    std_logic; | ||||
|     signal s_axi_arid:      std_logic_vector(5 downto 0); | ||||
|     signal s_axi_araddr:    std_logic_vector(31 downto 0); | ||||
|     signal s_axi_arlen:     std_logic_vector(3 downto 0); | ||||
|     signal s_axi_arsize:    std_logic_vector(2 downto 0); | ||||
|     signal s_axi_arburst:   std_logic_vector(1 downto 0); | ||||
|     signal s_axi_arlock:    std_logic_vector(1 downto 0); | ||||
|     signal s_axi_arcache:   std_logic_vector(3 downto 0); | ||||
|     signal s_axi_arprot:    std_logic_vector(2 downto 0); | ||||
|     signal s_axi_arqos:     std_logic_vector(3 downto 0); | ||||
|     signal s_axi_arvalid:   std_logic; | ||||
|     signal s_axi_arready:   std_logic; | ||||
|     signal s_axi_rid:       std_logic_vector(5 downto 0); | ||||
|     signal s_axi_rdata:     std_logic_vector(63 downto 0); | ||||
|     signal s_axi_rresp:     std_logic_vector(1 downto 0); | ||||
|     signal s_axi_rlast:     std_logic; | ||||
|     signal s_axi_rvalid:    std_logic; | ||||
|     signal s_axi_rready:    std_logic; | ||||
| 
 | ||||
|     -- Interrupts. | ||||
|     signal s_irq_pending:   std_logic_vector(1 downto 0); | ||||
|     signal s_irq_f2p:       std_logic_vector(7 downto 0); | ||||
| 
 | ||||
|     -- Registers. | ||||
|     signal s_reg_control:   registers_control; | ||||
|     signal s_reg_status:    registers_status; | ||||
| 
 | ||||
|     -- DMA write channel control. | ||||
|     signal s_dma_write_cmd_addr:    dma_address_array(0 to 1); | ||||
|     signal s_dma_write_cmd_length:  dma_burst_length_array(0 to 1); | ||||
|     signal s_dma_write_cmd_valid:   std_logic_vector(1 downto 0); | ||||
|     signal s_dma_write_cmd_ready:   std_logic_vector(1 downto 0); | ||||
|     signal s_dma_write_data:        dma_data_array(0 to 1); | ||||
|     signal s_dma_write_data_ready:  std_logic_vector(1 downto 0); | ||||
|     signal s_dma_write_finished:    std_logic_vector(1 downto 0); | ||||
| 
 | ||||
|     signal s_acq_dma_valid: std_logic; | ||||
|     signal s_acq_dma_ready: std_logic; | ||||
|     signal s_acq_dma_empty: std_logic; | ||||
|     signal s_acq_dma_data:  dma_data_type; | ||||
| 
 | ||||
|     signal s_tt_dma_valid:  std_logic; | ||||
|     signal s_tt_dma_ready:  std_logic; | ||||
|     signal s_tt_dma_empty:  std_logic; | ||||
|     signal s_tt_dma_data:   dma_data_type; | ||||
| 
 | ||||
|     signal s_timestamp:     std_logic_vector(timestamp_bits - 1 downto 0); | ||||
|     signal s_adc_data:      adc_data_array(0 to 3); | ||||
|     signal s_adc_sample:    adc_data_array(0 to 3); | ||||
|     signal s_dig_in:        std_logic_vector(3 downto 0); | ||||
|     signal s_dig_sync:      std_logic_vector(3 downto 0); | ||||
|     signal s_dig_deglitch:  std_logic_vector(3 downto 0); | ||||
|     signal s_dig_sample:    std_logic_vector(3 downto 0); | ||||
| 
 | ||||
| begin | ||||
| 
 | ||||
|     -- Global FPGA reset. | ||||
|     -- GPIO(0) = '0' to reset. | ||||
|     s_ext_reset_n   <= s_gpio_out(0); | ||||
| 
 | ||||
|     -- GPIO inputs to the PS. | ||||
|     -- GPIO(1) = '0' while in reset, '1' when reset released. | ||||
|     s_gpio_in(1) <= r_reset_done; | ||||
|     s_gpio_in(0) <= '0'; | ||||
|     s_gpio_in(23 downto 2) <= (others => '0'); | ||||
| 
 | ||||
|     -- Drive LEDs. | ||||
|     led_o(0)    <= r_adcclk_led;                    -- blinking LED, 1 Hz | ||||
|     led_o(1)    <= s_reg_control.acquisition_en;    -- acquisition enabled | ||||
|     led_o(2)    <= s_reg_status.trig_waiting;       -- waiting for trigger | ||||
|     led_o(3)    <= or_reduce(s_reg_control.timetagger_en);  -- timetagger enabled | ||||
|     led_o(7 downto 4) <= s_reg_control.led_state(7 downto 4); | ||||
| 
 | ||||
|     -- Drive safe levels to unused DAC pins. | ||||
|     dac_pwm_o   <= (others => 'Z'); | ||||
| 
 | ||||
|     -- Use extension I/O pins as inputs only. | ||||
|     exp_p_io    <= (others => 'Z'); | ||||
|     exp_n_io    <= (others => 'Z'); | ||||
| 
 | ||||
|     -- Drive SPI bus. | ||||
|     inst_obuf_spi_clk: OBUFT | ||||
|         port map ( | ||||
|             I => s_spi_sclk_o, | ||||
|             T => s_spi_sclk_t, | ||||
|             O => spi_clk_o ); | ||||
| 
 | ||||
|     inst_obuf_spi_mosi: OBUFT | ||||
|         port map ( | ||||
|             I => s_spi_mosi_o, | ||||
|             T => s_spi_mosi_t, | ||||
|             O => spi_mosi_o ); | ||||
| 
 | ||||
|     inst_obuf_spi_csa: OBUFT | ||||
|         port map ( | ||||
|             I => s_spi_ss_o(0), | ||||
|             T => s_spi_ss_t, | ||||
|             O => spi_csa_o ); | ||||
| 
 | ||||
|     inst_obuf_spi_csb: OBUFT | ||||
|         port map ( | ||||
|             I => s_spi_ss_o(1), | ||||
|             T => s_spi_ss_t,  | ||||
|             O => spi_csb_o ); | ||||
| 
 | ||||
|     -- Handle clock input and data input for each ADC. | ||||
|     gen_adcin: for i in 0 to 1 generate | ||||
| 
 | ||||
|         -- Differential clock input for ADC clock. | ||||
|         inst_ibuf_adc_clk: IBUFDS | ||||
|             port map ( | ||||
|                 O => s_adc_clk_ibuf(i), | ||||
|                 I => adc_clk_i(i)(1), | ||||
|                 IB => adc_clk_i(i)(0) ); | ||||
| 
 | ||||
|         -- Clock buffer for ADC clock. | ||||
|         -- BUFR is faster (lower propagation delay) than BUFG. | ||||
|         inst_bufg_adc_clk: BUFR | ||||
|             port map ( | ||||
|                 I => s_adc_clk_ibuf(i), | ||||
|                 O => clk_adc_capture(i), | ||||
|                 CE => '1', | ||||
|                 CLR => '0' ); | ||||
| 
 | ||||
|     end generate; | ||||
| 
 | ||||
|     -- PLL for 125 MHz clock. | ||||
|     -- Input clock comes from ADC A. | ||||
|     -- Output clock drives most of the FPGA design. | ||||
|     inst_pll: PLLE2_BASE | ||||
|         generic map ( | ||||
|             BANDWIDTH           => "OPTIMIZED", | ||||
|             CLKFBOUT_MULT       => 8, | ||||
|             CLKFBOUT_PHASE      => 0.0, | ||||
|             CLKIN1_PERIOD       => 8.0, | ||||
|             CLKOUT0_DIVIDE      => 8, | ||||
|             CLKOUT0_DUTY_CYCLE  => 0.5, | ||||
|             CLKOUT0_PHASE       => 0.0, | ||||
|             DIVCLK_DIVIDE       => 1, | ||||
|             STARTUP_WAIT        => "FALSE" ) | ||||
|         port map ( | ||||
|             CLKOUT0             => s_pll_clkout, | ||||
|             CLKFBOUT            => s_pll_clkfbout, | ||||
|             LOCKED              => s_pll_locked, | ||||
|             CLKIN1              => s_adc_clk_ibuf(0), | ||||
|             PWRDWN              => '0', | ||||
|             RST                 => s_pll_reset, | ||||
|             CLKFBIN             => s_pll_clkfbin ); | ||||
| 
 | ||||
|     -- Reset PLL when external reset is applied. | ||||
|     s_pll_reset <= not s_ext_reset_n; | ||||
| 
 | ||||
|     -- Clock buffers for PLL. | ||||
|     inst_bufg_pll_clkfb: BUFG | ||||
|         port map ( | ||||
|             I => s_pll_clkfbout, | ||||
|             O => s_pll_clkfbin ); | ||||
| 
 | ||||
|     inst_bufg_pll_clkout: BUFG | ||||
|         port map ( | ||||
|             I => s_pll_clkout, | ||||
|             O => clk_adc ); | ||||
| 
 | ||||
|     -- Since the design uses IDELAY, it must contain an IDELAYCTRL instance. | ||||
|     inst_idelayctrl: IDELAYCTRL | ||||
|         port map ( | ||||
|             RDY     => open, | ||||
|             REFCLK  => clk_fclk200, | ||||
|             RST     => s_pll_reset ); | ||||
| 
 | ||||
|     -- ARM/PS block design. | ||||
|     inst_blockdesign: entity work.puzzlefw_wrapper | ||||
|         port map ( | ||||
|             sys_clk             => clk_adc, | ||||
|             ps_fclk             => clk_fclk200, | ||||
|             peripheral_reset_0(0) => s_reset, | ||||
|             ext_reset_in_0      => s_ext_reset_n, | ||||
|             dcm_locked_0        => s_pll_locked, | ||||
|             DDR_0_addr          => DDR_0_addr, | ||||
|             DDR_0_ba            => DDR_0_ba, | ||||
|             DDR_0_cas_n         => DDR_0_cas_n, | ||||
|             DDR_0_ck_n          => DDR_0_ck_n, | ||||
|             DDR_0_ck_p          => DDR_0_ck_p, | ||||
|             DDR_0_cke           => DDR_0_cke, | ||||
|             DDR_0_cs_n          => DDR_0_cs_n, | ||||
|             DDR_0_dm            => DDR_0_dm, | ||||
|             DDR_0_dq            => DDR_0_dq, | ||||
|             DDR_0_dqs_n         => DDR_0_dqs_n, | ||||
|             DDR_0_dqs_p         => DDR_0_dqs_p, | ||||
|             DDR_0_odt           => DDR_0_odt, | ||||
|             DDR_0_ras_n         => DDR_0_ras_n, | ||||
|             DDR_0_reset_n       => DDR_0_reset_n, | ||||
|             DDR_0_we_n          => DDR_0_we_n, | ||||
|             FIXED_IO_0_ddr_vrn  => FIXED_IO_0_ddr_vrn, | ||||
|             FIXED_IO_0_ddr_vrp  => FIXED_IO_0_ddr_vrp, | ||||
|             FIXED_IO_0_mio      => FIXED_IO_0_mio, | ||||
|             FIXED_IO_0_ps_clk   => FIXED_IO_0_ps_clk, | ||||
|             FIXED_IO_0_ps_porb  => FIXED_IO_0_ps_porb, | ||||
|             FIXED_IO_0_ps_srstb => FIXED_IO_0_ps_srstb, | ||||
|             GPIO_I_0            => s_gpio_in, | ||||
|             GPIO_O_0            => s_gpio_out, | ||||
|             SPI0_MOSI_O_0       => s_spi_mosi_o, | ||||
|             SPI0_MOSI_T_0       => s_spi_mosi_t, | ||||
|             SPI0_SCLK_O_0       => s_spi_sclk_o, | ||||
|             SPI0_SCLK_T_0       => s_spi_sclk_t, | ||||
|             SPI0_SS1_O_0        => s_spi_ss_o(1), | ||||
|             SPI0_SS_O_0         => s_spi_ss_o(0), | ||||
|             SPI0_SS_T_0         => s_spi_ss_t, | ||||
|             IRQ_F2P             => s_irq_f2p, | ||||
|             APB_M_0_paddr       => s_apb_paddr, | ||||
|             APB_M_0_penable     => s_apb_penable, | ||||
|             APB_M_0_prdata      => s_apb_prdata, | ||||
|             APB_M_0_pready(0)   => s_apb_pready, | ||||
|             APB_M_0_psel(0)     => s_apb_psel, | ||||
|             APB_M_0_pslverr(0)  => s_apb_pslverr, | ||||
|             APB_M_0_pwdata      => s_apb_pwdata, | ||||
|             APB_M_0_pwrite      => s_apb_pwrite, | ||||
|             S_AXI_HP0_0_araddr  => s_axi_araddr, | ||||
|             S_AXI_HP0_0_arburst => s_axi_arburst, | ||||
|             S_AXI_HP0_0_arcache => s_axi_arcache, | ||||
|             S_AXI_HP0_0_arid    => s_axi_arid, | ||||
|             S_AXI_HP0_0_arlen   => s_axi_arlen, | ||||
|             S_AXI_HP0_0_arlock  => s_axi_arlock, | ||||
|             S_AXI_HP0_0_arprot  => s_axi_arprot, | ||||
|             S_AXI_HP0_0_arqos   => s_axi_arqos, | ||||
|             S_AXI_HP0_0_arready => s_axi_arready, | ||||
|             S_AXI_HP0_0_arsize  => s_axi_arsize, | ||||
|             S_AXI_HP0_0_arvalid => s_axi_arvalid, | ||||
|             S_AXI_HP0_0_awaddr  => s_axi_awaddr, | ||||
|             S_AXI_HP0_0_awburst => s_axi_awburst, | ||||
|             S_AXI_HP0_0_awcache => s_axi_awcache, | ||||
|             S_AXI_HP0_0_awid    => s_axi_awid, | ||||
|             S_AXI_HP0_0_awlen   => s_axi_awlen, | ||||
|             S_AXI_HP0_0_awlock  => s_axi_awlock, | ||||
|             S_AXI_HP0_0_awprot  => s_axi_awprot, | ||||
|             S_AXI_HP0_0_awqos   => s_axi_awqos, | ||||
|             S_AXI_HP0_0_awready => s_axi_awready, | ||||
|             S_AXI_HP0_0_awsize  => s_axi_awsize, | ||||
|             S_AXI_HP0_0_awvalid => s_axi_awvalid, | ||||
|             S_AXI_HP0_0_bid     => s_axi_bid, | ||||
|             S_AXI_HP0_0_bready  => s_axi_bready, | ||||
|             S_AXI_HP0_0_bresp   => s_axi_bresp, | ||||
|             S_AXI_HP0_0_bvalid  => s_axi_bvalid, | ||||
|             S_AXI_HP0_0_rdata   => s_axi_rdata, | ||||
|             S_AXI_HP0_0_rid     => s_axi_rid, | ||||
|             S_AXI_HP0_0_rlast   => s_axi_rlast, | ||||
|             S_AXI_HP0_0_rready  => s_axi_rready, | ||||
|             S_AXI_HP0_0_rresp   => s_axi_rresp, | ||||
|             S_AXI_HP0_0_rvalid  => s_axi_rvalid, | ||||
|             S_AXI_HP0_0_wdata   => s_axi_wdata, | ||||
|             S_AXI_HP0_0_wid     => s_axi_wid, | ||||
|             S_AXI_HP0_0_wlast   => s_axi_wlast, | ||||
|             S_AXI_HP0_0_wready  => s_axi_wready, | ||||
|             S_AXI_HP0_0_wstrb   => s_axi_wstrb, | ||||
|             S_AXI_HP0_0_wvalid  => s_axi_wvalid | ||||
|         ); | ||||
| 
 | ||||
|     -- Memory-mapped registers. | ||||
|     inst_registers: entity work.registers | ||||
|         generic map ( | ||||
|             num_acq_channels    => 4 ) | ||||
|         port map ( | ||||
|             clk                 => clk_adc, | ||||
|             reset               => s_reset, | ||||
|             apb_psel            => s_apb_psel, | ||||
|             apb_penable         => s_apb_penable, | ||||
|             apb_pwrite          => s_apb_pwrite, | ||||
|             apb_paddr           => s_apb_paddr, | ||||
|             apb_pwdata          => s_apb_pwdata, | ||||
|             apb_pready          => s_apb_pready, | ||||
|             apb_pslverr         => s_apb_pslverr, | ||||
|             apb_prdata          => s_apb_prdata, | ||||
|             reg_control         => s_reg_control, | ||||
|             reg_status          => s_reg_status | ||||
|         ); | ||||
| 
 | ||||
|     -- AXI master. | ||||
|     inst_axi_master: entity work.dma_axi_master | ||||
|         generic map ( | ||||
|             num_read_channels   => 0, | ||||
|             num_write_channels  => 2 ) | ||||
|         port map ( | ||||
|             clk                 => clk_adc, | ||||
|             reset               => s_reset, | ||||
|             dma_en              => s_reg_control.dma_en, | ||||
|             dma_busy            => s_reg_status.dma_busy, | ||||
|             window_base_addr    => s_reg_control.dma_buf_addr, | ||||
|             window_size         => s_reg_control.dma_buf_size, | ||||
|             err_read            => s_reg_status.dma_err_read, | ||||
|             err_write           => s_reg_status.dma_err_write, | ||||
|             err_address         => s_reg_status.dma_err_address, | ||||
|             err_any             => s_reg_status.dma_err_any, | ||||
|             clear_errors        => s_reg_control.dma_clear, | ||||
|             read_cmd_addr       => (others => (others => '0')), | ||||
|             read_cmd_length     => (others => (others => '0')), | ||||
|             read_cmd_valid      => (others => '0'), | ||||
|             read_cmd_ready      => open, | ||||
|             read_data           => open, | ||||
|             read_data_valid     => open, | ||||
|             write_cmd_addr      => s_dma_write_cmd_addr, | ||||
|             write_cmd_length    => s_dma_write_cmd_length, | ||||
|             write_cmd_valid     => s_dma_write_cmd_valid, | ||||
|             write_cmd_ready     => s_dma_write_cmd_ready, | ||||
|             write_data          => s_dma_write_data, | ||||
|             write_data_ready    => s_dma_write_data_ready, | ||||
|             write_finished      => s_dma_write_finished, | ||||
|             m_axi_awid          => s_axi_awid, | ||||
|             m_axi_awaddr        => s_axi_awaddr, | ||||
|             m_axi_awlen         => s_axi_awlen, | ||||
|             m_axi_awsize        => s_axi_awsize, | ||||
|             m_axi_awburst       => s_axi_awburst, | ||||
|             m_axi_awlock        => s_axi_awlock, | ||||
|             m_axi_awcache       => s_axi_awcache, | ||||
|             m_axi_awprot        => s_axi_awprot, | ||||
|             m_axi_awqos         => s_axi_awqos, | ||||
|             m_axi_awvalid       => s_axi_awvalid, | ||||
|             m_axi_awready       => s_axi_awready, | ||||
|             m_axi_wid           => s_axi_wid, | ||||
|             m_axi_wdata         => s_axi_wdata, | ||||
|             m_axi_wstrb         => s_axi_wstrb, | ||||
|             m_axi_wlast         => s_axi_wlast, | ||||
|             m_axi_wvalid        => s_axi_wvalid, | ||||
|             m_axi_wready        => s_axi_wready, | ||||
|             m_axi_bid           => s_axi_bid, | ||||
|             m_axi_bresp         => s_axi_bresp, | ||||
|             m_axi_bvalid        => s_axi_bvalid, | ||||
|             m_axi_bready        => s_axi_bready, | ||||
|             m_axi_arid          => s_axi_arid, | ||||
|             m_axi_araddr        => s_axi_araddr, | ||||
|             m_axi_arlen         => s_axi_arlen, | ||||
|             m_axi_arsize        => s_axi_arsize, | ||||
|             m_axi_arburst       => s_axi_arburst, | ||||
|             m_axi_arlock        => s_axi_arlock, | ||||
|             m_axi_arcache       => s_axi_arcache, | ||||
|             m_axi_arprot        => s_axi_arprot, | ||||
|             m_axi_arqos         => s_axi_arqos, | ||||
|             m_axi_arvalid       => s_axi_arvalid, | ||||
|             m_axi_arready       => s_axi_arready, | ||||
|             m_axi_rid           => s_axi_rid, | ||||
|             m_axi_rdata         => s_axi_rdata, | ||||
|             m_axi_rresp         => s_axi_rresp, | ||||
|             m_axi_rlast         => s_axi_rlast, | ||||
|             m_axi_rvalid        => s_axi_rvalid, | ||||
|             m_axi_rready        => s_axi_rready | ||||
|     ); | ||||
| 
 | ||||
|     -- DMA write channel for analog acquisition | ||||
|     inst_acq_dma: entity work.dma_write_channel | ||||
|         generic map ( | ||||
|             transfer_size_bits  => 4, | ||||
|             queue_size_bits     => 14, | ||||
|             idle_timeout        => 256 ) | ||||
|         port map ( | ||||
|             clk                 => clk_adc, | ||||
|             reset               => s_reset, | ||||
|             channel_en          => s_reg_control.acq_dma_en, | ||||
|             channel_busy        => s_reg_status.acq_dma_busy, | ||||
|             channel_init        => s_reg_control.acq_dma_init, | ||||
|             addr_start          => s_reg_control.acq_addr_start, | ||||
|             addr_end            => s_reg_control.acq_addr_end, | ||||
|             addr_limit          => s_reg_control.acq_addr_limit, | ||||
|             addr_interrupt      => s_reg_control.acq_addr_intr, | ||||
|             addr_pointer        => s_reg_status.acq_addr_ptr, | ||||
|             intr_en             => s_reg_control.acq_intr_en, | ||||
|             intr_clear          => s_reg_control.acq_intr_clear, | ||||
|             intr_out            => s_irq_pending(0), | ||||
|             in_valid            => s_acq_dma_valid, | ||||
|             in_ready            => s_acq_dma_ready, | ||||
|             in_empty            => s_acq_dma_empty, | ||||
|             in_data             => s_acq_dma_data, | ||||
|             write_cmd_addr      => s_dma_write_cmd_addr(0), | ||||
|             write_cmd_length    => s_dma_write_cmd_length(0), | ||||
|             write_cmd_valid     => s_dma_write_cmd_valid(0), | ||||
|             write_cmd_ready     => s_dma_write_cmd_ready(0), | ||||
|             write_data          => s_dma_write_data(0), | ||||
|             write_data_ready    => s_dma_write_data_ready(0), | ||||
|             write_finished      => s_dma_write_finished(0) ); | ||||
| 
 | ||||
|     -- DMA write channel for time tagger | ||||
|     inst_tt_dma: entity work.dma_write_channel | ||||
|         generic map ( | ||||
|             transfer_size_bits  => 4, | ||||
|             queue_size_bits     => 12, | ||||
|             idle_timeout        => 256 ) | ||||
|         port map ( | ||||
|             clk                 => clk_adc, | ||||
|             reset               => s_reset, | ||||
|             channel_en          => s_reg_control.tt_dma_en, | ||||
|             channel_busy        => s_reg_status.tt_dma_busy, | ||||
|             channel_init        => s_reg_control.tt_dma_init, | ||||
|             addr_start          => s_reg_control.tt_addr_start, | ||||
|             addr_end            => s_reg_control.tt_addr_end, | ||||
|             addr_limit          => s_reg_control.tt_addr_limit, | ||||
|             addr_interrupt      => s_reg_control.tt_addr_intr, | ||||
|             addr_pointer        => s_reg_status.tt_addr_ptr, | ||||
|             intr_en             => s_reg_control.tt_intr_en, | ||||
|             intr_clear          => s_reg_control.tt_intr_clear, | ||||
|             intr_out            => s_irq_pending(1), | ||||
|             in_valid            => s_tt_dma_valid, | ||||
|             in_ready            => s_tt_dma_ready, | ||||
|             in_empty            => s_tt_dma_empty, | ||||
|             in_data             => s_tt_dma_data, | ||||
|             write_cmd_addr      => s_dma_write_cmd_addr(1), | ||||
|             write_cmd_length    => s_dma_write_cmd_length(1), | ||||
|             write_cmd_valid     => s_dma_write_cmd_valid(1), | ||||
|             write_cmd_ready     => s_dma_write_cmd_ready(1), | ||||
|             write_data          => s_dma_write_data(1), | ||||
|             write_data_ready    => s_dma_write_data_ready(1), | ||||
|             write_finished      => s_dma_write_finished(1) ); | ||||
| 
 | ||||
|     -- Timestamp generator. | ||||
|     inst_timestamp_gen: entity work.timestamp_gen | ||||
|         port map ( | ||||
|             clk                 => clk_adc, | ||||
|             reset               => s_reset, | ||||
|             clear               => s_reg_control.timestamp_clear, | ||||
|             timestamp           => s_timestamp ); | ||||
| 
 | ||||
|     s_reg_status.timestamp <= s_timestamp; | ||||
| 
 | ||||
|     -- Capture ADC data. | ||||
|     -- ADC A handles channels 0 and 1. | ||||
|     -- ADC B handles channels 2 and 3. | ||||
|     -- Each channel receives one 14-bit sample per clock cycle. | ||||
|     -- The 14 bits are transferred through 7 DDR signals. | ||||
|     gen_adc_capture: for i in 0 to 3 generate | ||||
|         inst_adc_capture: entity work.adc_capture_ddr | ||||
|             port map ( | ||||
|                 clk_capture         => clk_adc_capture(i / 2), | ||||
|                 clk_intermediate    => clk_adc_capture(0), | ||||
|                 clk_handoff         => clk_adc, | ||||
|                 in_data             => adc_dat_i(i), | ||||
|                 out_data            => s_adc_data(i) ); | ||||
|     end generate; | ||||
| 
 | ||||
|     -- Optionally generate simulated ADC samples. | ||||
|     gen_adc_sample_stream: for i in 0 to 1 generate | ||||
|         inst_adc_sample_stream: entity work.adc_sample_stream | ||||
|             port map ( | ||||
|                 clk                 => clk_adc, | ||||
|                 reset               => s_reset, | ||||
|                 simulate            => s_reg_control.simulate_adc, | ||||
|                 in_data             => s_adc_data(2*i to 2*i+1), | ||||
|                 out_data            => s_adc_sample(2*i to 2*i+1) ); | ||||
|     end generate; | ||||
| 
 | ||||
|     -- Monitor range of ADC samples. | ||||
|     inst_monitor_gen: for i in 0 to 3 generate | ||||
|         inst_range_monitor: entity work.adc_range_monitor | ||||
|             generic map ( | ||||
|                 signed_data         => false ) | ||||
|             port map ( | ||||
|                 clk                 => clk_adc, | ||||
|                 reset               => s_reset, | ||||
|                 clear               => s_reg_control.adc_range_clear, | ||||
|                 in_data             => s_adc_sample(i), | ||||
|                 min_value           => s_reg_status.adc_min_value(i), | ||||
|                 max_value           => s_reg_status.adc_max_value(i) ); | ||||
|     end generate; | ||||
| 
 | ||||
|     -- Monitor current ADC sample value. | ||||
|     s_reg_status.adc_sample <= s_adc_sample; | ||||
| 
 | ||||
|     -- Analog acquisition data chain. | ||||
|     inst_acquisition_chain: entity work.acquisition_chain | ||||
|         generic map ( | ||||
|             num_channels        => 4 ) | ||||
|         port map ( | ||||
|             clk                 => clk_adc, | ||||
|             reset               => s_reset, | ||||
|             acquisition_en      => s_reg_control.acquisition_en, | ||||
|             trigger_delay       => s_reg_control.trigger_delay, | ||||
|             record_length       => s_reg_control.record_length, | ||||
|             decimation_factor   => s_reg_control.decimation_factor, | ||||
|             averaging           => s_reg_control.averaging_en, | ||||
|             shift_steps         => s_reg_control.shift_steps, | ||||
|             ch4_mode            => s_reg_control.ch4_mode, | ||||
|             trig_auto_en        => s_reg_control.trig_auto_en, | ||||
|             trig_ext_en         => s_reg_control.trig_ext_en, | ||||
|             trig_ext_once       => s_reg_control.trig_ext_once, | ||||
|             trig_force          => s_reg_control.trig_force, | ||||
|             trig_ext_select     => s_reg_control.trig_ext_select, | ||||
|             trig_ext_falling    => s_reg_control.trig_ext_falling, | ||||
|             timestamp_in        => s_timestamp, | ||||
|             adc_data_in         => s_adc_sample, | ||||
|             trig_ext_in         => s_dig_sample, | ||||
|             trig_waiting        => s_reg_status.trig_waiting, | ||||
|             trig_detected       => s_reg_status.trig_detected, | ||||
|             out_valid           => s_acq_dma_valid, | ||||
|             out_ready           => s_acq_dma_ready, | ||||
|             out_empty           => s_acq_dma_empty, | ||||
|             out_data            => s_acq_dma_data ); | ||||
| 
 | ||||
|     -- Capture digital inputs. | ||||
|     s_dig_in(0) <= exp_p_io(0); | ||||
|     s_dig_in(1) <= exp_n_io(0); | ||||
|     s_dig_in(2) <= exp_p_io(1); | ||||
|     s_dig_in(3) <= exp_n_io(1); | ||||
| 
 | ||||
|     inst_dig_capture_gen: for i in 0 to 3 generate | ||||
| 
 | ||||
|         -- Use a 2-flipflop synchronizer to avoid metastability. | ||||
|         inst_dig_sync: entity work.syncdff | ||||
|             port map ( | ||||
|                 clk             => clk_adc, | ||||
|                 di              => s_dig_in(i), | ||||
|                 do              => s_dig_sync(i) ); | ||||
| 
 | ||||
|         -- Deglitch filter. | ||||
|         inst_dig_deglitch: entity work.deglitch | ||||
|             generic map ( | ||||
|                 deglitch_cycles => 4 ) | ||||
|             port map ( | ||||
|                 clk             => clk_adc, | ||||
|                 din             => s_dig_sync(i), | ||||
|                 dout            => s_dig_deglitch(i) ); | ||||
| 
 | ||||
|     end generate; | ||||
| 
 | ||||
|     -- Optionally generate simulated digital signals. | ||||
|     process (clk_adc) is | ||||
|     begin | ||||
|         if rising_edge(clk_adc) then | ||||
|             if s_reg_control.dig_simulate = '1' then | ||||
|                 s_dig_sample <= s_reg_control.dig_sim_state; | ||||
|             else | ||||
|                 s_dig_sample <= s_dig_deglitch; | ||||
|             end if; | ||||
|         end if; | ||||
|     end process; | ||||
| 
 | ||||
|     -- Monitor digital signal state. | ||||
|     s_reg_status.dig_sample <= s_dig_sample; | ||||
| 
 | ||||
|     -- Time tagger. | ||||
|     inst_timetagger: entity work.timetagger | ||||
|         port map ( | ||||
|             clk                 => clk_adc, | ||||
|             reset               => s_reset, | ||||
|             channel_en          => s_reg_control.timetagger_en, | ||||
|             marker              => s_reg_control.timetagger_mark, | ||||
|             timestamp_in        => s_timestamp, | ||||
|             dig_sample          => s_dig_sample, | ||||
|             out_valid           => s_tt_dma_valid, | ||||
|             out_ready           => s_tt_dma_ready, | ||||
|             out_empty           => s_tt_dma_empty, | ||||
|             out_data            => s_tt_dma_data ); | ||||
| 
 | ||||
|     -- Collect interrupt signals from peripherals and generate interrupt to PS. | ||||
|     s_reg_status.irq_pending <= s_irq_pending; | ||||
|     s_irq_f2p(0) <= s_reg_control.irq_enable and or_reduce(s_irq_pending); | ||||
|     s_irq_f2p(7 downto 1) <= (others => '0'); | ||||
| 
 | ||||
|     -- Report reset status via GPIO. | ||||
|     process (clk_adc, s_ext_reset_n) is | ||||
|     begin | ||||
|         if s_ext_reset_n = '0' then | ||||
|             r_reset_done <= '0'; | ||||
|         elsif rising_edge(clk_adc) then | ||||
|             r_reset_done <= not s_reset; | ||||
|         end if; | ||||
|     end process; | ||||
| 
 | ||||
|     -- Blinking LED, 1 Hz. | ||||
|     process (clk_adc) is | ||||
|     begin | ||||
|         if rising_edge(clk_adc) then | ||||
|             if s_reset = '1' then | ||||
|                 r_adcclk_cnt <= (others => '0'); | ||||
|                 r_adcclk_led <= '0'; | ||||
|             elsif r_adcclk_cnt = 62499999 then | ||||
|                 r_adcclk_cnt <= (others => '0'); | ||||
|                 r_adcclk_led <= not r_adcclk_led; | ||||
|             else | ||||
|                 r_adcclk_cnt <= r_adcclk_cnt + 1; | ||||
|             end if; | ||||
|         end if; | ||||
|     end process; | ||||
| 
 | ||||
| end architecture; | ||||
		Loading…
	
		Reference in New Issue