Medición e Instrumentación
Diseño de grabadores de datos de alta velocidad basados en Fpga
Table of Contents
La adquisición de datos de alta velocidad es un requisito fundamental en campos que van desde la telemetría aeroespacial a la imagen médica y la instrumentación científica. Soluciones tradicionales como ASICs dedicados o grabadores de software a menudo no satisfacen la combinación de rendimiento en tiempo real, flexibilidad y baja latencia demandada por sistemas modernos.
¿Por qué FPGAs para Registro de Datos de Alta Velocidad
Paralelismo y latencia deterinista
A diferencia de microprocesadores o DSP que ejecutan instrucciones secuencialmente, FPGAs procesa datos en verdadero hardware paralelo. Para un registrador de datos, esto significa que puede capturar simultáneamente datos de múltiples canales de alta velocidad, realizar preprocesamiento (filtración, decimación o formato), amortiguar los resultados y transmitirlos al almacenamiento, todo en hardware sin CPU overhead.
Flexibilidad de la interfaz
Los registros de datos de alta velocidad deben interactuar con una variedad de fuentes: convertidores analógicos (ADCs) usando LVDS o JESD204B, interfaces multimedia de alta definición (HDMI), enlaces de cámara o autobuses de sensores personalizados. Los FPGAs admiten de forma nativa una amplia gama de estándares I/O (LgaDS, HSTL, SSTL, pares de serie) y transceptores de serie
Reconfigurabilidad en el vuelo
Muchas aplicaciones de grabación requieren que el sistema se adapte a diferentes tipos de datos, conteos de canales o esquemas de codificación sin cambios de hardware. Los FPGA pueden ser reconfigurados parcial o totalmente a través de un enlace PCIe, Ethernet o una interfaz de configuración dedicada. Esta capacidad permite una única tabla de registro para servir a múltiples misiones, por ejemplo, conmutando entre una configuración de radar de 12 bits de 4 canales y un software de 2 canales de radio MSDR 500
Consideraciones clave de diseño y operaciones comerciales
Arquitectura de la Computación y la Memoria
La entrada de datos en un grabador se limita por tres factores: la tasa de captura de entrada, la capacidad de amortiguación interna y el ancho de banda de salida al medio de almacenamiento (por ejemplo, el array SSD, DRAM o el enlace de streaming). La peor de los casos de rendimiento sostenido debe superar la tasa promedio de datos para evitar la pérdida de datos.
- RAM de bloques en chip (BRAM):] Fast, dual-port, pero limitado en capacidad (normalmente unas pocas decenas de Mbits en FPGAs modernos). Se utiliza para pequeños FIFOs, buffers de línea o almacenamiento de coeficiente.
- ] DRAM externo (DDR3/DDR4/LPDDR4):] Alta capacidad (multiple GB) pero con limitaciones de latencia y ancho de banda. Un controlador DDR bien diseñado (a menudo un proveedor IP) combinado con un interconexión AXI multicanal puede proporcionar decenas de ancho de banda agregado de GB/s.
- SRAM externo: Latencia inferior a la DRAM pero menor densidad; útil para los FIFOs profundos donde se necesita tiempo de acceso determinista.
- Almacenamiento en serie de alta velocidad:] Redacción directa a SSD NVMe sobre PCIe o a través de un puente dedicado (por ejemplo, Xilinx QDMA IP).Esto descarga grandes conjuntos de datos a la memoria no volátil, pero requiere un control de flujo cuidadoso para evitar el flujo de amortiguación.
En VHDL, modelas estos recuerdos como arrays o primitivos de proveedores instantáneos. Por ejemplo, un FIFO genérico que utiliza BRAM podría tener un parámetro de profundidad fijado en el tiempo de compilación, mientras que un búfer con respaldo DDR se interfiere a través de un motor con memoria AXI4.
Cierre Dominios y Metastabilidad
Los registradores de datos de alta velocidad abarcan inherentemente múltiples dominios del reloj del reloj de la muestra ADC (potencialmente ⁇ 1 GHz), el reloj de tela FPGA (a menudo una división de la referencia del transceptor), el reloj del controlador de memoria y el reloj de interfaz del sistema. Cruzar estos dominios requiere de seguridad las técnicas de sincronización adecuadas. El método más robusto es utilizar FIFOs de dobles (con biblioteca independiente de lectura y escritura)
La metastabilidad en los chanclas utilizados para el cruce de dominio del reloj puede mitigarse mediante dos o más registros de sincronización. Un patrón común de VHDL es:
signal async_sig, sync1, sync2 : std_logic;
begin
process(clk) begin
if rising_edge(clk) then
sync1 <= async_sig;
sync2 <= sync1;
end if;
end process;
Para los autobuses de datos, es más seguro utilizar un protocolo de apretón de manos o un FIFO en lugar de sincronizadores de múltiples bits.
Ropa de Timing en frecuencias altas
FPGA diseña con tasas de datos por encima de varios cientos de MHz debe cumplir con una configuración estricta y tener limitaciones de tiempo. VHDL mal estructurada, como la lógica combinada muy anidada, los multiplexores anchos o la obstrucción de asignaciones dentro de bloques de procesos, puede conducir a violaciones de tiempo.
- ]Etapas de tuberías: Insertar registros (esquejas de tubería) en vías de datos de alto contenido o largos. Por ejemplo, una escalera de 64 bits dentro de un bucle de acumulador debe estar registrada tanto en la entrada como en la salida.
- Clock Gating and Clock Enable: Usar señales de reloj en lugar de fijar el reloj para apagar la lógica; los relojes cerrados crean riesgos de tiempo y contribuyen a desactivar.
- Síntesis Atributos: Usar directivas específicas para proveedores (por ejemplo, guardar, sin preserve y max fanout) para guiar las herramientas. En VHDL se agregan a menudo como comentarios: .
- Floorplanning: Grupo de lógica de alta velocidad en regiones dedicadas de la FPGA para reducir los retrasos de interconexión.
Arquitectura de sistema de un grabador de alta velocidad
Entrada frontal
El primer módulo en la ruta de datos captura datos de la fuente externa. Para JESD204B ADCs, esto implica un transceptor JESD204B IP (generalmente suministrado por el proveedor FPGA) que maneja la sincronización de carriles, el rascacielos y la detección de errores. Para LVDS ADCs paralelos, utiliza un deserializador (ISERDES en Xilinx, ALTIO delay serial
Preprocesamiento y Formato de datos
Los datos capturados en bruto pueden requerir operaciones en tiempo real antes del almacenamiento:
- ]Declaración/Filtering: Reducción de la tasa de datos por factores enteros utilizando filtros de integrador-comb cascada (CIC) o filtros FIR implementados como bloques de multiplicación (MAC).
- Conversión a Formato Estándar:] Repasar datos en marcos con marcas de tiempo, ID de canal y palabras de verificación de errores (por ejemplo, CRC). Esto simplifica el procesamiento de corriente o el análisis de postgrabado.
- Zero Overhead: En modo de ráfaga, es posible que necesite insertar marcadores de pausa o rellenar ceros para mantener un flujo de bit constante desde la interfaz de almacenamiento.
Todos los módulos de procesamiento deben ser diluidos para mantener la latencia baja. Por ejemplo, un filtro de decimación de polifase puede ser estructurado como una matriz sístólica de rodajas DSP conectadas por las rutas de datos registradas.
Control de amortiguación y flujo
Un búfer elástico (FIFO) descodifica el dominio del reloj de captura del dominio del reloj de almacenamiento. La profundidad de la FIFO debe ser tallada en base a la longitud de la explosión de entrada peor de la maleta y el tiempo que toma para la interfaz de almacenamiento para comenzar a escribir. Un enfoque común es utilizar un FIFO con umbrales programables casi completos y casi vacíos para generar señales de presión.
Interfaz de almacenamiento
La etapa final escribe los datos amortiguados a un medio persistente.
- PCIe DMA to Host RAM or SSD:] Usar un motor DMA (por ejemplo, Xilinx QDMA o Intel P-Tile DMA) para transferir datos directamente a la memoria del sistema o a una unidad NVMe. La FPGA actúa como un punto final de PCIe y el controlador maneja anillos de amortiguación.
- ]Direct Drive of Flash Memory: Para grabadores independientes, puede interactuar con NAND flash o eMMC utilizando un controlador implementado en VHDL. Esto es más complejo pero proporciona una solución completamente incrustada.
- Enlaces serie de alta velocidad (por ejemplo, Aurora, GDS): Para el streaming a un servidor remoto u otra tarjeta FPGA.
Cada interfaz tiene su propio protocolo y mecanismo de control de flujo. Por ejemplo, un grabador basado en PCIe utilizaría una cadena descriptor DMA basada en memoria o en flujo; el VHDL debe gestionar las solicitudes de transacción, la tramitación de la terminación y el control de flujo basado en créditos.
Pasos de implementación en VHDL
Define la Entidad de Top-Level y Puertos
Comience por enumerar todas las interfaces externas: entradas de reloj (referencia relojes y reloj de tela de un PLL), entradas de datos de ADCs, señales de configuración y interfaz de almacenamiento (por ejemplo, pares diferenciales de PCIe).
entity high_speed_recorder is
generic (
ADC_CHANNELS : integer := 2;
DATA_WIDTH : integer := 16;
FIFO_DEPTH : integer := 1024
);
port (
ref_clk_p, ref_clk_n : in std_logic; -- differential reference
adc_data : in std_logic_vector(ADC_CHANNELS * DATA_WIDTH - 1 downto 0);
adc_clk : in std_logic; -- sample clock
pcie_tx_p, pcie_tx_n : out std_logic_vector(3 downto 0);
pcie_rx_p, pcie_rx_n : in std_logic_vector(3 downto 0);
-- more ports...
);
end entity;
Ropa de vendedor Instantiate y Primitivos I/O
Utilizar primitivos específicos para el reloj (por ejemplo, Xilinx MMCM/PLL) y I/O de alta velocidad (ISERDES, OSERDES o envoltorios transceptores). En VHDL, a menudo se llaman instantáneas de componentes. Por ejemplo, para instantánear un MMCM Xilinx con cambio de fase dinámico, se puede escribir:
mmcm_inst : entity work.mmcm_wrapper
generic map (
MULT => 8.0,
DIV => 1
)
port map (
clkin1 => ref_clk,
clkout0 => fabric_clk,
clkout1 => transceiver_clk,
locked => pll_locked
);
Construir el Camino de Datos
Escribe la lógica de control que procesa datos del desarrollador de entrada a la salida FIFO. Usar diseño jerárquico: cada bloque funcional (deserializador, FIFO, formatter de datos) es una entidad VHDL separada. Conéctalos a través de autobuses de señal (estd logic vector arrays) que siguen un protocolo consistente, como un simple apretón de manos válido/listo.
-- Producer side
if rising_edge(clk) then
if ready = '1' and valid = '1' then
-- data transferred
end if;
end if;
-- Consumer side
if rising_edge(clk) then
if valid = '1' and ready = '1' then
-- consume data
end if;
end if;
Este protocolo es la base de AXI4-Stream, que es ampliamente apoyado por las bibliotecas de proveedores.
Detalles de la implementación de FIFO
A continuación se muestra una versión mejorada de un FIFO de dos horas con parámetros genéricos y banderas casi completas/casi vacías. A diferencia del snippet original, esta versión utiliza aritmética entero para la gestión de contadores y punteros, y emplea código gris para la dirección que cruza el dominio del reloj para evitar errores de sincronización de múltiples bits. Un diseño real utilizaría primitivos de proveedores (por ejemplo, Lólo Xlinx
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity dual_clock_fifo is
generic (
DATA_WIDTH : integer := 64;
ADDR_WIDTH : integer := 10 -- depth = 2^ADDR_WIDTH
);
port (
wr_clk : in std_logic;
wr_rst : in std_logic;
wr_en : in std_logic;
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
full : out std_logic;
almost_full : out std_logic;
rd_clk : in std_logic;
rd_rst : in std_logic;
rd_en : in std_logic;
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0);
empty : out std_logic;
almost_empty: out std_logic
);
end entity;
architecture rtl of dual_clock_fifo is
type memory_t is array (0 to (2**ADDR_WIDTH)-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal mem : memory_t;
signal wr_ptr, rd_ptr : unsigned(ADDR_WIDTH-1 downto 0);
signal wr_gray, rd_gray : unsigned(ADDR_WIDTH-1 downto 0);
signal wr_count, rd_count : unsigned(ADDR_WIDTH downto 0); -- include overflow bit
signal sync_wr_ptr, sync_rd_ptr : unsigned(ADDR_WIDTH-1 downto 0);
signal sync_wr_count, sync_rd_count : unsigned(ADDR_WIDTH downto 0);
begin
-- Write pointer and memory write
process(wr_clk) begin
if rising_edge(wr_clk) then
if wr_rst = '1' then
wr_ptr <= (others => '0');
wr_count <= (others => '0');
elsif wr_en = '1' and full = '0' then
mem(to_integer(wr_ptr)) <= wr_data;
wr_ptr <= wr_ptr + 1;
wr_count <= wr_count + 1;
end if;
wr_gray <= (wr_ptr srl 1) xor wr_ptr; -- binary to gray
end if;
end process;
-- Read pointer and memory read
process(rd_clk) begin
if rising_edge(rd_clk) then
if rd_rst = '1' then
rd_ptr <= (others => '0');
rd_count <= (others => '0');
elsif rd_en = '1' and empty = '0' then
rd_count <= rd_count + 1;
rd_ptr <= rd_ptr + 1;
end if;
rd_gray <= (rd_ptr srl 1) xor rd_ptr;
end if;
end process;
-- Synchronize write pointer to read clock domain
process(rd_clk) begin
if rising_edge(rd_clk) then
sync_wr_ptr <= wr_gray;
end if;
end process;
-- Synchronize read pointer to write clock domain
process(wr_clk) begin
if rising_edge(wr_clk) then
sync_rd_ptr <= rd_gray;
end if;
end process;
-- Full and empty detection using gray-code pointers (simplified)
-- Full when (wr_gray ~ sync_rd_ptr) and top two bits differ
full <= '1' when (wr_gray(ADDR_WIDTH-1) /= sync_rd_ptr(ADDR_WIDTH-1) and
wr_gray(ADDR_WIDTH-2 downto 0) = sync_rd_ptr(ADDR_WIDTH-2 downto 0)) else '0';
empty <= '1' when (rd_gray = sync_wr_ptr) else '0';
-- Almost flags (threshold defined by constants)
almost_full <= '1' when wr_count >= 2**ADDR_WIDTH - 8 else '0';
almost_empty <= '1' when rd_count <= 8 else '0';
rd_data <= mem(to_integer(rd_ptr));
end rtl;
Integración y cableado de alto nivel
En la arquitectura de primer nivel, instantáneamente el PLL, deserializador, FIFO y la interfaz de almacenamiento, luego conectarlos con asignaciones de señal. Preste atención cuidadosa para restablecer la polaridad y el reloj permiten la propagación. Una mejor práctica es utilizar los resetes sincronizados impulsados por los respectivos relojes de dominio, asincrónicamente afirmados pero desactivados sincronizadamente, para evitar metástabilidad.
Estrategia de Pruebas y Verificación
Simulación con testbenches
Simula cada módulo de forma independiente: verifique el FIFO para secuencias correctas de lectura/escritura, condiciones de subida/regreso y seguimiento de punteros de código gris. Utilice un testbench de autocontrol que genere datos aleatorios y compare la salida después de un retraso.Para el sistema completo, cree un testbench que emule la interfaz ADC con un generador de onda programable y un modelo de memoria para el lado de almacenamiento.
Verificación de la Clausura y la posterior ejecución
Después de la síntesis y la implementación, ejecute el análisis de tiempo estático en todos los dominios del reloj. Preste especial atención a las rutas de ciclo múltiple (por ejemplo, operaciones de lectura de memoria que completan después de más de un ciclo del reloj) y caminos falsos (por ejemplo, sincronizadores de dominio cruzado).
Validación de hardware
El prototipo en una tabla de desarrollo FPGA con recursos similares (por ejemplo, Xilinx Kintex-7, Virtex-7, o AMD Zynq UltraScale+). Inyecte patrones de prueba conocidos (como una rampa de repetición o secuencia PRBS) en la entrada ADC y verifique los datos capturados coinciden con el patrón esperado después del almacenamiento o la devolución.
Aplicaciones y ejemplos en el mundo real
- Sistemas de radiación y de fibra de vidrio: Grabar datos de I/Q crudos de múltiples canales a varias tasas de muestreo de GHz para la detección y clasificación de objetivos de procesamiento posterior. Los FPGA manejan la conversión digital en tiempo real y amortiguan los datos a SSDs sobre SATA o PCIe.
- ] Radio definada por software (SDR): Los grabadores de alta velocidad capturan el espectro de banda ancha (por ejemplo, 400 MHz ancho de banda instantáneo) para el análisis posterior de patrones de interferencia o inteligencia de señal. El grabador a menudo incluye filtros de decimación que permiten la selección dinámica del ancho de banda durante la captura.
- Física de alta energía: En experimentos en CERN o instalaciones similares, los datos de miles de canales de detector deben ser registrados para las ráfagas cortas. FPGAs agrega los datos, añade los tiempos y escribe a DRAM antes de la lectura lenta a los servidores de almacenamiento.
- Ultrasonido medical: La formación de imágenes en tiempo real y de alta resolución requiere capturar múltiples canales transductores en decenas de MHz por canal. Los grabadores basados en FPGA almacenan datos de canales crudos para algoritmos de reconstrucción sin conexión.
Conclusión
Diseño de un registrador de datos de alta velocidad basado en FPGA es una tarea de ingeniería sofisticada que exige una comprensión completa del diseño digital, la gestión del reloj, las jerarquías de memoria y los protocolos de interfaz. VHDL proporciona la precisión y el control necesarios para implementar rutas de datos personalizados que operan en los límites del hardware. Al abordar metódicamente la velocidad de entrada, buffering, el cruce de dominio del reloj y el cierre de tiempo, los ingenieros pueden construir grabadores que satisfacen las exigencias de la inversión de la misma.
Para más lectura, consulte la Xilinx Memory Resources Guide para primitivos BRAM y FIFO detallados o Intel FPGA High-Speed I/O Design Guide para el uso de transceptores. Además, el libro VHDL para ingenieros