Skip to content

Commit

Permalink
Add files
Browse files Browse the repository at this point in the history
  • Loading branch information
MikukuOvO committed Aug 10, 2023
1 parent 6437347 commit c32d7ff
Show file tree
Hide file tree
Showing 22 changed files with 12,479 additions and 0 deletions.
126 changes: 126 additions & 0 deletions EX.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
`include "ctrl_encode_def.v"
`include "alu.v"

module EX(
input clk,
input rst,

input [31:0] ALU_A,
input [31:0] ALU_B,
input [4:0] ALUOp,

input [31:0] PC_in,
input [31:0] immout_in,
input [2:0] NPCOp_in,

input MemWrite_in, // 内存写信号
input [2:0] dm_ctrl_in,
input [31:0] raw_Data_out, // 写往 DM 的数据

input RegWrite_in, // 控制寄存器是否写
input [4:0] rd_in,
input [1:0] WDSel_in,

output reg flush,

// 冒险
output [31:0] EX_MEM_Forward_Data,

// 给 MEM 阶段的信号

output reg [31:0] PC,
output reg [31:0] immout,
output reg [2:0] NPCOp,

output reg MemWrite,
output reg [2:0] dm_ctrl,
output reg [3:0] wea,
output reg [31:0] dm_Data_out,
output reg [31:0] aluout,

// 给 WB 阶段的信号

output reg RegWrite,
output reg [4:0] rd,
output reg [1:0] WDSel,
output reg [31:0] WD

);

reg [3:0] wea_tmp;
wire Zero;
wire [31:0] aluout_w;
wire [31:0] WD_w;


// 运算单元的接线

alu U_alu(
.A(ALU_A),
.B(ALU_B),
.PC(PC),
.ALUOp(ALUOp),
.C(aluout_w),
.Zero(Zero)
);

// 考虑 Jalr 指令

assign WD_w=(WDSel_in==`WDSel_FromPC)?PC_in+4:aluout_w;
assign EX_MEM_Forward_Data=WD_w;

wire flush_w=(NPCOp_in[0]&Zero)|NPCOp_in[1]|NPCOp_in[2];

always @(*) begin
if(MemWrite_in) begin
case(dm_ctrl_in)
`dm_word: wea_tmp<=4'b1111;
`dm_halfword: wea_tmp<=4'b0011;
`dm_byte: wea_tmp<=4'b0001;
default wea_tmp<=4'b0000;
endcase
end
else wea_tmp<=4'b0000;
end

always @(posedge clk, posedge rst) begin
if(rst||flush) begin
PC<=32'b0;
immout<=32'b0;
NPCOp<=3'b0;

MemWrite<=1'b0;
dm_ctrl<=3'b0;
dm_Data_out<=32'b0;
wea<=4'b0;
aluout<=32'b0;

RegWrite<=1'b0;
rd<=5'b0;
WDSel<=2'b0;
WD<=32'b0;
flush<=1'b0;
end
else begin
PC<=PC_in;
immout<=immout_in;
NPCOp[0]<=NPCOp_in[0]&Zero;
NPCOp[1]<=NPCOp_in[1];
NPCOp[2]<=NPCOp_in[2];

MemWrite<=MemWrite_in;
dm_ctrl<=dm_ctrl_in;
dm_Data_out<=raw_Data_out;
wea<=wea_tmp;
aluout<=aluout_w;

RegWrite<=RegWrite_in;
rd<=rd_in;
WDSel<=WDSel_in;
WD<=WD_w;
flush<=flush_w;
end
end


endmodule
27 changes: 27 additions & 0 deletions EXT.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
`include "ctrl_encode_def.v"
module EXT(

input [4:0] iimm_shamt,
input [11:0] iimm,
input [11:0] simm,
input [11:0] bimm,
input [19:0] uimm,
input [19:0] jimm,
input [5:0] EXTOp,

output reg [31:0] immout
);

always @(*)
case (EXTOp)
`EXT_CTRL_ITYPE_SHAMT: immout<={27'b0,iimm_shamt[4:0]};
`EXT_CTRL_ITYPE: immout <= {{32-12{iimm[11]}}, iimm[11:0]};
`EXT_CTRL_STYPE: immout <= {{32-12{simm[11]}}, simm[11:0]};
`EXT_CTRL_BTYPE: immout <= {{32-13{bimm[11]}}, bimm[11:0], 1'b0};
`EXT_CTRL_UTYPE: immout <= {uimm[19:0], 12'b0}; //???????????12??0
`EXT_CTRL_JTYPE: immout <= {{32-21{jimm[19]}}, jimm[19:0], 1'b0};
default: immout <= 32'b0;
endcase


endmodule
173 changes: 173 additions & 0 deletions ID.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
`include "EXT.v"
`include "ctrl.v"

module ID(
input clk,
input rst,
input flush,
input [31:0] PC_in,
input [31:0] inst_in,

// 读取寄存器堆中的数据
input [31:0] RD1,
input [31:0] RD2,

// 数据冒险
input ID_EX_RegWrite,
input [4:0] ID_EX_rd,
input EX_MEM_RegWrite,
input [4:0] EX_MEM_rd,

// 数据冒险的旁路
input [1:0] ID_EX_WDSel,
input [31:0] EX_MEM_Forward_Data,
input [31:0] MEM_WB_Forward_Data,

output stall, // 检测阻塞
output [4:0] rs1, // 从寄存器堆中读取的寄存器编号
output [4:0] rs2, // 从寄存器堆中读取的寄存器编号

// EX 阶段使用的内容
output reg [31:0] ALU_A, // ALU 的输入
output reg [31:0] ALU_B, // ALU 的输入
output reg [4:0] ALUOp, // ALU 控制信号

// MEM 阶段使用的内容
output reg [31:0] PC,
output reg [31:0] immout,
output reg [2:0] NPCOp,
output reg MemWrite,
output reg [2:0] dm_ctrl,
output reg [31:0] DataWrite,

// WB 阶段使用的内容
output reg RegWrite,
output reg [4:0] rd, // 写入寄存器的编号
output reg [1:0] WDSel // 写入寄存器的数据来源
);

// 处理立即数的阶段
wire [4:0] iimm_shamt;
wire [11:0] iimm, simm, bimm;
wire [19:0] uimm, jimm;

assign iimm_shamt=inst_in[24:20];
assign iimm=inst_in[31:20];
assign simm={inst_in[31:25], inst_in[11:7]};
assign bimm={inst_in[31], inst_in[7], inst_in[30:25], inst_in[11:8]};
assign uimm=inst_in[31:12];
assign jimm={inst_in[31], inst_in[19:12], inst_in[20], inst_in[30:21]};

// 输出的定义
wire [31:0] immout_w;

EXT U_EXT(
// 输入
.iimm_shamt(iimm_shamt), .iimm(iimm), .simm(simm), .bimm(bimm),
.uimm(uimm), .jimm(jimm),
.EXTOp(EXTOp),
// 输出
.immout(immout_w)
);

// 处理信号的阶段
// 输入的定义以及处理
wire [6:0] Op;
wire [6:0] Funct7;
wire [2:0] Funct3;

assign Op=inst_in[6:0];
assign Funct7=inst_in[31:25];
assign Funct3=inst_in[14:12];
assign rs1=inst_in[19:15];
assign rs2=inst_in[24:20];
assign rd_w=inst_in[11:7];

// 输出的定义
wire [4:0] rd_w;
wire RegWrite_w;
wire MemWrite_w;
wire [5:0] EXTOp;
wire [4:0] ALUOp_w;
wire [2:0] NPCOp_w;
wire ALUSrc;
wire [1:0] GPRSel;
wire [1:0] WDSel_w;
wire [2:0] dm_ctrl_w;

wire use_rs1, use_rs2; // 寄存器是否被使用

ctrl U_ctrl(
.Op(Op), .Funct7(Funct7), .Funct3(Funct3),
.RegWrite(RegWrite_w), .MemWrite(MemWrite_w),
.EXTOp(EXTOp), .ALUOp(ALUOp_w), .NPCOp(NPCOp_w),
.ALUSrc(ALUSrc), .GPRSel(GPRSel), .WDSel(WDSel_w), .dm_ctrl(dm_ctrl_w),
.use_rs1(use_rs1), .use_rs2(use_rs2)
);

wire Rs1Legal=use_rs1&(rs1!=5'b0);
wire Rs2Legal=use_rs2&(rs2!=5'b0);
wire type_l=ID_EX_WDSel[0];

// 可以大致将冒险分为三类,其中一类与 ld 类型有关的冒险需要通过阻塞进行解决
// 剩下的两类冒险分为 EX 冒险和 MEM 冒险,我们在下面进行了处理

// 冒险的检测
// 注意这里我们用到的 ID_EX_rd 为 EX_MEM 阶段的输入值,所以相当于书中的 EX_MEM_rd
wire DataHazardA1=ID_EX_RegWrite&Rs1Legal&(ID_EX_rd==rs1);
wire DataHazardA2=ID_EX_RegWrite&Rs2Legal&(ID_EX_rd==rs2);
wire DataHazardB1=(!DataHazardA1)&EX_MEM_RegWrite&Rs1Legal&(EX_MEM_rd==rs1);
wire DataHazardB2=(!DataHazardA2)&EX_MEM_RegWrite&Rs2Legal&(EX_MEM_rd==rs2);

// 是否选择旁路
wire ForwardA1=DataHazardA1&(~type_l); // 排除 load 类型的指令
wire ForwardA2=DataHazardA2&(~type_l); // 排除 load 类型的指令
wire ForwardB1=DataHazardB1;
wire ForwardB2=DataHazardB2;

// load 类型的指令进行一个周期的阻塞,阻塞一个周期后相当于 MEM 冒险
assign stall=(~flush)&((DataHazardA1&type_l)|(DataHazardA2&type_l));

// 考虑数据的来源,分为三种:EX/MEM 旁路,MEM/WB 旁路,以及原始数据,注意优先级的顺序
wire [31:0] NewRD1, NewRD2;
assign NewRD1=ForwardA1?EX_MEM_Forward_Data:(ForwardB1?MEM_WB_Forward_Data:RD1);
assign NewRD2=ForwardA2?EX_MEM_Forward_Data:(ForwardB2?MEM_WB_Forward_Data:RD2);

// 开始进行数据的选择

always @(posedge clk, posedge rst) begin
if (rst||flush) begin
ALU_A<=32'b0;
ALU_B<=32'b0;
ALUOp<=5'b0;

PC<=32'b0;
immout<=32'b0;
NPCOp<=3'b0;

MemWrite<=1'b0;
dm_ctrl<=3'b0;

RegWrite<=1'b0;
rd<=5'b0;
WDSel<=2'b0;
end
else begin
ALU_A<=NewRD1;
ALU_B<=(ALUSrc)?immout_w:NewRD2;
ALUOp<=ALUOp_w;

PC<=PC_in;
immout<=immout_w;
NPCOp<=(stall)?3'b0:NPCOp_w;

MemWrite<=(stall)?1'b0:MemWrite_w;
dm_ctrl<=dm_ctrl_w;
DataWrite<=NewRD2;

RegWrite<=(stall)?1'b0:RegWrite_w;
rd<=rd_w;
WDSel<=WDSel_w;
end
end
endmodule
27 changes: 27 additions & 0 deletions IF.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// IF 阶段就是将指令读入然后保存到流水线寄存器中传给下一级就可以了
// 注意考虑下阻塞和结构冒险
module IF(
input clk,
input rst,
input flush,
input stall,
input [31:0] PC_in,
input [31:0] inst_in,
output reg [31:0] PC_out,
output reg [31:0] inst_out
);

always @(posedge clk, posedge rst)
begin
if (rst||flush) begin
PC_out<=32'b0;
inst_out<=32'b0;
end
else begin
if(!stall) begin
PC_out<=PC_in;
inst_out<=inst_in;
end
end
end
endmodule
Loading

0 comments on commit c32d7ff

Please sign in to comment.