blob: 3143cc8c84645bf37b49b5df95b1ec8caf77ba5d [file] [log] [blame]
module ibex_register_file_latch (
clk_i,
rst_ni,
test_en_i,
dummy_instr_id_i,
raddr_a_i,
rdata_a_o,
raddr_b_i,
rdata_b_o,
waddr_a_i,
wdata_a_i,
we_a_i
);
parameter [0:0] RV32E = 0;
parameter [31:0] DataWidth = 32;
parameter [0:0] DummyInstructions = 0;
input wire clk_i;
input wire rst_ni;
input wire test_en_i;
input wire dummy_instr_id_i;
input wire [4:0] raddr_a_i;
output wire [DataWidth - 1:0] rdata_a_o;
input wire [4:0] raddr_b_i;
output wire [DataWidth - 1:0] rdata_b_o;
input wire [4:0] waddr_a_i;
input wire [DataWidth - 1:0] wdata_a_i;
input wire we_a_i;
localparam [31:0] ADDR_WIDTH = (RV32E ? 4 : 5);
localparam [31:0] NUM_WORDS = 2 ** ADDR_WIDTH;
reg [DataWidth - 1:0] mem [0:NUM_WORDS - 1];
reg [NUM_WORDS - 1:1] waddr_onehot_a;
wire [NUM_WORDS - 1:1] mem_clocks;
reg [DataWidth - 1:0] wdata_a_q;
wire [ADDR_WIDTH - 1:0] raddr_a_int;
wire [ADDR_WIDTH - 1:0] raddr_b_int;
wire [ADDR_WIDTH - 1:0] waddr_a_int;
assign raddr_a_int = raddr_a_i[ADDR_WIDTH - 1:0];
assign raddr_b_int = raddr_b_i[ADDR_WIDTH - 1:0];
assign waddr_a_int = waddr_a_i[ADDR_WIDTH - 1:0];
wire clk_int;
assign rdata_a_o = mem[raddr_a_int];
assign rdata_b_o = mem[raddr_b_int];
prim_clock_gating cg_we_global(
.clk_i(clk_i),
.en_i(we_a_i),
.test_en_i(test_en_i),
.clk_o(clk_int)
);
always @(posedge clk_int or negedge rst_ni) begin : sample_wdata
if (!rst_ni)
wdata_a_q <= {DataWidth {1'sb0}};
else if (we_a_i)
wdata_a_q <= wdata_a_i;
end
function automatic signed [4:0] sv2v_cast_5_signed;
input reg signed [4:0] inp;
sv2v_cast_5_signed = inp;
endfunction
always @(*) begin : wad
begin : sv2v_autoblock_5
reg signed [31:0] i;
for (i = 1; i < NUM_WORDS; i = i + 1)
begin : wad_word_iter
if (we_a_i && (waddr_a_int == sv2v_cast_5_signed(i)))
waddr_onehot_a[i] = 1'b1;
else
waddr_onehot_a[i] = 1'b0;
end
end
end
generate
genvar x;
for (x = 1; x < NUM_WORDS; x = x + 1) begin : gen_cg_word_iter
prim_clock_gating cg_i(
.clk_i(clk_int),
.en_i(waddr_onehot_a[x]),
.test_en_i(test_en_i),
.clk_o(mem_clocks[x])
);
end
endgenerate
generate
genvar i;
for (i = 1; i < NUM_WORDS; i = i + 1) begin : g_rf_latches
always @(*)
if (mem_clocks[i])
mem[i] = wdata_a_q;
end
endgenerate
generate
if (DummyInstructions) begin : g_dummy_r0
wire we_r0_dummy;
wire r0_clock;
reg [DataWidth - 1:0] mem_r0;
assign we_r0_dummy = we_a_i & dummy_instr_id_i;
prim_clock_gating cg_i(
.clk_i(clk_int),
.en_i(we_r0_dummy),
.test_en_i(test_en_i),
.clk_o(r0_clock)
);
always @(*) begin : latch_wdata
if (r0_clock)
mem_r0 = wdata_a_q;
end
always @(*) mem[0] = (dummy_instr_id_i ? mem_r0 : {DataWidth {1'sb0}});
end
else begin : g_normal_r0
wire unused_dummy_instr_id;
assign unused_dummy_instr_id = dummy_instr_id_i;
initial mem[0] = {DataWidth {1'sb0}};
end
endgenerate
endmodule