Search code examples
veriloghdlvivadosoc

Vivado verilog 1 LUT cells form a combinatorial loop


I'm facing around 100 errors related to combinatorial loops when bitstreaming. The signals causing these errors are addr_121f, addr_store_1_f, and addr_store_2_f. I'm having difficulty understanding why my code is resulting in these combinatorial loop errors.

code description: The addr_store_1_f stores the value of addr_121f when jump_1 is triggered, and jump_1 depends on addr_store_1_f and other values. Similarly, addr_store_2_f and addr_122f serve the same purpose, but there's no error associated with `addr_122f.".

//simplify the assignment code below:
//assign jump_1= (some signals)?(addr_121s == addr_store_1_f + some value)
//assign jump_2= (some signals)?(addr_122s == addr_store_2_f + some value)
assign input_last_addr_1 = addr_store_1_f + addr_temp_cal_2;
assign input_last_addr_2 = addr_store_2_f + addr_temp_cal_2;                                                                   
assign last_addr_1 = (ram_cs == READ_FROM_S) ? addr_store_1_s + addr_temp_cal_1 : (ram_cs == READ_FROM_F) ? addr_store_1_f + addr_temp_cal_1 : input_last_addr_1;
assign last_addr_2 = (ram_cs == READ_FROM_S) ? addr_store_2_s + addr_temp_cal_1 : (ram_cs == READ_FROM_F) ? addr_store_2_f + addr_temp_cal_1 : input_last_addr_2;
assign jump_1= (conv_start) ? (ram_1_w_sd)? (ram_cs == READ_FROM_S) ? (addr_121s == last_addr_1):(addr_121f == last_addr_1) : 0 : 0;
assign jump_2= (conv_start) ? (ram_2_w_sd)? (ram_cs == READ_FROM_S) ? (addr_122s == last_addr_2):(addr_122f == last_addr_2) : 0 : 0;
assign addr_f_r_stop =  !(cs==FIRST_ROW_SD && ram_1_w_sd && ram_cs == READ_FROM_SD);
/////////////////////////////////////////////////////////////////////////
always@(posedge clk)begin//conv_b reading input from ram1
    if( ram_cs==CLEAR_STATE || ram_cs==SD_TO_F || ram_cs==F_TO_F || ram_cs==F_TO_S || ram_cs == TO_OUT)begin//change 1 is one clk before READ_FROM_F 
        addr_1f_r <= 1;
        addr_2f_r <= 0;
        addr_store_1_f <= 0;
        addr_store_2_f <= 0;
    end
    else if(ram_cs!= READ_FROM_S  )begin //input valid high indicates that the conv_cell will take value and the input is valid to store
        if( addr_f_r_stop && conv_start && input_valid)begin
                    if(ram_1_jump)
                    addr_2f_r <= addr_2f_r + 1;
                    if(ram_2_jump)
                    addr_1f_r <= addr_1f_r + 1;
        end
        if(jump_1)begin
            addr_store_1_f <= addr_121f +1;
        end
        if(jump_2)begin
            addr_store_2_f <= addr_122f +1;
        end
        
        
    end
end
////////////////////////////////////////////////
assign addr_121f = (conv_start) ? ( wen_121f ) ? addr_121f_w : (input_valid) ?  addr_1f_r : addr_121f : 0;
////////////////////////////////////////////////////

error message example: ERROR: [DRC LUTLP-1] Combinatorial Loop Alert: 1 LUT cells form a combinatorial loop. This can create a race condition. Timing analysis may not be accurate. The preferred resolution is to modify the design to remove combinatorial logic loops. If the loop is known and understood, this DRC can be bypassed by acknowledging the condition and setting the following XDC constraint on any one of the nets in the loop: 'set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets <myHier/myNet>]'. One net in the loop is design_1_i/e_top_0/inst/conv_top_1/addr_store_2_f[28]_i_9_n_0. Please evaluate your design. The cells in the loop are: design_1_i/e_top_0/inst/conv_top_1/addr_store_2_f[28]_i_9.


Solution

  • Thanks to sharvian, the issue here is that you cannot assign a net to itself. For instance, if you try something like assign a = (input_valid) ? b : a;, it will result in an error "Combinatorial Loop Alert: 1 LUT cells form a combinatorial loop".