Saltar a contenido

Capa de abstracción de fuente de muestras (SSA)

Sin esta capa, el trabajo en ZedBoard es desechable. Con ella, es transferible.

El interfaz

Se define un único interfaz AXI4-Stream de muestras con backpressure:

sample_stream: TDATA[N*16-1:0] (N canales entrelazados o N streams paralelos)
               TVALID / TREADY
               TUSER = {channel_id, sample_valid_mask, source_tag}
               TLAST = fin de ventana de captura

Las dos implementaciones

  • jesd204b_source — solo en ZU9. IP de Xilinx sobre transceptores GTH.
  • vector_source — reproductor de vectores. Es la implementación que existe hoy y la que sobrevive en la placa real como inyector de vectores digitales.

Todo lo que está aguas abajo — DDC, gating, DMA, PS — se desarrolla y se valida contra la SSA, nunca contra la fuente concreta. Eso convierte la inyección de vectores digitales en ciudadano de primera clase en lugar de un hack de bring-up, lo cual también es lo correcto para la placa final: el plan original ya contaba con inyección digital al nivel del ADC/JESD como método de prueba determinista.

Reproductor de vectores: los modos previstos, y el que quedó

El ancho de banda de DDR3 de la ZedBoard (32 bits a 533 MT/s, unos 2133 MB/s de pico; estimación de ~1400 MB/s sostenidos) limita lo que se puede reproducir en tiempo real dilatado. El diseño original preveía por eso tres modos con compromisos distintos:

Modo Fuente Tasa Estado
BRAM-loop BRAM interna, forma de onda repetitiva una muestra por ciclo el único implementado, y desde el 4-oct-2026 cargable en tiempo de ejecución
RT DDR vía MM2S DMA tiempo real dilatado sin implementar
Throttled DDR con backpressure AXIS < tiempo real implementado en Z4.3, retirado el 4-oct-2026

BRAM total del 7Z020: 140 tiles de 36 Kbit, 32768 bits de dato cada uno → 2048 muestras de 16 bits por tile, 286 720 en toda la pieza. Lo que el reproductor usa hoy es VECTOR_BRAM_DEPTH = 8192 muestras por canal × N_CH = 3 = 12 tiles, sobre una ocupación total del diseño que se queda en el entorno del 27 %.

4-oct-2026: BRAM-loop cargable en tiempo de ejecución, y Throttled fuera

Lo único que le faltaba a BRAM-loop era poder elegir el vector sin volver a sintetizar. Desde hoy lo tiene: el PS escribe los bancos por la ventana VEC_ADDR/VEC_DATA/VEC_LEN del mapa de registros v11, protegida por CTRL bit 2 (vector_load), y el mensaje test_stimulus_select del contrato sigue siendo la interfaz del par remoto. El catálogo de ocho vectores cuesta ocho mensajes, igual que con Throttled, pero ahora además sale a tasa plena, que es lo que lo hace medible.

Con eso, Throttled(DDR) deja de tener razón de ser y sale del RTL y del block design: el canal MM2S del AXI DMA, el puerto m_axis_vec y CTRL bit 1 desaparecen. RT sigue sin implementar.

Consecuencia aceptada: nada en el diseño ejercita ya el camino DMA PS→PL. M_AXI_MM2S contra S_AXI_HP0 era la única cobertura de ese sentido. El camino S2MM (rayos) no se toca.

Por qué se retiró, y no es por el DMA: ver el cuadro de P-16 más abajo.

1-oct-2026: Throttled implementado y verificado en ZedBoard (Z4.3) — retirado el 4-oct

rtl/vector_source.sv tiene desde hoy los dos modos: BRAM-loop, que es el que tenía, y Throttled(DDR), con las muestras llegando por AXI4-Stream desde el canal MM2S de un AXI DMA alimentado por la DDR del PS. Se elige en tiempo de ejecución con CTRL bit 1 (mapa de registros v8) y el vector concreto con el mensaje test_stimulus_select del contrato (v0.5). RT sigue sin implementar.

Formato del stream: 16 bits, UNA muestra por beat, canales en orden ascendente y repitiendo. Los N_CH canales avanzan en bloque —se juntan N_CH beats en un conjunto y los N_CH salidas se presentan a la vez, y el conjunto no se retira hasta que todos los consumidores lo han tomado—, que es más estricto de lo que exige AXI4-Stream y es justo el punto de este modo: dejar que un canal se adelantara convertiría un desfase de muestra en un resultado distinto sin ningún error visible.

Verificado en placa por JTAG: el DMA completa pasadas enteras con 0 errores, y eso es la prueba de que los bytes entraron en la PL, porque el stream tiene backpressure y el único que levanta tready es vector_source en este modo. Lo que ese ensayo no prueba es que el dato llegue correcto hasta la salida del DDC: no hay camino de vuelta para leerlo hasta que Z4.4 ensamble rayos. Ver fases.md#z4, entrada del 1-oct.

El modo Throttled produce salida bit a bit idéntica al modo RT; solo tarda más. Eso era el razonamiento, y resultó ser falso por una razón que el análisis no miró — ver el cuadro siguiente. El que de verdad cubre hoy la corrección funcional y la fidelidad temporal a la vez es BRAM-loop, porque entrega una muestra por ciclo y ya es elegible en caliente.

1-oct-2026 (Z4.4): Throttled y el motor de timing no pueden correr a la vez

«Solo tarda más» es cierto para la aritmética y falso para el range gating, y la diferencia importa en placa. drx_range_gate corta rayos donde se lo dice ray_start, que viene del motor de timing y llega cada prf_div ciclos de reloj; el número de bins que caben, en cambio, depende de cuántas muestras VÁLIDAS lleguen en ese tiempo.

En Throttled(DDR), vector_source junta N_CH muestras de un stream de 16 bits —una por beat— y presenta el conjunto un ciclo, así que s_valid hacia el DDC está alto como mucho 1 de cada N_CH+1 ciclos. Con N_CH = 3 eso es un cuarto de la tasa: una muestra decimada sale cada ≈4·R₁ ciclos en vez de cada R₁, y un rayo de bins_for_pri(prf_div) bins necesita unas cuatro veces el PRI. ray_start lo trunca antes de completarse, GATE_TRUNCATED sube y no sale ni un rayo entero.

Consecuencia práctica: la medida de rayos de Z4.4 corre en BRAM-loop, y el catálogo elegible en caliente de Z4.3 sirve para ejercitar el camino de datos, no para producir rayos con el motor de timing en marcha. Ver P-16.

Resuelto en RTL el 3-oct-2026, y no por donde se esperaba. La salida que este párrafo daba por única —que el DMA entregase N_CH muestras por ciclo, un stream de N_CH·16 bits— no hizo falta. El problema no era la tasa del DMA sino que el motor de timing y la cadena de datos miden el tiempo con reglas distintas: ciclos de reloj el primero, valid la segunda. Con el motor contando avances de muestra (rtl/drx_sample_pacer.sv, TIMING_CTRL bit 1 del mapa v10) las dos se frenan con el mismo factor y el rayo se llena con los bins que toca a cualquier tasa. Esto no sube la tasa de este modo: sigue siendo «por debajo de tiempo real», que es lo que su nombre dice y lo que esta tabla promete.

Y resolvió el síntoma, no el dato. GATE_TRUNCATED bajó a 0x0 y los rayos salieron enteros, pero el espectro dio −87,3 dBFS contra −9,02 del modelo dorado. Había una TERCERA base de tiempo que nadie había mirado: el DDS Compiler no tiene aclken (rtl/drx_ddc_mixer.sv:99, tcl/gen_ip.tcl:238), así que avanza un paso de fase por ciclo de reloj mire o no valid. Con la fuente a una muestra de cada N_CH, el DDC mezcla a ~N_CH veces el IF y la salida cae al suelo de ruido.

El arreglo simétrico existía —regenerar la IP con Has_ACLKEN {true} y cablear aclken = advance, con la matriz de 16 corridas de D-12 como gate, 2–3 h—, y no se tomó. El 4-oct-2026 se eliminó en su lugar la fuente con huecos: BRAM-loop pasó a ser cargable en tiempo de ejecución y Throttled(DDR) salió del diseño. Esto NO cierra P-16: la causa raíz sigue en el RTL y vuelve el día que haya una fuente con huecos de verdad — un ADC real, la ZU9—, en una plataforma donde medirlo cuesta mucho más.

Consecuencia para la portabilidad

Cuando llegue la ZU9, la migración de la fuente de muestras es sustituir un módulo que cumple un interfaz por otro que cumple el mismo interfaz. Nada aguas abajo cambia, y el vector_source se queda para inyectar vectores conocidos en la placa real — que sigue siendo la única forma de tener un oráculo exacto e independiente del frontal analógico.