119 lines
3.4 KiB
VHDL
119 lines
3.4 KiB
VHDL
|
--
|
||
|
-- 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;
|