MicroprogrammingProcessor, as its name reveals, is a hardware program that simulate the behavior of a trivial single cycle CPU with micropramming controller. As a homework assigned in the computer organization course for sophomore majoring in CS, it is an individual project for non-comercial purposes.
- Design the Datapath, bring together the basic units into Single-cycle clock CPU
- Implement at least 9instructions: Add, Sub, And, Or, Lw, Sw, Slt, Beq, J.
- Better implement the 16instructions: Add, Sub, And, Or, Addi, Ori, Sll, Srl, Lw, Sw, Slt, Beq, Bne, J, Jal, Jr
- Verify the CPU with program and observe the execution of program
- Datapath
It’s still all the same as what in the multiple-cycle CPU:
- State figure
It’s similar with that of the multiple-cycle CPU, except that some details are a little bit different. That’s we don’t have to maintain all things about each state since the dispatch logic curcuit and the control signals stored in the controller can help.
Here are exactly what in the codes (Just a relative part of the controller):
wire [2:0] AddrCtrl;
// AddrCtrl == 000 for back to state 0
// AddrCtrl == 001 for general decode
// AddrCtrl == 010 for lw/sw decode
// AddrCtrl == 011 for state++
// AddrCtrl == 100 for R-type ALU completion
// AddrCtrl == 101 for I-type ALU completion
// seconde decoder
reg [4:0] state;
always @ (posedge clk or posedge rst) begin
if(rst) state <= 5'd0;
else case(AddrCtrl)
3'd0: state <= 5'd0;
3'd1: begin
if(lw | sw)
state <= 5'd2;
else if(addr | subr | andr | orr | xorr | norr | sltr)
state <= 5'd6;
else if(addi | slti)
state <= 5'd10;
else if(andi | ori | xori)
state <= 5'd11;
else if(branch)
state <= 5'd8;
else if(j)
state <= 5'd9;
else if(jal)
state <= 5'd16;
else if(shift)
state <= 5'd13;
else if(lui)
state <= 5'd14;
else if(jr)
state <= 5'd15;
else if(jalr)
state <= 5'd17;
end
3'd2: begin
if(lw)
state <= 5'd3;
else if(sw)
state <= 5'd5;
end
3'd3: state <= state + 5'd1;
3'd4: state <= 5'd7;
3'd5: state <= 5'd12;
default:;
endcase
end
- Control signals for microprogramming It is also similar with that of the multiple-cycle CPU, except that they are not assigned in the combinational logic curcuit but the ROM. ( Here I use register in the verilog HDL exactly, since it behaves just like ROM and what’s more, it is convenient for debugging. All the meanings are the same as those I have introduced in the report of multiple-cycle CPU, except that the last three bits, AddrCtrl[2:0], which I just mentioned in the previous part. Here is exactly the code:
//22.PCWriteCond 21.PCWrite 20.MemWrite
//19.IRWrite 18.RegWrite 17.PCsrc[1] 16.PCsrc[0] 15.RegDst[1]
//14.RegDst[0] 13.MemToReg[1] 12.MemToReg[0] 11.ALUsrcA[1] 10.ALUsrcA[0]
//9.ALUsrcB[2] 8.ALUsrcB[1] 7.ALUsrcB[0] 6.op[1] 5.op[0]
//4.IorD 3.ext 2.AddrCtrl[2] 1.AddrCtrl[1] 0.AddrCtrl[0]
reg [22:0] ctrl[0:17];
always @(posedge rst) begin
// for instruction fetch
ctrl[0] <= 23'b01010000000000010100011;
// for waiting state
ctrl[1] <= 23'b00000000000000110101001;
// for calculate memaddr
ctrl[2] <= 23'b00000000000010100101010;
// for read memory
ctrl[3] <= 23'b00000000000000001110011;
// for write back
ctrl[4] <= 23'b00001000001000001100000;
// for write memory
ctrl[5] <= 23'b00100000000000001110000;
// for Rtype-ALU execution
ctrl[6] <= 23'b00000000000010000000100;
// for Rtype-ALU completion
ctrl[7] <= 23'b00001000100000001100000;
// for branch execution
ctrl[8] <= 23'b10000010000010001000000;
// for jump execution
ctrl[9] <= 23'b01000100000000001100000;
// for Itype-ALU_signedext execution
ctrl[10] <= 23'b00000000000010100001101;
// for Itype-ALU_zeroext execution
ctrl[11] <= 23'b00000000000010100000101;
// for Itype-ALU completion
ctrl[12] <= 23'b00001000000000001100000;
// for shift execution
ctrl[13] <= 23'b00000000000101000000100;
// for lui execution
ctrl[14] <= 23'b00000000000111011100101;
// for jump register execution
ctrl[15] <= 23'b01000110000000001100000;
// for jal completion
ctrl[16] <= 23'b01001101010000001100000;
// for jalr completion
ctrl[17] <= 23'b01001110110000001100000;
end
Everything went well in the following four tests:
The content of all the codes are supposed to use a licence AGPLv3
- Learn what is a AGPLv3, if you have not yet done so (see details above).
- Create your change to the repo in question.
- Fork the desired repo, develop and test your code changes.
- Ensure that your code is clear and comprehensible.
- Ensure that your code has an appropriate set of unit tests which all pass.
- Submit a pull request.
- The repo owner will review your request. If it is approved, the change will be merged. If it needs additional work, the repo owner will respond with useful comments.
First of all, I would like to extend my sincere gratitude to my supervisor, Xiaohong Jiang, for her instructive advice and useful suggestions on my learning on computer organization.
I am also deeply grateful of Zhe Pan, the TA's help in the completion and assessment of this project.
High tribute shall be paid to Licheng Guo, whose profound knowledge of CPU and Verilog HDL triggers my inspiration for this brilliant project.