# How to debug combinational loop warning in Xilinx ISE

I am designing a Binary to BCD converter logic circuit for implementation on Xilinx Spartan 6 FPGA's, and I have a warning during synthesis that looks like this :

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


I am trying to understand how this warning translates into my design, by trying to read the RTL Schematic, but I can't figure out a sane way to do it. There are just a lot of things I don't understand here :

• What does GND_1_o_shift_reg_next[11]_LessThan_9_o_mmx_out1 mean? Is there a naming convention or something (the input of some mux combined with the output of another mux or something like that)
• some components don't even show up on the schematic (like shift_reg_next : there are just a lot of multiplexers and adders that contain the name "shift_reg_next" in them, but no particular component named "shift_reg_next")

So, my question is :

• Is there some other way, other that looking at the schematic, that can help me solve this problem ?
• How can I understand (if I really am that crazy) how this warning translates into the schematic ?

EDIT : Here is my code for the binary to BCD converter

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

• Without seeing the original source (HDL or schematic), it's impossible to help you. Do you not recognize any of the signals in the list? It's possible that many of them are internally-generated names for intermediate signals created during synthesis, but there should be at least one that exists in the original source, such as start_conversion_mmx_out or shift_reg_next. If your original source is a schematic and it has many unnamed wires on it, you should try adding meaningful names to them and see if any of those names show up in this report. – Dave Tweed Mar 3 '16 at 20:49
• @DaveTweed see the edit. If you could implement the module and recreate the schematic to help me debug the design, it would be very helpful. – ironstein Mar 3 '16 at 20:54
• Please include the relevant part of your code in the question, so that, the question will be useful even if you remove the file from your Google Drive. As you already accepted the answer, it should be easy for you to make it a small, but still complete example. – Martin Zabel Mar 12 '16 at 18:15
• @MartinZabel that is actually good advice. I'll do it ASAP. – ironstein Mar 12 '16 at 18:20

## 1 Answer

In a combinatorial block (always @* begin ...), you can't have an assignment statement in which the same signal appears on both the left and right sides.

For example, you have several instances of:

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


That's a combinatorial loop. If the condition is true, it will just keep doing the addition over and over again as fast as it can. This is not synthesizable, and the tools complain about it.

You need to go through that block with a fine-tooth comb and make sure that the set of input signals (anything on the right side of any assignments) is completely distinct from the set of output signals (the left side of any assignments).