Cómo depurar la advertencia de bucle combinacional en Xilinx ISE

Estoy diseñando un circuito lógico convertidor de binario a BCD para su implementación en Xilinx Spartan 6 FPGA, y tengo una advertencia durante la síntesis que se ve así:

WARNING:Xst:2170 - Unit binary_to_bcd_converter : the following signal(s) form a combinatorial loop: 
start_conversion_mmx_out,
GND_1_o_shift_reg_next[11]_LessThan_9_o_mmx_out1,
GND_1_o_shift_reg_next[11]_LessThan_9_o, 
shift_reg_next<1>,
GND_1_o_shift_reg_next[19]_LessThan_12_o_mmx_out1, 
n0067<0>, 
n0067<9>, 
shift_reg_next<10>, 
n0065<9>, 
n0065<0>.

Estoy tratando de entender cómo se traduce esta advertencia en mi diseño, tratando de leer el esquema RTL, pero no puedo encontrar una forma sensata de hacerlo. Hay muchas cosas que no entiendo aquí:

  • ¿Qué significa GND_1_o_shift_reg_next[11]_LessThan_9_o_mmx_out1? ¿Existe una convención de nomenclatura o algo así (la entrada de algún mux combinada con la salida de otro mux o algo así)
  • algunos componentes ni siquiera aparecen en el esquema (como shift_reg_next: hay muchos multiplexores y sumadores que contienen el nombre "shift_reg_next", pero ningún componente en particular llamado "shift_reg_next")

Entonces, mi pregunta es:

  • ¿Hay alguna otra forma, además de mirar el esquema, que pueda ayudarme a resolver este problema?
  • ¿Cómo puedo entender (si realmente estoy tan loco) cómo se traduce esta advertencia en el esquema?

EDITAR: Aquí está mi código para el convertidor binario a BCD

module binary_to_bcd_converter(
// signals
input wire clk,
input wire reset,
input wire start_conversion,
output reg end_of_conversion,
// data
input wire [7:0] binary_data,
output reg [11:0] bcd_data
);

// state declarations 
localparam 
    idle = 1'b0,
    converting = 1'b1;

// signal declarations
reg state_reg, state_next;
reg [11:0] bcd_data_next;
reg [19:0] shift_reg,shift_reg_next;
reg [2:0] count,count_next;
reg end_of_conversion_next;

// state_updation_logic
always @(posedge(clk),posedge(reset)) begin
    if(reset) begin
        state_reg = idle;
        bcd_data = 12'b0;
        shift_reg = 20'b0;
        count = 4'b0;
        end_of_conversion = 1'b0;
    end else begin
        // the last activity should be the 
        // synchronous activity
        state_reg = state_next;
        bcd_data = bcd_data_next;
        shift_reg = shift_reg_next;
        count = count_next;
        end_of_conversion = end_of_conversion_next;
    end
end

always @* begin

    // in idle state
    if(state_reg == idle) begin
        // moore signals
        count_next <= 4'b0;
        bcd_data_next <= bcd_data;
        end_of_conversion_next <= 1'b0;

        // mealey signals
        if(start_conversion) begin
            state_next <= converting;
            shift_reg_next = {12'b0,binary_data};
        end else begin
            state_next <= idle;
            shift_reg_next = 20'b0;
        end

    // in converting state
    end else if(state_reg == converting) begin
        if(count == 7) begin
            count_next <= 4'b0;
            bcd_data_next <= shift_reg[19:8];
            state_next <= idle;
            end_of_conversion_next <= 1'b1;
            shift_reg_next = 20'b0;
        end else begin
            count_next <= count + 1;
            bcd_data_next <= bcd_data;
            state_next <= converting;
            end_of_conversion_next <= 1'b0;

            if(shift_reg[10:7] > 4'd4) begin
                if(shift_reg[14:11] > 4'd4) begin
                    if(shift_reg[18:15] > 4'd4) begin
                        shift_reg_next = {shift_reg[18:0],1'b0} + 20'b0011_0011_0011_0000_0000;
                    end else begin
                        shift_reg_next = {shift_reg[18:0],1'b0} + 10'b0000_0011_0011_0000_0000;
                    end
                end else begin
                    if(shift_reg[18:15] > 4'd4) begin
                        shift_reg_next = {shift_reg[18:0],1'b0} + 20'b0011_0000_0011_0000_0000;
                    end else begin
                        shift_reg_next = {shift_reg[18:0],1'b0} + 10'b0000_0000_0011_0000_0000;
                    end
                end else begin
                    if(shift_reg[14:11] > 4'd4) begin
                        if(shift_reg[18:15] > 4'd4) begin
                            shift_reg_next = {shift_reg[18:0],1'b0} + 20'b0011_0011_0000_0000_0000;
                        end else begin
                            shift_reg_next = {shift_reg[18:0],1'b0} + 10'b0000_0011_0000_0000_0000;
                        end
                    end else begin
                        if(shift_reg[18:15] > 4'd4) begin
                            shift_reg_next = {shift_reg[18:0],1'b0} + 20'b0011_0000_0000_0000_0000;
                        end else begin
                            shift_reg_next = {shift_reg[18:0],1'b0} + 10'b0000_0000_0000_0000_0000;
                        end
                    end
                end
            end
        end
    end else begin
        count_next <= count;
        bcd_data_next <= bcd_data;
        end_of_conversion_next <= end_of_conversion;
        count_next <= count;
        shift_reg_next = shift_reg;
    end
end

endmodule
Sin ver la fuente original (HDL o esquema), es imposible ayudarte. ¿ No reconoces ninguna de las señales de la lista? Es posible que muchos de ellos sean nombres generados internamente para señales intermedias creadas durante la síntesis, pero debería haber al menos uno que exista en la fuente original, como start_conversion_mmx_outo shift_reg_next. Si su fuente original es un esquema y tiene muchos cables sin nombre, debe intentar agregarles nombres significativos y ver si alguno de esos nombres aparece en este informe.
@DaveTweed mira la edición. Si pudiera implementar el módulo y recrear el esquema para ayudarme a depurar el diseño, sería muy útil.
Incluya la parte relevante de su código en la pregunta, de modo que la pregunta sea útil incluso si elimina el archivo de su Google Drive. Como ya aceptó la respuesta, debería ser fácil para usted convertirlo en un ejemplo pequeño pero completo.
@MartinZabel ese es realmente un buen consejo. Lo haré lo antes posible.

Respuestas (1)

En un bloque combinatorio ( always @* begin ...), no puede tener una declaración de asignación en la que aparezca la misma señal en los lados izquierdo y derecho.

Por ejemplo, tiene varias instancias de:

if (/* some condition */) begin
  shift_reg_next = shift_reg_next + 20'b0000_0000_0011_00000000;
end

Eso es un bucle combinatorio. Si la condición es verdadera, seguirá sumando una y otra vez tan rápido como pueda. Esto no es sintetizable, y las herramientas se quejan de ello.

Debe revisar ese bloque con un peine de dientes finos y asegurarse de que el conjunto de señales de entrada (cualquier cosa en el lado derecho de cualquier asignación) sea completamente distinto del conjunto de señales de salida (el lado izquierdo de cualquier asignación).