1
\$\begingroup\$

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
\$\endgroup\$
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Dave Tweed Mar 3 '16 at 20:49
  • \$\begingroup\$ @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. \$\endgroup\$ – ironstein Mar 3 '16 at 20:54
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Martin Zabel Mar 12 '16 at 18:15
  • \$\begingroup\$ @MartinZabel that is actually good advice. I'll do it ASAP. \$\endgroup\$ – ironstein Mar 12 '16 at 18:20
4
\$\begingroup\$

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

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.