convención de código HDL para reinicios de registro

0

Cuando se trata de restablecer (de forma síncrona) los registros en HDL (usaré Verilog), ¿se considera una mala práctica codificar el reinicio de manera combinatoria? Por lo que puedo decir, los siguientes dos fragmentos son funcionalmente equivalentes.

Comportamiento:

always @ (posedge clk) begin
    if (rst) current_val <= 1'b0;
    else     current_val <= din;
end

Estructural:

assign next_val = (rst == 1'b0) ? din : 1'b0;
always @ (posedge clk) begin
    current_val <= next_val;
end

Aprendí a escribir la lógica de manera conductual, y solo recientemente encontré la segunda. En términos de convenciones / mejores prácticas de HDL, ¿es una preferible a la otra? Además, ¿se asignarán a un hardware diferente?

    
pregunta Ben Granger

3 respuestas

1

No hay garantía de que la lógica en el ejemplo "Estructural" sea reconocida por las herramientas de síntesis estándar. Es totalmente posible que no obtenga un registro con reinicio síncrono. Para comprender por qué es necesario, debemos considerar exactamente cómo se traduce el código a la tecnología del dispositivo que se está utilizando.

A continuación se muestra un diagrama de la mitad de un módulo lógico adaptable Cyclone V de Intel FPGA (imagen protegida por derechos de autor de Intel FPGA).

Enlapartesuperiordelaimagensepuedenverunaseriedeseñalesllamadassyncload,sclryaclr.Estassonlasseñalesdecontrolparalosregistrosenelbloque.Otrasfamiliasdedispositivostendrándiferentesseñalesdedicadas.Elcódigoescritocorrectamenteinferiráelusodeestasseñalesdecontroldedicadas.Silasseñalesdecontroldedicadodeseadasnoestándisponibles,osededucenincorrectamente,entoncesseutilizaránlasentradasalasLUT.Enelmejordeloscasos,estodesperdiciarárecursos,enelpeordeloscasos,estopodríahacerquelafuncionalidadsedividaenvariosALMyocasionefallaseneltiempo.Notenemoscontroldirectosobreesto,sololacapacidaddeinferiratravésdeHDL.Puedeencontrarunabuenalecturadeestoeneldocumentotécnicoaquí: enlace

Además, la inspección de su código muestra que no es funcionalmente equivalente al ejemplo "Conductual". Next_val se está actualizando de forma asíncrona a Current_val, que tiene todo tipo de implicaciones para el enrutamiento, el tiempo y la metaestabilidad. Sin embargo, en la simulación no verías nada de eso y ambos conjuntos de código serían superficialmente idénticos.

La convención de HDL es utilizar patrones reconocidos para construcciones de bajo nivel como esto para garantizar que las herramientas de síntesis las reconocerán. Estos son proporcionados por los diseñadores de herramientas de síntesis. Un ejemplo de la Guía del usuario Quartus Prime de Intel FPGA: Recomendaciones de diseño ( enlace ):

always @ (posedge clock)
begin
  if (!rst_n)
  begin
    reg1 <= 1’bo;
    reg2 <= 1’b0;
  end
  else
  begin
    reg1 <= data_a;
    reg2 <= data_b;
  end
end

Además, el principio general de legibilidad en el código sugeriría que su ejemplo "estructural" no debe ser favorecido.

    
respondido por el Vance
4

No hará ninguna diferencia en el hardware sintetizado. Pero escribir en un HDL, o más precisamente, escribir en la abstracción del nivel de transferencia de registro (RTL) debería alejarlo del nivel estructural. Sin duda, será más eficiente simular y que otros entiendan su código cuando escriba en un estilo mucho más simple.

    
respondido por el dave_59
1

Ambos de estos son RTL, son funcionalmente equivalentes y es probable que produzcan el mismo HW si todas las demás cosas permanecen iguales entre las dos configuraciones de síntesis.

Normalmente, "Comportamiento" se refiere a construcciones "no sintetizables", y "estructural" se refiere al uso de primitivas (por ejemplo, netlist o netlist-like). "RTL" son construcciones sintetizables de alto nivel, como ha escrito (suponiendo que el resto del archivo se ajuste a esas definiciones).

Tu primer ejemplo es más típico, al menos en términos de reinicio. Sin embargo, es posible que tenga lógica (aparte de restablecer) que los fans ingresen a más de un registro u otro (s) término (s) combinatorio (s) y, por lo tanto, lo obligue a crear ese término intermedio. Aparte de eso, depende completamente de usted y su estilo ... y, si es solo una cuestión de estilo, le recomendaría que emplee el método KISS, haciendo que sea fácil de seguir y entender, como en su primer ejemplo. .

Si desea (intentar y) "forzar" el sintetizador para que implemente algo específico, puede intentar escribir código estructural. Sin embargo, el código estructural no es portátil, se cambia con menos facilidad y, por lo general, no es necesario. Las herramientas son realmente buenas en PAR, por lo que si sientes la necesidad de crear instancias primitivas, fuera de tus relojes y reinicios (búferes, DCM, etc.), memorias (quizás) e IO (nuevamente, tal vez), probablemente quieras reevalúe su selección de piezas y / o diseño.

Sin embargo, es una buena pregunta que hiciste. Debes ver las guerras religiosas relacionadas con las máquinas de estado de 1, 2 y 3 procesos. Personalmente, utilizo máquinas de estado de 3 procesos (estado combinatorio siguiente, salidas combinatorias, actualizaciones síncronas) ... es un enfoque retenido desde hace mucho tiempo con respecto a la interpretación de las herramientas de síntesis, que no es un problema en estos días. Aquí hay una buena discusión al respecto enlace

    
respondido por el CapnJJ

Lea otras preguntas en las etiquetas