blob: 3460e52d0a4296bf439ebfbb78d68c56409c9df8 [file] [log] [blame]
module ibex_wb_stage (
clk_i,
rst_ni,
en_wb_i,
instr_type_wb_i,
pc_id_i,
instr_is_compressed_id_i,
instr_perf_count_id_i,
ready_wb_o,
rf_write_wb_o,
outstanding_load_wb_o,
outstanding_store_wb_o,
pc_wb_o,
perf_instr_ret_wb_o,
perf_instr_ret_compressed_wb_o,
perf_instr_ret_wb_spec_o,
perf_instr_ret_compressed_wb_spec_o,
rf_waddr_id_i,
rf_wdata_id_i,
rf_we_id_i,
rf_wdata_lsu_i,
rf_we_lsu_i,
rf_wdata_fwd_wb_o,
rf_waddr_wb_o,
rf_wdata_wb_o,
rf_we_wb_o,
lsu_resp_valid_i,
lsu_resp_err_i,
instr_done_wb_o
);
parameter [0:0] ResetAll = 1'b0;
parameter [0:0] WritebackStage = 1'b0;
input wire clk_i;
input wire rst_ni;
input wire en_wb_i;
input wire [1:0] instr_type_wb_i;
input wire [31:0] pc_id_i;
input wire instr_is_compressed_id_i;
input wire instr_perf_count_id_i;
output wire ready_wb_o;
output wire rf_write_wb_o;
output wire outstanding_load_wb_o;
output wire outstanding_store_wb_o;
output wire [31:0] pc_wb_o;
output wire perf_instr_ret_wb_o;
output wire perf_instr_ret_compressed_wb_o;
output wire perf_instr_ret_wb_spec_o;
output wire perf_instr_ret_compressed_wb_spec_o;
input wire [4:0] rf_waddr_id_i;
input wire [31:0] rf_wdata_id_i;
input wire rf_we_id_i;
input wire [31:0] rf_wdata_lsu_i;
input wire rf_we_lsu_i;
output wire [31:0] rf_wdata_fwd_wb_o;
output wire [4:0] rf_waddr_wb_o;
output wire [31:0] rf_wdata_wb_o;
output wire rf_we_wb_o;
input wire lsu_resp_valid_i;
input wire lsu_resp_err_i;
output wire instr_done_wb_o;
wire [31:0] rf_wdata_wb_mux [0:1];
wire [1:0] rf_wdata_wb_mux_we;
generate
if (WritebackStage) begin : g_writeback_stage
reg [31:0] rf_wdata_wb_q;
reg rf_we_wb_q;
reg [4:0] rf_waddr_wb_q;
wire wb_done;
reg wb_valid_q;
reg [31:0] wb_pc_q;
reg wb_compressed_q;
reg wb_count_q;
reg [1:0] wb_instr_type_q;
wire wb_valid_d;
assign wb_valid_d = (en_wb_i & ready_wb_o) | (wb_valid_q & ~wb_done);
assign wb_done = (wb_instr_type_q == 2'd2) | lsu_resp_valid_i;
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
wb_valid_q <= 1'b0;
else
wb_valid_q <= wb_valid_d;
if (ResetAll) begin : g_wb_regs_ra
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni) begin
rf_we_wb_q <= 1'sb0;
rf_waddr_wb_q <= 1'sb0;
rf_wdata_wb_q <= 1'sb0;
wb_instr_type_q <= 2'd0;
wb_pc_q <= 1'sb0;
wb_compressed_q <= 1'sb0;
wb_count_q <= 1'sb0;
end
else if (en_wb_i) begin
rf_we_wb_q <= rf_we_id_i;
rf_waddr_wb_q <= rf_waddr_id_i;
rf_wdata_wb_q <= rf_wdata_id_i;
wb_instr_type_q <= instr_type_wb_i;
wb_pc_q <= pc_id_i;
wb_compressed_q <= instr_is_compressed_id_i;
wb_count_q <= instr_perf_count_id_i;
end
end
else begin : g_wb_regs_nr
always @(posedge clk_i)
if (en_wb_i) begin
rf_we_wb_q <= rf_we_id_i;
rf_waddr_wb_q <= rf_waddr_id_i;
rf_wdata_wb_q <= rf_wdata_id_i;
wb_instr_type_q <= instr_type_wb_i;
wb_pc_q <= pc_id_i;
wb_compressed_q <= instr_is_compressed_id_i;
wb_count_q <= instr_perf_count_id_i;
end
end
assign rf_waddr_wb_o = rf_waddr_wb_q;
assign rf_wdata_wb_mux[0] = rf_wdata_wb_q;
assign rf_wdata_wb_mux_we[0] = rf_we_wb_q & wb_valid_q;
assign ready_wb_o = ~wb_valid_q | wb_done;
assign rf_write_wb_o = wb_valid_q & (rf_we_wb_q | (wb_instr_type_q == 2'd0));
assign outstanding_load_wb_o = wb_valid_q & (wb_instr_type_q == 2'd0);
assign outstanding_store_wb_o = wb_valid_q & (wb_instr_type_q == 2'd1);
assign pc_wb_o = wb_pc_q;
assign instr_done_wb_o = wb_valid_q & wb_done;
assign perf_instr_ret_wb_spec_o = wb_count_q;
assign perf_instr_ret_compressed_wb_spec_o = perf_instr_ret_wb_spec_o & wb_compressed_q;
assign perf_instr_ret_wb_o = (instr_done_wb_o & wb_count_q) & ~(lsu_resp_valid_i & lsu_resp_err_i);
assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & wb_compressed_q;
assign rf_wdata_fwd_wb_o = rf_wdata_wb_q;
end
else begin : g_bypass_wb
assign rf_waddr_wb_o = rf_waddr_id_i;
assign rf_wdata_wb_mux[0] = rf_wdata_id_i;
assign rf_wdata_wb_mux_we[0] = rf_we_id_i;
assign perf_instr_ret_wb_spec_o = 1'b0;
assign perf_instr_ret_compressed_wb_spec_o = 1'b0;
assign perf_instr_ret_wb_o = (instr_perf_count_id_i & en_wb_i) & ~(lsu_resp_valid_i & lsu_resp_err_i);
assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i;
assign ready_wb_o = 1'b1;
wire unused_clk;
wire unused_rst;
wire [1:0] unused_instr_type_wb;
wire [31:0] unused_pc_id;
assign unused_clk = clk_i;
assign unused_rst = rst_ni;
assign unused_instr_type_wb = instr_type_wb_i;
assign unused_pc_id = pc_id_i;
assign outstanding_load_wb_o = 1'b0;
assign outstanding_store_wb_o = 1'b0;
assign pc_wb_o = 1'sb0;
assign rf_write_wb_o = 1'b0;
assign rf_wdata_fwd_wb_o = 32'b00000000000000000000000000000000;
assign instr_done_wb_o = 1'b0;
end
endgenerate
assign rf_wdata_wb_mux[1] = rf_wdata_lsu_i;
assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i;
assign rf_wdata_wb_o = ({32 {rf_wdata_wb_mux_we[0]}} & rf_wdata_wb_mux[0]) | ({32 {rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]);
assign rf_we_wb_o = |rf_wdata_wb_mux_we;
endmodule