在lab4的基础上,加入适当的数据前递通路来减少阻塞,要求能成功通过仿真且仿真运行时间比lab4有所下降。
1.添加将执行级、访存级、写回级的数据前递到译码级的总线
ID_stage:
input [`ES_TO_DS_FORWARD_BUS -1:0] es_to_ds_forward_bus, //EXE->DS
input [`MS_TO_DS_FORWARD_BUS -1:0] ms_to_ds_forward_bus, //MEM->DS
input [`MS_TO_DS_FORWARD_BUS-1:0] ws_to_ds_forward_bus //WB->DS
EXE_stage:
output [`ES_TO_DS_FORWARD_BUS -1:0] es_to_ds_forward_bus
MEM_stage:
output [`MS_TO_DS_FORWARD_BUS-1:0] ms_to_ds_forward_bus
WB_stage:
output [`MS_TO_DS_FORWARD_BUS-1:0] ws_to_ds_forward_bus
2.在mycpu_top相应模块的实例化中添加对应的信号:
//实例化变量
wire [`ES_TO_DS_FORWARD_BUS -1:0] es_to_ds_forward_bus;
wire [`MS_TO_DS_FORWARD_BUS-1:0] ms_to_ds_forward_bus;
wire [`MS_TO_DS_FORWARD_BUS-1:0] ws_to_ds_forward_bus;
ID_stage:
.es_to_ds_forward_bus (es_to_ds_forward_bus);
.ms_to_ds_forward_bus (ms_to_ds_forward_bus);
.ws_to_ds_forward_bus (ws_to_ds_forward_bus);
EXE_stage:
.es_to_ds_forward_bus (es_to_ds_forward_bus)
MEM_stage:
.ms_to_ds_forward_bus (es_to_ds_forward_bus)
WB_stage:
.ws_to_ds_forward_bus (es_to_ds_forward_bus)
3.根据添加的总线完成各级的数据通路:
EXE_stage:
assign dest_zero = (es_dest == 5'b0); //判断是否是0号寄存器
assign forward_enable = es_gr_we & ~dest_zero & es_valid; //EXE前递使能信号
assign dep_need_stall = es_load_op ; //判断是否需要阻塞
assign es_to_ds_forward_bus = {dep_need_stall , //38:38
forward_enable , //37:37
es_dest , //36:32
es_alu_result //31:0
};
MEM_stage:
assign dest_zero = (ms_dest == 5'b0);
assign forward_enable = ms_gr_we & ~dest_zero & ms_valid;
assign dep_need_stall = ms_load_op && !ms_to_ws_valid; //由于访存指令的存在导致EXE和MEM有点区别
assign ms_to_ds_forward_bus = {dep_need_stall, //38:38
forward_enable, //37:37
ms_dest , //36:32
ms_final_result //31:0
};
assign ms_to_ws_valid = ms_valid && ms_ready_go;
WB_stage:
assign dest_zero = (ws_dest == 5'b0);
assign forward_enable = ws_gr_we & ~dest_zero & ws_valid;
assign dep_need_stall = !(ws_valid && ws_ready_go); //和EME级的!ms_to_ws_valid效果一样
assign ws_to_ds_forward_bus = {dep_need_stall , //38:38
forward_enable , //37:37
ws_dest , //36:32
ws_final_result //31:0
};
ID_stage:
wire ms_forward_enable; //前递使能信号
wire [ 4:0] ms_forward_reg; //前递的数据的的地址
wire [31:0] ms_forward_data; //前递的数据的值
wire ms_dep_need_stall; //判断是否需要阻塞
wire es_dep_need_stall;
wire es_forward_enable;
wire [ 4:0] es_forward_reg;
wire [31:0] es_forward_data;
wire ws_dep_need_stall;
wire ws_forward_enable;
wire [ 4:0] ws_forward_reg;
wire [31:0] ws_forward_data;
wire rf1_forward_stall; //阻塞信号
wire rf2_forward_stall;
wire br_need_reg_data;
wire inst_need_rs; //是否需要读rs
wire inst_need_rt; //是否需要读rt
assign {es_dep_need_stall, //控制es级是否阻塞
es_forward_enable,
es_forward_reg ,
es_forward_data
} = es_to_ds_forward_bus;
assign {ms_dep_need_stall, //控制ms级是否阻塞
ms_forward_enable,
ms_forward_reg ,
ms_forward_data
} = ms_to_ds_forward_bus;
assign {ws_dep_need_stall,
ws_forward_enable,
ws_forward_reg ,
ws_forward_data
} = ws_to_ds_forward_bus;
//inst_need_rs用于判断是否需要读rs
assign inst_need_rs = inst_addu | //rd,rs,rt
inst_addiu | //rt,rs,imm
inst_subu | //rd,rs,rt
inst_slt | //rd,rs,rt
inst_sltu | //rd,rs,rt
inst_and | //rd,rs,rt
inst_or | //rd,rs,rt
inst_xor | //rd,rs,rt
inst_nor | //rd,rs,rt
inst_sw | //rt,offset
inst_beq | //rs,rt,offset
inst_bne | //rs,rt,offset
inst_jr ; //rs
//jal target
//inst_need_rt用于判断是否需要读rt
assign inst_need_rt = inst_addu | //rd,rs,rt
inst_addiu | //rt,rs,imm
inst_subu | //rd,rs,rt
inst_slt | //rd,rs,rt
inst_sltu | //rd,rs,rt
inst_and | //rd,rs,rt
inst_or | //rd,rs,rt
inst_xor | //rd,rs,rt
inst_nor | //rd,rs,rt
inst_lui | //rt,imm
inst_sll | //rd,rt,sa
inst_sra | //rd,rt,sa
inst_lw | //rt,offset
inst_sw | //rt,offset
inst_beq | //rs,rt,offset
inst_bne ; //rs,rt,offset
wire inst_jbr; //所有分支跳转指令
assign inst_jbr = inst_jal | inst_beq | inst_bne |inst_jr ;
assign br_need_reg_data = inst_jbr;
//exe stage first forward 选择器选择前递的数据且有优先顺序EXE>MEM>WB
//inst_need_rs也可以不用判断,因为rf_raddr1 == es_forward_reg如果相同且es_forward_enable为1那么就一定要把前递过来的数据赋给rs_value
assign {rf1_forward_stall, rs_value} = ((rf_raddr1 == es_forward_reg) && es_forward_enable && inst_need_rs) ? {es_dep_need_stall, es_forward_data} :
((rf_raddr1 == ms_forward_reg) && ms_forward_enable && inst_need_rs) ? {ms_dep_need_stall || br_need_reg_data, ms_forward_data} :
((rf_raddr1 == ws_forward_reg) && ws_forward_enable && inst_need_rs) ? {ws_dep_need_stall,ws_forward_data} :
{1'b0, rf_rdata1};
//inst_need_rt同理上面inst_need_rs
assign {rf2_forward_stall, rt_value} = ((rf_raddr2 == es_forward_reg) && es_forward_enable && inst_need_rt) ? {es_dep_need_stall, es_forward_data} :
((rf_raddr2 == ms_forward_reg) && ms_forward_enable && inst_need_rt) ? {ms_dep_need_stall || br_need_reg_data, ms_forward_data} :
((rf_raddr2 == ws_forward_reg) && ws_forward_enable && inst_need_rt) ? {ws_dep_need_stall,ws_forward_data} :
{1'b0, rf_rdata2};
//ds_ready_go信号要做出相应的调整
assign ds_ready_go = ds_valid & ~rf1_forward_stall & ~rf2_forward_stall & (~inst_jbr | IF_over);
至此第四章实践任务三完成