基于FPGA设计的MIPS指令集CPU
导读:网上已经有很多MIPS设计资料和方法,这里就开门见山的了,直接说明从设计到验证的过程。
- 内容:支持单周期\多周期\流水线 冒泡法和字符串统计算法已经验证 本文主要是单周期、其他后面整理发布中
- 开发语言:verilog 开发环境:modelsim
- 已经验证以下指令
add/sub/and/or/slt/sltu/addu/subu/addi/ori/lw/sw/beqj/jal/sll/nor/lui/slti/bne/andi/srl/sllv/srlv/jr/jalr - 采用对比验证方法 Mars与Modelsim对比验证
- 仿真结果正确
对比寄存器和内存仿真图
Mars仿真结果,Mars断点
Modelsim仿真结果,Modelsim断点,r是寄存器数据,dmem是内存数据
下面是MIPS各个模块代码
仿真testbench代码和汇编测试代码在最后
module sccomp(clk, rstn, reg_sel, reg_data);
input clk;
input rstn;
input [4:0] reg_sel;
output [31:0] reg_data;
wire [31:0] instr;
wire [31:0] PC;
wire MemWrite;
wire [31:0] dm_addr, dm_din, dm_dout;
wire rst = ~rstn;
// instantiation of single-cycle CPU
sccpu U_SCCPU(
.clk(clk), // input: cpu clock
.rst(rst), // input: reset
.instr(instr), // input: instruction
.readdata(dm_dout), // input: data to cpu
.MemWrite(MemWrite), // output: memory write signal
.PC(PC), // output: PC
.aluout(dm_addr), // output: address from cpu to memory
.writedata(dm_din), // output: data from cpu to memory
.reg_sel(reg_sel), // input: register selection
.reg_data(reg_data) // output: register data
);
// instantiation of data memory
dm U_DM(
.clk(clk), // input: cpu clock
.DMWr(MemWrite), // input: ram write
.addr(dm_addr[8:2]), // input: ram address
.din(dm_din), // input: data to ram
.dout(dm_dout) // output: data from ram
);
// instantiation of intruction memory (used for simulation)
im U_IM (
.addr(PC[8:2]), // input: rom address
.dout(instr) // output: instruction
);
endmodule
module sccpu( clk, rst, instr, readdata, PC, MemWrite, aluout, writedata, reg_sel, reg_data);
input clk; // clock
input rst; // reset
input [31:0] instr; // instruction
input [31:0] readdata; // data from data memory
output [31:0] PC; // PC address
output MemWrite; // memory write
output [31:0] aluout; // ALU output
output [31:0] writedata; // data to data memory
input [4:0] reg_sel; // register selection (for debug use)
output [31:0] reg_data; // selected register data (for debug use)
wire RegWrite; // control signal to register write
wire EXTOp; // control signal to signed extension
wire [4:0] ALUOp; // ALU opertion
wire [1:0] NPCOp; // next PC operation
wire [1:0] WDSel,MDSel; // (register) write data selection
wire [1:0] GPRSel; // general purpose register selection
wire ALUSrc; // ALU source for A
wire Zero; // ALU ouput zero
wire [31:0] NPC; // next PC
wire [4:0] rs; // rs
wire [4:0] rt; // rt
wire [4:0] rd; // rd
wire [5:0] Op; // opcode
wire [5:0] Funct; // funct
wire [15:0] Imm16; // 16-bit immediate
wire [31:0] Imm32; // 32-bit immediate
wire [25:0] IMM; // 26-bit immediate (address)
wire [4:0] A3; // register address for write
wire [31:0] WD; // register write data
wire [31:0] RD1,RD2; // register data specified by rs
wire [31:0] B; // operator for ALU B
wire [4:0] move_s;
wire ShiftSlt;
assign Op = instr[31:26]; // instruction
assign Funct = instr[5:0]; // funct
assign rs = instr[25:21]; // rs
assign rt = instr[20:16]; // rt
assign rd = instr[15:11]; // rd
assign Imm16 = instr[15:0];// 16-bit immediate
assign IMM = instr[25:0]; // 26-bit immediate
// instantiation of control unit
ctrl U_CTRL (
.Op(Op), .Funct(Funct), .Zero(Zero),
.RegWrite(RegWrite), .MemWrite(MemWrite),
.EXTOp(EXTOp), .ALUOp(ALUOp), .NPCOp(NPCOp), .ShiftSlt(ShiftSlt),
.ALUSrc(ALUSrc), .GPRSel(GPRSel),.MDSel(MDSel), .WDSel(WDSel)
);
// instantiation of PC
PC U_PC (
.clk(clk), .rst(rst), .NPC(NPC), .PC(PC)
);
// instantiation of NPC
NPC U_NPC (
.PC(PC), .NPCOp(NPCOp), .IMM(IMM), .RS(RD1), .NPC(NPC)
);
// instantiation of register file
RF U_RF (
.clk(clk), .rst(rst), .RFWr(RegWrite),
.A1(rs), .A2(rt), .A3(A3