So debuggen Sie die kombinatorische Schleifenwarnung in Xilinx ISE

Ich entwerfe eine Binär-zu-BCD-Konverter-Logikschaltung zur Implementierung auf Xilinx Spartan 6 FPGAs, und ich habe während der Synthese eine Warnung, die so aussieht:

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>.

Ich versuche zu verstehen, wie sich diese Warnung in mein Design übersetzt, indem ich versuche, das RTL-Schema zu lesen, aber ich kann keinen vernünftigen Weg finden, dies zu tun. Hier verstehe ich einfach einiges nicht:

  • Was bedeutet GND_1_o_shift_reg_next[11]_LessThan_9_o_mmx_out1? Gibt es eine Namenskonvention oder so etwas (die Eingabe eines Mux kombiniert mit der Ausgabe eines anderen Mux oder so ähnlich)
  • Einige Komponenten werden nicht einmal im Schaltplan angezeigt (wie shift_reg_next : Es gibt nur viele Multiplexer und Addierer, die den Namen "shift_reg_next" enthalten, aber keine bestimmte Komponente namens "shift_reg_next")

Also meine Frage ist:

  • Gibt es eine andere Möglichkeit als das Betrachten des Schaltplans, die mir helfen kann, dieses Problem zu lösen?
  • Wie kann ich verstehen (wenn ich wirklich so verrückt bin), wie diese Warnung in den Schaltplan übersetzt wird?

EDIT: Hier ist mein Code für den Binär-zu-BCD-Konverter

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
Ohne die Originalquelle (HDL oder Schaltplan) zu sehen, ist es unmöglich, Ihnen zu helfen. Erkennen Sie keines der Signale in der Liste? Es ist möglich, dass viele von ihnen intern generierte Namen für Zwischensignale sind, die während der Synthese erstellt wurden, aber es sollte mindestens einen geben, der in der Originalquelle vorhanden ist, z. B. start_conversion_mmx_outoder shift_reg_next. Wenn Ihre ursprüngliche Quelle ein Schaltplan ist und viele unbenannte Drähte enthält, sollten Sie versuchen, ihnen aussagekräftige Namen hinzuzufügen, und prüfen, ob einer dieser Namen in diesem Bericht auftaucht.
@DaveTweed siehe die Bearbeitung. Wenn Sie das Modul implementieren und den Schaltplan neu erstellen könnten, um mir beim Debuggen des Designs zu helfen, wäre dies sehr hilfreich.
Bitte fügen Sie den relevanten Teil Ihres Codes in die Frage ein, damit die Frage auch dann nützlich ist, wenn Sie die Datei aus Ihrem Google Drive entfernen. Da Sie die Antwort bereits akzeptiert haben, sollte es Ihnen leicht fallen, daraus ein kleines, aber dennoch vollständiges Beispiel zu machen.
@MartinZabel, das ist eigentlich ein guter Rat. Ich werde es so schnell wie möglich tun.

Antworten (1)

In einem kombinatorischen Block ( always @* begin ...) können Sie keine Zuweisungsanweisung haben, in der das gleiche Signal auf der linken und rechten Seite erscheint.

Sie haben beispielsweise mehrere Instanzen von:

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

Das ist eine kombinatorische Schleife. Wenn die Bedingung wahr ist, wird die Addition so schnell wie möglich immer und immer wieder ausgeführt. Dies ist nicht synthetisierbar, und die Tools beschweren sich darüber.

Sie müssen diesen Block mit einem feinen Kamm durchgehen und sicherstellen, dass sich der Satz von Eingangssignalen (alles auf der rechten Seite von Zuweisungen) vollständig von dem Satz von Ausgangssignalen (auf der linken Seite von Zuweisungen) unterscheidet.