以下进行模块化分析与代码实现
取指阶段模块实现:
1 PC模块:给出指令地址
`include "defines.v"
module pc_reg(
input wire clk,
input wire rst,
output reg[`InstAddrBus] pc, // program counter
output reg ce
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
ce <= `ChipDisable;
end else begin
ce <= `ChipEnable;
end
end
always @ (posedge clk) begin
if (ce == `ChipDisable) begin
pc <= 32'h00000000;
end else begin
pc <= pc + 1'h4;
end
end
endmodule
2 IF/ID模块:暂时保存取指阶段取得的指令以及对应的指令地址,并在下一个时钟传递到译码模块
`include "defines.v"
module if_id(
input wire clk,
input wire rst,
input wire[`InstAddrBus] if_pc,
input wire[`InstBus] if_inst,
output reg[`InstAddrBus] id_pc,
output reg[`InstBus] id_inst
);
always @ (posedge clk) begin
if (rst == `RstDisable) begin
id_pc <= `ZeroWord;
id_inst <= `ZeroWord;
end else begin
id_pc <= if_pc;
id_inst <= if_inst;
end
end
endmodule
译码阶段模块实现:
1 Regfile模块:同时经行两个寄存器的读操作和一个寄存器的写操作
`include "defines.v"
module regfile(
input wire clk,
input wire rst,
input wire[`RegAddrBus] waddr, // write address
input wire[`RegBus] wdata, // write data
input wire we, // write enable
input wire[`RegAddrBus] raddr1, // read address
output reg[`RegBus] rdata1, // read data
input wire re1, // read enable
input wire[`RegAddrBus] raddr2,
output reg[`RegBus] rdata2,
input wire re2
);
reg[`RegBus] regs[0:`RegNum - 1];
always @ (posedge clk) begin
if (rst == `RstDisable) begin
if (we == `WriteEnable && waddr != `RegNumLog2'h0) begin
regs[waddr] <= wdata;
end
end
end
always @ (*) begin
if (rst == `RstEnable) begin
rdata1 <= `ZeroWord;
end else if (raddr1 == `RegNumLog2'h0) begin
rdata1 <= `ZeroWord;
end else if (raddr1 == waddr && re1 == `ReadEnable && we == `WriteEnable) begin
rdata1 <= wdata;
end else if (re1 == `ReadEnable) begin
rdata1 <= regs[raddr1];
end begin
rdata1 <= `ZeroWord;
end
end
always @ (*) begin
if (rst == `RstEnable) begin
rdata2 <= `ZeroWord;
end else if (raddr2 == `RegNumLog2'h0) begin
rdata2 <= `ZeroWord;
end else if (raddr2 == waddr && re2 == `ReadEnable && we == `WriteEnable) begin
rdata2 <= wdata;
end else if (re2 == `ReadEnable) begin
rdata2 <= regs[raddr2];
end begin
rdata2 <= `ZeroWord;
end
end
endmodule
2 ID模块:对指令进行译码,得到指令的类型、子类型、操作数1、操作数2、目的寄存器地址
`include "defines.v"
module id(
input wire rst, // reset
input wire[`InstAddrBus] pc_i, // order address
input wire[`InstBus] inst_i, // order itself
input wire[`RegBus] reg1_data_i,
input wire[`RegBus] reg2_data_i,
output reg[`RegBus] reg1_read_o,
output reg[`RegBus] reg2_read_o,
output reg[`RegAddrBus] reg1_addr_o,
output reg[`RegAddrBus] reg2_addr_o,
output reg[`AluOpBus] aluop_o, // order sub type
output reg[`AluSelBus] alusel_o, // order type
output reg[`RegBus] reg1_o, // first operator
output reg[`RegBus] reg2_o, // second operator
output reg[`RegAddrBus] wd_o, // write address
output reg wreg_o // weite register
);
wire[5:0] op = inst_i[31:26];
reg[`RegBus] imm;
reg instvalid;
always @ (*) begin
if (rst == `RstEnable) begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
instvalid <= `InstInvalid;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= `NOPRegAddr;
reg2_addr_o <= `NOPRegAddr;
imm <= `ZeroWord;
end else 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 <= `ZeroWord;
end
case (op)
`EXE_ORI: 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];
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
default: begin
end
endcase
end
always @ (*) begin
if (rst == `RstEnable) begin
reg1_o <= `ZeroWord;
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) 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
3 ID/EX模块:将上述属性传递在下一个时钟阶段传递给流水线执行阶段
`include "defines.v"
module id_ex(
input wire rst,
input wire clk,
input wire[`AluOpBus] id_aluop,
input wire[`AluSelBus] id_alusel,
input wire[`RegBus] id_reg1,
input wire[`RegBus] id_reg2,
input wire[`RegAddrBus] id_wd,
input wire id_wreg,
output reg[`AluOpBus] ex_aluop,
output reg[`AluSelBus] ex_alusel,
output reg[`RegBus] ex_reg1,
output reg[`RegBus] ex_reg2,
output reg[`RegAddrBus] ex_wd,
output reg ex_wreg
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
ex_aluop <= `EXE_NOP_OP;
ex_alusel <= `EXE_RES_NOP;
ex_reg1 <= `ZeroWord;
ex_reg2 <= `ZeroWord;
ex_wd <= `NOPRegAddr;
ex_wreg <= `WriteDisable;
end else begin
ex_aluop <= id_aluop;
ex_alusel <= id_alusel;
ex_reg1 <= id_reg1;
ex_reg2 <= id_reg2;
ex_wd <= id_wd;
ex_wreg <= id_wreg;
end
end
endmodule
执行阶段模块实现
1 EX模块:判断指令的类型并给出运算的结果
`include "defines.v"
module ex(
input wire rst,
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,
output reg[`RegBus] wdata_o,
output reg[`RegAddrBus] wd_o,
output reg wreg_o
);
reg[`RegBus] logicout;
// logic type
always @ (*) begin
if (rst == `RstEnable) begin
logicout <= `ZeroWord;
end else begin
case (aluop_i)
`EXE_OR_OP: begin
logicout <= reg1_i | reg2_i;
end
default : begin
logicout <= `ZeroWord;
end
endcase
end
end
// choose type
always @ (*) begin
wd_o <= wd_i;
wreg_o <= wreg_i;
case (alusel_i)
`EXE_RES_LOGIC: begin
wdata_o <= logicout;
end
default : begin
wdata_o <= `ZeroWord;
end
endcase
end
endmodule
2 EX/MEM模块:将指令阶段得到的运算结果在下一个时钟传递到流水线访存阶段
`include "defines.v"
module ex_mem(
input wire rst,
input wire clk,
input wire[`RegBus] ex_wdata,
input wire[`RegAddrBus] ex_wd,
input wire ex_wreg,
output reg[`RegBus] mem_wdata,
output reg[`RegAddrBus] mem_wd,
output reg mem_wreg
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
mem_wdata <= `ZeroWord;
mem_wd <= `NOPRegAddr;
mem_wreg <= `WriteDisable;
end else begin
mem_wdata <= ex_wdata;
mem_wd <= ex_wd;
mem_wreg <= ex_wreg;
end
end
endmodule
访存阶段模块实现
1 MEM模块:
`include "defines.v"
module mem(
input wire rst,
input wire[`RegBus] wdata_i,
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
output reg[`RegBus] wdata_o,
output reg[`RegAddrBus] wd_o,
output reg wreg_o
);
always @ (*) begin
if (rst == `RstEnable) begin
wdata_o <= `ZeroWord;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
end else begin
wdata_o <= wdata_i;
wd_o <= wd_i;
wreg_o <= wreg_i;
end
end
endmodule
2 MEM/WB模块:将访存阶段的运算结果在下一个时钟传递到回写阶段
`include "defines.v"
module mem_wb(
input wire rst,
input wire clk,
input wire[`RegBus] mem_wdata,
input wire[`RegAddrBus] mem_wd,
input wire mem_wreg,
output reg[`RegBus] wb_wdata,
output reg[`RegAddrBus] wb_wd,
output reg wb_wreg
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
wb_wdata <= `ZeroWord;
wb_wd <= `NOPRegAddr;
wb_wreg <= `WriteDisable;
end else begin
wb_wdata <= mem_wdata;
wb_wd <= mem_wd;
wb_wreg <= mem_wreg;
end
end
endmodule
openMIPS顶层模块实现
openMIPS:对上述各个模块进行例化与连接
module openmips(
input wire rst,
input wire clk,
input wire[`RegBus] rom_data_i,
output wire[`RegBus] rom_data_o,
output wire[`RegAddrBus] rom_addr_o,
output wire rom_ce_o
);
wire[`InstAddrBus] pc;
wire[`InstAddrBus] id_pc_i;
wire[`InstAddrBus] id_inst_i;
wire[`AluOpBus] id_aluop_o;
wire[`AluSelBus] id_alusel_o;
wire[`RegBus] id_reg1_o;
wire[`RegBus] id_reg2_o;
wire[`RegAddrBus] id_wd_o;
wire id_wreg_o;
wire[`AluOpBus] ex_aluop_i;
wire[`AluSelBus] ex_alusel_i;
wire[`RegBus] ex_reg1_i;
wire[`RegBus] ex_reg2_i;
wire[`RegAddrBus] ex_wd_i;
wire ex_wreg_i;
wire[`RegBus] ex_wdata_o;
wire[`RegAddrBus] ex_wd_o;
wire ex_wreg_o;
wire[`RegBus] mem_wdata_i;
wire[`RegAddrBus] mem_wd_i;
wire mem_wreg_i;
wire[`RegBus] mem_wdata_o;
wire[`RegAddrBus] mem_wd_o;
wire mem_wreg_o;
wire[`RegBus] wb_wdata_i;
wire[`RegAddrBus] wb_wd_i;
wire wb_wreg_i;
wire reg1_read;
wire reg2_read;
wire[`RegBus] reg1_data;
wire[`RegBus] reg2_data;
wire[`RegAddrBus] reg1_addr;
wire[`RegAddrBus] reg2_addr;
pc_reg pc_reg0(
.clk(clk), .rst(rst),
.pc(pc), .ce(rom_ce_o)
);
if_id if_id0(
.clk(clk), .rst(rst),
.if_pc(pc), .if_inst(rom_data_i),
.id_pc(id_pc_i), .id_inst(id_inst_i)
);
id id0(
.rst(rst), .pc_i(id_pc), .inst_i(id_inst_i),
.reg1_data_i(reg1_data), .reg2_data_i(reg2_data),
.reg1_read_i(reg1_read), .reg2_read_i(reg2_read),
.reg1_addr_i(reg1_addr), .reg2_addr_i(reg2_addr),
.aluop_o(id_aluop_o), .alusel_o(id_alusel_o),
.reg1_o(id_reg1_o), .reg2_o(id_reg2_o),
.wd_o(id_wd_o), .wreg_o(id_wreg_o)
);
regfile regfile0(
.clk(clk), .rst(rst),
.waddr(wb_wd), .wdata(wb_wdata), .we(wb_wreg),
.raddr1(reg1_addr), .rdata1(reg1_data), .re1(reg1_read),
.raddr2(reg2_addr), .rdata2(reg2_data), .re2(reg2_read)
);
id_ex id_ex0(
.clk(clk), .rst(rst),
.id_aluop(id_aluop_o), .id_alusel(id_alusel_o),
.id_reg1(id_reg1_o), .id_reg2(id_reg2_o),
.id_wd(id_wd_o), .id_wreg(id_wreg_o),
.ex_aluop(ex_aluop_i), .ex_alusel(ex_alusel_i),
.ex_reg1(ex_reg1_i), .ex_reg2(ex_reg2_i),
.ex_wd(ex_wd_i), .ex_wreg(ex_wreg_i)
);
ex ex0(
.rst(rst),
.aluop_i(ex_aluop_i), .alusel_i(ex_alusel_i),
.reg1_i(ex_reg1_i), .reg2_i(ex_reg2_i),
.wd_i(ex_wd_i), .wreg_i(ex_wreg_i),
.wdata_o(ex_wdata_o), .wd_o(ex_wd_o), .wreg_o(ex_wreg_o)
);
ex_mem ex_mem0(
.clk(clk), .rst(rst),
.ex_wdata(ex_wdata_o), .ex_wd(ex_wd_o), .ex_wreg(ex_wreg_o),
.mem_wdata(mem_wdata_i), .mem_wd(mem_wd_i), .mem_wreg(mem_wreg_i)
);
mem mem0(
.rst(rst),
.wdata_i(mem_wdata_i), .wd_o(mem_wd_i), .wreg_o(mem_wreg_i),
.wdata_o(mem_wdata_o), .wd_o(mem_wd_o), .wreg_o(mem_wreg_o)
);
mem_wb mem_wb0(
.clk(clk), .rst(rst),
.mem_wdata(mem_wdata_o), .mem_wd(mem_wd_o), .mem_wreg(mem_wreg_o),
.wb_wdata(wb_wdata_i), .wb_wd(wb_wd_i), .wb_wreg(wb_wreg_i)
);
endmodule
宏定义参考
`define InstAddrBus 31:0
`define InstBus 31:0
`define RegAddrBus 4:0 // register address bus
`define RegBus 31:0 // register bus
`define RegWidth 32
`define DoubleRegWidth 64
`define DoubleRegBus 63:0
`define RegNum 32
`define RegNumLog2 5
`define NOPRegAddr 5'b000000
`define RstEnable 1'b1 // reset enable
`define RstDisable 1'b0 // reset disable
`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'b1
`define InstInvalid 1'b0
`define True_v 1'b1
`define False_v 1'b0
`define ChipEnable 1'b1
`define ChipDisable 1'b0
`define EXE_ORI 6'b001101
`define EXE_NOP 6'b000000
`define EXE_OR_OP 8'b00100101
`define EXE_NOP_OP 8'b00000000
`define EXE_RES_LOGIC 3'b001
`define EXE_RES_NOP 6'b000