title: Verilog: if statement unexpected behavior
body: <p>I am implementing the MIPS data path (behavioral) in Verilog and the when I simulate my code, the behavior is unexpected.
  Here the case of BEQ and BNE (branch if equal/not equal) instructions is shown. ALU_Out determines whether the two registers are equal or not. Non of these really matter cause my problem is basically how verily skips my condition. So, I from the signals in waveform, ALU_out <strong>is</strong> zero, yet whatever happens inside the <strong>if (ALU_Out == 32'd1)</strong> is executed once. such that My PC becomes PC+6. now if my ALU_Out actually equals 1, the PC becomes PC+6+6 (It's 1 ==> becomes 13) I have also integrated some kinna flags inside this if statement and made sure it executes once.
  Even when I added <strong>else</strong> to this if, my flags clearly indicated that the <strong>if had been executed once before else</strong>.
  The very same thing occurs in the case of BNE and desired condition is checked after the if statement is executed once.
  Would you tell me what is wrong with this code.
  Many thanks in advance.</p>
  
  <pre><code>            if (ALU_op == 6'd30)        //BEQ
              begin
                  ALU_out = ((ALU_in1) == (ALU_in2));
                  if (ALU_out == 32'd1)
                      begin
                          PC = PC + Imm_32;
                      end
              end
  
  
          if (ALU_op == 6'd31)        //BNE
              begin
                  ALU_out = ((ALU_in1) == (ALU_in2));
                  if (ALU_out == 0)
                      begin
                          PC = PC + Imm_32;
                      end
              end
  </code></pre>
  
  <p><a href="http://i.stack.imgur.com/ZtRQB.png" rel="nofollow">a screen shot of my waveform</a></p>
  
  <p><strong>UPDATE:</strong> still haven't done anything about the non-blocking assignment, But i did modify the way I update PC by adding a next_PC to my code.the If statement problem is gone. Still, the problem is when a jump or branch occurs, the next PC is calculated properly but the instruction at the branch target won't be fetched the same clock! 
  <a href="http://i.stack.imgur.com/J0q0o.png" rel="nofollow">please look at this photo</a></p>
  
  <p>and this is supposed to be a single-cycle MIPS processor so that an instruction should be fetched and executed at one cycle. that's why the delay caused by non-blocking assignment is not desired!</p>
  
  <pre><code>always @(*)
      begin
          IR &lt;= Instruction;
      end
  always @(posedge clk)
      begin
  
          PC = next_PC;
  
          OverFlow = 0;
  
      end
  
  // Decode + Operand Fetch //    
  always @ (IR)
      begin
          Op_code = IR[31:26];
          if (Op_code == 6'd0)        //R-type Instructions
              begin
                  Func = IR[5:0];
  
  
                  if (Func == 6'b100000)  //ADD
                      begin
                          ALU_op = 6'd1;          //as numbered in LAB manual
                          read_addr1 = IR [25:21];    //Rs
                          read_addr2 = IR [20:16];    //Rt
  
                      end     //end of ADD
  
  
                  if (Func == 6'b100001)  //ADDU
                      begin
                          ALU_op = 6'd2;          //as numbered in LAB manual
                          read_addr1 = IR [25:21];    //Rs
                          read_addr2 = IR [20:16];    //Rt
                      end     //end of ADDU
  
  
                  /* some code here skipped to make the code shorter*/
  
              if (Op_code == 6'b000100)   //BEQ (Branch if Equal)
                  begin
                      ALU_op = 6'd30;         //as numbered in LAB manual
                      read_addr1 = IR [25:21];    //Rs
                      read_addr2 = IR [20:16];    //Rt
                      Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16) 
                      //BT =  PC + Imm_32;
                  end
  
  
              if (Op_code == 6'b000101)   //BNE (Branch if NOT Equal)
                  begin
                      ALU_op = 6'd31;         //as numbered in LAB manual
                      read_addr1 = IR [25:21];    //Rs
                      read_addr2 = IR [20:16];    //Rt 
                      Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16)  
                  end
  
  
              if (Op_code == 6'b000001)   
                  begin
                      if ( IR [20:16] == 5'b00001)    //BGEZ (Branch on Greater than or Equal to Zero)
                          begin
                              ALU_op = 6'd33;         //as numbered in LAB manual
                              read_addr1 = IR [25:21];    //Rs
                              Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16)  
                          end
  
  
                      if (IR [20:16] == 5'b10000)     //BLTZAL (Branch on less than Zero And Link)
                          begin
                              ALU_op = 6'd34;         //as numbered in LAB manual
                              read_addr1 = IR [25:21];    //Rs
                              Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16)  
                          end
                  end
  
  
              if (Op_code == 6'b000010)   //J (Jump)
                  begin
                      ALU_op = 6'd35;         //as numbered in LAB manual
                      Imm_32 = {PC [31:26],IR [25:0]};    //Jump Address  
                  end
  
  
              if (Op_code == 6'b000011)   //JAL (Jump And Link)
                  begin
                      ALU_op = 6'd36;         //as numbered in LAB manual
                      Imm_32 = {PC [31:26],IR [25:0]};    //Jump Address  
                  end                     
  
  
      end // end of DECODE
  
  // Execution &amp; Write Back//
  
  always @ (ALU_op, ALU_in1, ALU_in2)
      begin
          next_PC = PC+1;
          wr_En = 0;  
          DM_wrEn_0 = 0;
          DM_wrEn_1 = 0;
          DM_wrEn_2 = 0;
          DM_wrEn_3 = 0;
  
          if (ALU_op == 6'd1)     //ADD
              begin
                  ALU_out = ALU_in1 + ALU_in2;
                  write_addr = IR [15:11];    //Rd
                  if( ( (ALU_in1[31]) &amp;&amp; (ALU_in2[31]) &amp;&amp; (!ALU_out[31]) )||( (!ALU_in1[31]) &amp;&amp; (!ALU_in2[31]) &amp;&amp; (ALU_out[31]) ) )
                      OverFlow = 1'b1;
                  wr_En = 1;
                  write_data = ALU_out;                       
              end
  
          if (ALU_op == 6'd2)     //ADDU
              begin
                  ALU_out = ALU_in1 + ALU_in2;
                  write_addr = IR [15:11];    //Rd
                  wr_En = 1;
                  write_data = ALU_out;                   
              end
  
  
          /* some code here skipped to make it shorter*/
  
  
  
          if (ALU_op == 6'd30)        //BEQ
              begin
                  ALU_out = ((ALU_in1) == (ALU_in2));
                  if (ALU_out == 32'd1)
                      begin
                          //PC = PC + Imm_32;
                          next_PC = PC + Imm_32;
                          BT = 32'd56;
                          //PC = BT;
                      end
              end
  
  
          if (ALU_op == 6'd31)        //BNE
              begin
                  ALU_out = ((ALU_in1) == (ALU_in2));
                  if (ALU_out == 0)
                      begin
                          //PC = PC + Imm_32;
                          next_PC = PC + Imm_32;
                          BT = 32'd90;
                      end
              end
  
  
          if (ALU_op == 6'd33)        //BGZE
              begin
                  ALU_out = ((ALU_in1) &gt;= 0);
                  if (ALU_out)
                      begin
                          //PC = PC + Imm_32;
                          next_PC = PC + Imm_32;
                      end
              end
  
  
          if (ALU_op == 6'd34)        //BLTZAL
              begin
                  ALU_out = ((ALU_in1) &lt; 0);
                  if (ALU_out)
                      begin
                          write_addr = 5'd31; //$ra ($31)
                          write_data = PC;
                          wr_En = 1;
                          //PC = PC + Imm_32;
                          next_PC = PC + Imm_32;
                      end
              end
  
  
          if (ALU_op == 6'd32)        //JR
              begin
                  //PC = ALU_in1;
                  next_PC = ALU_in1;
              end
  
  
          if (ALU_op == 6'd35)        //J
              begin
                  //PC = Imm_32;
                  next_PC = Imm_32;
              end
  
  
          if (ALU_op == 6'd36)        //JAL
              begin
                  write_addr = 5'd31; //$ra
                  wr_En = 1;
                  write_data = PC;
                  //PC = Imm_32;
                  next_PC = Imm_32;
              end
  
      end  //end of EXE and WB always block
  </code></pre>