blob: ce7dbbdbf59d9d95b3e6c4587dd5c25fa74a0824 [file] [log] [blame]
/**
* RISC-V register file
*
* Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0.
* This register file is based on flip flops. Use this register file when
* targeting FPGA synthesis or Verilator simulation.
*/
module brq_register_file_ff #(
parameter bit RV32E = 0,
parameter int unsigned DataWidth = 32,
parameter bit DummyInstructions = 0
) (
// Clock and Reset
input logic clk_i,
input logic rst_ni,
// input logic test_en_i,
input logic dummy_instr_id_i,
//Read port R1
input logic [4:0] raddr_a_i,
output logic [DataWidth-1:0] rdata_a_o,
//Read port R2
input logic [4:0] raddr_b_i,
output logic [DataWidth-1:0] rdata_b_o,
// Write port W1
input logic [4:0] waddr_a_i,
input logic [DataWidth-1:0] wdata_a_i,
input logic we_a_i
);
localparam int unsigned ADDR_WIDTH = RV32E ? 4 : 5;
localparam int unsigned NUM_WORDS = 2**ADDR_WIDTH;
logic [NUM_WORDS-1:0][DataWidth-1:0] rf_reg;
logic [NUM_WORDS-1:1][DataWidth-1:0] rf_reg_q;
logic [NUM_WORDS-1:1] we_a_dec;
always_comb begin : we_a_decoder
for (int unsigned i = 1; i < NUM_WORDS; i++) begin
we_a_dec[i] = (waddr_a_i == 5'(i)) ? we_a_i : 1'b0;
end
end
// No flops for R0 as it's hard-wired to 0
for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rf_reg_q[i] <= '0;
end else if(we_a_dec[i]) begin
rf_reg_q[i] <= wdata_a_i;
end
end
end
// With dummy instructions enabled, R0 behaves as a real register but will always return 0 for
// real instructions.
if (DummyInstructions) begin : g_dummy_r0
logic we_r0_dummy;
logic [DataWidth-1:0] rf_r0_q;
// Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions)
assign we_r0_dummy = we_a_i & dummy_instr_id_i;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rf_r0_q <= '0;
end else if (we_r0_dummy) begin
rf_r0_q <= wdata_a_i;
end
end
// Output the dummy data for dummy instructions, otherwise R0 reads as zero
assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : '0;
end else begin : g_normal_r0
logic unused_dummy_instr_id;
assign unused_dummy_instr_id = dummy_instr_id_i;
// R0 is nil
assign rf_reg[0] = '0;
end
assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1];
assign rdata_a_o = rf_reg[raddr_a_i];
assign rdata_b_o = rf_reg[raddr_b_i];
// Signal not used in FF register file
// logic unused_test_en;
// assign unused_test_en = test_en_i;
endmodule