- #1
pags920
- 21
- 0
I am trying to design a multi-cycle processor in Verilog for the MIPS instruction set. However, I cannot get one of my instructions that I stored in memory to execute. This program is a continuation of a lab assignment that was given to my class.
The instruction that I am trying to execute is in Memory[6]. If anyone experienced in MIPS and Verilog can see where the problem is, that would be so helpful.
The instruction that I am trying to execute is in Memory[6]. If anyone experienced in MIPS and Verilog can see where the problem is, that would be so helpful.
Code:
module cpu_tb;
wire[31:0] PC, IR, ALUOut, MDR, A, B, reg7;
reg clock;
CPU cpu1 (clock,PC, IR, ALUOut, MDR, A, B, reg7);// Instantiate CPU module
initial
begin
clock = 0;
repeat (300)
begin
#10 clock = ~clock; //alternate clock signal
end
end
initial #5000 $finish; //end simulation after 110 nano second
endmodule
module CPU (clock,PC, IR, ALUOut, MDR, A, B, reg7);
parameter BNE = 6'b000001; //opcode for BNE
parameter J = 6'b000010; //opcode for J
parameter JAL = 6'b000011; //opcode for JAL
parameter BEQ = 6'b000100; //opcode for BEQ
parameter ADDI = 6'b001000; //opcode for ADDI
parameter SLTI = 6'b001010; //opcode for SLTI
parameter ANDI = 6'b001100; //opcode for ANDI
parameter ORI = 6'b001101; //opcode for ORI
parameter SINC = 6'b011111; //opcode for SINC
parameter LW = 6'b100011; //opcode for LW
parameter SB = 6'b101000; //opcode for SB
parameter SW = 6'b101011; //opcode for SW
parameter LI = 6'b111111; //opcode for LI
input clock; //the clock is an external input
//Make these datapath registers available outside the module in order to do the testing
output PC, IR, ALUOut, MDR, A, B;
reg[31:0] PC, IR, ALUOut, MDR, A, B;
output [31:0] reg7; //output reg 7 for testing
// The architecturally visible registers and scratch registers for implementation
reg [31:0] Regs[0:31], Memory [0:1023];
assign reg7 = Regs[7]; //output reg 7
reg [2:0] state; // processor state
wire [5:0] opcode; //use to get opcode easily
wire [31:0] SignExtend, PCOffset; //used to get sign extended offset field
assign opcode = IR[31:26]; //opcode is upper 6 bits
//sign extension of lower 16-bits of instruction
assign SignExtend = {{16{IR[15]}},IR[15:0]};
assign PCOffset = SignExtend << 2; //PC offset is shifted
assign ZeroExtend = {{16{IR[1'b0]}}, IR[15:0]};
assign BranchAddr = {{14{IR[15]}}, IR[15:0], 2'b0};
assign JumpAddr = {{PC+{IR[31:28]}}, IR[25:0], 2'b0};
//Load a test program and data into memory
initial
begin
Memory[2] = 32'h8c070078; //lw instruction
Memory[3] = 32'hac0700f8; //sw instruction
Memory[4] = 32'b111111_01000_00000_0000000000000001; //li instruction
Memory[5] = 32'b000001_01000_01000_0000000000000001; //bne instruction
Memory[6] = 32'b000000_01000_01000_00000_00000_010100; //add
Memory[30] = 9;
end
// set the PC to 8 and start the control in state 1 to start fetch instructions from Memory[2] (byte 8)
initial
begin
PC = 8;
state = 1;
end
always @(posedge clock) begin
//make R0 0
//short-cut way to make sure R0 is always 0
Regs[0] = 0;
case (state) //action depends on the state
1: begin //first step: fetch the instruction, increment PC, go to next state
IR <= Memory[PC>>2]; //changed
PC <= PC + 4; //changed
state = 2; //next state
end
2: begin //second step: Instruction decode, register fetch, also compute branch address
A = Regs[IR[25:21]];
B = Regs[IR[20:16]];
state= 3;
ALUOut <= PC + PCOffset; // compute PC-relative branch target
end
3: begin //third step: Load/Store execution, ALU execution, Branch completion
state = 4; // default next state
if ((opcode==LW) |(opcode==SW)) ALUOut <= A + SignExtend; //compute effective address
else if (opcode==6'b0) case (IR[5:0]) //case for the various R-type instructions
0: ALUOut = B << IR[10:6]; //sll operation
2: ALUOut = B >> IR[10:6]; //srl operation
8: PC = A; //jr operation
20: ALUOut = A + B; //add operation
22: ALUOut = A - B; //sub operation
24: ALUOut = A & B; //and operation
25: ALUOut = A | B; //or operation
27: ALUOut = ~(A | B); //nor operation
28: ALUOut = (A < B) ? 1:0; //slt operation
default: ALUOut = A; //other R-type operations
endcase
else if (opcode==6'b111111) begin Regs[IR[25:21]]<= SignExtend; state = 1; end //ALU operation for LI instruction
else if (opcode==6'b001000) begin Regs[IR[20:16]]<= SignExtend; ALUOut = A + SignExtend; state = 4; end //ALU operation for ADDI instruction
else if (opcode==6'b001100) begin Regs[IR[20:16]]<= ZeroExtend; ALUOut = A & ZeroExtend; state = 4; end //ALU operation for ANDI instruction
else if (opcode==6'b001101) begin Regs[IR[20:16]]<= ZeroExtend; ALUOut = A | ZeroExtend; state = 4; end //ALU operation for ORI instruction
else if (opcode==6'b001010) begin Regs[IR[20:16]]<= SignExtend; ALUOut = (A < SignExtend) ? 1:0; state = 4; end //ALU operation for SLTI instruction
else if (opcode==6'b000001) if(A!=B) begin PC = ALUOut; state = 1; end //ALU instruction for BNE instruction
else if (opcode==6'b000100) if(A==B) begin PC = ALUOut; state = 1; end //ALU instruction for BEQ instruction
else state = 1;
else ; // other opcodes or exception for undefined instruction would go here
end
4: begin
if (opcode==6'b0) begin //ALU Operation
Regs[IR[15:11]] <= ALUOut; // write the result
state = 1;
end //R-type finishes
else if (opcode == LW) begin // load instruction
MDR <= Memory[ALUOut>>2]; // read the memory
state = 5; // next state
end
else if (opcode == SW) begin
Memory[ALUOut>>2] <= B; // write the memory
state = 1; // return to state 1
end //store finishes
else if (opcode == LI) begin //load immediate
Regs[IR[25:21]] <= ALUOut; //write to IR
state = 1; //return to state 1
end
else if (opcode == ADDI) begin //add immediate
Regs[IR[20:16]] <= ALUOut; //write to IR
state = 1; //return to state 1
end
else if (opcode == ANDI) begin //and immediate
Regs[IR[20:16]] <= ALUOut; //write to IR
state = 1; //return to state 1
end
else if (opcode == BEQ) begin //branch if equal
if (ALUOut != 0)
state = 1; //return to state 1
else
PC <= IR[15:0] + SignExtend; //write to program counter, branch address
state = 1; //return to state 1
end
else if (opcode == ORI) begin //or immediate
Regs[IR[20:16]] <= A | ZeroExtend; //write to IR
state = 1; //return to state 1
end
else if (opcode == SLTI) begin //set if less than immediate
Regs[IR[20:16]] <= ALUOut; //write to IR
state = 1; //return to state 1
end
else if (opcode == SB) begin //store byte
Memory[A + {SignExtend[7:0]}] <= B; //write to memory
state = 1; //reurn to state 1
end
else if (opcode == J) begin //jump
PC <= JumpAddr; //write to program counter, jump address
state = 1; //return to state 1
end
else if (opcode == JAL) begin //jump and link
IR[31] <= PC + 8; //write to the last bit in IR
PC <= JumpAddr; // write to program counter, jump address
state = 1;
end
else if (opcode == SINC) begin //sinc
MDR <= Memory[ALUOut>>2]; //write to memory
Regs[IR[20:16]] <= A + SignExtend; //write to IR
state = 5; //proceed to state 5
end
else if (opcode == BNE) begin //branch if not equal
if (ALUOut == 0)
state = 1; //return to state 1
else
PC <= IR[15:0] + SignExtend; //write to program counter, branch address
state = 1; //return to state 1
end
end
5: begin //LW is the only instruction still in execution
Regs[IR[20:16]] = MDR; // write the MDR to the register
state = 1;
end //complete a LW instruction
endcase
end
endmodule