一个字节为8位,一个半字为16位,一个字为32位
修改ID,主要是增加译码和一个输出inst_o
lwl模块中reg2也需要读!
`include "defines.v"
module id_ex(
input wire clk,
input wire rst,
//从译码阶段传递的信息
input wire[`AluOpBus] id_aluop, //[7:0]
input wire[`AluSelBus] id_alusel, //[2:0]
input wire[`RegBus] id_reg1,
input wire[`RegBus] id_reg2,
input wire[`RegAddrBus] id_wd,
input wire id_wreg,
input wire[`RegBus] id_link_address, //处于译码阶段的转移指令要保存的返回地址
input wire id_is_in_delayslot, //当前处于译码阶段的指令是否位于延迟槽
input wire next_inst_in_delayslot_i, //下一条进入译码阶段的指令是否位于延迟槽
//当前处于译码阶段的指令
input wire[`RegBus] id_inst,
//来自控制模块的
input wire[5:0] stall,
//传递到执行阶段的
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,
output reg[`RegBus] ex_link_address, //处于执行阶段的转移指令要保存的返回地址
output reg ex_is_in_delayslot, //当前处于执行阶段的指令是否位于延迟槽
output reg is_in_delayslot_o, //当前译码阶段的指令是否位于延迟槽
//当前处于执行阶段的指令
output reg[`RegBus] ex_inst
);
//打一拍传过去
//1.当stall[2]为stop,stall[3]为nostop,表示译码阶段暂停,执行阶段继续
// 使用空指令作为下一个周期进入执行阶段的指令
//2.当stall[2]为nostop,译码阶段继续,译码后的指令进入执行阶段
//3.其余情况,保持不变
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;
ex_link_address <= `ZeroWord;
ex_is_in_delayslot <= `NotInDelaySlot;
is_in_delayslot_o <= `NotInDelaySlot;
ex_inst <= `ZeroWord;
end
else if(stall[2] == `Stop && stall[3] == `NoStop) begin
ex_aluop <= `EXE_NOP_OP;
ex_alusel <= `EXE_RES_NOP;
ex_reg1 <= `ZeroWord;
ex_reg2 <= `ZeroWord;
ex_wd <= `NOPRegAddr;
ex_wreg <= `WriteDisable;
ex_link_address <= `ZeroWord;
ex_is_in_delayslot <= `NotInDelaySlot;
ex_inst <= `ZeroWord;
end
else if(stall[2] == `NoStop) 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;
ex_link_address <= id_link_address;
ex_is_in_delayslot <= id_is_in_delayslot;
is_in_delayslot_o <= next_inst_in_delayslot_i;
ex_inst <= id_inst;
end
end
endmodule
`include "defines.v"
module mem(
input wire rst,
//来自执行阶段的信息
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
input wire[`RegBus] wdata_i,
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
input wire whilo_i,
//
input wire[`AluOpBus] aluop_i, //访存阶段的指令要进行的运算的子类型
input wire[`RegBus] mem_addr_i, //访存阶段加载、存储指令对应的存储器地址
input wire[`RegBus] reg2_i, //访存阶段的存储指令要存储的数据或lwl/lwr要加载到的目的段寄存器原始值
//来自memory的信息
input wire[`RegBus] mem_data_i, //从数据存储器读取的数据
//送到回写阶段的信息
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
output reg[`RegBus] wdata_o,
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o,
output reg whilo_o,
//送到memory的信息
output reg[`RegBus] mem_addr_o, //要访问的数据存储器地址
output wire mem_we_o, //是否写操作
output reg[3:0] mem_sel_o, //字节选择信号
output reg[`RegBus] mem_data_o, //要写入数据存储器的数据
output reg mem_ce_o //数据存储器使能信号
);
wire[`RegBus] zero32;
reg mem_we;
assign mem_we_o = mem_we ; //外部数据存储器RAM的读、写信号
assign zero32 = `ZeroWord;
always @ (*) begin
if(rst == `RstEnable) begin
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
wdata_o <= `ZeroWord;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
whilo_o <= `WriteDisable;
mem_addr_o <= `ZeroWord;
mem_we <= `WriteDisable;
mem_sel_o <= 4'b0000;
mem_data_o <= `ZeroWord;
mem_ce_o <= `ChipDisable;
end
else begin
wd_o <= wd_i;
wreg_o <= wreg_i;
wdata_o <= wdata_i;
hi_o <= hi_i;
lo_o <= lo_i;
whilo_o <= whilo_i;
mem_we <= `WriteDisable;
mem_addr_o <= `ZeroWord;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipDisable;
case (aluop_i)
`EXE_LB_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable; //加载操作
mem_ce_o <= `ChipEnable; //要访问数据存储器
case (mem_addr_i[1:0]) //反正就是根据算出来的地址的后两位来确定字节
2'b00: begin
wdata_o <= {{24{mem_data_i[31]}},mem_data_i[31:24]};
mem_sel_o <= 4'b1000;
end
2'b01: begin
wdata_o <= {{24{mem_data_i[23]}},mem_data_i[23:16]};
mem_sel_o <= 4'b0100;
end
2'b10: begin
wdata_o <= {{24{mem_data_i[15]}},mem_data_i[15:8]};
mem_sel_o <= 4'b0010;
end
2'b11: begin
wdata_o <= {{24{mem_data_i[7]}},mem_data_i[7:0]};
mem_sel_o <= 4'b0001;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LBU_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {{24{1'b0}},mem_data_i[31:24]};
mem_sel_o <= 4'b1000;
end
2'b01: begin
wdata_o <= {{24{1'b0}},mem_data_i[23:16]};
mem_sel_o <= 4'b0100;
end
2'b10: begin
wdata_o <= {{24{1'b0}},mem_data_i[15:8]};
mem_sel_o <= 4'b0010;
end
2'b11: begin
wdata_o <= {{24{1'b0}},mem_data_i[7:0]};
mem_sel_o <= 4'b0001;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LH_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {{16{mem_data_i[31]}},mem_data_i[31:16]};
mem_sel_o <= 4'b1100;
end
2'b10: begin
wdata_o <= {{16{mem_data_i[15]}},mem_data_i[15:0]};
mem_sel_o <= 4'b0011;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LHU_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {{16{1'b0}},mem_data_i[31:16]};
mem_sel_o <= 4'b1100;
end
2'b10: begin
wdata_o <= {{16{1'b0}},mem_data_i[15:0]};
mem_sel_o <= 4'b0011;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LW_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
wdata_o <= mem_data_i;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end
`EXE_LWL_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00}; //lwl地址后两位置0
mem_we <= `WriteDisable;
mem_sel_o <= 4'b1111; //lwl读一个字,所以全1
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0]) //根据后两位与原始值组合 就是只保存高位
2'b00: begin
wdata_o <= mem_data_i[31:0];
end
2'b01: begin
wdata_o <= {mem_data_i[23:0],reg2_i[7:0]};
end
2'b10: begin
wdata_o <= {mem_data_i[15:0],reg2_i[15:0]};
end
2'b11: begin
wdata_o <= {mem_data_i[7:0],reg2_i[23:0]};
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LWR_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00};
mem_we <= `WriteDisable;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {reg2_i[31:8],mem_data_i[31:24]};
end
2'b01: begin
wdata_o <= {reg2_i[31:16],mem_data_i[31:16]};
end
2'b10: begin
wdata_o <= {reg2_i[31:24],mem_data_i[31:8]};
end
2'b11: begin
wdata_o <= mem_data_i;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_SB_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable; //存储操作
mem_data_o <= {reg2_i[7:0],reg2_i[7:0],reg2_i[7:0],reg2_i[7:0]}; //最低字节
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
mem_sel_o <= 4'b1000;
end
2'b01: begin
mem_sel_o <= 4'b0100;
end
2'b10: begin
mem_sel_o <= 4'b0010;
end
2'b11: begin
mem_sel_o <= 4'b0001;
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
`EXE_SH_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable;
mem_data_o <= {reg2_i[15:0],reg2_i[15:0]};
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
mem_sel_o <= 4'b1100;
end
2'b10: begin
mem_sel_o <= 4'b0011;
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
`EXE_SW_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable;
mem_data_o <= reg2_i;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end
`EXE_SWL_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00}; //置0 因为swl最多可能向RAM写入一个字
mem_we <= `WriteEnable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0]) //zero32拿来补0的
2'b00: begin
mem_sel_o <= 4'b1111;
mem_data_o <= reg2_i;
end
2'b01: begin
mem_sel_o <= 4'b0111;
mem_data_o <= {zero32[7:0],reg2_i[31:8]};
end
2'b10: begin
mem_sel_o <= 4'b0011;
mem_data_o <= {zero32[15:0],reg2_i[31:16]};
end
2'b11: begin
mem_sel_o <= 4'b0001;
mem_data_o <= {zero32[23:0],reg2_i[31:24]};
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
`EXE_SWR_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00};
mem_we <= `WriteEnable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
mem_sel_o <= 4'b1000;
mem_data_o <= {reg2_i[7:0],zero32[23:0]};
end
2'b01: begin
mem_sel_o <= 4'b1100;
mem_data_o <= {reg2_i[15:0],zero32[15:0]};
end
2'b10: begin
mem_sel_o <= 4'b1110;
mem_data_o <= {reg2_i[23:0],zero32[7:0]};
end
2'b11: begin
mem_sel_o <= 4'b1111;
mem_data_o <= reg2_i[31:0];
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
default: begin
end
endcase
end
end
endmodule
`include "defines.v"
module data_ram(
input wire clk,
input wire ce,
input wire we,
input wire[`DataAddrBus] addr,
input wire[3:0] sel,
input wire[`DataBus] data_i, //要写入的数据
output reg[`DataBus] data_o
);
//定义四个字节数组
//ByteWidth 7:0 字节宽度
//DataMemNum 131071 RAM大小 单位是字 此处是128K word
reg[`ByteWidth] data_mem0[0:`DataMemNum-1];
reg[`ByteWidth] data_mem1[0:`DataMemNum-1];
reg[`ByteWidth] data_mem2[0:`DataMemNum-1];
reg[`ByteWidth] data_mem3[0:`DataMemNum-1];
//写操作
//DataMemNumLog2 17 实际使用的地址宽度
always @ (posedge clk) begin
if (ce == `ChipDisable) begin
//data_o <= ZeroWord;
end
else if(we == `WriteEnable) begin
if (sel[3] == 1'b1) begin
data_mem3[addr[`DataMemNumLog2+1:2]] <= data_i[31:24];
end
if (sel[2] == 1'b1) begin
data_mem2[addr[`DataMemNumLog2+1:2]] <= data_i[23:16];
end
if (sel[1] == 1'b1) begin
data_mem1[addr[`DataMemNumLog2+1:2]] <= data_i[15:8];
end
if (sel[0] == 1'b1) begin
data_mem0[addr[`DataMemNumLog2+1:2]] <= data_i[7:0];
end
end
end
//读操作
always @ (*) begin
if (ce == `ChipDisable) begin
data_o <= `ZeroWord;
end
else if(we == `WriteDisable) begin //地址仍左移了两位 因为按字节寻址 所以乘4
data_o <= {data_mem3[addr[`DataMemNumLog2+1:2]],
data_mem2[addr[`DataMemNumLog2+1:2]],
data_mem1[addr[`DataMemNumLog2+1:2]],
data_mem0[addr[`DataMemNumLog2+1:2]]};
end
else begin
data_o <= `ZeroWord;
end
end
endmodule
`include "defines.v"
module LLbit_reg(
input wire clk,
input wire rst,
input wire flush, //是否有异常发生
//写端口
input wire LLbit_i, //要写到LLbit寄存器的值
input wire we, //是否要写LLbit寄存器
//读端口1
output reg LLbit_o //LLbit寄存器的值
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
LLbit_o <= 1'b0;
end
else if((flush == 1'b1)) begin //如果异常发生,设置为0
LLbit_o <= 1'b0;
end
else if((we == `WriteEnable)) begin
LLbit_o <= LLbit_i;
end
end
endmodule
`EXE_LL_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
wdata_o <= mem_data_i;
LLbit_we_o <= 1'b1;
LLbit_value_o <= 1'b1;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end
`EXE_SC_OP: begin
if(LLbit == 1'b1) begin
LLbit_we_o <= 1'b1;
LLbit_value_o <= 1'b0;
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable;
mem_data_o <= reg2_i;
wdata_o <= 32'b1;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end
else begin
wdata_o <= 32'b0;
end
end