Comportamiento extraño en la union de bits

Diseño HDL con este lenguaje. Módulos y testbenchs. Estilos y trucos de codificación, etc. NOTA: dado que hay entornos como ISE que soportan Verilog pero no SystemVerilog, señalad dentro de un post que de lo que se va a tratar es SystemVerilog si es el caso.
Responder
Avatar de Usuario
spark2k06
PLA
Mensajes: 49
Registrado: 17 Ago 2018, 18:43

Comportamiento extraño en la union de bits

Mensaje por spark2k06 » 07 Dic 2021, 12:22

Hola,

He observado un comportamiento extraño con la unión de bits, no se si se trata de un error del sintetizador de Xilinx pero me gustaría entender exactamente por qué se produce, a ver si alguien tiene alguna idea. Partimos de este código:

Código: Seleccionar todo


module cga_pixel(
...
    input thin_font,
...
);

reg[7:0] char_rom[0:4095];
reg[7:0] charbits;

initial $readmemh("cga.hex", char_rom, 0, 4095);

    always @ (posedge clk)
    begin
        // Only load character bits at this point
        if (...) begin				
            charbits <= char_rom[{~thin_font,rom_addr}]; // El bit alto (thin_font invertido) se aplica o no dependiendo del resto de código. ¿problema del sintetizador de Xilinx?
        end
    end

El carácter charbits se obtiene a partir de buffer char_rom, desplazándonos 800h en caso de que thin_font invertido sea 1. Pues bien, tal y como indico en el comentario, esto no siempre se aplica. Y es que inicialmente me funcionaba, pero haciendo limpieza de código en otros módulos de repente dejó de funcionar, no aplicando el desplazamiento en ningún caso... como ignorando ese bit alto.

Es extraño, porque por ejemplo esto lo soluciona:

Código: Seleccionar todo


reg[7:0] char_rom[0:4096]; // 4096 en lugar de 4095 lo soluciona, pero no explica el problema, al igual que teniendo otro código en otros módulos que nada tiene que ver con este buffer.

La solución que más sentido tiene para mi es hacer lo mismo pero de diferente manera, para saltarme este extraño comportamiento:

Código: Seleccionar todo


charbits <= char_rom[{~thin_font, 11'd0} | rom_addr]; // Fix correcto, pero habría que entender por qué hay que llegar a este punto para hacer lo mismo, ya que puede provocar otros comportamientos extraños en el core y habría que saber exactamente por qué se produce para aplicar la solución correcta en cada caso.

Dicho lo cuál, ¿alguien entiende qué puede estar sucediendo y cuál es el problema realmente?

Avatar de Usuario
yombo
Veroboard
Mensajes: 18
Registrado: 17 Ago 2018, 10:51

Re: Comportamiento extraño en la union de bits

Mensaje por yombo » 07 Dic 2021, 12:30

Y es que inicialmente me funcionaba, pero haciendo limpieza de código en otros módulos de repente dejó de funcionar
Sé lo que está ocurriendo. Probablemente la utilización de la fpga ya es muy alta. El compilador de Xilinx usa los nombres de variables como hash para tomar decisiones durante el sintetizado. Si la utilización es muy alta, estas decisiones pueden implicar que ya no se cumplan los tiempos de propagación de las señales, por el simple hecho de refactorizar un poco el código para hacerlo más legible.
ERROR:NgdBuild:455 - logical net 'yombo' has multiple driver(s):
ERROR:NgdBuild:924 - input pad net 'yombo' is driving non-buffer primitives:

Avatar de Usuario
spark2k06
PLA
Mensajes: 49
Registrado: 17 Ago 2018, 18:43

Re: Comportamiento extraño en la union de bits

Mensaje por spark2k06 » 08 Dic 2021, 08:12

yombo escribió:
07 Dic 2021, 12:30

Sé lo que está ocurriendo. Probablemente la utilización de la fpga ya es muy alta. El compilador de Xilinx usa los nombres de variables como hash para tomar decisiones durante el sintetizado. Si la utilización es muy alta, estas decisiones pueden implicar que ya no se cumplan los tiempos de propagación de las señales, por el simple hecho de refactorizar un poco el código para hacerlo más legible.
Tras las últimas optimizaciones que llevé a cabo a partir de los fuentes originales de @distwave, tampoco me parece a mí que ahora mismo se encuentre muy al límite de recursos:

Imagen

Sin embargo, sí que se puede apreciar lo que comentas acerca del uso de los nombres de variables como hash. Y a partir de ello, se puede entender lo que sucede, aunque no el por qué... que posiblemente sea debido a un bug del sintetizador ISE de Xilinx:

Imagen

Esto es parte del reporte de síntesis, que tal como me ha sugerido @mcleod_ideafix, es un buen recurso para entender cómo se ha llevado a cabo la sintetización. Aquí podemos observar que la memoria generada es del tamaño que se le ha indicado durante su declaración:

Código: Seleccionar todo

// Character ROM
reg[7:0] char_rom[0:4095];
initial $readmemh("cga.hex", char_rom, 0, 4095);
Y también podemos ver cómo addrA está correctamente direccionada a partir del código original:

Código: Seleccionar todo

    always @ (posedge clk)
    begin
        // Only load character bits at this point
        if (...) begin				
            charbits <= char_rom[{~thin_font,rom_addr}]; // El bit alto (thin_font invertido) se aplica o no dependiendo del resto de código. ¿problema del sintetizador de Xilinx?
        end
    end
donde se encuentra la etiqueta thin_font que menciona @yombo. Pero una vez que se ha llevado a cabo la limpieza de código innecesario, con el mismo código nos encontramos con la siguiente síntesis de char_rom:

Imagen

Es decir, se ha creado una memoria de la 2KB en lugar de 4KB, y la referencia a thin_font simplemente ha desaparecido del direccionamiento como bit alto. A partir de aquí, de nada sirve fijar este bit con 1'b1 por ejemplo, o reestructurar el código de múltiples maneras para hacérselo más sencillo al sintetizador, tal como me ha sugerido @mcleod_ideafix vía Telegram en el grupo de ZXUno. Hasta el momento, las únicas soluciones que me han funcionado son las comentadas inicialmente:

Código: Seleccionar todo


// 1. Declarando char_rom como un solo byte más de tamaño

reg[7:0] char_rom[0:4096];
o:

Código: Seleccionar todo


// 2. Accediendo a la memoria de esta otra forma:

charbits <= char_rom[{~thin_font, 11'd0} | rom_addr];
En ambos casos, obtenemos la generación de una memoria de 4KB correctamente, y con addrA direccionado de la misma forma adecuada, ya que thin_font en este caso está fijo a 0, y tras la negación es 1... esta vez sin el uso de etiquetas, pero con un mismo resultado satisfactorio:

Imagen

Todo esto me lleva a la conclusión de que es de vital importancia revisar los mensajes generados y ver si son coherentes con el resultado que se espera, no deberíamos tener que preocuparnos por estas cosas, pero los bugs que por lo visto hay en el sintetizador ISE de Xilinx nos obligan a ello.

Responder

Volver a “Verilog / SystemVerilog”