Add support for 4-input Red Pitaya

This commit is contained in:
Joris van Rantwijk 2024-10-08 08:49:34 +02:00
parent 6016d2d706
commit 6a39840821
7 changed files with 1158 additions and 0 deletions

3
fpga/.gitignore vendored
View File

@ -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

35
fpga/12_build_bitfile_4ch.sh Executable file
View File

@ -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 .

View File

@ -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]

View File

@ -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;

51
fpga/rtl/ffpair.vhd Normal file
View File

@ -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;

View File

@ -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";

View File

@ -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;