首页 > 解决方案 > 单周期 mips verilog 实现的程序计数器调试

问题描述

我目前正在尝试在 Verilog 上实现一个 32 位单周期处理器。到目前为止,我的代码运行顺利(我能够成功实现 r 型指令、分支、j 和 jal),但是当我尝试实现 jr 时我的代码开始失败。在调试时,我认为我的程序计数器实现可能是错误的。如果有人能指出我在哪里出错了,那将意味着很多。

这是我没有实现 jr 的程序计数器:

assign PCplus4 = inst_addr + 32'd4;
assign extendedimm = { {16{inst[15]}} , inst[15:0] };
assign extendedimmafter = extendedimm << 2;
assign PCbeforeBranch = PCplus4 + extendedimmafter;

always @ (posedge clk or negedge nrst)
    begin
      if(!nrst) 
                inst_next <= 0;
      else if(Jump)
                inst_next <= {PCplus4[31:28],inst[25:0],2'b00 };
      else if(PCSrc)
                inst_next <= PCbeforeBranch;  
      else
                inst_next <= PCplus4;                     
    end

assign inst_addr = inst_next;

这是我实现 jr 后的程序计数器:

assign PCSrc = Branch & (Zero ^ B);
assign PCplus4 = inst_addr + 32'd4;
assign extendedimm = { {16{inst[15]}} , inst[15:0] };
assign extendedimmafter = extendedimm << 2;
assign PCbeforeBranch = PCplus4 + extendedimmafter;

always @ (posedge clk or negedge nrst)
    begin
      if(!nrst) 
                inst_next <= 0;
      else if(Jump)
                inst_next <= {PCplus4[31:28],inst[25:0],2'b00 };
      else if(PCSrc)
                inst_next <= PCbeforeBranch;  
      else if(PCSrc3)
                inst_next <= rd_dataA;
      else
                inst_next <= PCplus4;                     
    end

assign inst_addr = inst_next;

编辑:正如有人在评论中指出的那样,rd_dataA 和 regfile 之间可能存在数据竞争,所以我发布了我的 regfile 实现以及我如何在下面的主代码中实例化它!

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] <= 32'd0;
            regf[1] <= 32'd0;
            regf[2] <= 32'd0;
            regf[3] <= 32'd0;
            regf[4] <= 32'd0;
            regf[5] <= 32'd0;
            regf[6] <= 32'd0;
            regf[7] <= 32'd0;
            regf[8] <= 32'd0;
            regf[9] <= 32'd0;
            regf[10] <= 32'd0;
            regf[11] <= 32'd0;
            regf[12] <= 32'd0;
            regf[13] <= 32'd0;
            regf[14] <= 32'd0;
            regf[15] <= 32'd0;
            regf[16] <= 32'd0;
            regf[17] <= 32'd0;
            regf[18] <= 32'd0;
            regf[19] <= 32'd0;
            regf[20] <= 32'd0;
            regf[21] <= 32'd0;
            regf[22] <= 32'd0;
            regf[23] <= 32'd0;
            regf[24] <= 32'd0;
            regf[25] <= 32'd0;
            regf[26] <= 32'd0;
            regf[27] <= 32'd0;
            regf[28] <= 32'd0;
            regf[29] <= 32'd0;
            regf[30] <= 32'd0;
            regf[31] <= 32'd0;
        end
        else
            if (wr_en)
                case (wr_addr)
                    5'd0: regf[wr_addr] <= 0;
                    default: regf[wr_addr] <= wr_data;
                endcase

    assign rd_dataA = regf[rd_addrA];
    assign rd_dataB = regf[rd_addrB];

endmodule

以下是我在主代码中实例化 regfile 的方式:

always @ (*) begin
     opcode <= inst[31:26];
     rd_addrA <= inst[25:21];
     rd_addrB <= inst[20:16];
     shamt <= inst[10:6];
     funct <= inst[5:0];
end

rf regf( clk, nrst, rd_addrA, rd_addrB, rd_dataA, rd_dataB, wr_en, wr_addr, WriteData);

标签: mipsverilog

解决方案


推荐阅读