Search code examples
verilogquartus

Combinational loop in a program


There is a error in the program and I'm sure it's caused by negedge iChang in the always block. The error is:

Zero-time oscillation in node....... Check the design or vector source file for combinational loop.

My partial program is as follow:

input  clk, rst,iChang;
always@(posedge clk or negedge rst or negedge iChang)
    begin 
        if(!iChang)//auto mode,serious problems!!!!!!!!!!!!!!!!!!
            begin
                if(!rst)
                    begin
                        s1<=state1;
                        A<=3'b0;
                        B<=3'b0;
                        count1<=3'd4;
                        count2<=3'd2;
                        count3<=3'd3;
                        count4<=3'd2;
                        temp<=1'b1;
                    end
                else
                    begin
                        if(temp==1)
                            begin
                                temp<=1'b0;
                                case(s1)
                                    state1:
                                        begin
                                            times<=count1;
                                            A<=3'b001;
                                            B<=3'b100;
                                            s1<=state2;
                                        end
                                    state2:
                                        begin
                                            times<=count2;
                                            A<=3'b010;
                                            B<=3'b100;
                                            s1<=state3;             
                                        end
                                    state3:
                                        begin
                                            times<=count3;
                                            A<=3'b100;
                                            B<=3'b001;
                                            s1<=state4;

                                        end
                                    state4:
                                        begin
                                            times<=count4;
                                            A<=3'b100;
                                            B<=3'b010;
                                            s1<=state1;
                                        end
                                    default:
                                        begin
                                            A<=3'b000;
                                            B<=3'b000;
                                        end
                                    endcase
                            end     

If I remove negedge iChang in the always block and the if(!iChang) block ,there will be no error. I don't understand the relation between the negedge iChang and the combination loop. It seemed that there is no feedback can cause combination loop.


Solution

  • Edge-triggered always blocks are used for synchronous logic. It should have a clock reference and it may have one asynchronous reset and may have one asynchronous set. Based on your code, it looks like iChang should be sampled on posedge clk, so it should not be in the sensitivity list. I believe you are confusing sensitivity list requirements of synchronous always blocks with the IEEE1364-1995 style of combinational always blocks. IEEE1364-1995 style combinational always blocks require all inputs signals to be listed in the sensitivity list. (Recommend useing IEEE1364-2001's auto-sensitivity list (@*/@(*)) for combinational always blocks)

    Assuming you want an asynchronous reset, then your always blocks should look like:

    always @(posedge clk or negedge rst) begin 
      if(!rst) begin
        // ... reset code ...
      end
      else if (!iChang) begin
        // ... synchronous code ...
      end
    end
    

    If you truely want iChang to prevent a reset, then make the reset synchronous as well:

    always @(posedge clk) begin 
      if (!iChang) begin
        if(!rst) begin
          // ... reset code ...
        end
        else begin
          // ... synchronous code ...
        end
      end
    end