简体   繁体   中英

Verilog simulation problems

Hello I am implementing a simple single cycle 32-bit mips processor in verilog. I have successfully compiled all the modules however my output waveform displays XX for all inputs/outputs. These are my register file, cpu module and cpu testbench whihch is where I suspect my problem is but I cant find it. I also have a fetch instructions module, control, alu control and adder module.

    module regsFile( rgr1,rgr2,write,rgw1,rgw1data,clk,reset,rg1data,rg2data);
    
        input [4:0] rgr1;
        input [4:0] rgr2;
        input [4:0]     rgw1;
        input [31:0]  rgw1data;
        input clk;
        input reset;
        input write;
        output reg [31:0] rg1data;
        output reg [31:0] rg2data;
        
        reg [31:0] regMem [31:0]; // register memory
        
    
    
        assign rg1data = regMem[rgr1];
        assign rg2data = regMem[rgr2];
    
    
      always @(rgr1 or rgr2)
      begin
        rg1data = regMem[rgr1];
        rg2data = regMem[rgr2];
      end
    
      always @(posedge write)
      begin
        if(rgw1 == 5'b0) regMem[0] = 5'b0;
        else regMem[rgw1] = rgw1data;
      end
    
        ///write to register
        integer i;
    
        initial 
        begin
          //  $monitor("%d %d %d %d ", regMem[0],regMem[1],regMem[2],regMem[3]);
            //set all register values to reg number 
            for( i = 0; i < 32; i = i + 1 )
                regMem[i] = i;
        end
    
    
      always @(posedge clk or negedge reset)
        begin
            regMem[0] = 32'b0; //register 0 is hardwired to zero;
            if(reset == 1'b0)
            begin 
                regMem[0] = 32'b0;
                // set all registers to their defaults 
                for( i = 0; i < 32; i = i + 1 )
                    regMem[i] = i;
            end
            else if(write == 1'b1 && rgw1 != 5'd0) //$zero register is hardwired to zero
                regMem[rgw1] = rgw1data;
        end
    
    endmodule

    module mips32(dataBus,clk,reset,ReadWrite,memOpDone,addressBus);
        output reg [31:0] addressBus;
        inout [31:0] dataBus;
        input clk,reset,memOpDone;
        output reg ReadWrite;

  

    reg [2:0] stage; 

    parameter IF = 3'd0;
    parameter ID = 3'd1;
    parameter EX = 3'd2;
    parameter MEM = 3'd3;
    parameter WB = 3'd4;


    /* PC_regs */
    reg [31:0] pc;
    wire [31:0] pc_next;
    reg [31:0] NextAdd;
    wire pcOverflow;  

    /* fetch stage*/
    reg [31:0] fetchPC;
    wire [31:0] fetchedInst;

    /* instruction fields */
    reg [31:0] instruction;
    wire [5:0] opcode;
    wire [4:0] rs;
    wire [4:0] rd;
    wire [4:0] rt;
    wire [15:0] addrim; //address offset / immediate 
    wire [31:0] immediate;
    wire [25:0] instidx; // jump address distination shifted to left two bits <add 00 at lsb in execute>
    wire [4:0] sa; // shift amount for shift instructions 
    wire [5:0] fn;
    wire [4:0] rgw;

    /*Control Unit */
    wire contDstReg;
    wire contJmp;
    wire contBranch;
    wire contMemRead;
    wire contMemtoReg;
    wire contALUSrc;
    wire contRegWrite;
    wire contMemWrite;
    wire [1:0] contAluop;

    /*register File */
    reg RegWrite;
    wire [31:0] rdata1;
    wire [31:0] rdata2;
    reg [31:0] rgwdata;

    /* ALU  */
    reg [1:0 ]aluOp;
    reg [31:0] data1;
    reg [31:0] data2;
    reg [31:0] imm;
    reg aluSrc;
    wire [3:0] aluCtrl;
    wire [31:0] result;
    wire zero;
    wire overflow;

    /**/
    reg MemopInProg;
    reg [31:0] MemData;

    assign dataBus = ReadWrite ? MemData : 32'bz;

    assign opcode = instruction[31:26];
    assign rs = instruction[25:21];
    assign rt = instruction[20:16];
    assign rd = instruction[15:11];
    assign addrim = instruction[15:0];
    assign instidx = instruction[25:0];
    assign sa = instruction[10:6];
    assign fn = instruction[5:0];
    assign rgw = contDstReg ? rd : rt;
//    assign immediate = {{16{1'b0}}, addrim};
    assign immediate = addrim;

    addsub32 NexTinst(.A(pc), .B(NextAdd), .sos(1'b0), .Sum(pc_next), .carry(pcOverflow));

    Imem fetchIns(.pc(pc),.instruction(fetchedInst)); // fetch the next instruction

    control controlUnit(.Opcode(opcode),.RegDst(contDstReg),.jump(contJmp),.branch(contBranch),.MemRead(contMemRead),
        .MemToReg(contMemtoReg),
        .ALUop(contAluop),
        .MemWrite(contMemWrite),
        .ALUsrc(contALUSrc),
        .RegWrite(contRegWrite),
    .reset(reset)
    );

    regsFile RegisterFile ( 
    .rgr1(rs),
    .rgr2(rt),
    .write(RegWrite), //output from control unit
    .rgw1(rgw),
    .rgw1data(rgwdata),
    .clk(clk),
    .reset(reset),
    .rg1data(rdata1),
    .rg2data(rdata2)
    );

    aluCtrl aluControl (
    .aluOp(aluOp),
    .fn(fn),
    .aluCtrl(aluCtrl)
    );


    alu alu0(
    .aluSrc(aluSrc),
    .A(data1), 
    .B(data2),
    .imm(imm), 
    .aluCtrl(aluCtrl),
    .result(result),
    .zero(zero),
    .overflow(overflow)
    );

always @(posedge clk or negedge reset)
    begin
        if(reset == 1'b0)
        begin
            pc <= 32'b0;
            stage <= IF;
            NextAdd <= 32'd4; // the added amount to the address
            ReadWrite <= 1'bz;
            MemData <= 32'b0;
            data1 <= 0;
            data2 <= 0;
        end
        else
            case(stage)
                IF:
                    begin
                        RegWrite <= 1'b0;
                        instruction <= fetchedInst;
                        stage <= ID;
                        ReadWrite <= 1'bz;
                        data1 <= 0;
                        data2 <= 0;
                    end
                ID:
                    begin
                        aluOp <= contAluop;
                        aluSrc <= contALUSrc;
                        data1 <= rdata1;
                        data2 <= rdata2;
                        imm <= immediate;
                        ReadWrite <= 1'bz;
                        stage <= EX; 
                    end
                EX:
                    begin
                        ReadWrite <= 1'bz;
                        if(contJmp == 1'b1) 
                        begin 
                            pc <= instidx << 2;
                            stage <= IF;
                        end
                        else if (contBranch == 1'b1)
                        begin 
                            if(zero == 1'b0) // zero means $r1 and $r2 condition is satisfied
                                NextAdd <= addrim << 2;
                                pc <= pc_next;
                                stage <= IF;
                        end
                        else if (contMemRead == 1'b1 | contMemWrite == 1'b1) stage <= MEM;
                        else if (contRegWrite == 1'b1) 
                        begin 
                            stage <= WB;
                            rgwdata <= result;
/*                          // already accounted for it using assign   
                            if (contDstReg == 1'b0)
                                rgw <= rt;//the register to write into
                            else rgw <= rd;
*/
                        end 
                        else
                            begin 
                                NextAdd <= 4'd4;
                                pc <= pc_next;
                                stage <= IF;
                            end
                    end
                MEM:
                    begin
                        data1 <= 0;
                        data2 <= 0;
                        if (MemopInProg == 1'b1)
                            begin
                            if (memOpDone == 1'b1)
                            begin
                                MemopInProg <= 1'b0;
                                if(contMemtoReg == 1'b1)
                                begin
                                    rgwdata <= dataBus;
                                    stage <= WB;
/*                          // already accounted for it using assign   
                                    if (contDstReg == 1'b1)
                                        rgw <= rd;//the register to write into
                                    else rgw <= rt;
*/
                                end
                                else
                                begin
                                    stage <= IF;
                                    NextAdd <= 4'd4;
                                    pc <= pc_next;
                                end
                            end 
                        end
                        else if(contMemWrite == 1'b1)
                            begin
                                addressBus <= rdata1;
                                MemData <= rdata2;
                                ReadWrite <= 1'b1;
                                MemopInProg <= 1'b1;
                                stage <= MEM;
                            end
                        else if (contMemRead == 1'b1)
                            begin
                                addressBus <= rdata1;
                                ReadWrite <= 1'b0;
                                MemopInProg <= 1'b1;
                                stage <= MEM;
                            end
                    end
                WB:
                    begin
                        data1 <= 0;
                        data2 <= 0;
                        ReadWrite <= 1'bz;
                        RegWrite <= 1'b1;
                        stage <= IF;
                        pc <= pc_next;
                    end
                default:    
                begin 
                    stage <= IF; 
                    pc <= pc_next;
                    RegWrite <= 1'b0;
                end
            endcase
    end

endmodule 

    module mips32_TB;
    
    
    reg clk,reset;
    reg memOpDone;
    wire [31:0] dataBus;
    
    wire [31:0] addressBus;
    wire memRWPin;
    
    reg [31:0] MemData;
    
    
    /* instance */
    mips32 MipsCpu( //cpu input/output pins
        .dataBus(dataBus),
        .clk(clk), 
        .reset(reset),
        .ReadWrite(memRWPin), // 1: write, 0: read
        .memOpDone(memOpDone),
        .addressBus(addressBus)
        );
    
    
    assign dataBus = memRWPin ? 32'bz : MemData;
    
    /*Initializing inputs*/
    initial 
    begin 
     //initialize here 
        clk = 0;
        reset = 1;
    end 
    
    
    /*Monitor values*/
    initial 
    begin 
    //  $display ("\t\ttime,\t\tPC,\tstage,\trt:d,\trs:d,\trd:d,\timm,\talusrc\tRegister File");
    //  $monitor ("%d, %d, %d, %d:%d, %d:%d, %d:%d,%d %d %p", $time, MipsCpu.pc, MipsCpu.stage,MipsCpu.rt,MipsCpu.rdata1,MipsCpu.rs,MipsCpu.rdata2,MipsCpu.rd, MipsCpu.rgwdata,MipsCpu.imm ,MipsCpu.aluSrc,MipsCpu.RegisterFile.regMem);
    
      $display ("\t\ttime,\tPC,\tstage,\tRegister File");
      $monitor ("%d, %d, %d, %p", $time, MipsCpu.pc, MipsCpu.stage,MipsCpu.RegisterFile.regMem);
    end
    
    //Generate clock 
    always 
    #1 clk = ~clk;
    
    event reset_done;
    /*Generating input values */
    task rst();
      begin
      @(negedge clk);
        reset = 0;
        #5
      @(negedge clk);
            begin 
            reset = 1;
            ->reset_done;
            end
        
    end 
    endtask
    
    initial 
    begin 
        #1 rst();
    end
    
    always @(posedge clk)
    begin 
        #1
        if(memRWPin == 1'b1)
        begin
            /* write from cpu to memory  */
            #1
            $display ("Memory Access TO address: %d , data: %d", addressBus, dataBus);
            MemData <= dataBus;
            #1
            memOpDone <= 1'b1;
            #3
            memOpDone <= 1'b0;
        end
        else if(memRWPin == 1'b0)
        begin
            /* write from memory to cpu  */
         //  MemData <= 32'd302; 
            #1
            $display ("Memory Access FROM address:%d , data: %d", addressBus,dataBus);
            memOpDone <= 1'b1;
            #3
            memOpDone <= 1'b0;
        end
    end
    
    initial
    begin 
      @(reset_done)
      begin
    
        #500; // wait for a while let the instructions in mipsIM.txt run 
        $stop;
      end
    end 
    endmodule

I guess the problem is you assign more than one values to rg1data and rg2data. delete the following lines:

    assign rg1data = regMem[rgr1];
    assign rg2data = regMem[rgr2];

And use nonblocking assignment in always block like this(the result may show up one cycle later):

always @(rgr1 or rgr2)
begin

    rg1data <= regMem[rgr1];

    rg2data <= regMem[rgr2];

end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM