title: program counter debugging for single cycle mips verilog implementation
body: <p>I'm currently trying to implement a 32-bit single-cycle processor on Verilog. So far my code was running smoothly (I was able to successfully implement r-type instructions, branches, j and jal) but my code started failing when I tried  to implement jr. Upon debugging, I think my implementation of the program counter could be the one at fault. It would mean a lot if someone can point out where I'm going wrong with this.</p>
  <p>Here's my program counter without implementing jr:</p>
  <pre><code>assign PCplus4 = inst_addr + 32'd4;
  assign extendedimm = { {16{inst[15]}} , inst[15:0] };
  assign extendedimmafter = extendedimm &lt;&lt; 2;
  assign PCbeforeBranch = PCplus4 + extendedimmafter;
  
  always @ (posedge clk or negedge nrst)
      begin
        if(!nrst) 
                  inst_next &lt;= 0;
        else if(Jump)
                  inst_next &lt;= {PCplus4[31:28],inst[25:0],2'b00 };
        else if(PCSrc)
                  inst_next &lt;= PCbeforeBranch;  
        else
                  inst_next &lt;= PCplus4;                     
      end
  
  assign inst_addr = inst_next;
  </code></pre>
  <p>And here's my program counter after implementing jr:</p>
  <pre><code>assign PCSrc = Branch &amp; (Zero ^ B);
  assign PCplus4 = inst_addr + 32'd4;
  assign extendedimm = { {16{inst[15]}} , inst[15:0] };
  assign extendedimmafter = extendedimm &lt;&lt; 2;
  assign PCbeforeBranch = PCplus4 + extendedimmafter;
  
  always @ (posedge clk or negedge nrst)
      begin
        if(!nrst) 
                  inst_next &lt;= 0;
        else if(Jump)
                  inst_next &lt;= {PCplus4[31:28],inst[25:0],2'b00 };
        else if(PCSrc)
                  inst_next &lt;= PCbeforeBranch;  
        else if(PCSrc3)
                  inst_next &lt;= rd_dataA;
        else
                  inst_next &lt;= PCplus4;                     
      end
  
  assign inst_addr = inst_next;
  </code></pre>
  <p>Edit: as someone pointed out in the comments, there might be a data race going on between rd_dataA and the regfile so I posted my regfile implementation and how I instantiated it in the main code below as well!</p>
  <pre><code>module rf(
      input clk,
      input nrst,
      input [4:0] rd_addrA,
      input [4:0] rd_addrB,
      output [31:0] rd_dataA,
      output [31:0] rd_dataB,
      input wr_en,
      input [4:0] wr_addr,
      input [31:0] wr_data
  );
  
      reg [31:0] regf [31:0];
      
      wire [31:0] reg1;
      wire [31:0] reg2;
      wire [31:0] reg3;
      wire [31:0] reg4;
      wire [31:0] reg5;
      wire [31:0] reg6;
      wire [31:0] reg7;
      wire [31:0] reg8;
      wire [31:0] reg9;
      wire [31:0] reg10;
      wire [31:0] reg11;
      wire [31:0] reg12;
      wire [31:0] reg13;
      wire [31:0] reg14;
      wire [31:0] reg15;
      wire [31:0] reg16;
      wire [31:0] reg17;
      wire [31:0] reg18;
      wire [31:0] reg19;
      wire [31:0] reg20;
      wire [31:0] reg21;
      wire [31:0] reg22;
      wire [31:0] reg23;
      wire [31:0] reg24;
      wire [31:0] reg25;
      wire [31:0] reg26;
      wire [31:0] reg27;
      wire [31:0] reg28;
      wire [31:0] reg29;
      wire [31:0] reg30;
      wire [31:0] reg31;
      wire [31:0] reg32;
  
      assign reg1 = regf[0];
      assign reg2 = regf[1];
      assign reg3 = regf[2];
      assign reg4 = regf[3];
      assign reg5 = regf[4];
      assign reg6 = regf[5];
      assign reg7 = regf[6];
      assign reg8 = regf[7];
      assign reg9 = regf[8];
      assign reg10 = regf[9];
      assign reg11 = regf[10];
      assign reg12 = regf[11];
      assign reg13 = regf[12];
      assign reg14 = regf[13];
      assign reg15 = regf[14];
      assign reg16 = regf[15];
      assign reg17 = regf[16];
      assign reg18 = regf[17];
      assign reg19 = regf[18];
      assign reg20 = regf[19];
      assign reg21 = regf[20];
      assign reg22 = regf[21];
      assign reg23 = regf[22];
      assign reg24 = regf[23];
      assign reg25 = regf[24];
      assign reg26 = regf[25];
      assign reg27 = regf[26];
      assign reg28 = regf[27];
      assign reg29 = regf[28];
      assign reg30 = regf[29];
      assign reg31 = regf[30];
      assign reg32 = regf[31];
  
  
      always @ (posedge clk, negedge nrst)
          if (!nrst) begin
              regf[0] &lt;= 32'd0;
              regf[1] &lt;= 32'd0;
              regf[2] &lt;= 32'd0;
              regf[3] &lt;= 32'd0;
              regf[4] &lt;= 32'd0;
              regf[5] &lt;= 32'd0;
              regf[6] &lt;= 32'd0;
              regf[7] &lt;= 32'd0;
              regf[8] &lt;= 32'd0;
              regf[9] &lt;= 32'd0;
              regf[10] &lt;= 32'd0;
              regf[11] &lt;= 32'd0;
              regf[12] &lt;= 32'd0;
              regf[13] &lt;= 32'd0;
              regf[14] &lt;= 32'd0;
              regf[15] &lt;= 32'd0;
              regf[16] &lt;= 32'd0;
              regf[17] &lt;= 32'd0;
              regf[18] &lt;= 32'd0;
              regf[19] &lt;= 32'd0;
              regf[20] &lt;= 32'd0;
              regf[21] &lt;= 32'd0;
              regf[22] &lt;= 32'd0;
              regf[23] &lt;= 32'd0;
              regf[24] &lt;= 32'd0;
              regf[25] &lt;= 32'd0;
              regf[26] &lt;= 32'd0;
              regf[27] &lt;= 32'd0;
              regf[28] &lt;= 32'd0;
              regf[29] &lt;= 32'd0;
              regf[30] &lt;= 32'd0;
              regf[31] &lt;= 32'd0;
          end
          else
              if (wr_en)
                  case (wr_addr)
                      5'd0: regf[wr_addr] &lt;= 0;
                      default: regf[wr_addr] &lt;= wr_data;
                  endcase
  
      assign rd_dataA = regf[rd_addrA];
      assign rd_dataB = regf[rd_addrB];
  
  endmodule
  </code></pre>
  <p>And here's how I instantiated the regfile in the main code:</p>
  <pre><code>always @ (*) begin
       opcode &lt;= inst[31:26];
       rd_addrA &lt;= inst[25:21];
       rd_addrB &lt;= inst[20:16];
       shamt &lt;= inst[10:6];
       funct &lt;= inst[5:0];
  end
  
  rf regf( clk, nrst, rd_addrA, rd_addrB, rd_dataA, rd_dataB, wr_en, wr_addr, WriteData);
  </code></pre>