概述
目录
流水线暂停信号hold_flag_o
第一级pc_reg(program counter):
第二级if_id:
第三级id_ex:
跳转标志 jump_flag_i (来自ex)
保持标志hold_flag_rib_i (来自rib)
保持标志hold_flag (来自ex)
保持标志hold_flag_clint_i (来自clint)
代码
流水线暂停信号hold_flag_o
1.两个个模块使用流水线暂停信号:pc-reg,if_id和id_ex.
2. Hole_no 3'b000 (无暂停操作)
Hole_pc 3'b001 (暂停pc_reg取值地址不变)(发生再总线被占用无法读取指令时)
Hole_id 3'b010 (暂停pc_reg和if_id)从if_id开始传输NOP,执行模块并没有清零也就是还会再执行一次。
Hole_ex 3'b011 (暂停pc_reg和if_id和id_ex)整条流水线清零传输NOP
第一级pc_reg(program counter):
1. 地址递增和跳转。
2. 通过hold_flag_o暂停流水线,取指地址不变。
第二级if_id:
1. pc_reg(对于总线属于master1)的地址通过总线访问各个slave取得指令inst_i,在if_id打一拍。
2. 通过hold_flag_o将inst_i(指令)置为NOP空操作,inst_addr(取指地址)置0,int_flag_i(中断)置零。
第三级id_ex:
1. 将译码模块(id)的通用寄存器(reg),写使能,SRC寄存器,指令内容,指令地址打一拍。
2. 通过hold_flag_o将inst_i(指令)置NOP,其余信号置0。
跳转标志 jump_flag_i (来自ex)
1. 在执行(ex)判断为跳转指令或者除法指令运算结束后(组合逻辑)后将jump_addr_i,和jump_flag传输到ctrl,在ctrl(组合逻辑)判断后输出Hold_Id冲刷整条流水线将因为流水线操作提前进入译码和取指的错误指令清除。
2. 在流水线操作下,一条指令在进入ex之前无法判断他是否是跳转指令,如果是跳转指令说明下两条+4地址的指令不应该被执行,而该执行跳转后的地址对应的指令,所以这个时候冲刷流水线清除错误数据。
保持标志hold_flag_rib_i(来自rib)
1. 当主设备0(ex),主设备2(jtag),主设备3(uart_debug),要使用总线时hold_flag_rib_i被拉高(组合逻辑),只有主设备1(pc_reg)使用总线取指时不拉高。
2. 在hold_flag_rib_i拉高时,hold_flag_o置为Hole_pc 暂停pc因为这个时候pc_reg无法访问总线来取指(赋值NOP),所以暂停pc_reg来等待pc_reg可以访问总线的时候。
保持标志hold_flag_ex_i(来自ex)
1. 在执行除法运算时,可能需要多个时钟为了等待计算完成将hold_flag_ex_i拉高,冲刷流水线,在除法计算完成时,将计算的结果写入对应的地址,同时将 jump_flag_i拉高jump_addr_i置为除法指令地址的下一个地址。
保持标志hold_flag_clint_i(来自clint)
1. 发生中断时拉高,冲刷流水线。
代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/07/27 10:27:32
// Design Name:
// Module Name: ctrl
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`define HoldEnable 1'b1
`define JumpEnable 1'b1
`define Hold_Flag_Bus 2:0
`define Hole_no 3'b000;
`define Hole_pc 3'b001; //暂停pc(发生再总线被占用无法读取指令时)
`define Hole_id 3'b010; //暂停pc_reg和if_id从if_id开始传输NOP,执行模块并没有清零也就是还会再执行一次。
`define Hole_ex 3'b011; //暂停pc_reg和if_id和id_ex整条流水线清零传输NOP
module ctrl(
// from ex
input wire jump_flag_i,
input wire[31:0] jump_addr_i,
input wire hold_flag_ex_i,
// from rib
input wire hold_flag_rib_i,
// from jtag
input wire jtag_halt_flag_i,
// from clint
input wire hold_flag_clint_i,
output reg[`Hold_Flag_Bus] hold_flag_o,
// to pc_reg
output reg jump_flag_o,
output reg[31:0] jump_addr_o
);
always @(*) begin
jump_flag_o=jump_flag_i;
jump_addr_o=hold_flag_o;
hold_flag_o=`Hole_no;
if( hold_flag_ex_i==`HoldEnable ||
hold_flag_clint_i==`HoldEnable ||
jump_flag_i==`JumpEnable )begin
hold_flag_o=`Hole_ex;
end else if(hold_flag_rib_i==`HoldEnable) begin //总线被占用
hold_flag_o=`Hole_pc; //pc暂停
end else if(jtag_halt_flag_i==`HoldEnable)begin
hold_flag_o=`Hole_ex;
end else begin
hold_flag_o=`Hole_no;
end
end
endmodule
最后
以上就是疯狂大象为你收集整理的tinyriscv-ctrl(流水线暂停和地址跳转模块)流水线暂停信号hold_flag_o 跳转标志 jump_flag_i (来自ex) 保持标志hold_flag_rib_i(来自rib)保持标志hold_flag_ex_i(来自ex)保持标志hold_flag_clint_i(来自clint)代码的全部内容,希望文章能够帮你解决tinyriscv-ctrl(流水线暂停和地址跳转模块)流水线暂停信号hold_flag_o 跳转标志 jump_flag_i (来自ex) 保持标志hold_flag_rib_i(来自rib)保持标志hold_flag_ex_i(来自ex)保持标志hold_flag_clint_i(来自clint)代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复