我使用 verilog 实现了一个 RV32。但是输出总是0,即y=0

时间:2021-02-08 21:05:09

标签: verilog

`timescale 1 ns/10 ps
module datapath(
    input wire clk, reset, mod, [1:0] mode, [31:0] ins,
    output reg i_flag, r_flag, rz, [31:0] y,
    // y holds the result register value
    // Zero Flag register
    // Flag for keeping track when the processor reads instructions
// i_flag is 1 when an instruction has been completed
    output reg [6:0] pc, [31:0] ir);
// Program Counter for keeping track of code blocks,
//  for selecting instructions and
//  for tracking Adresses of registers
reg [4:0] rs1, rs2, rd;
reg [2:0] func1;
reg [6:0] func2;
reg [31:0] x [0:15];
reg [31:0] s;// s For signed arithematic, ir for the current instruction
reg [31:0] imm;// For handling I-Type Instructions
reg [31:0] i_mem [0:127];// This Processor can store 128 lines of code
reg [6:0] inst;// inst keeps track of the final line of instruction written
integer i;
//--------------------------------------------------------------------------
always@(posedge clk, posedge reset)begin
    if(reset)begin
    for(i=0;i<=127;i=i+1)begin
        i_mem[i]<=0;
    end
    for(i=0;i<=15;i=i+1)begin
        x[i]<=0;
    end
    ir<=0;
    pc<=0;
    inst<=0;
    y<=32'h00000000;
    r_flag<=0;
    i_flag<=0;
    s<=32'h00000000;
    rz<=0;
    rs1<=0;
    rs2<=0;
    rd<=0;
    func1<=0;
    func2<=0;
    imm<=0;
    end
    else begin
        if(mod==1)begin// mod = 1 is for implementing the instructions
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            if(r_flag==1)begin 
                r_flag<=0;
                inst<=pc;
                pc = 1;
            end
            //if(pc>inst)pc<=1;// Infinite looped processor
            i_flag <= 1;
            ir<=i_mem[pc];
            if(mode==2'b01)begin// R-Type Instructions
                //rd <= ir[11:7]
                rd[0] = ir[7];
                rd[1] = ir[8];
                rd[2] = ir[9];
                rd[3] = ir[10];
                rd[4] = ir[11];
                //func1 <= ir[14:12]
                func1[0] = ir[12];
                func1[1] = ir[13];
                func1[2] = ir[14];
                //rs1 <= ir[19:15]
                rs1[0] = ir[15];
                rs1[1] = ir[16];
                rs1[2] = ir[17];
                rs1[3] = ir[18];
                rs1[4] = ir[19];
                //ir[24:20]
                rs2[0] = ir[20];
                rs2[1] = ir[21];
                rs2[2] = ir[22];
                rs2[3] = ir[23];
                rs2[4] = ir[24];
                //ir[31:25]
                func2[0] = ir[25];
                func2[1] = ir[26];
                func2[2] = ir[27];
                func2[3] = ir[28];
                func2[4] = ir[29];
                func2[5] = ir[30];
                func2[6] = ir[31];
                
                if(func1==3'b000) x[rd] <= (x[rs1] + x[rs2]);// ADD
                else if(func1==3'b001) x[rd] <= (x[rs1] + ((~x[rs2])+1));// SUB
                else if(func1==3'b010) x[rd] <= (x[rs1] | x[rs2]);// OR
                else if(func1==3'b011) x[rd] <= ((~x[rs1]) & x[rs2]) | (x[rs1] & (~x[rs2]));// XOR
                else if(func1==3'b100) x[rd] <= (x[rs1] & x[rs2]);// AND
                
                else if(func1==3'b101)begin// SLT
                    if((x[rs1]<0) & (x[rs2]<0))begin
                        if(((~x[rs1])+1) < ((~x[rs2])+1)) x[rd] <= 1;
                        else if(((~x[rs1])+1) == ((~x[rs2])+1)) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                    if((x[rs1]<0) & (x[rs2]>0))begin
                        if(((~x[rs1])+1) < x[rs2]) x[rd] <= 1;
                        else if(((~x[rs1])+1) == x[rs2]) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                    if((x[rs1]>0) & (x[rs2]<0))begin
                        if(x[rs1] < ((~x[rs2])+1)) x[rd] <= 1;
                        else if(x[rs1] == ((~x[rs2])+1)) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                    if((x[rs1]>0) & (x[rs2]>0))begin
                        if(x[rs1] < x[rs2]) x[rd] <= 1;
                        else if(x[rs1] == x[rs2]) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                end
                if(func1==3'b110)begin// SLTU
                    if(x[rs1] < x[rs2]) x[rd] <= 1;
                    else if(x[rs2]==x[rs1]) x[rd] <= 0;
                    else x[rd] <= 0;
                end
                // Extra function added for better accessibility
                if(func1==3'b111)begin// NOT
                    x[rd] <= ~(x[rs1]);
                    if(x[rd] == 0)rz<=1;
                end
            end
            else if(mode==2'b10)begin// I-Type Instructions
                //rd <= ir[11:7]
                rd[0] = ir[7];
                rd[1] = ir[8];
                rd[2] = ir[9];
                rd[3] = ir[10];
                rd[4] = ir[11];
                //func1 <= ir[14:12]
                func1[0] = ir[12];
                func1[1] = ir[13];
                func1[2] = ir[14];
                //rs1 <= ir[19:15]
                rs1[0] = ir[15];
                rs1[1] = ir[16];
                rs1[2] = ir[17];
                rs1[3] = ir[18];
                rs1[4] = ir[19];
                //imm <= ir[31:20]
                imm[0] = ir[20];
                imm[1] = ir[21];
                imm[2] = ir[22];
                imm[3] = ir[23];
                imm[4] = ir[24];
                imm[5] = ir[25];
                imm[6] = ir[26];
                imm[7] = ir[27];
                imm[8] = ir[28];
                imm[9] = ir[29];
                imm[10] = ir[30];
                imm[11] = ir[31];
                s <= 0;
                
                if(func1 == 3'b000) x[rd] <= x[rs1] + imm;// ADDi
                else if(func1 == 3'b001) x[rd] <= x[rs1] | imm;// ORi
                else if(func1 == 3'b010) x[rd] <= x[rs1] & imm;// ANDi
                
                else if(func1 == 3'b011)begin// SLTi
                    s <= imm;
                    if((x[rs1]<0) & (s<0))begin
                        if(((~x[rs1])+1) < ((~s)+1)) x[rd] <= 1;
                        else if(((~x[rs1])+1) == ((~s)+1)) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                    if((x[rs1]<0) & (s>0))begin
                        if(((~x[rs1])+1) < s) x[rd] <= 1;
                        else if(((~x[rs1])+1) == s) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                    if((x[rs1]>0) & (s<0))begin
                        if(x[rs1] < ((~s)+1)) x[rd] <= 1;
                        else if(x[rs1] == ((~s)+1)) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                    if((x[rs1]>0) & (s>0))begin
                        if(x[rs1] < s) x[rd] <= 1;
                        else if(x[rs1] == s) x[rd] <= 0;
                        else x[rd] <= 0;
                    end
                end
            end
            else if(mode==2'b11)begin// J-Type Instructions
                //rd <= ir[11:7]
                rd[0] = ir[7];
                rd[1] = ir[8];
                rd[2] = ir[9];
                rd[3] = ir[10];
                rd[4] = ir[11];
                //imm <= imm+ir[31:12]
                imm[0] = ir[12];
                imm[1] = ir[13];
                imm[2] = ir[14];
                imm[3] = ir[15];
                imm[4] = ir[16];
                imm[5] = ir[17];
                imm[6] = ir[18];
                imm[7] = ir[19];
                imm[8] = ir[20];
                imm[9] = ir[21];
                imm[10] = ir[22];
                imm[11] = ir[23];
                imm[12] = ir[24];
                imm[13] = ir[25];
                imm[14] = ir[26];
                imm[15] = ir[27];
                imm[16] = ir[28];
                imm[17] = ir[29];
                imm[18] = ir[30];
                imm[19] = ir[31];
                //Load the new memory address
                //The PC can only hold a 7-bit long memory address
                pc[0] = imm[0];
                pc[1] = imm[1];
                pc[2] = imm[2];
                pc[3] = imm[3];
                pc[4] = imm[4];
                pc[5] = imm[5];
                pc[6] = imm[6];
            end
        end
        else begin// mod = 0 is for reading instructions
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            if(r_flag==0)begin
                pc<=inst;
                r_flag<=1;
            end
            i_mem[pc]<=ins;
        end
        pc<=pc+1;
    end
    if(x[rd]==0)rz<=1;
    else rz<=0;
    y = x[rd][31:0];
end
always@*begin
    x[0] = 0;
end
endmodule

//============================================================================

问题是,我尝试过循环、间接赋值,但没有任何效果。如果我将数组中的一个寄存器传递给 y,则输出很好,但行 y <= x[rd];或 y=x[rd] 不返回存储在寄存器中的正确值。 我能做些什么来修复它? 我尝试了多种方法,包括将 x 作为输出,但 verilog 不允许将数组作为输出。其余的代码很好。我测试了它。我没有足够的声誉来发布图片。 感谢您抽出宝贵时间。

1 个答案:

答案 0 :(得分:0)

那里有很多代码,看起来你在阻塞和非阻塞赋值方面一团糟。

您询问了 y。在您的情况下,我注意到您的块中有两个语句:

  y <= 0;
  ...
  y = x[rd][31:0];

在这个特殊的组合中,第一个语句将获胜,y 将是 0。原因是第一个语句将赋值安排到稍后的时间,而第二个语句立即执行。您也应该在第二种情况下使用 <=。实际上,看起来您应该在块中使用非阻塞赋值。不要混合使用。

一般建议是将庞大的 always 块拆分为较小的任务并分别调试每个任务。