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/ip
|
||||||
vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ipshared
|
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/puzzlefw.bda
|
||||||
|
vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ui
|
||||||
vivado/redpitaya_puzzlefw.gen
|
vivado/redpitaya_puzzlefw.gen
|
||||||
vivado/redpitaya_puzzlefw.cache
|
vivado/redpitaya_puzzlefw.cache
|
||||||
vivado/redpitaya_puzzlefw.hw
|
vivado/redpitaya_puzzlefw.hw
|
||||||
|
vivado/redpitaya_puzzlefw.ip_user_files
|
||||||
vivado/redpitaya_puzzlefw.runs
|
vivado/redpitaya_puzzlefw.runs
|
||||||
vivado/output
|
vivado/output
|
||||||
|
vivado/output_4ch
|
||||||
vivado/.Xil
|
vivado/.Xil
|
||||||
vivado/NONE
|
vivado/NONE
|
||||||
vivado/*.html
|
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.
|
-- 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 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.
|
-- Register addresses.
|
||||||
constant reg_addr_mask: std_logic_vector(31 downto 0) := x"0010fffc";
|
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