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

1

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

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 esta advertencia se traduce en mi diseño, al 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? ¿Hay una convención de nomenclatura o algo (la entrada de algunos mux combinada con la salida de otro mux o algo así)
  • algunos componentes ni siquiera aparecen en el esquema (como shift_reg_next: solo hay muchos multiplexores y sumadores que contienen el nombre "shift_reg_next" en ellos, pero no hay ningún componente en particular llamado "shift_reg_next")

Entonces, mi pregunta es:

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

EDITAR: Aquí está mi código para el convertidor de 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
    
pregunta ironstein

1 respuesta

4

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, tienes 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, simplemente seguirá haciendo la adición una y otra vez tan rápido como sea posible. Esto no es sintetizable, y las herramientas se quejan de ello.

Debe pasar por 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 tareas).

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas