Assignment
这个作业是测试你对讲座中介绍的MIPS-Lite多周期处理器设计的行为规范的理解。
Verilog代码示例见附录A。
你需要在设计中添加一个指令存储器,并用你的汇编代码对其进行初始化。程序在附录B中给出。目前指令存储器ROM的存储器初始化文件是空的。你可以把你的MIPS指令的机器代码写进初始化文件的内存位置。
附录C中注明了具体任务。
该任务要分一系列步骤进行,你应该按顺序完成。
• 绘制状态机的ASM图。
• 2. 写一个方案,以。
•
• a. 将存储在数据存储器X和Y位置的数据装入寄存器P和Q。
•
• b. 将寄存器P与常数6相加,并将结果存储在寄存器R中。
•
• c. 如果寄存器Q和R中的结果相等,则分支到指令a。
•
• d. 将寄存器R中的结果存储到存储器位置24中。
•
• e. 跳转到指令a。
•
• 3. 模拟你的程序。为了测试指令d和e,你需要在某个阶段改变数据存储器中的数据。
•
• 4. 增加支持AND、OR、sub、slt、NOR等R型指令的代码,并模拟附表中各学生指定的指令。
•
• 增加一些扩展,以应对当检测到该MIPS-lite处理器不支持的操作码或PC进入数据存储器的地址时的异常情况。
报告
你的报告应包括以下内容。
1. 状态机的ASM图。
2. MIPS代码和相应的机器代码。
3. 必须演示运算码、状态机、PC、IR、ALUOut和相关寄存器(P、Q、R)的仿真波形,并加以注释。你应该清楚地指出为什么仿真显示操作正确或不正确。
4. 说明为实现附加指令或扩展所做的修改。突出显示在代码中所作的修改。
Appendix A
// The behavioural specification of a MIPS multicycle processor originaly developed for simulation by Patterson and Hennesy
// Modified by Dr. M. Xu in June 2010
module CPU (clock, reset, opcode, state, PC, IR, ALUOut, MDR, A, B, P, Q, R);
parameter R_Type = 6’b000000, LW = 6’b100011, SW = 6’b101011, BEQ=6’b000100, J=6’000010;
input clock, reset; //external inputs
output [31:0] PC, IR, ALUOut, MDR, A, B, P, Q, R;
output [2:0] state;
output [5:0] opcode;
// The architecturally visible registers and scratch registers for implementation
reg [31:0] PC, Regs[0:31], Memory [0:31], IR, ALUOut, MDR, A, B;
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
assign SignExtend = {{16{IR[15]}},IR[15:0]}; //sign extension of lower 16-bits of instruction
assign PCOffset = SignExtend << 2; //PC offset is shifted
assign P = Regs[1]; // you must change registers according to your tasks !
assign Q = Regs[2];
assign R = Regs[3];
// set the PC to 0 and start the control in state 1
initial begin PC = 0; state = 1; end
//The state machine--triggered on a rising clock
always @(posedge clock or posedge reset) begin
Regs[0] = 0; // to make sure R0 is always 0
if (reset) begin
PC = 0;
state = 1;
Memory[16]=32'h00000005; // words 16-31 used for data memory
Memory[17]=32'h0000000B;
Memory[18]=32'h00000055;
Memory[19]=32'h000000BB;
Memory[20]=32'h00005555;
Memory[21]=32'h0000BBBB;
Memory[22]=32'h55555555;
Memory[23]=32'hBBBBBBBB;
// words 0-15 used for instruction memory
// add the machine code of your instructions here
end
else begin
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 == R_Type) 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 == R_Type) 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 ; // 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
default: state = 1;
endcase
end
end
endmodule
Appdendix B
Inserting LPM ROM
Select MegaWizard Plug-In Manager from the tools menu and click on the Next button.
Select the ROM: 1-PORT and give a name to the output file. This name should be the same as the one which has been used for Instruction memory instantiation in your Verilog code.
Select the width and depth of the memory.
Deselect the input and output registers.
Give a name to the memory initialisation file, e.g. Instruction.mif. You can use your name as the file name. In this case you should edit the Verilog module name in the provided code.
Deselect the creation of the optional files and click on Finish button.
Click on the New icon and select the Memory Initialization File.
Input 32 for the Number of words and 32 for the Word size.
Now you can insert your machine code into the Instruction memory locations. You should be noted that this memory is not byte oriented and addresses are incremented by one not by 4.
Memory locations (X,Y):16,17
Registers
• (P,Q,R):2,3,4
• Simulation:OR