Reglas de diseño de FPGA - Uso de un valor de registro de salida de módulo interno

1

Estoy tratando de optimizar un código verilog y encontré algo que no creo que sea correcto. Encontré un módulo que tiene una salida y utiliza ese valor de salida como condición en una declaración de caso. Hay un ejemplo:

module TT
(   
    output  reg                             Busy        =   1'b0
,   output  reg                             Finished    =   1'b0

,   input   wire                            clk
,   input   wire                            rst
,   input   wire                            start
,   input   wire    [   5 - 1   :   0   ]   freq
);

always @ (posedge clk)
begin
    if(!rst)
    begin
        case(Busy)
            1'b0:
            begin
                //do some logic...
                if(something)
                    Busy = 1'b1;
            end

            1'b1:
            begin
                //do some logic...
                if(something_else)
                    Busy = 1'b0;
            end
        endcase
    end
end
endmodule

¿Es una buena práctica hacer esto? Si no, ¿por qué? Muchas gracias.

    
pregunta Rui Cunha

1 respuesta

4

Parece bien.

Tres sugerencias / recomendaciones:

  1. Use asignaciones no bloqueantes para registros

  2. Use un if-else en lugar del caso.

  3. Le falta la cláusula de restablecimiento: ¿cómo sabe qué valor tomar cuando se reinicia?

Entonces el código se convertiría en:

always @ (posedge clk) begin
    if (rst) begin
        Busy <= 1'b0; //Reset busy with the reset signal?
    end else begin
        if (!Busy && something) begin
            //When not busy and something happens
            Busy <= 1'b1;
        end

        if (Busy && something_else) begin
            //When busy and something else happens
            Busy <= 1'b0;
        end
    end
end

Vale la pena mencionar en lo anterior que está bien tener dos sentencias if independientes que controlan el mismo registro porque está bastante claro que nunca sucederán al mismo tiempo (una sucede en !Busy la otra en Busy , por lo que son mutuamente excluyentes).

También puede ver aquí que he usado declaraciones no bloqueantes. Este es el enfoque preferido para siempre bloques. Siempre que sea posible, intente utilizar el no bloqueo, utilizando las asignaciones de bloqueo solo en las funciones y tareas. Hay algunos lugares donde el bloqueo puede ser útil, pero la mayoría de las veces no hay razón para usarlos.

Si estuvieras haciendo más cosas, quizás te resulte más fácil tenerlo en un formato if-else , como:

if (!Busy) begin
   //Logic when not busy. E.g.
   if (something) begin
       Busy <= 1'b1;
   end
end else begin
   //Logic when busy. E.g.
   if (something_else) begin
       Busy <= 1'b0;
   end
end
    
respondido por el Tom Carpenter

Lea otras preguntas en las etiquetas