¿Qué pasó con el paquete ieee.float_pkg del estándar VHDL?
Una auditoría publicada en un repositorio abierto sometió a ieee.float_pkg —el paquete de punto flotante del estándar VHDL, IEEE Std 1076-2008 y 1076-2019— a 3.439.564 llamadas y encontró 371.873 resultados incorrectos y 1.302 caídas del simulador. El ejemplo más simple: en float64, sqrt(2.0) devuelve 3FF6A09E667F3BCC, cuando el valor correctamente redondeado es 3FF6A09E667F3BCD. La diferencia es de un bit en el último lugar.
Para un equipo que diseña o verifica hardware, el problema no es ese bit: es que el paquete con esos errores es el que GHDL y NVC distribuyen sin cambios, y es el código que corre en los testbenches con los que se valida un diseño antes de fabricarlo. Si la herramienta de simulación redondea mal, la verificación deja de ser una red de seguridad.
¿De dónde sale el código auditado?
- El cuerpo auditado es el del propio IEEE:
ieee/float_generic_pkg-body.vhdl, de la rama release deopensource.ieee.org/vasg/Packages, con 5.712 líneas y$Revision: 1220 $. - La rama develop del grupo de trabajo, en
gitlab.com/IEEE-P1076/Packages, tiene los mismos bytes. - Los ensayos corrieron en GHDL 7.0.0-dev y NVC 1.23.1. Donde ambos ejecutaron los mismos vectores, escribieron el mismo archivo de resultados: 8.693.248 líneas para el formato de 7 bits y 3.680.000 para los cuatro formatos, con las mismas 1.302 paradas en las mismas líneas.
- La referencia de comparación es aritmética exacta: el operando se parte en un signo y una fracción de dos enteros, la operación se hace sobre las fracciones y el resultado se redondea una sola vez, al estilo que nombra cada llamada.
¿Qué errores concretos aparecen?
Con los ajustes propios del paquete —round_nearest, 3 bits de guarda, números denormales activados— el catálogo de fallos incluye casos que caben en una línea:
¿Y esto cómo se aplica en tu negocio?
Dueños de negocio de Latinoamérica y España usan un agente de IA para ganar más y recuperar su tiempo. El Kit «tu mano derecha con IA» te muestra cómo en un video de 11 minutos, con una ficha para armar el tuyo. CAR está cerrada por ahora; al anotarte, te avisamos cuando abra.
👥 Quiero el Kit →mac(-6.0, -1.0, -5.0)devuelve -15.0; el resultado exacto es 1.0. Es un cambio de signo, no un redondeo.mac(1.0, 1.0, -infinity)devuelve +infinity; lo correcto es -infinity.resize(2.0**-512 en float64, 8, 23)devuelve 1.0 en lugar de 0.0, yresize(2.0**-1074 en float64, 8, 23)devuelve +infinity en lugar de 0.0.resize(2.0**-650 en float64, 8, 23)detiene el simulador con un índice fuera de rango en la línea 358 del cuerpo del paquete.reciprocal(2.0**127)devuelve +infinity en lugar de 2.0-127**.scalb(1.0, 300)devuelve *0.0* en lugar de +infinity.to_unsigned(199.78125, 8)devuelve 199 en lugar de 200, yto_signed(0.50000006, 32)devuelve 0 en lugar de 1.to_float(100000, 5, 10, round_zero)devuelve +infinity en lugar del mayor número representable, 65504.0.add(1.0, -1.0, round_neginf)devuelve +0.0 cuando el estilo pide -0.0.
El archivo mínimo de prueba reúne 25 llamadas: 24 imprimen WRONG y la número 25 tumba el simulador. Y los operandos no son exóticos: de los enteros del 1 al 4.096, sqrt se va una unidad en 256 casos en float32 y 264 en float64; de las 4.913 tripletas de mac armadas con números pequeños, 290 dan mal en float32.
¿Cuántos resultados están mal en total?
Los barridos por formato, con 10.000 llamadas por celda de operación y estilo, dejan cifras difíciles de ignorar: 81.068 mal y 272 paradas en 859.771 llamadas en float32, 86.081 mal y 445 paradas en 857.234 en float64, 113.980 mal en 866.782 en float16 y 90.744 mal y 585 paradas en 855.777 en float128.
Donde el formato es lo bastante chico para agotarlo, la auditoría probó todos los operandos:
- Formato de 7 bits (3 de exponente, 3 de fracción): 8.692.326 llamadas, 1.271.619 mal. Solo en
macconround_nearestfalla en 243.520 de las 2.097.152 tripletas posibles. - Formato de 10 bits: 17.340.682 llamadas, 883.716 mal.
- float16, funciones de un solo operando: 2.998.266 llamadas, 266.342 mal.
En el conjunto de cuatro formatos, eso es más de uno de cada diez resultados. No es un caso de borde: es la tasa base.
¿Cuáles son las causas, línea por línea?
La auditoría no se queda en los síntomas. Señala el mecanismo en cada punto del cuerpo del paquete:
normalize, línea 422. El exponente se recorta a dos bits más que el del formato destino, así que desde float64 a float32 queda en diez bits y se toma módulo 1.024: 2^-512 sale como 1.0 y 2^600 como 2^88. Cuando el exponente recortado cae entre los denormales, el conteo de desplazamiento indexa fuera de la fracción y el simulador se detiene.divide(1243) yreciprocal(1099). El bit pegajoso que se entrega al redondeo es la constante ‘1’: un cociente exacto se redondea como si sobrara algo.reciprocal(1053 a 1093). El exponente del resultado, -e – 3, se guarda en tantos bits como e, y para el binado superior no entra: en float32 todo argumento desde 2^127 devuelve infinito.sqrt, línea 1787. La iteración de Newton arranca demasiado lejos para los denormales: 128 de 359 denormales en float32 están mal, 104 de ellos por más de dos unidades, ysqrt(2.0**-149)devuelve 11 veces la raíz.mac, líneas 1438 a 1536. El producto se recorta al ancho de un operando antes de sumar, así que una suma que se cancela devuelve lo que quedó del recorte.add, línea 839. Un cero exacto de operandos de signos opuestos es +0 en todos los estilos, cuando el párrafo que el propio comentario cita pide -0 al redondear hacia menos infinito.- Conversiones a entero (301 a 345, 3193). Se guardan tres bits bajo el entero y el resto se descarta sin bit pegajoso.
¿Qué hace el parche que acompaña la auditoría?
El repositorio publica un parche que aplica al archivo del IEEE, cambia solo el cuerpo del paquete, 33 hunks, ninguna declaración. En esencia: normalize decide entre cero, denormal, normal e infinito con el exponente a ancho completo; divide y reciprocal sacan el bit pegajoso del resto de la división; sqrt usa raíz cuadrada entera del significando; mac arma el producto completo en una ventana y redondea una sola vez, como un multiply-add fusionado.
Con eso, sobre los mismos vectores, los 371.873 errores y 1.302 paradas pasan a 0 y 0. El formato de 7 bits pasa de 1.271.619 errores a cero, el de 10 bits de 883.716 a cero, y el caso mínimo de 24 errores y una caída a cero.
Hay una segunda capa: ieee.fixed_pkg, que sale del mismo origen y que NVC distribuye byte por byte. En 751.418 llamadas todo está bien salvo la división, con 41.026 errores concentrados ahí. Un ejemplo: 0.125 / 1.875 en ufixed (3 downto -3) devuelve 0.0625, cuando el cociente es 0.0667 y el número más cercano que el formato puede guardar es 0.0703. El parche correspondiente también lo lleva a cero.
¿Qué significa esto para tu startup?
Si tu producto depende de FPGA, ASIC o IP licenciada, este hallazgo toca directamente tu proceso de verificación. La lección no es «VHDL está roto»: es que el paquete que viene con la herramienta no equivale a un paquete correcto, y que asumirlo es un riesgo de proyecto, no un detalle académico.
- Audita tus vectores de regresión, no tu contrato. Un error de verificación que llega a silicio se paga con una máscara nueva y meses de calendario. La auditoría muestra exactamente dónde atacar: denormales, ambos extremos del rango de exponente, empates exactos, ceros con signo, infinitos, y fracciones que redondean hacia el binado siguiente.
- Compara contra una referencia independiente. El método del repositorio es replicable con lo que ya tienes: aritmética exacta en Python 3.9 o superior contra el resultado del simulador, operación por operación. La propia auditoría validó su referencia contra la aritmética de la máquina en 99.135 operaciones de float32 y float64 en
round_nearest, sin una sola diferencia. - Fija la versión del simulador en tu pipeline. Como GHDL y NVC distribuyen el mismo cuerpo sin cambios, dos corridas en fechas distintas pueden estar usando bytes distintos. Un pin de versión explícito en CI es un seguro barato.
- Mira el costo de guarda. Con los ajustes por defecto (3 bits de guarda) el parche corrige 28.103 resultados sobre 258.075 llamadas; con un solo bit de guarda, 2.194 resultados no se redondean bien ni con el parche ni sin él. La configuración del paquete importa tanto como el paquete.
¿Cómo empezar a verificar hoy, sin comprar herramientas?
La barrera de entrada es baja: la auditoría usa GHDL o NVC y Python 3.9 o superior, más los tres archivos del directorio ieee del repositorio del IEEE o de lib/ghdl/src/ieee2008 de una instalación de GHDL. El caso mínimo de 25 llamadas es un archivo que se analiza y se corre con dos comandos.
- Levanta tu referencia exacta primero y valida la referencia contra la aritmética de tu propia máquina en
add,subtract,multiply,divideysqrtenround_nearest. Sin eso, no tienes contra qué comparar. - Genera vectores dirigidos a los puntos de quiebre, no vectores aleatorios: denormales, potencias de dos en los bordes del exponente, empates, ceros con signo e infinitos.
- Corre el mismo testbench contra el paquete que distribuye tu simulador y contra una versión compilada en una librería propia, como hace el script del repositorio. La comparación línea a línea es la única prueba que vale.
El script incluido permite empezar chico: con 100 vectores por operación, formato y estilo, el barrido completo tarda alrededor de medio minuto y reporta 3.696 errores y 8 paradas en 34.440 operaciones con el paquete tal como se distribuye, y cero con el corregido.
Conclusión
El caso va más allá de un repositorio: la auditoría fue enviada al grupo de trabajo IEEE P1076 el 13 de noviembre de 2026 como VHDL-Issues#388 y por correo, y reportada además en ghdl/ghdl#3486, nickg/nvc#1758 y FPHDL/fphdl#4. La versión VHDL-93 del paquete, float_pkg_c.vhdl en FPHDL/fphdl, lleva las mismas líneas, aunque no fue ejecutada en esta auditoría.
Para un founder, el mensaje es incómodo pero útil: la cadena de herramientas abierta de hardware es hoy lo bastante madura para que una sola persona encuentre, documente y parchee bugs de fondo en la aritmética que acompaña a un estándar IEEE desde hace más de una década. Eso también es una señal de oportunidad: la verificación automática de silicio y de IP sigue siendo un terreno donde la evidencia reproducible vale más que la marca del proveedor.
Las búsquedas realizadas para este artículo no arrojaron cobertura periodística adicional verificable sobre la auditoría; todas las cifras citadas provienen del repositorio original.
Fuentes
- Auditoría del paquete ieee.float_pkg (repositorio original) (fuente original)
¿Y esto cómo se aplica en tu negocio?
Dueños de negocio de Latinoamérica y España usan un agente de IA para ganar más y recuperar su tiempo. El Kit «tu mano derecha con IA» te muestra cómo en un video de 11 minutos, con una ficha para armar el tuyo. CAR está cerrada por ahora; al anotarte, te avisamos cuando abra.
👥 Quiero el Kit →













