Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Could someone help me find where the combinatorial loop is in my code?

Status
Not open for further replies.

hobbskw

Junior Member level 3
Joined
Oct 19, 2021
Messages
25
Helped
1
Reputation
2
Reaction score
1
Trophy points
3
Activity points
197
Greetings,
I am trying to generate a bitstream, but it is telling me there is a combinatorial loop occurring with pwm1N, pwm2N, and pwm3N. It does not say where/how/why this happens in the code, so I am at a loss for how to fix this. Is there someone who could help me identify where/how it is happening? I would greatly appreciate your help! I think this happened after adding the "if-else" statements at the beginning of the "posedge clk" statement, though I am not certain whether that is the cause.

1650034703657.png


Code:
`timescale 1ns / 1ps

module sine_LUT(
        input clk,
        input rst_n,
        output pwm1P,
        output pwm2P,
        output pwm3P,
        output pwm1N,
        output pwm2N,
        output pwm3N
    );

// initialize the lookup table
reg [12:0] sineLUT[0:49];
integer addr=0;
// res = number of eleents in the lookup table
localparam res = 49;
always @* begin
    case (addr)
        0: sineLUT[0] = 1407;
        1: sineLUT[1] = 1561;
        2: sineLUT[2] = 1710;
        3: sineLUT[3] = 1852;
        4: sineLUT[4] = 1985;
        5: sineLUT[5] = 2106;
        6: sineLUT[6] = 2213;
        7: sineLUT[7] = 2305;
        8: sineLUT[8] = 2381;
        9: sineLUT[9] = 2439;
        10: sineLUT[10] = 2478;
        11: sineLUT[11] = 2498;
        12: sineLUT[12] = 2498;
        13: sineLUT[13] = 2478;
        14: sineLUT[14] = 2439;
        15: sineLUT[15] = 2381;
        16: sineLUT[16] = 2305;
        17: sineLUT[17] = 2213;
        18: sineLUT[18] = 2106;
        19: sineLUT[19] = 1985;
        20: sineLUT[20] = 1852;
        21: sineLUT[21] = 1710;
        22: sineLUT[22] = 1561;
        23: sineLUT[23] = 1407;
        24: sineLUT[24] = 1250;
        25: sineLUT[25] = 1093;
        26: sineLUT[26] = 939;
        27: sineLUT[27] = 790;
        28: sineLUT[28] = 648;
        29: sineLUT[29] = 515;
        30: sineLUT[30] = 394;
        31: sineLUT[31] = 287;
        32: sineLUT[32] = 195;
        33: sineLUT[33] = 119;
        34: sineLUT[34] = 61;
        35: sineLUT[35] = 22;
        36: sineLUT[36] = 2;
        37: sineLUT[37] = 2;
        38: sineLUT[38] = 22;
        39: sineLUT[39] = 61;
        40: sineLUT[40] = 119;
        41: sineLUT[41] = 195;
        42: sineLUT[42] = 287;
        43: sineLUT[43] = 394;
        44: sineLUT[44] = 515;
        45: sineLUT[45] = 648;
        46: sineLUT[46] = 790;
        47: sineLUT[47] = 939;
        48: sineLUT[48] = 1093;
        49: sineLUT[49] = 1250;
    endcase;
end

// when active == 0, the SPWM signals will all be set to 0. This is for implementing safety features (UNFINISHED)
integer active = 1;

// these are used to detect the negative edges of he PWM signals, in order to trigger the deadtime timers
integer T1P = 0;
integer T1N = 0;
integer T2P = 0;
integer T2N = 0;
integer T3P = 0;
integer T3N = 0;

// the Side variable ensures the top and bottom mosfets take turns. One can not turn on twice in a row (UNFINISHED)
integer Side1 = 1;
integer Side2 = 1;
integer Side3 = 1;

// the magnitude of triangle and sinewave is from 0 to 2*D, with the midpoints being equal to D
localparam  D = 1250;
integer triangle = D;
integer sinewave = D;

// updown tells what direction the triangle wave counter should be going
integer updown = 1;

// sineCount1 and 2 are counters/timers for the sinewave. There are two: sineCount2 increements when sineCount1 reaches its limit
integer sineCount1 = 0;
integer sineCount2 = 0;

// each sinewave is shifted up by D. Addr1, 2, and 3 effectively phase shift the sinewaves
integer sinewave1 = D;
integer sinewave2 = D;
integer sinewave3 = D;
integer addr1 = 32;
integer addr2 = 16;
integer addr3 = 0;

// each mosfets has their own deadtime timer, which count down from 100
integer deadtime = 100;
integer deadtimer1P = 0;
integer deadtimer1N = 0;
integer deadtimer2P = 0;
integer deadtimer2N = 0;
integer deadtimer3P = 0;
integer deadtimer3N = 0;

always@(posedge clk) begin
    if(sineCount1 == 100)
    begin // increment sineCount2
        sineCount1 = 0;
        sineCount2 = sineCount2 + 1;
    end
    sineCount1 = sineCount1 + 1;
    if(sineCount2 == 333)
    begin // increment addr values
        sineCount2 = 0;
        if (addr == res)
        begin
            addr = 0;
        end
        else begin
            addr = addr + 1;
        end
        if (addr1 == res)
        begin
            addr1 = 0;
        end
        else begin
            addr1 = addr1 + 1;
        end
        if (addr2 == res)
        begin
            addr2 = 0;
        end
        else begin
            addr2 = addr2 + 1;
        end
        if (addr3 == res)
        begin
            addr3 = 0;
        end
        else begin
            addr3 = addr3 + 1;
        end
    end

    // deadtime timer triggers / negative edge detection
    if ((pwm1P == 0) && (T1P == 0))
    begin
        T1P = 1;
        deadtimer1N = deadtime;
    end
    if ((pwm1N == 0) && (T1N == 0))
    begin
        T1N = 1;
        deadtimer1P = deadtime;
    end
    if ((pwm2P == 0) && (T2P == 0))
    begin
        T2P = 1;
        deadtimer2N = deadtime;
    end
    if ((pwm2N == 0) && (T2N == 0))
    begin
        T2N = 1;
        deadtimer2P = deadtime;
    end
    if ((pwm3P == 0) && (T3P == 0))
    begin
        T3P = 1;
        deadtimer3N = deadtime;
    end
    if ((pwm3N == 0) && (T3N == 0))
    begin
        T3N = 1;
        deadtimer3P = deadtime;
    end
    
    // when a PWM signal == 1, its T variable = 0, which allows the above if-statement to trigger when PWM signal == 0 (edge detection)
    if (pwm1P == 1)
    begin
        T1P = 0;
    end
    if (pwm1N == 1)
    begin
        T1N = 0;
    end
    if (pwm2P == 1)
    begin
        T2P = 0;
    end
    if (pwm2N == 1)
    begin
        T2N = 0;
    end
    if (pwm3P == 1)
    begin
        T3P = 0;
    end
    if (pwm3N == 1)
    begin
        T3N = 0;
    end
    
    // decrement the deadtime timers if they are not == 0
    if (deadtimer1P != 0)
    begin
        deadtimer1P <= deadtimer1P - 1;
    end
    if (deadtimer2P != 0)
    begin
        deadtimer2P <= deadtimer2P - 1;
    end
    if (deadtimer3P != 0)
    begin
        deadtimer3P <= deadtimer3P - 1;
    end
    if (deadtimer1N != 0)
    begin
        deadtimer1N <= deadtimer1N - 1;
    end
    if (deadtimer2N != 0)
    begin
        deadtimer2N <= deadtimer2N - 1;
    end
    if (deadtimer3N != 0)
    begin
        deadtimer3N <= deadtimer3N - 1;
    end
    
    // update the values of the sinewaves from the lookup table
    sinewave = sineLUT[addr];
    sinewave1 = sineLUT[addr1];
    sinewave2 = sineLUT[addr2];
    sinewave3 = sineLUT[addr3];
    
    // generation of the triangle wave
    if (triangle == 2*D)
        begin
            updown <= -1;
        end
    if (triangle == 1)
        begin
            updown <= 1;
        end
    triangle <= triangle + updown;
    
end

// generation of PWM signals, as well as interlocks
assign pwm1P = ((deadtimer1P == 0)&&(sinewave1 > triangle)&&(pwm1N==0))?1:0;
assign pwm2P = ((deadtimer2P == 0)&&(sinewave2 > triangle)&&(pwm2N==0))?1:0;
assign pwm3P = ((deadtimer3P == 0)&&(sinewave3 > triangle)&&(pwm3N==0))?1:0;
assign pwm1N = ((deadtimer1N == 0)&&(sinewave1 < triangle)&&(pwm1P==0))?1:0;
assign pwm2N = ((deadtimer2N == 0)&&(sinewave2 < triangle)&&(pwm2P==0))?1:0;
assign pwm3N = ((deadtimer3N == 0)&&(sinewave3 < triangle)&&(pwm3P==0))?1:0;
endmodule
 

It tells you, right there in the error message, where your combinational loops are, e.g.

"The cells in the loop are: design_1_i/sine_LUT_0/inst/pwm1N_INST_0."

Click on that link and it will probably tell you even more.
 

It tells you, right there in the error message, where your combinational loops are, e.g.

"The cells in the loop are: design_1_i/sine_LUT_0/inst/pwm1N_INST_0."

Click on that link and it will probably tell you even more.
Clicking the link opens this view:
1650036305452.png

I can click "view schematic" to see the loop itself, but I am not sure where this happens in the Verilog.
1650036701651.png
 

The problem is right here in the pair of assignments.

assign pwm1P = ((deadtimer1P == 0)&&(sinewave1 > triangle)&&(pwm1N==0))?1:0;
assign pwm1N = ((deadtimer1N == 0)&&(sinewave1 < triangle)&&(pwm1P==0))?1:0;

There is feedback loop as the two signals are based on each other.
 
The problem is right here in the pair of assignments.

assign pwm1P = ((deadtimer1P == 0)&&(sinewave1 > triangle)&&(pwm1N==0))?1:0;
assign pwm1N = ((deadtimer1N == 0)&&(sinewave1 < triangle)&&(pwm1P==0))?1:0;

There is feedback loop as the two signals are based on each other.
Thank you so much! That was the issue!
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top