为了再水一篇文章,所以把流水线处理器附加部分又新建了一篇文章(就是水!)。
流水线处理器的verilog实现在下面!(一些没有改动的模块就不放在这里了)
具体思路
我的实现方法具体如下:
IF阶段设置一个指令冲突分析模块,在IF阶段指令读取之后,将这条指令以及之前的三条指令作为输入(因为最多与前三条指令发生冲突),分析是哪种冲突,是否需要暂停或者定向?并输出标志信号。
ID阶段设置一个多选二寄存器,因为附加实验的指令冲突都是关于寄存器的读后写(RAW)冲突,所以放在寄存器读出来的数与ID_EX寄存器之间,再将需要重定向的数据定向过来,通过冲突分析输出的标志信号作为控制信号决定输出。
暂停:如果分析出来必须暂停,那么下一个时钟周期PC值保持不变,IF_ID传出去的信息全都为0,相当于在本条指令之前插入一个空周期,来避免冲突。
代码实现
CPU.v
`timescale 1ns / 1ps
module cpu(
input clk,
input resetn,
output [31:0] debug_wb_pc ,
output debug_wb_rf_wen ,
output [4 :0] debug_wb_rf_addr,
output [31:0] debug_wb_rf_wdata
);
/**********************************Start defining the connection lines********************************/
/**********************************IF Part********************************/
wire [31:0]IF_NPC;
wire [31:0]IF_PC;
wire [31:0]IF_INS;
wire [31:0]IF_ADDNPC;
wire [3:0]signal_1;
wire [3:0]signal_2;
wire [3:0]base;
wire stall;
/**********************************ID Part********************************/
wire [31:0]ID_NPC;
wire [31:0]ID_INS;
wire [31:0]ID_IMM;
wire [31:0]ID_RS;
wire [31:0]ID_RT;
wire [31:0]ID_PC;
wire [31:0]ID_A;
wire [31:0]ID_B;
/**********************************EX Part********************************/
wire [31:0]EX_NPC;
wire [31:0]EX_INS;
wire [31:0]EX_RS;
wire [31:0]EX_RT;
wire [31:0]EX_A;
wire [31:0]EX_B;
wire [31:0]EX_IMM;
wire EX_JUDG;
wire [31:0]EX_ALUOUT;
wire [31:0]EX_PC;
/**********************************MEM Part********************************/
wire [31:0]MEM_INS;
wire MEM_JUDG;
wire [31:0]MEM_ALUOUT;
wire [31:0]MEM_RT;
wire [31:0]MEM_MEMOUT;
wire [31:0]MEM_PC;
/**********************************WB Part********************************/
wire [31:0]WB_INS;
wire [31:0]WB_MEMOUT;
wire [31:0]WB_ALUOUT;
wire [31:0]WB_DATA;
wire [31:0]WB_PC;
wire [4:0]WB_ADDR;
wire WB_ABLE;
/**********************************Data conflict part********************************/
/**********************************Start link module**************************************/
assign debug_wb_pc=WB_PC;
assign debug_wb_rf_wen=WB_ABLE;
assign debug_wb_rf_addr=WB_ADDR;
assign debug_wb_rf_wdata=WB_DATA;
/**********************************IF Part********************************/
PC PC(
.clk(clk),
.resetn(resetn),
.next_pc(IF_NPC),
.stall(stall),
.pc(IF_PC)
);
ADD ADD(
.pc(IF_PC),
.add_result(IF_ADDNPC)
);
Ins_reg Ins_reg(
.ins_addr(IF_PC),
.ins_out(IF_INS)
);
NPC_MUX NPC_MUX(
.ori_npc(IF_ADDNPC),
.jmp_npc(MEM_ALUOUT),
.select(MEM_JUDG),
.npc(IF_NPC)
);
IF_ID IF_ID(
.clk(clk),
.resetn(resetn),
.stall(stall),
.wdata_1_1(IF_NPC),
.wdata_1_2(IF_INS),
.wdata_1_3(IF_PC),
.rdata_1_1(ID_NPC),
.rdata_1_2(ID_INS),
.rdata_1_3(ID_PC)
);
Conflict Conflict(
.clk(clk),
.resetn(resetn),
.id_ins(ID_INS),
.ex_ins(EX_INS),
.mem_ins(MEM_INS),
.new_ins(IF_INS),
.base(base),
.stall(stall),
.signal_1(signal_1),
.signal_2(signal_2)
);
/**********************************ID Part********************************/
Regs Regs(
.clk(clk),
.we(WB_ABLE),
.raddr1(ID_INS[25:21]),
.raddr2(ID_INS[20:16]),
.rdata1(ID_RS),
.rdata2(ID_RT),
.waddr(WB_ADDR),
.wdata(WB_DATA)
);
Extender Extender(
.imm(ID_INS[25:0]),
.opcode(ID_INS[31:26]),
.extend_result(ID_IMM)
);
ID_EX ID_EX(
.clk(clk),
.resetn(resetn),
.wdata_2_1(ID_NPC),
.wdata_2_2(ID_A),
.wdata_2_3(ID_B),
.wdata_2_4(ID_IMM),
.wdata_2_5(ID_INS),
.wdata_2_6(ID_PC),
.rdata_2_1(EX_NPC),
.rdata_2_2(EX_RS),
.rdata_2_3(EX_RT),
.rdata_2_4(EX_IMM),
.rdata_2_5(EX_INS),
.rdata_2_6(EX_PC)
);
Con_mux Con_mux(
.clk(clk),
.signal_1(signal_1),
.signal_2(signal_2),
.base(base),
.id_rs(ID_RS),
.id_rt(ID_RT),
.ex_aluout(EX_ALUOUT),
.mem_aluout(MEM_ALUOUT),
.mem_memout(MEM_MEMOUT),
.wb_data(WB_DATA),
.id_a(ID_A),
.id_b(ID_B)
);
/**********************************EX Part********************************/
zero zero(
.a(EX_RS),
.b(EX_RT),
.opcode(EX_INS[31:26]),
.judge(EX_JUDG)
);
MUX_1 MUX_1(
.d0(EX_NPC),
.d1(EX_RS),
.select(EX_INS[31:26]),
.out(EX_A)
);
MUX_2 MUX_2(
.d0(EX_IMM),
.d1(EX_RT),
.select(EX_INS[31:26]),
.out(EX_B)
);
ALU ALU(
.A(EX_A),
.B(EX_B),
.sll(EX_INS[10:6]),
.Card(EX_INS[5:0]),
.opcode(EX_INS[31:26]),
.F(EX_ALUOUT)
);
EX_MEM EX_MEM(
.clk(clk),
.resetn(resetn),
.wdata_3_1(EX_JUDG),
.wdata_3_2(EX_ALUOUT),
.wdata_3_3(EX_RT),
.wdata_3_4(EX_INS),
.wdata_3_5(EX_PC),
.rdata_3_1(MEM_JUDG),
.rdata_3_2(MEM_ALUOUT),
.rdata_3_3(MEM_RT),
.rdata_3_4(MEM_INS),
.rdata_3_5(MEM_PC)
);
/**********************************MEM Part********************************/
Data_reg Data_reg(
.clk(clk),
.opcode(MEM_INS[31:26]),
.data_reg_wdata(MEM_RT),
.data_reg_addr(MEM_ALUOUT),
.data_reg_rdata(MEM_MEMOUT)
);
MEM_WB MEM_WB(
.clk(clk),
.resetn(resetn),
.wdata_4_1(MEM_MEMOUT),
.wdata_4_2(MEM_ALUOUT),
.wdata_4_3(MEM_INS),
.wdata_4_4(MEM_PC),
.rdata_4_1(WB_MEMOUT),
.rdata_4_2(WB_ALUOUT),
.rdata_4_3(WB_INS),
.rdata_4_4(WB_PC),
.wb_enable(WB_ABLE)
);
/**********************************WB Part********************************/
WB_MUX WB_MUX(
.d0(WB_MEMOUT),
.d1(WB_ALUOUT),
.select(WB_INS[31:26]),
.out(WB_DATA)
);
WB_MUX_2 WB_MUX_2(
.a(WB_INS[20:16]),
.b(WB_INS[15:11]),
.opcode(WB_INS[31:26]),
.result(WB_ADDR)
);
endmodule
涉及到修改以及添加的模块并不多:冲突分析、多选二选择器、PC、IF_ID:
Conflict
`timescale 1ns / 1ps
module Conflict(
input clk,
input resetn,
input [31:0]new_ins,
input [31:0]id_ins,
input [31:0]ex_ins,
input [31:0]mem_ins,
output reg stall,
output reg [3:0]base,
output reg [3:0]signal_1,
output reg [3:0]signal_2
);
always @(*) begin
stall=0;
base=0;
signal_1=0;
signal_2=0;
/*******Stall************************************/
if(id_ins[31:26]==6'b100011&&(id_ins[20:16]==new_ins[25:21]||(new_ins[31:26]==6'b000000&&id_ins[20:16]==new_ins[20:16]))) begin
stall=1;
end
else if(id_ins[31:26]!=6'b100011) begin
stall=0;
end
/*********signal_1**************************/
if(id_ins!=32'b0&&id_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&new_ins[25:21]==id_ins[15:11]) begin
signal_1=4'b0100;
end
else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b000000&&new_ins[25:21]==ex_ins[15:11]) begin
signal_1=4'b1000;
end
else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b100011&&new_ins[25:21]==ex_ins[20:16]) begin
signal_1=4'b0010;
end
else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b000000&&new_ins[25:21]==mem_ins[15:11]) begin
signal_1=4'b1100;
end
else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b100011&&new_ins[25:21]==mem_ins[20:16]) begin
signal_1=4'b0011;
end
/**************signal_2***********************/
if(id_ins!=32'b0&&id_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&new_ins[20:16]==id_ins[15:11]) begin
signal_2=4'b0100;
end
else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b000000&&new_ins[20:16]==ex_ins[15:11]) begin
signal_2=4'b1000;
end
else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b100011&&new_ins[20:16]==ex_ins[20:16]) begin
signal_2=4'b0010;
end
else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b000000&&new_ins[20:16]==mem_ins[15:11]) begin
signal_2=4'b1100;
end
else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b100011&&new_ins[20:16]==mem_ins[20:16]) begin
signal_2=4'b0011;
end
/****************base*****************/
if(id_ins!=32'b0&&id_ins[31:26]==6'b000000&&new_ins[31:26]==6'b100011&&new_ins[25:21]==id_ins[15:11]) begin
base=4'b0100;
end
else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b100011&&new_ins[31:26]==6'b100011&&ex_ins[31:26]==6'b100011&&new_ins[25:21]==ex_ins[20:16]) begin
base=4'b0010;
end
else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b000000&&new_ins[31:26]==6'b100011&&ex_ins[31:26]==6'b000000&&new_ins[25:21]==ex_ins[15:11]) begin
base=4'b1000;
end
else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b100011&&new_ins[31:26]==6'b100011&&mem_ins[31:26]==6'b100011&&new_ins[25:21]==mem_ins[20:16]) begin
base=4'b0011;
end
else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b000000&&new_ins[31:26]==6'b100011&&mem_ins[31:26]==6'b000000&&new_ins[25:21]==mem_ins[15:11]) begin
base=4'b1100;
end
end
endmodule
Con_mux
`timescale 1ns / 1ps
module Con_mux(
input clk,
input [3:0]signal_1,
input [3:0]signal_2,
input [3:0]base,
input [31:0]id_rs,
input [31:0]id_rt,
input [31:0]ex_aluout,
input [31:0]mem_memout,
input [31:0]wb_data,
input [31:0]mem_aluout,
output reg [31:0]id_a,
output reg [31:0]id_b
);
always @(posedge clk) begin
/**********RS端口******************/
if(base==4'b0100||signal_1==4'b0100) begin
assign id_a=ex_aluout;
end
else if(base==4'b0010||signal_1==4'b0010) begin
assign id_a=mem_memout;
end
else if(base==4'b1000||signal_1==4'b1000) begin
assign id_a=mem_aluout;
end
else if(base==4'b1100||base==4'b0011||signal_1==4'b1100||signal_1==4'b0011) begin
assign id_a=wb_data;
end
else begin
assign id_a=id_rs;
end
/**********RT端口************************/
if(signal_2==4'b0100) begin
assign id_b=ex_aluout;
end
else if(signal_2==4'b0010)begin
assign id_b=mem_memout;
end
else if(signal_2==4'b1000) begin
assign id_b=mem_aluout;
end
else if(signal_2==4'b1100||signal_2==4'b0011) begin
assign id_b=wb_data;
end
else begin
assign id_b=id_rt;
end
end
endmodule
PC
`timescale 1ns / 1ps
module PC(
input clk,
input resetn,
input stall,
input [31:0]next_pc,
output reg [31:0]pc
);
always @(posedge clk)
if(resetn==1'b0) begin
pc<=0;
end
else if(stall==1) begin
pc=pc;
end
else begin
pc<=next_pc;
end
endmodule
IF_ID
`timescale 1ns / 1ps
module IF_ID(
input clk,
input resetn,
input [31:0]wdata_1_1,
input [31:0]wdata_1_2,
input [31:0]wdata_1_3,
input stall,
output reg [31:0]rdata_1_1,
output reg [31:0]rdata_1_2,
output reg [31:0]rdata_1_3
);
always @(posedge clk)
if(resetn==0||stall==1) begin
rdata_1_1<=0;
rdata_1_2<=0;
rdata_1_3<=0;
end
else begin
rdata_1_1<=wdata_1_1;
rdata_1_2<=wdata_1_2;
rdata_1_3<=wdata_1_3;
end
endmodule
结束
整个lab1到此结束 !