Search code examples
verilogcpu-architecturefpga

Program counter error while implement single cycle mips processor


I'm trying to implement single cycle mips processor using Verilog and I'm facing a problem while trying to test the code, it seems like the program counter isn't increasing after the first cycle but I can't figure out what is wrong.

This is my component code of the Program counter and Instruction Memory

Program Counter

module ProgramCounter(
input CLK,
input reset,
input [31:0]PCin,
output reg [31:0]PCout
);

always @(posedge CLK, posedge reset)
    begin
    PCout <= PCin+4;
        if(reset)
            PCout <= 0;
    end
endmodule

Instruction Memory

module InstructionMemory(
input CLK,
input [31:0] Address,
output reg [31:0] Instr
);

reg [31:0] RAM[16:0];
initial 
    begin
        RAM[0]  <= 32'h22300004; //addi
        RAM[4]  <= 32'h22310003; //add
        RAM[8]  <= 32'h02119020; //and
        RAM[12]  <= 32'h0250a824; //or
        RAM[16]  <= 32'h0211b822; //sub
    end
always @(posedge CLK)
    begin
        Instr <= RAM[Address];
    end
endmodule

And this is the MIPS code that have all the components

    module MIPS(
    input  CLK,
    input  reset,
    output wire [31:0] PCin, 
    output wire [31:0] PCout,
    output wire [31:0] instruction,
    output wire memtoreg,memwrite,branch,alusrc,regdst,regwrite,jump,
    output wire [2:0] alucontrol,
    output wire [4:0] WriteReg,
    output wire[31:0] ReadData1,
    output wire[31:0] ReadData2,
    output wire[31:0] WriteDataReg,
    output wire[31:0] SignExtend,
    output wire[31:0] ALU_B,
    output wire[31:0] ShiftOut,
    output wire[31:0] ALUOut,
    output wire Zero,
    output wire [31:0]Add_ALUOut,
    output wire AndOut,
    output wire [31:0] ReadData
    );
    
//Program Counter
ProgramCounter pc(
    //inputs
        .CLK(CLK),
        .reset(reset),
        .PCin(PCin),
    //outputs
        .PCout(PCout)
);

//Instruction Memory
InstructionMemory instrmem(
    //inputs
    .CLK(CLK),
    .Address(PCout),
    //outputs
    .Instr(instruction)
);

//Control Unit
Control Controller
( 
    //inputs
    .OPcode(instruction[31:26]),
    .func(instruction[5:0]),
    //outputs
    .memtoreg(memtoreg),
    .memwrite(memwrite),
    .branch(branch),
    .alusrc(alusrc),
    .regdst(regdst),
    .regwrite(regwrite),
    .jump(jump),
    .alucontrol(alucontrol)
);

//MUX between instr and reg
MUX1 mux1
(
    //inputs
    .instr1(instruction[20:16]),
    .instr2(instruction[15:11]),
    .regdst(regdst),
    //output
    .WriteReg(WriteReg)
);

//Register File
RegisterFile regfile
(
    //inputs
    .CLK(CLK),
    .WE3(regwrite),
    .RA1(instruction[25:21]),
    .RA2(instruction[20:16]),
    .WA3(WriteReg),
    .WD3(WriteDataReg),
    //outputs
    .RD1(ReadData1),
    .RD2(ReadData2)
);

//Sign Extend
signextend sign_extend
(
    //inputs
    .A(instruction[15:0]),
    //outputs
    .Y(SignExtend)
);

//MUX between reg and ALU
MUX2 mux2
(
    //inputs
    .alusrc(alusrc),
    .RA2(ReadData2),
    .Extend(SignExtend),
    //outputs
    .ALU2(ALU_B)
);

//Shift Left
ShiftLeft Shift_Left
(
    //inputs
    .ShiftIn(SignExtend),
    //outputs
    .ShiftOut(ShiftOut)
);

//ALU
ALU mainALU
(
    //inputs
    .A(ReadData1),
    .B(ALU_B),
    .ALUcontrol(alucontrol),
    //outputs
    .ALUOut(ALUOut),
    .Zero(Zero)
);

//Addition ALU
ALUaddition addALU
(
    //inputs
    .PCout(PCout),
    .ShiftOut(ShiftOut),
    //outputs
    .Add_ALUOut(Add_ALUOut)
);

//And Gate
AND andGate
(
    //inputs
    .Branch(branch),
    .Zero(Zero),
    //outputs
    .Out(AndOut)
);

//MUX for PC
MUX4 mux4
(
    //inputs
    .PCout(PCout),
    .ADD_ALUOut(Add_ALUOut),
    .ANDOut(AndOut),
    //outputs
    .PCin(PCin)
);

//DataMemory
DataMemory datamemory
(
    //inputs
     .CLK(CLK),
     .WE(memwrite),
     .WD(ReadData2),
     .A(ALUOut),
    //outputs
    .RD(ReadData)
);

//MUX after DataMemory
MUX3 mux3
(
    //inputs
    .RD(ReadData),
    .ALUOut(ALUOut),
    .memtoreg(memtoreg),
    //outputs
    .WriteData(WriteDataReg)
);
endmodule

And this is the test bench that I wrote

module Test();
reg CLK;                                                        
reg reset;                                                      
wire [31:0] PCin;                                           
wire [31:0] PCout;                                          
wire [31:0] instruction;                                    
wire memtoreg;
wire memwrite;
wire branch;
wire alusrc;
wire regdst;
wire regwrite;
wire jump;  
wire [2:0] alucontrol;                                      
wire [4:0] WriteReg;                                        
wire[31:0] ReadData1;                                       
wire[31:0] ReadData2;                                       
wire[31:0] WriteDataReg;                                    
wire[31:0] SignExtend;                                      
wire[31:0] ALU_B;                                           
wire[31:0] ShiftOut;                                        
wire[31:0] ALUOut;                                          
wire Zero;                                                  
wire [31:0]Add_ALUOut;                                      
wire AndOut;                                                
wire [31:0] ReadData;

MIPS mips(CLK,reset,PCin,PCout,instruction,memtoreg,memwrite,branch,alusrc,regdst,regwrite,jump,alucontrol,WriteReg,ReadData1,ReadData2,WriteDataReg,SignExtend
,ALU_B,ShiftOut,ALUOut,Zero,Add_ALUOut,AndOut,ReadData);

initial
begin
    CLK = 0;
    reset = 1;
    #5 
    reset = 0;
    #5
    forever #5 CLK = ~CLK;
end                                 
endmodule

Now when I look at the simulation, this is how at looks, the program counter only gets initialized the first cycle and then it becomes don't care Simulation Picture


Solution

  • In the following PCout <= PCin+4; — where is PCin given a value?  I don't see that anywhere.

    PCin looks to me like an uninitialized variable, so PCout becomes uninitialized + 4, which is still unknown.  I would have expected to see something like PCin <= PCout somewhere.

    Though alternately, I'm also not sure why there's both PCin and PCout everywhere instead of just one PC.  Sure you may want to differentiate between the in and the out in some modules, but in other cases I'm thinking its one and the same register.