module CPU (clock, PC, IR, ALUOut, MDR, A, B); input clock; //the clock is an external input // Make datapath registers available outside the module for testing output reg [31:0] PC, IR, ALUOut, MDR, A, B; // The architecturally visible registers and scratch registers for implementation reg [31:0] Regs[0:31], Memory [0:1023]; 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 parameter LW = 6'b100011, SW = 6'b101011, BEQ=6'b000100, J=6'd2; assign opcode = IR[31:26]; //opcode is upper 6 bits assign SignExtend = {{16{IR[15]}},IR[15:0]}; //sign extension of lower 16-bits of instruction assign PCOffset = SignExtend << 2; //PC offset is shifted // Load a test program and data into memory initial begin // program Memory [0] = 32'h8C080040; // lw $8, 64($0) Memory [1] = 32'h01084820; // add $9, $8, $8 // data at byte address 64 Memory [16] = 32'd1; // .word 1 end // set the PC to 0 and start the control in state 0 initial begin PC = 0; state = 1; end //The state machine--triggered on a rising clock always @(posedge clock) begin Regs[0] = 0; //make R0 0 //short-cut way to make sure R0 is always 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]; PC <= PC + 4; 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 32: ALUOut= A + B; //add operation default: ALUOut= A; //other R-type operations: subtract, SLT, etc. endcase else if (opcode == BEQ) begin if (A==B) PC <= ALUOut; // branch taken--update PC state = 1; end else if (opcode == J) begin PC = {PC[31:28], IR[25:0],2'b00}; // the jump target PC state = 1; end //Jumps 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 == LW) begin Memory[ALUOut>>2] <= B; // write the memory state = 1; // return to state 1 end //store finishes else ; // other instructions go here 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 //-------------------------------------------------------------------- // Test module module test_mips (); reg clock; wire [31:0] PC, IR, ALUOut, MDR, A, B; CPU cpu1(clock, PC, IR, ALUOut, MDR, A, B); always begin #1 clock = ~clock; end initial begin $monitor ("%d %d PC=%2d IR=%h MDR=%2d A=%2d B=%2d ALUOut=%2d", $time,clock,PC,IR,MDR,A,B,ALUOut); clock = 0; #20 $finish; end endmodule //-------------------------------------------------------------------- /* Compile and execute C:\Verilog\bin>iverilog -o t mips.vl C:\Verilog\bin>vvp mips 0 0 PC= 0 IR=xxxxxxxx MDR= x A= x B= x ALUOut= x 1 1 PC= 4 IR=8c080040 MDR= x A= x B= x ALUOut= x 2 0 PC= 4 IR=8c080040 MDR= x A= x B= x ALUOut= x 3 1 PC= 4 IR=8c080040 MDR= x A= 0 B= x ALUOut=260 4 0 PC= 4 IR=8c080040 MDR= x A= 0 B= x ALUOut=260 5 1 PC= 4 IR=8c080040 MDR= x A= 0 B= x ALUOut=64 6 0 PC= 4 IR=8c080040 MDR= x A= 0 B= x ALUOut=64 7 1 PC= 4 IR=8c080040 MDR= 1 A= 0 B= x ALUOut=64 8 0 PC= 4 IR=8c080040 MDR= 1 A= 0 B= x ALUOut=64 9 1 PC= 4 IR=8c080040 MDR= 1 A= 0 B= x ALUOut=64 10 0 PC= 4 IR=8c080040 MDR= 1 A= 0 B= x ALUOut=64 11 1 PC= 8 IR=01084820 MDR= 1 A= 0 B= x ALUOut=64 12 0 PC= 8 IR=01084820 MDR= 1 A= 0 B= x ALUOut=64 13 1 PC= 8 IR=01084820 MDR= 1 A= 1 B= 1 ALUOut=73864 14 0 PC= 8 IR=01084820 MDR= 1 A= 1 B= 1 ALUOut=73864 15 1 PC= 8 IR=01084820 MDR= 1 A= 1 B= 1 ALUOut= 2 16 0 PC= 8 IR=01084820 MDR= 1 A= 1 B= 1 ALUOut= 2 17 1 PC= 8 IR=01084820 MDR= 1 A= 1 B= 1 ALUOut= 2 18 0 PC= 8 IR=01084820 MDR= 1 A= 1 B= 1 ALUOut= 2 19 1 PC=12 IR=xxxxxxxx MDR= 1 A= 1 B= 1 ALUOut= 2 */