CPU设计实战实践任务三:用前递技术解决相关引发的冲突

在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);

至此第四章实践任务三完成 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
静态5级流水线CPU设计是现代计算机硬件设计的一项关键技术,具有高效、稳定、可靠的特点。在设计过程中,需要考虑如何完成前递设计,以提高CPU的执行效率和吞吐量。 前递设计是通过引入前递单元,来解决数据冲突的问题,从而避免数据停顿和流水线停滞。在静态5级流水线CPU中,前递单元一般被设计为一个独立的硬件模块,用于处理指令间的数据依赖和冲突。 具体来说,前递单元需要完成以下几个任务: 1. 感知数据冲突前递单元需要监测流水线中的指令,发现数据冲突的情况。数据冲突包括RAW冲突、WAR冲突和WAW冲突。 2. 选择前递目标:在发现数据冲突的情况下,前递单元需要选择合适的前递目标,以满足指令执行的需求。前递目标一般是距离当前指令最近的指令,且指令类型和寄存器编号满足一定条件。 3. 执行前递操作:前递单元需要将数据从前递源传前递目标,完成前递操作。前递操作可以是单周期操作,也可以是多周期操作。 4. 确认前递完成:前递单元需要监测前递操作的结果,确认前递操作是否成功完成。如果前递操作失败,前递单元需要退出前递状态,通知后续指令继续等待。 总之,静态5级流水线CPU前递设计是一个非常关键的环节,它的正确实现可以大大提高CPU的运行效率和性能。设计人员需要仔细分析数据冲突的各种情况,并通过优秀的算法和设计来实现前递功能,从而实现静态5级流水线CPU的高效运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值