五级流水线MIPS模型机系统结构示意图
MIPS指令格式
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
`define IOBase 32'hfffff000
//MipsAluOp
`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_MULT 6'b011000
`define EXE_MUL 6'b000010
`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_MULT_OP 8'b00011000
`define EXE_MUL_OP 8'b10101001
`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 511//131071
`define InstMemNumLog2 10//17
`define KeyBus 15:0
`define SEGBus 31:0
//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 511 //131071
`define DataMemNumLog2 10 //17
//IO
`define IONum 511//4095
`define IOWidth 32
`define IOBus 31:0
`define IOAddrBus 31:0
`define IONumLog2 10//12
//IO _ Addr
`define SEG_ADDR 32'hFFFFF000
`define LED_ADDR 32'hFFFFF004
`define KEY_ADDR 32'hFFFFF008
`define BUTTON_ADDR 32'hFFFFF00c
test.v
`include "top.v"
module inst_rom(input wire ce,
input wire [`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'h8fc50008;
inst_mem[1] = 32'hafc20004;
inst_mem[2] = 32'h8fc6000c;
inst_mem[3] = 32'hafc40000;
end
*/
always@(*)
if(ce == `ChipDisable)
inst <= `ZeroWord;
else
inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
endmodule
module openmips_min_sopc(input wire clk,
input wire 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 = `RstDisable;
#195 rst = `RstEnable;
#1000 $stop;
end
openmips_min_sopc openmips_min_sopc0(.clk(clk),
.rst(rst));
endmodule
top.v
`include "defines.v"
module OpenMIPS(input wire rst,
input wire clk,
input wire [`RegBus] rom_data_i,
output wire [`RegBus] rom_addr_o,
output wire rom_ce_o);
//if_id to id input
wire[`RegBus] rom_data_i1;
wire[`RegBus] rom_addr_i1;
//ID to ID_EX
wire[`RegBus] branch_addr;
wire branch_flag;
//ID_EX to pc
wire[`RegBus] branch_addr1;
wire branch_flag1;
//ID to ID_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_EX to EX
wire[`AluOpBus] id_aluop1;
wire[`AluSelBus] id_alusel1;
wire[`RegBus] id_reg11;
wire[`RegBus] id_reg21;
wire id_wreg1;
wire[`RegAddrBus] id_wd1;
wire[`RegBus] link_addr1;
wire[`InstAddrBus] inst1;
//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 EX_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;
//EX_WB to WB
wire ex_wreg1;
wire[`RegAddrBus] ex_wd1;
wire[`RegBus] ex_wdata1;
wire[`AluOpBus] ex_aluop1;
wire[`MemAddrBus] ex_memaddr1;
wire[`MemBus] ex_reg1data1;
wire[`MemBus] ex_reg2data1;
//WB to wb_moic
wire[`RegAddrBus] wb_wd;
wire wb_wreg;
wire[`RegBus] wb_wdata;
//wb to wb_mioc
wire[`RegAddrBus] wb_wd1;
//MIOC to id input
wire[`RegAddrBus] wb_wd2;
//wb to id
wire[`RegAddrBus] wb_wd_id;
wire wb_wreg_id;
wire[`RegBus] wb_wdata_id;
//ex to id
wire[`RegAddrBus] ex_wd_id;
wire ex_wreg_id;
wire[`RegBus] ex_wdata_id;
/*
//WB to MIOC
wire[`MemBus] mem_wmemdata;
wire[`MemAddrBus] mem_memaddr;
wire mem_wmem;
wire mem_mce;
wire[3:0] mem_msel;
wire[`MemBus] mem_rm_idata;//MEM input into WB
*/
//HILO to ex
wire[`RegBus] ex_hi;
wire[`RegBus] ex_lo;
//HI - LO to ex input
wire[`RegBus] HILO_hi;
wire[`RegBus] HILO_lo;
wire HILO_whilo;
//wb to wb_mioc input
wire ior;
wire iow;
wire [`MemBus] rm_idata;
wire [`MemBus] wm_idata;
wire [`MemAddrBus] m_iaddr;
wire mw;
wire mr;
wire [3:0] msel;
//wb_mioc to mioc input
wire ior1;
wire iow1;
wire [`MemBus] rm_idata1;
wire [`MemBus] wm_idata1;
wire [`MemAddrBus] m_iaddr1;
wire mw1;
wire mr1;
wire [3:0] msel1;
//MIOC to Mem output
wire[`MemBus] rmdata;
wire[`MemBus] wmdata;
wire[`MemAddrBus] maddr;
wire memw;
wire mce;
wire[3:0] MI_msel;
//MIOC to IO output
wire [`IOBus] wiodata;
wire [`IOBus] riodata;
wire iow2;
wire ice;
wire [`IOAddrBus] ioaddr;
//IO to FPGA
wire [`KeyBus] key;
wire [`SEGBus] SEG;
wire [`KeyBus] LED;
// id to ctrl req
wire stallreq_from_id;
//wire stallreq_from_mem;
//ctrl signal
wire [5:0] stall_ctrl;
//deal with load data relation
wire[`AluOpBus] ex_aluop_to_id;
wire[`AluOpBus] wb_aluop_to_id;
wire[`AluOpBus] MIOC_aluop_to_id;
wire[`AluOpBus] wb_MIOC_aluop;
wire[`AluOpBus] wb_MIOC_aluop1;
wire rst_sig = !rst;
assign wb_wd1 = wb_wd;
assign ex_aluop_to_id = ex_aluop;
assign wb_aluop_to_id = wb_MIOC_aluop;
ctrl ctrl1(
.rst(rst_sig),
//from ex stop req
.stallreq_from_id(stallreq_from_id),
//.stallreq_from_mem(stallreq_from_mem),
.stall(stall_ctrl)
);
//pc_reg real
pc_reg pc_reg0(
.clk(clk),
.rst(rst_sig),
.stall(stall_ctrl),
.branch_addr_i(branch_addr),
.branch_flag_i(branch_flag),
.pc(rom_addr_o),
.ce(rom_ce_o)
);
//IF_ID real
IF_ID if_id1(
.clk(clk),
.rst(rst_sig),
.stall(stall_ctrl),
//rom to IF-ID input
.inst_i(rom_data_i),
//pc to IF-ID input
.pc_i(rom_addr_o),
//IF-ID to id output
.inst_o(rom_data_i1),
.pc_o(rom_addr_i1)
);
//ID real
id id0(
.rst(rst_sig),
.pc_i(rom_addr_i1),
.inst_i(rom_data_i1),
//deal with data relation
.ex_aluop_i(ex_aluop_to_id),
.wb_aluop_i(wb_aluop_to_id),
.MIOC_aluop_i(MIOC_aluop_to_id),
//Regfile - id input
.reg1_data_i(reg1_data), .reg2_data_i(reg2_data),
//MIOC to id
.MIOC_wd_to_id_i(wb_wd2),
//wb to id input
.wb_wd_to_id_i(wb_wd_id),
.wb_wreg_to_id_i(wb_wreg_id),
.wb_wdata_to_id_i(wb_wdata_id),
//ex to id input
.ex_wd_to_id_i(ex_wd_id),
.ex_wreg_to_id_i(ex_wreg_id),
.ex_wdata_to_id_i(ex_wdata_id),
//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),
.stallreq(stallreq_from_id)
);
//Regfile real
regfile regfile1(
.clk(clk),
.rst(rst_sig),
//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)
);
//ID_EX real
ID_EX id_ex1(
.clk(clk),
.rst(rst_sig),
.stall(stall_ctrl),
// id to ID_EX input
.branch_addr_i(branch_addr),
.branch_flag_i(branch_flag),
//id to 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),
//ID_EX to pc output
.branch_addr_o(branch_addr1),
.branch_flag_o(branch_flag1),
//ID_EX to Ex output
.link_addr_o(link_addr1),
.inst_o(inst1),
.aluop_o(id_aluop1),
.alusel_o(id_alusel1),
.reg1_o(id_reg11),
.reg2_o(id_reg21),
.wd_o(id_wd1),
.wreg_o(id_wreg1)
);
//EX real
ex ex0(
.rst(rst_sig),
//ID-ex input
.link_addr_i(link_addr1),
.inst_i(inst1),
.aluop_i(id_aluop1), .alusel_i(id_alusel1),
.reg1_i(id_reg11), .reg2_i(id_reg21),
.wd_i(id_wd1), .wreg_i(id_wreg1),
//ex_to_id output
.ex_wd_to_id_o(ex_wd_id),
.ex_wreg_to_id_o(ex_wreg_id),
.ex_wdata_to_id_o(ex_wdata_id),
//HI?LO?????
.hi_i(ex_hi),
.lo_i(ex_lo),
.hi_o(HILO_hi),
.lo_o(HILO_lo),
.whilo_o(HILO_whilo),
// ex-WB output
.aluop_o(ex_aluop),
.memaddr_o(ex_memaddr),
.reg1data_o(ex_reg1data),//
.reg2data_o(ex_reg2data),
.wd_o(ex_wd),
.wreg_o(ex_wreg),
.wdata_o(ex_wdata)
);
// EX_WB real
EX_WB ex_wb1(
.clk(clk),
.rst(rst_sig),
.stall(stall_ctrl),
//ex to EX_WB input
.aluop_i(ex_aluop),
.memaddr_i(ex_memaddr),
.reg1data_i(ex_reg1data),
.reg2data_i(ex_reg2data),
.wd_i(ex_wd),
.wreg_i(ex_wreg),
.wdata_i(ex_wdata),
//EX_WB to wb output
.aluop_o(ex_aluop1),
.memaddr_o(ex_memaddr1),
.reg1data_o(ex_reg1data1),
.reg2data_o(ex_reg2data1),
.wd_o(ex_wd1),
.wreg_o(ex_wreg1),
.wdata_o(ex_wdata1)
);
hilo_reg hilo_reg1(
.clk(clk),
.rst(rst_sig),
.we(HILO_whilo),
.hi_i(HILO_hi),
.lo_i(HILO_lo),
.hi_o(ex_hi),
.lo_o(ex_lo)
);
//WB real
wb wb0(
.rst(rst_sig),
//ex - wb input
.aluop_i(ex_aluop1),
.memaddr_i(ex_memaddr1),
.rmemdata_i(rm_idata),
.reg1data_i(ex_reg1data1),
.reg2data_i(ex_reg2data1),
// input
.ex_wd(ex_wd1),
.ex_wreg(ex_wreg1),
.ex_wdata(ex_wdata1),
.aluop_o(wb_MIOC_aluop),
//wb_to_id output
.wb_wd_to_id_o(wb_wd_id),
.wb_wreg_to_id_o(wb_wreg_id),
.wb_wdata_to_id_o(wb_wdata_id),
//Wb-regfile output
.wb_wd(wb_wd), .wb_wreg(wb_wreg),
.wb_wdata(wb_wdata),
//wb - mem-ram output
.mem_wmemdata_o(wm_idata),
.mem_memaddr_o(m_iaddr),
.mem_wmem_o(mw),
.mem_rmem_o(mr),
.mem_msel_o(msel),
.iow(iow),
.ior(ior)
);
WB_MIOC wb_mioc1(
.clk(clk),
.rst(rst_sig),
.stall(stall_ctrl),
.aluop_i(wb_MIOC_aluop),
.aluop_o(wb_MIOC_aluop1),
//wb to WB_MIOC input
.rmemdata_o(rm_idata),
.iow_i(iow),
.ior_i(ior),
.mem_wmemdata_i(wm_idata),
.mem_memaddr_i(m_iaddr),
.mem_wmem_i(mw),
.mem_rmem_i(mr),
.mem_msel_i(msel),
//wb-wb-moic input
.wb_wd_i(wb_wd1),
//.wb_wreg_i(wb_wreg),
//.wb_wdata_i(wb_wdata),
//WB_MIOC to MIOC output
.ior_o(ior1),
.iow_o(iow1),
.rm_idata_i(rm_idata1),
.wm_idata_o(wm_idata1),
.m_iaddr_o(m_iaddr1),
.mw_o(mw1),
.mr_o(mr1),
.msel_o(msel1),
//WB_MIOC-Regfile output
.wb_wd_o(wb_wd2)
//.wb_wreg_o(wb_wreg1),
//.wb_wdata_o(wb_wdata1),
//.stallreq_from_mem(stallreq_from_mem)
);
MIOC MIOC1(//wb to mioc input
.rst(rst_sig),
.aluop_i(wb_MIOC_aluop1),
.ior_i(ior1),
.iow_i(iow1),
.rm_idata_o(rm_idata1),
.wm_idata_i(wm_idata1),
.m_iaddr_i(m_iaddr1),
.mw_i(mw1),
.mr_i(mr1),
.msel_i(msel1),
.aluop_o(MIOC_aluop_to_id),
//MIOC to Mem output
.rmdata_i(rmdata),
.wmdata_o(wmdata),
.maddr_o(maddr),
.memw_o(memw),
.mce_o(mce),
.msel_o(MI_msel),
//MIOC to IO output
.wiodata_o(wiodata),
.riodata_i(riodata),
.iow_o(iow2),
.ice_o(ice),
.ioaddr_o(ioaddr)
);
//MEM real
mem mem1(
.clk(clk),
.mem_wmemdata_i(wmdata),
.mem_memaddr_i(maddr),
.mem_wmem_i(memw),
.mem_msel_i(MI_msel),
.mem_mce_i(mce),
.rmemdata_o(rmdata)
);
IO IO1(
.addr_i(ioaddr),
.ce_i(ice),
.iow_i(iow2),
.rdata_o(riodata),
.wdata_i(wiodata),
.clk(clk),
.rst(rst_sig),
.key(key),
.SEG(SEG),
.LED(LED)
);
endmodule
module IF_ID(
input wire clk,
input wire rst,
//?????????
input wire[5:0] stall,
//rom to IF-ID input
input wire [`InstBus] inst_i,
//pc to IF-ID input
input wire [`InstAddrBus] pc_i,
//IF-ID to id output
output reg [`InstBus] inst_o,
output reg [`InstAddrBus] pc_o
);
always@(posedge clk)
begin
if(rst == `RstEnable)
begin
inst_o <= `ZeroWord;
pc_o <= `ZeroWord;
end else if(stall[1] == `Stop && stall[2] == `NoStop) begin
inst_o <= `ZeroWord;
pc_o <= `ZeroWord;
end else if(stall[1] == `NoStop) begin
inst_o <= inst_i;
pc_o <= pc_i;
end
end
endmodule
module ID_EX(
input wire clk,
input wire rst,
//?????????
input wire[5:0] stall,
// id to ID_EX input
input wire[`RegBus] branch_addr_i,
input wire branch_flag_i,
//id to 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,
//ID_EX to pc output
output reg[`RegBus] branch_addr_o,
output reg branch_flag_o,
//ID_EX to 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
);
always@(posedge clk)
begin
if(rst == `RstEnable)
begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
link_addr_o <= `ZeroWord;
inst_o <= `ZeroWord;
branch_addr_o <= `ZeroWord;
branch_flag_o <= `NotBranch;
reg1_o <= `ZeroWord;
reg2_o <= `ZeroWord;
end else if(stall[2] == `Stop && stall[3] == `NoStop) begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
link_addr_o <= `ZeroWord;
inst_o <= `ZeroWord;
branch_addr_o <= `ZeroWord;
branch_flag_o <= `NotBranch;
reg1_o <= `ZeroWord;
reg2_o <= `ZeroWord;
end else if(stall[2] == `NoStop) begin
branch_addr_o <= branch_addr_i;
branch_flag_o<= branch_flag_i;
link_addr_o<= link_addr_i;
inst_o<= inst_i;
aluop_o<= aluop_i;
alusel_o<= alusel_i;
reg1_o<= reg1_i;
reg2_o<= reg2_i;
wd_o<= wd_i;
wreg_o<= wreg_i;
end
end
endmodule
module EX_WB(
input wire clk,
input wire rst,
//?????????
input wire[5:0] stall,
//ex to EX_WB input
input wire[`AluOpBus] aluop_i,
input wire[`MemAddrBus] memaddr_i,
input wire[`MemBus] reg1data_i,
input wire[`MemBus] reg2data_i,
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
input wire[`RegBus] wdata_i,
//EX_WB to 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
);
always@(posedge clk)
begin
if(rst == `RstEnable)
begin
aluop_o <= `EXE_NOP_OP;
memaddr_o <= `ZeroWord;
reg1data_o <= `ZeroWord;
reg2data_o <= `ZeroWord;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
wdata_o <= `ZeroWord;
end else if(stall[3] == `Stop && stall[4] == `NoStop) begin
aluop_o <= `EXE_NOP_OP;
memaddr_o <= `ZeroWord;
reg1data_o <= `ZeroWord;
reg2data_o <= `ZeroWord;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
wdata_o <= `ZeroWord;
end else if(stall[3] == `NoStop) begin
aluop_o <= aluop_i;
memaddr_o <= memaddr_i;
reg1data_o <= reg1data_i;
reg2data_o <= reg2data_i;
wd_o <= wd_i;
wreg_o <= wreg_i;
wdata_o <= wdata_i;
end
end
endmodule
module WB_MIOC(
input wire clk,
input wire rst,
//?????????
input wire[5:0] stall,
input wire[`AluOpBus] aluop_i,
//wb to WB_MIOC input
output reg[`MemBus] rmemdata_o,
input wire iow_i,
input wire ior_i,
input wire[`MemBus] mem_wmemdata_i,
input wire[`MemAddrBus] mem_memaddr_i,
input wire mem_wmem_i,
input wire mem_rmem_i,
input wire[3:0] mem_msel_i,
//wb - WB_MIOC input
input wire[`RegAddrBus] wb_wd_i,
input wire wb_wreg_i,
input wire[`RegBus] wb_wdata_i,
output reg[`AluOpBus] aluop_o,
//WB_MIOC to MIOC output
output reg ior_o,
output reg iow_o,
input wire [`MemBus] rm_idata_i,
output reg [`MemBus] wm_idata_o,
output reg [`MemAddrBus] m_iaddr_o,
output reg mw_o,
output reg mr_o,
output reg [3:0] msel_o,
//WB_MIOC-Regfile output
output reg[`RegAddrBus] wb_wd_o,
output reg wb_wreg_o,
output reg[`RegBus] wb_wdata_o
);
always@(posedge clk)
begin
if(rst == `RstEnable)
begin
rmemdata_o <= `ZeroWord;
ior_o <= `ReadDisable;
iow_o <= `WriteDisable;
wm_idata_o <= `ZeroWord;
m_iaddr_o <= `ZeroWord;
mw_o <= `WriteDisable;
mr_o <= `ReadDisable;
msel_o <= 4'b0000;
wb_wd_o <= `NOPRegAddr;
wb_wreg_o <= `WriteDisable;
wb_wdata_o <= `ZeroWord;
aluop_o <= `EXE_NOP_OP;
end else if(stall[4] == `Stop && stall[5] == `NoStop) begin
rmemdata_o <= `ZeroWord;
ior_o <= `ReadDisable;
iow_o <= `WriteDisable;
wm_idata_o <= `ZeroWord;
m_iaddr_o <= `ZeroWord;
mw_o <= `WriteDisable;
mr_o <= `ReadDisable;
msel_o <= 4'b0000;
wb_wd_o <= `NOPRegAddr;
wb_wreg_o <= `WriteDisable;
wb_wdata_o <= `ZeroWord;
aluop_o <= `EXE_NOP_OP;
end else if(stall[4] == `NoStop) begin
rmemdata_o <= rm_idata_i;
ior_o <= ior_i;
iow_o <= iow_i;
wm_idata_o <= mem_wmemdata_i;
m_iaddr_o <= mem_memaddr_i;
mw_o <= mem_wmem_i;
mr_o <=mem_rmem_i;
msel_o <= mem_msel_i;
wb_wd_o <= wb_wd_i;
wb_wreg_o <= wb_wreg_i;
wb_wdata_o <= wb_wdata_i;
aluop_o <= aluop_i;
end
end
endmodule
module ctrl(
input wire rst,
//from ex stop req
input wire stallreq_from_id,
//input wire stallreq_from_mem,
output reg[5:0] stall
);
always @ (*) begin
if(rst == `RstEnable) begin
stall <= 6'b000000;
end /*else if(stallreq_from_mem == `Stop) begin
stall <= 6'b000011;
end*/ else if(stallreq_from_id == `Stop) begin
stall <= 6'b110000;
end else begin
stall <= 6'b000000;
end //if
end //always
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 wire clk,
input wire rst,
//from ctrl info
input wire[5:0] stall,
input wire [`RegBus] branch_addr_i,
input wire 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 if(stall[0] == `NoStop)
pc <= pc + 3'b100;
endmodule
// HI-LO
module hilo_reg(
input wire clk,
input wire rst,
//???
input wire we,
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
//???1
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o
);
always @ (*) begin
if (rst == `RstEnable) begin
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end else if((we == `WriteEnable)) begin
hi_o <= hi_i;
lo_o <= lo_i;
end
end
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[30]=32'hfffff000;
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,
//deal with load data relation
input wire[`AluOpBus] ex_aluop_i,
input wire[`AluOpBus] wb_aluop_i,
input wire[`AluOpBus] MIOC_aluop_i,
//Regfile - id input
input wire[`RegBus] reg1_data_i,
input wire[`RegBus] reg2_data_i,
//MIOC to id
input wire[`RegAddrBus] MIOC_wd_to_id_i,
//wb to id
input wire[`RegAddrBus] wb_wd_to_id_i,
input wire wb_wreg_to_id_i,
input wire[`RegBus] wb_wdata_to_id_i,
//ex to id
input wire[`RegAddrBus] ex_wd_to_id_i,
input wire ex_wreg_to_id_i,
input wire[`RegBus] ex_wdata_to_id_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,
output reg stallreq
);
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;
reg stallreq_for_reg1_loadrelate;
reg stallreq_for_reg2_loadrelate;
wire pre_inst_is_load;
wire pre2_inst_is_load;
wire pre3_inst_is_load;
assign pre_inst_is_load = (ex_aluop_i == `EXE_LW_OP)? 1'b1 : 1'b0;
assign pre2_inst_is_load = (wb_aluop_i == `EXE_LW_OP)? 1'b1 : 1'b0;
assign pre3_inst_is_load = (MIOC_aluop_i == `EXE_LW_OP)? 1'b1 : 1'b0;
//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
//stream stop
always@(*)begin
stallreq = stallreq_for_reg1_loadrelate | stallreq_for_reg2_loadrelate;
end
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;
stallreq <= `NoStop;
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;
stallreq <= `NoStop;
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_MULT: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_MULT_OP;
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; //stallreq <= `Stop;
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; // stallreq <= `Stop;
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
`EXE_SPECIAL2_INST: begin
case ( op3 )
`EXE_MUL: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_MUL_OP;
alusel_o <= `EXE_RES_MUL; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
default: begin
end
endcase //EXE_SPECIAL_INST2 case
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
stallreq_for_reg1_loadrelate <= `NoStop;
if(rst == `RstEnable) begin
reg1_o <= `ZeroWord;
end
else if(pre_inst_is_load == 1'b1 && ex_wd_to_id_i == reg1_addr_o && reg1_read_o == 1'b1 ) begin
stallreq_for_reg1_loadrelate <= `Stop;
end
else if(pre2_inst_is_load == 1'b1 && wb_wd_to_id_i == reg1_addr_o && reg1_read_o == 1'b1 ) begin
stallreq_for_reg1_loadrelate <= `Stop;
end
else if(pre3_inst_is_load == 1'b1 && MIOC_wd_to_id_i == reg1_addr_o && reg1_read_o == 1'b1 ) begin
stallreq_for_reg1_loadrelate <= `Stop;
end
else if((reg1_read_o == 1'b1) && (ex_wreg_to_id_i == 1'b1) && (ex_wd_to_id_i == reg1_addr_o)) begin
reg1_o <= ex_wdata_to_id_i;
end
else if((reg1_read_o == 1'b1) && (wb_wreg_to_id_i == 1'b1) && (wb_wd_to_id_i == reg1_addr_o)) begin
reg1_o <= wb_wdata_to_id_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
stallreq_for_reg2_loadrelate <= `NoStop;
if(rst == `RstEnable) begin
reg2_o <= `ZeroWord;
end
else if(pre_inst_is_load == 1'b1 && ex_wd_to_id_i == reg2_addr_o && reg2_read_o == 1'b1 ) begin
stallreq_for_reg2_loadrelate <= `Stop;
end
else if(pre2_inst_is_load == 1'b1 && wb_wd_to_id_i == reg2_addr_o && reg2_read_o == 1'b1 ) begin
stallreq_for_reg2_loadrelate <= `Stop;
end
else if(pre3_inst_is_load == 1'b1 && MIOC_wd_to_id_i == reg2_addr_o && reg2_read_o == 1'b1 ) begin
stallreq_for_reg2_loadrelate <= `Stop;
end
else if((reg2_read_o == 1'b1) && (ex_wreg_to_id_i == 1'b1) && (ex_wd_to_id_i == reg2_addr_o)) begin
reg2_o <= ex_wdata_to_id_i;
end
else if((reg2_read_o == 1'b1) && (wb_wreg_to_id_i == 1'b1) && (wb_wd_to_id_i == reg2_addr_o)) begin
reg2_o <= wb_wdata_to_id_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 wire 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,
//HI?LO?????
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o,
output reg whilo_o,
output reg[`RegAddrBus] ex_wd_to_id_o,
output reg ex_wreg_to_id_o,
output reg[`RegBus] ex_wdata_to_id_o,
//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
// output reg stallreq
);
//logic result
reg[`RegBus] logicout;
reg[`RegBus] shiftres;
reg[`RegBus] arithmeticres;
reg[`DoubleRegBus] mulres;
reg[`RegBus] HI;
reg[`RegBus] LO;
wire[`RegBus] reg2_i_mux;
wire[`RegBus] reg1_i_not;
wire[`RegBus] result_sum;
wire ov_sum;
wire[`RegBus] opdata1_mult;
wire[`RegBus] opdata2_mult;
wire[`DoubleRegBus] hilo_temp;
//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
reg1data_o <= reg1_i;
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
//add?sub op2
assign reg2_i_mux = (aluop_i == `EXE_SUB_OP)
? (~reg2_i)+1 : reg2_i;
//add?sub result
assign result_sum = reg1_i + reg2_i_mux;
//overflag
assign ov_sum = ((!reg1_i[31] && !reg2_i_mux[31]) && result_sum[31]) ||
((reg1_i[31] && reg2_i_mux[31]) && (!result_sum[31]));
always @ (*) begin
if(rst == `RstEnable) begin
arithmeticres <= `ZeroWord;
end else begin
case (aluop_i)
`EXE_ADD_OP: begin
arithmeticres <= result_sum;
end
`EXE_SUB_OP: begin
arithmeticres <= result_sum;
end
default: begin
arithmeticres <= `ZeroWord;
end
endcase
end
end
//mul two op
assign opdata1_mult = (((aluop_i == `EXE_MUL_OP) || (aluop_i == `EXE_MULT_OP))
&& (reg1_i[31] == 1'b1)) ? (~reg1_i + 1) : reg1_i;
assign opdata2_mult = (((aluop_i == `EXE_MUL_OP) || (aluop_i == `EXE_MULT_OP))
&& (reg2_i[31] == 1'b1)) ? (~reg2_i + 1) : reg2_i;
//mul result
assign hilo_temp = opdata1_mult*opdata2_mult;
always @ (*) begin
if(rst == `RstEnable) begin
mulres <= {`ZeroWord,`ZeroWord};
end else if ((aluop_i == `EXE_MULT_OP) || (aluop_i == `EXE_MUL_OP))begin
if(reg1_i[31] ^ reg2_i[31] == 1'b1) begin
mulres <= ~hilo_temp + 1;
end else begin
mulres <= hilo_temp;
end
end else begin
mulres <= hilo_temp;
end
end
//ex to mem?wb
always @ (*) begin
if(rst == `RstEnable) begin
{HI,LO} <= {`ZeroWord,`ZeroWord};
end else begin
{HI,LO} <= {hi_i,lo_i};
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)) && (ov_sum == 1'b1)) begin
wreg_o <= `WriteDisable;
end else begin
wreg_o <= wreg_i;
end
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_MUL: begin
wdata_o <= mulres[31:0];
end
`EXE_RES_JUMP_BRANCH: begin
wdata_o <= link_addr_i;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
//HI _ LO
always @ (*) begin
if(rst == `RstEnable) begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end else if(aluop_i == `EXE_MULT_OP||aluop_i == `EXE_MUL_OP) begin
whilo_o <= `WriteEnable;
hi_o <= mulres[63:32];
lo_o <= mulres[31:0];
end else begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end
end
//ex - id
always @ (*) begin
ex_wd_to_id_o <= wd_o;
ex_wreg_to_id_o <= wreg_o;
ex_wdata_to_id_o <= wdata_o;
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] reg1data_i,
input wire[`MemBus] reg2data_i,
//mem-wb input
input wire[`MemBus] rmemdata_i,
output reg[`AluOpBus] aluop_o,
output reg[`RegAddrBus] wb_wd_to_id_o,
output reg wb_wreg_to_id_o,
output reg[`RegBus] wb_wdata_to_id_o,
//
output reg iow,
output reg ior,
//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_rmem_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_rmem_o <= `ReadDisable;
mem_msel_o <= 4'b0000;
mem_wmemdata_o <= `ZeroWord;
iow <= `WriteDisable;
ior <= `ReadDisable;
//mem_mce_o <= `ChipDisable;
aluop_o <= `EXE_NOP_OP;
end else begin
wb_wd <= ex_wd;
wb_wreg <= ex_wreg;
wb_wdata <= ex_wdata;
mem_memaddr_o <= `ZeroWord;
mem_wmem_o <= `WriteDisable;
mem_rmem_o <= `ReadDisable;
mem_msel_o <= 4'b1111;
mem_wmemdata_o <= `ZeroWord;
//mem_mce_o <= `ChipDisable;
iow <= `WriteDisable;
ior <= `ReadDisable;
aluop_o <= aluop_i;
case (aluop_i)
`EXE_LW_OP: begin
mem_rmem_o <= ((memaddr_i & `IOBase)!=`IOBase)?1:0;
ior <= ((memaddr_i & `IOBase)==`IOBase)?1:0;
if(ior == `ReadEnable) begin
mem_memaddr_o <= memaddr_i;
//mem_rmem_o <= `ReadEnable;
wb_wdata <= rmemdata_i;
// mem_mce_o <= `ChipEnable;
end else if (mem_rmem_o == `ReadEnable) begin
mem_memaddr_o <= memaddr_i;
//mem_rmem_o <= `ReadEnable;
wb_wdata <= rmemdata_i;
// mem_mce_o <= `ChipEnable;
end
end
`EXE_SW_OP: begin
mem_wmem_o <= ((memaddr_i & `IOBase)!=`IOBase)?1:0;
iow <= ((memaddr_i & `IOBase)==`IOBase)?1:0;
if(iow == `WriteEnable)begin
mem_memaddr_o <= memaddr_i;
//mem_wmem_o <= `WriteEnable;
mem_wmemdata_o <= reg2data_i;
end else if(mem_wmem_o == `WriteEnable) begin
mem_memaddr_o <= memaddr_i;
//mem_wmem_o <= `WriteEnable;
mem_wmemdata_o <= reg2data_i;
// mem_mce_o <= `ChipEnable;
end
end
default: begin
//?????
end
endcase
end //if
end //always
//wb - id
always @ (*) begin
wb_wd_to_id_o <= wb_wd;
wb_wreg_to_id_o <= wb_wreg;
wb_wdata_to_id_o <= wb_wdata;
end
endmodule
//mem-io
module MIOC(
input wire rst,
input wire[`AluOpBus] aluop_i,
//wb to mioc input
input wire ior_i,
input wire iow_i,
output reg [`MemBus] rm_idata_o,
input wire [`MemBus] wm_idata_i,
input wire [`MemAddrBus] m_iaddr_i,
input wire mw_i,
input wire mr_i,
input wire [3:0] msel_i,
output reg [`AluOpBus] aluop_o,
//MIOC to Mem output
input wire[`MemBus] rmdata_i,
output reg [`MemBus] wmdata_o,
output reg [`MemAddrBus] maddr_o,
output reg memw_o,
output reg mce_o,
output reg [3:0] msel_o,
//MIOC to IO output
output reg [`IOBus] wiodata_o,
input wire [`IOBus] riodata_i,
output reg iow_o,
output reg ice_o,
output reg [`IOAddrBus] ioaddr_o
);
always @ (*) begin
if(rst == `RstEnable) begin
//output to wb
rm_idata_o <= `ZeroWord;
wmdata_o <= `ZeroWord;
maddr_o <= `ZeroWord;
memw_o <= `WriteDisable;
mce_o <= `ChipDisable;
msel_o <= 4'b0000;
wiodata_o <= `ZeroWord;
iow_o <= `WriteDisable;
ice_o <= `ChipDisable;
ioaddr_o <= `ZeroWord;
aluop_o <= `EXE_NOP_OP;
end else begin
aluop_o <= aluop_i;
if(ior_i == `ReadEnable) begin
rm_idata_o <= riodata_i;
iow_o <= `WriteDisable;
ice_o <= `ChipEnable;
ioaddr_o <= m_iaddr_i;
end else if (iow_i == `WriteEnable) begin
ioaddr_o <= m_iaddr_i;
iow_o <= `WriteEnable;
ice_o <= `ReadEnable;
wiodata_o <= wm_idata_i;
end else if(mr_i == `ReadEnable)begin
rm_idata_o <= rmdata_i;
maddr_o <= m_iaddr_i;
memw_o <= `WriteDisable;
mce_o <= `ChipEnable;
msel_o <= 4'b1111;
end else if(mw_i == `WriteEnable) begin
maddr_o <= m_iaddr_i;
memw_o <= `WriteEnable;
wmdata_o <= wm_idata_i;
mce_o <= `ChipEnable;
msel_o <= 4'b1111;
end
end //if
end //always
endmodule
module IO(
//MIOC to IO input
input wire [`IOAddrBus] addr_i,
input wire ce_i,
input wire iow_i,
output reg [`IOBus] rdata_o,
input wire [`IOBus] wdata_i,
input wire clk,
input wire rst,
input wire [`KeyBus] key,//0xFFFFF008
input wire [`RegBus] Button,//0xFFFFF00c
output reg [`SEGBus] SEG,//0xFFFFF000
output reg [`KeyBus] LED//0xFFFFF004
);
//IO model
reg [`IOBus] IO [`IONum-1:0];
always@(posedge clk)
begin
if(rst == `RstEnable) begin
LED <= `ZeroWord;
SEG <= `ZeroWord;
end else begin
case(addr_i)
`LED_ADDR: begin
LED <= wdata_i[15:0];
end
`SEG_ADDR: begin
SEG <= wdata_i;
end
endcase
end
end
always@(*)
begin
if(ce_i == `ChipDisable) begin
rdata_o <= `ZeroWord;
end else begin
case(addr_i)
`KEY_ADDR: begin
//rdata_o <= {{16{1'b0}},key[15:0]};
rdata_o <= 32'hffff000f;
end
`BUTTON_ADDR: begin
//rdata_o <= Button;
rdata_o <= 32'hffffffff;
end
endcase
end
end
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五级流水线模型机的设计代码,仅供参考!!!