Substrato Z0: qué existe y cómo se corre¶
Esta página es el inventario: qué hay construido, en qué estado y cómo ejecutarlo. La planificación está en Fases Z0–Z5 y la disposición de directorios en Estructura del repositorio.
Si lo que quieres es entenderlo, no inventariarlo
El tutorial recorre lo mismo en siete páginas en orden, explicando por qué existe cada pieza, con enlaces a la documentación de cada herramienta externa y con las gráficas y los números reales que produce el modelo. Esta página asume que ya sabes de qué va.
Arranque¶
make venv # crea .venv e instala requirements-dev.txt (pinado)
make check # todos los gates que corre el CI en el job de substrato
make check necesita verilator y gcc en el PATH. Verilator viene de los repositorios de la
distribución (apt install verilator); no hace falta Vivado para nada de lo anterior.
La fuente única de verdad¶
config/params.toml es el paquete de parámetros de D-02. De él
salen, por generación, las vistas de los cuatro consumidores:
| Consumidor | Cómo lo lee |
|---|---|
rtl/ |
rtl/generated/drx_params_pkg.sv, generado |
fw/ |
fw/include/drx_params.h, generado |
tcl/ |
tcl/generated/drx_params.tcl, generado |
model/, sim/ |
drx_model.params, que lee el TOML directamente |
python3 tools/gen_params.py # regenera
python3 tools/gen_params.py --check # gate de CI: falla si hay desfase
Cambiar fs, R₁ o R₂ —que es lo que va a pasar cuando se cierren
P-01 y P-08— empieza por editar
dos líneas del TOML y regenerar (a 8-oct-2026 el cierre además exige auditar constantes de PRF y
ancho de pulso y repetir la verificación; ver la revisión del
ADR-001). Ese es el motivo entero de que este fichero exista antes que el RTL.
El gate de la constante hardcodeada es real, no decorativo
tools/check_hardcoded_clock.py falla la build si aparece un literal decimal ≥ 10⁶ en rtl/,
fw/, sim/, model/, tcl/ o contract/. Ignora comentarios y ficheros generados, y admite
el marcador clock-const-ok: <razón> para las excepciones legítimas —que hoy son dos: la
velocidad de la luz y una conversión de unidades—. Cada excepción lleva su razón escrita.
Modelo dorado¶
model/drx_model/ es el oráculo de D-03: NCO con truncamiento de
fase, mezclador complejo, CIC de Hogenauer con desbordamiento intencionado, FIR de coeficientes
cuantizados, enrejado en rango y generador de vectores con degradaciones inyectables. Todo en
aritmética entera; la coma flotante solo aparece antes de cuantizar y en el análisis.
Los coeficientes del FIR están congelados en config/coeffs/ y son los que se cargarán en el
FIR Compiler. No se rediseñan en cada ejecución: si lo hicieran, una actualización de scipy movería
el oráculo por debajo.
python3 tools/gen_coeffs.py --check
La suite del modelo incluye una huella del oráculo: un vector conocido produce una salida cuyo SHA-256 está fijado en el test. Cualquier cambio de comportamiento del modelo la mueve, y eso obliga a justificarlo en el commit en lugar de que pase inadvertido.
Lo que el modelo todavía no puede prometer
La cadena está modelada contra la configuración pretendida de la IP de Xilinx, no contra la IP real: en Z0 no hay Vivado ni IP generada. La correspondencia bit a bit modelo↔IP se establece en Z1 y es ahí donde pueden aparecer ajustes de redondeo. Hoy el modelo es autoconsistente, determinista y reproducible, que es lo que Z0 promete — no más.
Simulación¶
Dos niveles, dos caminos. El runner único que pedía D-05 no existe: cocotb no tiene backend para xsim (P-09, decidido el 30 de agosto de 2026). Lo compartido es el oráculo, no la herramienta.
- L0 — Verilator, bajo cocotb. Funciona.
make sim. - L1 — SystemVerilog nativo, sobre xsim. El oráculo del modelo dorado cruza por fichero:
tools/gen_l1_vectors.pyescribestimulus.hex,expected_i.hex,expected_q.hexy unmanifest.jsoncon conteos, modo, transitorio de arranque y la huella SHA-256 deconfig/params.toml.sim/tb_sv/drx_l1_file_source.svlos reproduce con handshake ysim/tb_sv/drx_l1_checker.svcompara bit a bit. Lo lanzatcl/sim_l1.tcl.
El arnés de L1 está verificado sin Vivado. sim/tests/test_l1_harness.py lo corre en Verilator
sobre los vectores del propio modelo y comprueba las dos direcciones: cero discrepancias con
vectores limpios y exactamente una cuando se invierte un bit de una muestra. La segunda es la
que vale, porque el modo de fallo peligroso de un comparador es dar verde. Lo que no se ha ejecutado
nunca es tcl/sim_l1.tcl —falta Vivado— y sim/tb_sv/tb_l1_ddc.sv no elabora todavía porque su
DUT, drx_ddc_top, es trabajo de Z1; el make check lo linta para que no se pudra mientras tanto.
Contrato DRx↔DSP v0.1¶
Congelado unilateralmente según D-08. Fuente única en
contract/schema/drx_dsp_v0_1.toml; de ahí salen las tres implementaciones: C (lado DRx), Rust
(lado DSP, que es un servicio Rust) y Python (referencia de los tests).
El test de contrato compila un programa en C con la cabecera generada, vuelca los bytes de cada mensaje y los compara con los que produce la implementación de Python. Si los layouts divergen, el test falla. La implementación de Rust no se compila aquí —no hay toolchain de Rust en este repositorio— y de ella solo se comprueba que las constantes de tamaño coinciden; el test de layout del lado Rust le toca al proyecto DSP.
Formato: little-endian, empaquetado, sin relleno implícito, solo enteros en el cable. Los
ángulos viajan como cuenta cruda del encoder y la corrección AFC como palabra de fase absoluta del
NCO: en Hz haría falta que el DSP conociera el FS_HZ del DRx, y eso rompería D-02.
Gateware: escrito, no ejecutado¶
tcl/build.tcl implementa el flujo no-project de D-07 —síntesis,
implementación con el WNS como gate duro, informes y bitstream con -bin_file—, tcl/ip.tcl
regenera la IP desde los XCI versionados, tcl/sim_l1.tcl lanza la simulación L1 sobre xsim y
tools/make_boot.sh empaqueta el BOOT.BIN y comprueba la reproducibilidad empaquetando dos veces
y comparando.
Nada de esto se ha ejecutado nunca: no hay Vivado en el entorno de desarrollo ni runner de CI
con licencia. El job gateware del CI existe y está condicionado a que aparezca un runner
etiquetado. Hasta que corra, el hito ZM0 no está cerrado: CI verde sobre el substrato no es lo
mismo que un BOOT.BIN reproducible byte a byte.
Estado de los puntos de Z0¶
| Punto de Z0 | Estado |
|---|---|
| Estructura de repositorio | Hecho |
Paquete único de parámetros con FS_HZ |
Hecho, con gate de regeneración y de constante hardcodeada |
| Flujo Vivado no-project en Tcl | Escrito, no ejecutado (falta Vivado) |
| Runner cocotb de doble backend | L0 hecho. El doble backend no se hace así: P-09 decidido, L1 es SystemVerilog nativo con oráculo por fichero; arnés verificado, flujo xsim sin ejecutar |
| Modelo dorado NumPy + generador de vectores | Hecho |
| Congelado del esquema DRx↔DSP v0.1 | Hecho, con codegen para C, Rust y Python |
| Gates de CI | Hechos salvo los que necesitan Vivado |
BOOT.BIN reproducible byte a byte |
Pendiente: depende de Vivado |