单指令周期MIPS模型机系统结构示意图
image.pngMIPS指令格式
image.pngimage.png
defines.v
//GLOBALFLAG
`define RstEnable 1'b1
`define RstDisable 1'b0
`define ZeroWord 32'h00000000
`define WriteEnable 1'b1
`define WriteDisable 1'b0
`define ReadEnable 1'b1
`define ReadDisable 1'b0
`define AluOpBus 7:0
`define AluSelBus 2:0
`define InstValid 1'b0
`define InstInvalid 1'b1
`define Stop 1'b1
`define NoStop 1'b0
`define InDelaySlot 1'b1
`define NotInDelaySlot 1'b0
`define Branch 1'b1
`define NotBranch 1'b0
`define InterruptAssert 1'b1
`define InterruptNotAssert 1'b0
`define TrapAssert 1'b1
`define TrapNotAssert 1'b0
`define True_v 1'b1
`define False_v 1'b0
`define ChipEnable 1'b1
`define ChipDisable 1'b0
//OPCODE
`define EXE_AND 6'b100100
`define EXE_OR 6'b100101
`define EXE_XOR 6'b100110
`define EXE_NOR 6'b100111
`define EXE_ANDI 6'b001100
`define EXE_ORI 6'b001101
`define EXE_XORI 6'b001110
`define EXE_LUI 6'b001111
`define EXE_ADDI 6'b001000
`define EXE_ADD 6'b100000
`define EXE_SUB 6'b100010
`define EXE_SLL 6'b000000
`define EXE_SRL 6'b000010
`define EXE_SRA 6'b000011
`define EXE_LW 6'b100011
`define EXE_SW 6'b101011
`define EXE_J 6'b000010
`define EXE_JAL 6'b000011
`define EXE_JR 6'b001000
`define EXE_BEQ 6'b000100
`define EXE_BNE 6'b000101
`define EXE_NOP 6'b000000
`define SSNOP 32'b00000000000000000000000001000000
`define EXE_SPECIAL_INST 6'b000000
`define EXE_REGIMM_INST 6'b000001
`define EXE_SPECIAL2_INST 6'b011100
//AluOp
`define EXE_AND_OP 8'b00100100
`define EXE_OR_OP 8'b00100101
`define EXE_XOR_OP 8'b00100110
`define EXE_NOR_OP 8'b00100111
`define EXE_ANDI_OP 8'b01011001
`define EXE_ORI_OP 8'b01011010
`define EXE_XORI_OP 8'b01011011
`define EXE_LUI_OP 8'b01011100
`define EXE_ADDI_OP 8'b01001000
`define EXE_ADD_OP 8'b00100000
`define EXE_SUB_OP 8'b00100010
`define EXE_SLL_OP 8'b01111100
`define EXE_SRL_OP 8'b00000010
`define EXE_SRA_OP 8'b00000011
`define EXE_LW_OP 8'b11100011
`define EXE_SW_OP 8'b11101011
`define EXE_J_OP 8'b01001111
`define EXE_JAL_OP 8'b01010000
`define EXE_JR_OP 8'b00001000
`define EXE_BEQ_OP 8'b01010001
`define EXE_BNE_OP 8'b01010010
`define EXE_NOP_OP 8'b00000000
//AluSel
`define EXE_RES_LOGIC 3'b001
`define EXE_RES_SHIFT 3'b010
`define EXE_RES_MOVE 3'b011
`define EXE_RES_ARITHMETIC 3'b100
`define EXE_RES_MUL 3'b101
`define EXE_RES_JUMP_BRANCH 3'b110
`define EXE_RES_LOAD_STORE 3'b111
`define EXE_RES_NOP 3'b000
//inst_rom
`define InstAddrBus 31:0
`define InstBus 31:0
`define InstMemNum 131071
`define InstMemNumLog2 17
//regfile
`define RegAddrBus 4:0
`define RegBus 31:0
`define RegWidth 32
`define DoubleRegWidth 64
`define DoubleRegBus 63:0
`define RegNum 32
`define RegNumLog2 5
`define NOPRegAddr 5'b00000
//mem
`define MemBus 31:0
`define MemAddrBus 31:0
`define MemWidth 32
`define DataMemNum 131071
`define DataMemNumLog2 17
top.v
`include "defines.v"
module OpenMIPS(input rst,
input clk,
input [`RegBus] rom_data_i,
output [`RegBus] rom_addr_o,
output rom_ce_o);
//ID to Pc
wire[`RegBus] branch_addr;
wire branch_flag;
//ID to EX
wire[`AluOpBus] id_aluop;
wire[`AluSelBus] id_alusel;
wire[`RegBus] id_reg1;
wire[`RegBus] id_reg2;
wire id_wreg;
wire[`RegAddrBus] id_wd;
wire[`RegBus] link_addr;
wire[`InstAddrBus] inst;
//ID to Regfile
wire reg1_read;
wire reg2_read;
wire[`RegBus] reg1_data;
wire[`RegBus] reg2_data;
wire[`RegAddrBus] reg1_addr;
wire[`RegAddrBus] reg2_addr;
//EX to WB
wire ex_wreg;
wire[`RegAddrBus] ex_wd;
wire[`RegBus] ex_wdata;
wire[`AluOpBus] ex_aluop;
wire[`MemAddrBus] ex_memaddr;
wire[`MemBus] ex_reg1data;
wire[`MemBus] ex_reg2data;
//WB to Regfile
wire[`RegAddrBus] wb_wd;
wire wb_wreg;
wire[`RegBus] wb_wdata;
//WB to RamMemdata
wire[`MemBus] mem_wmemdata;
wire[`MemAddrBus] mem_memaddr;
wire mem_wmem;
wire mem_mce;
wire[3:0] mem_msel;
wire[`MemBus] mem_rmemdata;//MEM input into WB
//pc_reg real
pc_reg pc_reg0(
.clk(clk),
.rst(rst),
.branch_addr_i(branch_addr),
.branch_flag_i(branch_flag),
.pc(rom_addr_o),
.ce(rom_ce_o)
);
//ID real
id id0(
.rst(rst),
.pc_i(rom_addr_o),
.inst_i(rom_data_i),
//Regfile - id input
.reg1_data_i(reg1_data), .reg2_data_i(reg2_data),
//id - Regfile output
.reg1_read_o(reg1_read), .reg2_read_o(reg2_read),
.reg1_addr_o(reg1_addr), .reg2_addr_o(reg2_addr),
//id - EX output
.link_addr_o(link_addr),
.inst_o(inst),
.aluop_o(id_aluop), .alusel_o(id_alusel),
.reg1_o(id_reg1), .reg2_o(id_reg2),
.wd_o(id_wd), .wreg_o(id_wreg),
//id - pc output
.branch_addr_o(branch_addr),
.branch_flag_o(branch_flag)
);
//Regfile real
regfile regfile1(
.clk(clk),
.rst(rst),
//WB-regfile input
.we(wb_wreg), .waddr(wb_wd),
.wdata(wb_wdata),
//ID-regfile input
.re1(reg1_read), .raddr1(reg1_addr),
.rdata1(reg1_data),
.re2(reg2_read), .raddr2(reg2_addr),
.rdata2(reg2_data)
);
//EX real
ex ex0(
.rst(rst),
//ID-ex input
.link_addr_i(link_addr),
.inst_i(inst),
.aluop_i(id_aluop), .alusel_i(id_alusel),
.reg1_i(id_reg1), .reg2_i(id_reg2),
.wd_i(id_wd), .wreg_i(id_wreg),
// ex-WB output
.aluop_o(ex_aluop),
.memaddr_o(ex_memaddr),
.reg1data_o(ex_reg1data),//auto
.reg2data_o(ex_reg2data),
.wd_o(ex_wd),
.wreg_o(ex_wreg),
.wdata_o(ex_wdata)
);
//WB real
wb wb0(
.rst(rst),
//ex - wb input
.aluop_i(ex_aluop),
.memaddr_i(ex_memaddr),
.rmemdata_i(mem_rmemdata),
.reg2data_i(ex_reg2data),
// input
.ex_wd(ex_wd),
.ex_wreg(ex_wreg),
.ex_wdata(ex_wdata),
//Wb-regfile output
.wb_wd(wb_wd), .wb_wreg(wb_wreg),
.wb_wdata(wb_wdata),
//wb - mem-ram output
.mem_wmemdata_o(mem_wmemdata),
.mem_memaddr_o(mem_memaddr),
.mem_wmem_o(mem_wmem),
.mem_mce_o(mem_mce),
.mem_msel_o(mem_msel)
);
//MEM real
mem mem1(
.clk(clk),
.mem_wmemdata_i(mem_wmemdata),
.mem_memaddr_i(mem_memaddr),
.mem_wmem_i(mem_wmem),
.mem_msel_i(mem_msel),
.mem_mce_i(mem_mce),
.rmemdata_o(mem_rmemdata)
);
endmodule
module mem(
input wire clk,
input wire [`MemBus] mem_wmemdata_i,
input wire [`MemAddrBus] mem_memaddr_i,
input wire mem_wmem_i,
input wire [3:0] mem_msel_i,
input wire mem_mce_i,
output reg[`MemBus] rmemdata_o
);
reg [`MemBus] ram [`DataMemNum-1:0];
always@(*)
begin
if(mem_mce_i == `ChipDisable)//ce=0 read
begin
rmemdata_o <= `ZeroWord;
end
else
begin
rmemdata_o<=ram[mem_memaddr_i[`DataMemNumLog2+1:2]];
end
end
always@(posedge clk)
begin
if(mem_mce_i == `ChipEnable && mem_wmem_i == `WriteEnable)
begin
ram[mem_memaddr_i[`DataMemNumLog2+1:2]]<=mem_wmemdata_i;
end
end
endmodule
module pc_reg(input clk,
input rst,
input[`RegBus] branch_addr_i,
input branch_flag_i,
output reg [`InstAddrBus] pc,
output reg ce);
always@(posedge clk)
if(rst == `RstEnable)
ce <= `ChipDisable;
else
ce <= `ChipEnable;
always@(posedge clk)
if(ce == `ChipDisable)
pc <= `ZeroWord;
else if(branch_flag_i == `Branch)
pc <= branch_addr_i;
else
pc <= pc + 4'h4;
endmodule
module regfile(
input wire clk,
input wire rst,
//wb-reg input
input wire we,
input wire[`RegAddrBus] waddr,
input wire[`RegBus] wdata,
//id-reg 1
input wire re1,
input wire[`RegAddrBus] raddr1,
output reg[`RegBus] rdata1,
//id-reg 2
input wire re2,
input wire[`RegAddrBus] raddr2,
output reg[`RegBus] rdata2
);
//32 bit 32 depth
reg[`RegBus] regs[0:`RegNum-1];
initial
begin
regs[1]=32'hffff0000;
regs[2]=32'h0000ffff;
regs[3]=32'h0fff0000;
regs[4]=32'h00ff0000;
regs[10]=32'h00ff0000;
regs[11]=32'h00ff0000;
end
//???
always @ (posedge clk) begin
if(rst==`RstDisable)begin
if((we==`WriteEnable) && (waddr !=`RegNumLog2'h0))begin
regs[waddr]<=wdata;
end
end
end
//read reg1
always @ (*) begin
if(rst==`RstEnable) begin
rdata1<=`ZeroWord;
end
else if(raddr1==`RegNumLog2'h0) begin
rdata1<=`ZeroWord;
end
else if(re1==`ReadEnable) begin
rdata1<=regs[raddr1];
end
else begin
rdata1<=`ZeroWord;
end
end
//read reg2
always @ (*) begin
if(rst==`RstEnable) begin
rdata2<=`ZeroWord;
end
else if(raddr2==`RegNumLog2'h0) begin
rdata2<=`ZeroWord;
end
else if(re2==`ReadEnable) begin
rdata2<=regs[raddr2];
end
else begin
rdata2<=`ZeroWord;
end
end
endmodule
module id(
input wire rst,
input wire[`InstAddrBus] pc_i,
input wire[`InstBus] inst_i,
//Regfile - id input
input wire[`RegBus] reg1_data_i,
input wire[`RegBus] reg2_data_i,
//Id - pc output
output reg[`RegBus] branch_addr_o,
output reg branch_flag_o,
//Id - Regfile output
output reg reg1_read_o,
output reg reg2_read_o,
output reg[`RegAddrBus] reg1_addr_o,
output reg[`RegAddrBus] reg2_addr_o,
//ID- Ex output
output reg[`RegBus] link_addr_o,
output reg[`InstAddrBus] inst_o,
output reg[`AluOpBus] aluop_o,
output reg[`AluSelBus] alusel_o,
output reg[`RegBus] reg1_o,
output reg[`RegBus] reg2_o,
output reg[`RegAddrBus] wd_o,
output reg wreg_o
);
wire [5:0] op = inst_i[31:26];//I!=0 _ R=000000
wire [4:0] op2 = inst_i[10:6];
wire [5:0] op3 = inst_i[5:0];
wire [4:0] op4 = inst_i[20:16];//wregaddr rt
reg[`RegBus] imm;
reg instvalid;
wire[`RegBus] pc_plus_4;
wire[`RegBus] pc_plus_8;
wire[`RegBus] imm_sll2_signedext;
//jump attribute
assign pc_plus_4 = pc_i + 3'b100;//j inst nextinst adress
assign pc_plus_8 = pc_i + 4'b1000;//save jal inst return inst adress
assign imm_sll2_signedext = {{14{inst_i[15]}}, inst_i[15:0], 2'b00 }; //imm extend jump address
always@(*)
if(rst == `RstEnable)
begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
instvalid <= `InstValid;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= `NOPRegAddr;
reg2_addr_o <= `NOPRegAddr;
imm <= 32'h0;
link_addr_o <= `ZeroWord;
inst_o <= `ZeroWord;
branch_addr_o <= `ZeroWord;
branch_flag_o <= `NotBranch;
//SW need inst
inst_o <= inst_i;
end
else
begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= inst_i[15:11];
wreg_o <= `WriteDisable;
instvalid <= `InstInvalid;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= inst_i[25:21];
reg2_addr_o <= inst_i[20:16];
imm <= `ZeroWord;
link_addr_o <= `ZeroWord;
inst_o <= `ZeroWord;
branch_addr_o <= `ZeroWord;
branch_flag_o <= `NotBranch;
//SW need inst
inst_o <= inst_i;
case (op)
`EXE_SPECIAL_INST: begin
case (op2)
5'b00000: begin
case (op3)
`EXE_OR: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_OR_OP;
alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_AND: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_AND_OP;
alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_XOR: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_XOR_OP;
alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_ADD: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_ADD_OP;
alusel_o <= `EXE_RES_ARITHMETIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SUB: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_SUB_OP;
alusel_o <= `EXE_RES_ARITHMETIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_JR: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_JR_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;
link_addr_o <= `ZeroWord;
branch_addr_o <= reg1_o;
branch_flag_o <= `Branch;
instvalid <= `InstValid;
end
default: begin
end
endcase
end
default: begin
end
endcase
end
`EXE_ORI: begin //ORI??
wreg_o <= `WriteEnable; aluop_o <= `EXE_OR_OP;
alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;
imm <= {16'h0, inst_i[15:0]}; wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_ANDI: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_AND_OP;
alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;
imm <= {16'h0, inst_i[15:0]}; wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_XORI: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_XOR_OP;
alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;
imm <= {16'h0, inst_i[15:0]}; wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_ADDI: begin //addi
wreg_o <= `WriteEnable; aluop_o <= `EXE_ADD_OP;
alusel_o <= `EXE_RES_ARITHMETIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}}, inst_i[15:0]}; wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LUI: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_OR_OP;
alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;
imm <= {inst_i[15:0], 16'h0}; wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LW: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_LW_OP;
alusel_o <= `EXE_RES_LOAD_STORE; reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;
wd_o <= inst_i[20:16]; instvalid <= `InstValid;
end
`EXE_SW: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_SW_OP;
reg1_read_o <= 1'b1; reg2_read_o <= 1'b1; instvalid <= `InstValid;
alusel_o <= `EXE_RES_LOAD_STORE;
end
`EXE_J: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_J_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH; reg1_read_o <= 1'b0; reg2_read_o <= 1'b0;
link_addr_o <= `ZeroWord;
branch_addr_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};
branch_flag_o <= `Branch;
instvalid <= `InstValid;
end
`EXE_JAL: begin
wreg_o <= `WriteEnable;//write back 31 register
aluop_o <= `EXE_JAL_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH; reg1_read_o <= 1'b0; reg2_read_o <= 1'b0;
wd_o <= 5'b11111;//save return address register
link_addr_o <= pc_plus_4 ;//return instr address
branch_addr_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};
branch_flag_o <= `Branch;
instvalid <= `InstValid;
end
`EXE_BEQ: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_BEQ_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
if(reg1_o == reg2_o) begin
branch_addr_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
end
end
`EXE_BNE: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_BNE_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
if(reg1_o != reg2_o) begin
branch_addr_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
end
end
default: begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= inst_i[15:11];
wreg_o <= `WriteDisable;
instvalid <= `InstValid;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= inst_i[25:21];
reg2_addr_o <= inst_i[20:16];
imm <= 32'h0;
link_addr_o <= `ZeroWord;
inst_o <= `ZeroWord;
branch_addr_o <= `ZeroWord;
branch_flag_o <= `NotBranch;
end
endcase //case op
if (inst_i[31:21] == 11'b00000000000) begin
if (op3 == `EXE_SLL) begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_SLL_OP;
alusel_o <= `EXE_RES_SHIFT; reg1_read_o <= 1'b0; reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6]; wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end else if ( op3 == `EXE_SRL ) begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_SRL_OP;
alusel_o <= `EXE_RES_SHIFT; reg1_read_o <= 1'b0; reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6]; wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end else if ( op3 == `EXE_SRA ) begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_SRA_OP;
alusel_o <= `EXE_RES_SHIFT; reg1_read_o <= 1'b0; reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6]; wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end
end //if
end //always
always @ (*) begin
if(rst == `RstEnable) begin
reg1_o <= `ZeroWord;
end
/*else if((reg1_read_o == 1'b1) && (wreg_o == 1'b1) && (wd_o == reg1_addr_o)) begin
reg1_o <= ex_wdata_i;
end
else if((reg1_read_o == 1'b1) && (mem_wreg_i == 1'b1) && (mem_wd_i == reg1_addr_o)) begin
reg1_o <= mem_wdata_i;
end*/
else if(reg1_read_o == 1'b1) begin
reg1_o <= reg1_data_i;
end else if(reg1_read_o == 1'b0) begin
reg1_o <= imm;
end else begin
reg1_o <= `ZeroWord;
end
end
always @ (*) begin
if(rst == `RstEnable) begin
reg2_o <= `ZeroWord;
end
/*else if((reg2_read_o == 1'b1) && (wreg_o == 1'b1) && (wd_o == reg2_addr_o)) begin
reg2_o <= ex_wdata_i;
end
else if((reg2_read_o == 1'b1) && (mem_wreg_i == 1'b1) && (mem_wd_i == reg2_addr_o)) begin
reg2_o <= mem_wdata_i;
end */
else if(reg2_read_o == 1'b1) begin
reg2_o <= reg2_data_i;
end else if(reg2_read_o == 1'b0) begin
reg2_o <= imm;
end else begin
reg2_o <= `ZeroWord;
end
end
endmodule
module ex(
input rst,
//ID-EX input
input wire[`RegBus] link_addr_i,
input wire[`InstAddrBus] inst_i,
input wire[`AluOpBus] aluop_i,
input wire[`AluSelBus] alusel_i,
input wire[`RegBus] reg1_i,
input wire[`RegBus] reg2_i,
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
//EX-WB output
output reg[`AluOpBus] aluop_o,
output reg[`MemAddrBus] memaddr_o,
output reg[`MemBus] reg1data_o,
output reg[`MemBus] reg2data_o,
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
output reg[`RegBus] wdata_o
);
//logic result
reg[`RegBus] logicout;
reg[`RegBus] shiftres;
reg[`RegBus] arithmeticres;
//LW SW mem
always @ (*) begin
//op
aluop_o <= aluop_i;
//mem_addr
memaddr_o <= reg1_i + {{16{inst_i[15]}},inst_i[15:0]};
//sw save reg2value to memaddr
reg2data_o <= reg2_i;
end
always @ (*) begin
if(rst == `RstEnable) begin
logicout <= `ZeroWord;
end else begin
case (aluop_i)
`EXE_OR_OP: begin
logicout <= reg1_i | reg2_i;
end
`EXE_AND_OP: begin
logicout <= reg1_i & reg2_i;
end
`EXE_XOR_OP: begin
logicout <= reg1_i ^ reg2_i;
end
default: begin
logicout <= `ZeroWord;
end
endcase
end //if
end //always
always @ (*) begin
if(rst == `RstEnable) begin
shiftres <= `ZeroWord;
end else begin
case (aluop_i)
`EXE_SLL_OP: begin
shiftres <= reg2_i << reg1_i[4:0] ;
end
`EXE_SRL_OP: begin
shiftres <= reg2_i >> reg1_i[4:0];
end
`EXE_SRA_OP: begin
shiftres <= ({32{reg2_i[31]}} << (6'd32-{1'b0, reg1_i[4:0]}))
| reg2_i >> reg1_i[4:0];
end
default: begin
shiftres <= `ZeroWord;
end
endcase
end //if
end //always
always @ (*) begin
if(rst == `RstEnable) begin
arithmeticres <= `ZeroWord;
end else begin
case (aluop_i)
`EXE_ADD_OP: begin
arithmeticres <= reg1_i+reg2_i;
end
`EXE_SUB_OP: begin
arithmeticres <= reg1_i-reg2_i;
end
default: begin
arithmeticres <= `ZeroWord;
end
endcase
end
end
//output
always @ (*) begin
wd_o <= wd_i;
/*if(((aluop_i == `EXE_ADD_OP) || (aluop_i == `EXE_ADDI_OP) ||
(aluop_i == `EXE_SUB_OP))) begin
wreg_o <= `WriteDisable;
end else begin
wreg_o <= wreg_i;
end*/
wreg_o <= wreg_i;
aluop_o <= aluop_i;
reg1data_o <= reg1_i;
reg2data_o <= reg2_i;
case ( alusel_i )
`EXE_RES_LOGIC: begin
wdata_o <= logicout;
end
`EXE_RES_SHIFT: begin
wdata_o <= shiftres;
end
`EXE_RES_ARITHMETIC: begin
wdata_o <= arithmeticres;
end
`EXE_RES_JUMP_BRANCH: begin
wdata_o <= link_addr_i;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
endmodule
module wb(
input wire rst,
//EX-WB input
input wire[`RegAddrBus] ex_wd,
input wire ex_wreg,
input wire[`RegBus] ex_wdata,
input wire[`AluOpBus] aluop_i,
input wire[`MemAddrBus] memaddr_i,
input wire[`MemBus] reg2data_i,
//mem-wb input
input wire[`MemBus] rmemdata_i,
//wb-Regfile output
output reg[`RegAddrBus] wb_wd,
output reg wb_wreg,
output reg[`RegBus] wb_wdata,
//wb-mem output
output reg[`MemBus] mem_wmemdata_o,
output reg[`MemAddrBus] mem_memaddr_o,
output reg mem_wmem_o,
output reg mem_mce_o,
output reg[3:0] mem_msel_o
);
always @ (*) begin
if(rst == `RstEnable) begin
wb_wd <= `NOPRegAddr;
wb_wreg <= `WriteDisable;
wb_wdata <= `ZeroWord;
mem_memaddr_o <= `ZeroWord;
mem_wmem_o <= `WriteDisable;
mem_msel_o <= 4'b0000;
mem_wmemdata_o <= `ZeroWord;
mem_mce_o <= `ChipDisable;
end else begin
wb_wd <= ex_wd;
wb_wreg <= ex_wreg;
wb_wdata <= ex_wdata;
mem_wmem_o <= `WriteDisable;
mem_memaddr_o <= `ZeroWord;
mem_msel_o <= 4'b1111;
mem_mce_o <= `ChipDisable;
case (aluop_i)
`EXE_LW_OP: begin
mem_memaddr_o <= memaddr_i;
mem_wmem_o <= `WriteDisable;
mem_wmemdata_o <= rmemdata_i;
mem_msel_o <= 4'b1111;
mem_mce_o <= `ChipEnable;
end
`EXE_SW_OP: begin
mem_memaddr_o <= memaddr_i;
mem_wmem_o <= `WriteEnable;
mem_wmemdata_o <= reg2data_i;
mem_msel_o <= 4'b1111;
mem_mce_o <= `ChipEnable;
end
default: begin
//?????
end
endcase
end //if
end //always
/*
always @ (*) begin
if(rst == `RstEnable) begin
wb_wd <= `NOPRegAddr;
wb_wreg <= `WriteDisable;
wb_wdata <= `ZeroWord;
end else begin
wb_wd <= ex_wd;
wb_wreg <= ex_wreg;
wb_wdata <= ex_wdata;
end //if
end //always
*/
endmodule
text.v
`include "top.v"
module inst_rom(input ce,
input [`InstAddrBus] addr,
output reg [`InstBus] inst);
reg [`InstBus] inst_mem [`InstMemNum-1:0];
initial $readmemh ("G:\init_h.txt",inst_mem);
/*initial
begin
inst_mem[0] = 32'h34011100;
inst_mem[4] = 32'h34020020;
inst_mem[8] = 32'h3403ff00;
inst_mem[12] = 32'h3404ffff;
end
*/
always@(*)
if(ce == `ChipDisable)
inst <= `ZeroWord;
else
inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
endmodule
module openmips_min_sopc(input clk,
input rst);
wire [`InstAddrBus] inst_addr;
wire [`InstBus] inst;
wire rom_ce;
OpenMIPS OpenMIPS0(.clk(clk),
.rst(rst),
.rom_addr_o(inst_addr),
.rom_data_i(inst),
.rom_ce_o(rom_ce));
inst_rom inst_rom0(.ce(rom_ce),
.addr(inst_addr),
.inst(inst));
endmodule
module OpenMIPS_tb;
reg clk;
reg rst;
initial
begin
clk = 1'b0;
forever #10 clk = ~clk;
end
initial
begin
rst = `RstEnable;
#195 rst = `RstDisable;
#1000 $stop;
end
openmips_min_sopc openmips_min_sopc0(.clk(clk),
.rst(rst));
endmodule
测试文件代码:
.org 0x0
.set noat
.set noreorder
.set nomacro
.global _start
_start:
ori $1,$0,0x0001 # $1 = 0x01
ori $2,$0,0x0003
j 0x20
andi $2,$2,0x0001 #if this instruction exed $2=0x01
.org 0x20
addi $3,$1,0x0003 # $3 = $1+0x0003
jal 0x40 # $31 = 0x2c
add $5,$31,$1
j 0x80
.org 0x40
ori $5,$0,0x0001
jr $31
.org 0x80
#è®؟ه�ک
ori $6,$0,0x4455
sll $6,$6,0x10
ori $6,$6,0x6677
sw $6,0x8($0) # [0x8] = 0x44, [0x9]= 0x55, [0xa]= 0x66, [0xb] = 0x77
lw $7,0x8($0) # $1 = 0x4455667
beq $10,$11,s1
or $1,$0,$0
ori $1,$0,0x0001 # $1 = 0x01
ori $2,$0,0x0003
.org 0x00b0
s1:
ori $1,$0,0x1111
nop
bne $10,$1,_start
_loop:
j _loop
生成的机器码:
34010001
34020003
08000008
30420001
00000000
00000000
00000000
00000000
20230003
0c000010
03e12820
08000020
00000000
00000000
00000000
00000000
34050001
03e00008
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
34064455
00063400
34c66677
ac060008
8c070008
114b0006
00000825
34010001
34020003
00000000
00000000
00000000
34011111
00000000
1541ffd1
0800002f
00000000
以上单周期mips模型机的设计代码,仅供参考!!!
网友评论