2. 流水线寄存器设计
任务目标
在RISC-V五级流水线(IF、ID、EX、MEM、WB)中,流水线寄存器是连接相邻级的关键时序元件。本案例要求设计IF/ID、ID/EX、EX/MEM、MEM/WB四级流水线寄存器,明确各级之间传递的控制信号与数据信号,并给出一个最小可综合的Verilog实现。
信号约定
采用RV32I基础整数指令集,数据通路为32位。控制信号采用局部解码方式:ID级产生全部控制信号,随指令逐级传递并在对应阶段使用后失效(写回信号在WB使用,访存信号在MEM使用等)。
关键完整代码
// 流水线寄存器定义(最小可综合实现)
// 时钟上升沿触发,同步复位(rst_n低有效)
// ---------- IF/ID 寄存器 ----------
module IF_ID_reg(
input wire clk, rst_n,
input wire stall, flush, // stall: 暂停;flush: 清空(分支跳转)
input wire [31:0] pc_if, instr_if, // IF级输入
output reg [31:0] pc_id, instr_id // ID级输出
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
pc_id <= 32'b0;
instr_id <= 32'b0;
end else if (flush) begin
pc_id <= 32'b0;
instr_id <= 32'b0; // 插入气泡(空指令)
end else if (!stall) begin
pc_id <= pc_if;
instr_id <= instr_if;
end
// stall=1时保持原值
end
endmodule
// ---------- ID/EX 寄存器 ----------
module ID_EX_reg(
input wire clk, rst_n,
input wire stall, flush,
// 控制信号(ID级产生)
input wire reg_write_id, mem_to_reg_id,
input wire mem_read_id, mem_write_id,
input wire [1:0] alu_op_id,
input wire alu_src_id,
input wire branch_id,
// 数据信号
input wire [31:0] pc_id, rs1_data_id, rs2_data_id,
input wire [31:0] imm_id,
input wire [4:0] rs1_addr_id, rs2_addr_id, rd_addr_id,
// 输出
output reg reg_write_ex, mem_to_reg_ex,
output reg mem_read_ex, mem_write_ex,
output reg [1:0] alu_op_ex,
output reg alu_src_ex, branch_ex,
output reg [31:0] pc_ex, rs1_data_ex, rs2_data_ex,
output reg [31:0] imm_ex,
output reg [4:0] rs1_addr_ex, rs2_addr_ex, rd_addr_ex
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
{reg_write_ex, mem_to_reg_ex, mem_read_ex, mem_write_ex,
alu_op_ex, alu_src_ex, branch_ex} <= 9'b0;
{pc_ex, rs1_data_ex, rs2_data_ex, imm_ex} <= 128'b0;
{rs1_addr_ex, rs2_addr_ex, rd_addr_ex} <= 15'b0;
end else if (flush) begin
{reg_write_ex, mem_to_reg_ex, mem_read_ex, mem_write_ex,
alu_op_ex, alu_src_ex, branch_ex} <= 9'b0; // 控制信号清零
// 数据信号无需清零(不会被使用)
end else if (!stall) begin
reg_write_ex <= reg_write_id;
mem_to_reg_ex <= mem_to_reg_id;
mem_read_ex <= mem_read_id;
mem_write_ex <= mem_write_id;
alu_op_ex <= alu_op_id;
alu_src_ex <= alu_src_id;
branch_ex <= branch_id;
pc_ex <= pc_id;
rs1_data_ex <= rs1_data_id;
rs2_data_ex <= rs2_data_id;
imm_ex <= imm_id;
rs1_addr_ex <= rs1_addr_id;
rs2_addr_ex <= rs2_addr_id;
rd_addr_ex <= rd_addr_id;
end
end
endmodule
// ---------- EX/MEM 寄存器 ----------
module EX_MEM_reg(
input wire clk, rst_n,
input wire stall, flush,
// 控制信号(EX级使用后剩余部分)
input wire reg_write_ex, mem_to_reg_ex,
input wire mem_read_ex, mem_write_ex,
input wire branch_ex, branch_taken_ex, // branch_taken: EX级分支判决结果
// 数据信号
input wire [31:0] pc_ex, alu_result_ex, rs2_data_ex,
input wire [4:0] rd_addr_ex,
// 输出
output reg reg_write_mem, mem_to_reg_mem,
output reg mem_read_mem, mem_write_mem,
output reg branch_mem, branch_taken_mem,
output reg [31:0] pc_mem, alu_result_mem, rs2_data_mem,
output reg [4:0] rd_addr_mem
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
{reg_write_mem, mem_to_reg_mem, mem_read_mem, mem_write_mem,
branch_mem, branch_taken_mem} <= 6'b0;
{pc_mem, alu_result_mem, rs2_data_mem} <= 96'b0;
rd_addr_mem <= 5'b0;
end else if (flush) begin
{reg_write_mem, mem_to_reg_mem, mem_read_mem, mem_write_mem,
branch_mem, branch_taken_mem} <= 6'b0;
end else if (!stall) begin
reg_write_mem <= reg_write_ex;
mem_to_reg_mem <= mem_to_reg_ex;
mem_read_mem <= mem_read_ex;
mem_write_mem <= mem_write_ex;
branch_mem <= branch_ex;
branch_taken_mem <= branch_taken_ex;
pc_mem <= pc_ex;
alu_result_mem <= alu_result_ex;
rs2_data_mem <= rs2_data_ex;
rd_addr_mem <= rd_addr_ex;
end
end
endmodule
// ---------- MEM/WB 寄存器 ----------
module MEM_WB_reg(
input wire clk, rst_n,
input wire stall, flush,
// 控制信号(MEM级使用后剩余部分)
input wire reg_write_mem, mem_to_reg_mem,
// 数据信号
input wire [31:0] alu_result_mem, mem_read_data_mem,
input wire [4:0] rd_addr_mem,
// 输出
output reg reg_write_wb, mem_to_reg_wb,
output reg [31:0] alu_result_wb, mem_read_data_wb,
output reg [4:0] rd_addr_wb
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
{reg_write_wb, mem_to_reg_wb} <= 2'b0;
{alu_result_wb, mem_read_data_wb} <= 64'b0;
rd_addr_wb <= 5'b0;
end else if (flush) begin
{reg_write_wb, mem_to_reg_wb} <= 2'b0;
end else if (!stall) begin
reg_write_wb <= reg_write_mem;
mem_to_reg_wb <= mem_to_reg_mem;
alu_result_wb <= alu_result_mem;
mem_read_data_wb <= mem_read_data_mem;
rd_addr_wb <= rd_addr_mem;
end
end
endmodule
信号传递说明
- IF/ID:传递PC和原始指令字,ID级负责指令译码并生成全部控制信号。
- ID/EX:传递控制信号(reg_write、mem_to_reg、mem_read、mem_write、alu_op、alu_src、branch)、PC、两个源寄存器数据、立即数、寄存器地址(rs1/rs2/rd)。
- EX/MEM:ALU运算结果、分支判决结果(branch_taken)、写数据(rs2_data)、控制信号中访存与写回相关部分。
- MEM/WB:ALU结果或访存读数据(由mem_to_reg选择)、目标寄存器地址、reg_write信号。
验证方法
编写testbench依次完成以下检查:
- 复位后所有输出为0;
- 正常流水(stall=0, flush=0)时,每个时钟沿后数据逐级延迟一拍传递;
- stall=1时,本级寄存器保持原值不变;
- flush=1时,控制信号清零(数据信号可不清零,因不会被后续级使用)。
通过条件:仿真波形中各级数据与控制信号满足上述时序关系,且无亚稳态或X态传播。
上图展示了四级流水线寄存器在流水线中的位置及各级传递的信号类别。控制信号在ID级集中生成后随流水逐级传递,在对应阶段使用完毕后不再向后传递(如alu_op仅在EX使用,branch_taken在MEM用于分支决策)。