redpitaya-puzzlefw/fpga/rtl/puzzlefw_top_4ch.vhd

710 lines
29 KiB
VHDL

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