/* SPDX-License-Identifier: CERN-OHL-P-2.0 */ /* * Copyright 2026 UBC ASIC contributors (Montreal project). * * Author: Warrick Lo * * Register file * * This module contains the register file for the RISC-V core. Each word is * partitioned into slices (default 8 bits). A global slice selector determines * which slice of each word is accessed for both read and write operations. * * The register file has one synchronous write port and a configurable number of * read ports (default 2). Register 0 is fixed to 0 for all reads. */ `include "types.svh" module regfile #( parameter int unsigned XLEN = config_pkg::XLEN, parameter int unsigned SLICE_WIDTH = config_pkg::SLICE_WIDTH, parameter int unsigned ADDR_WIDTH = config_pkg::REG_ADDR_WIDTH, parameter int unsigned NUM_READ_PORTS = config_pkg::REG_NUM_READ_PORTS, localparam int unsigned NUM_WORDS = 2 ** ADDR_WIDTH, localparam int unsigned SLICE_ADDR_WIDTH = $clog2(XLEN / SLICE_WIDTH) ) ( /* Expose the internal register state for formal verification. * Yosys/SBY cannot reliably reference hierarchical signals after * elaboration and optimisation. */ `ifdef FORMAL /* verilog_lint: waive port-name-suffix */ output word_bank_t register_dbg, `endif input logic clk_i, input logic rst_ni, input logic [SLICE_ADDR_WIDTH-1:0] slice_sel_i, input logic [NUM_READ_PORTS-1:0][ADDR_WIDTH-1:0] raddr_i, output logic [NUM_READ_PORTS-1:0][SLICE_WIDTH-1:0] rdata_o, input logic wen_i, input logic [ADDR_WIDTH-1:0] waddr_i, input logic [SLICE_WIDTH-1:0] wdata_i ); word_bank_t register; /* Debug signal for formal verification. See above. */ `ifdef FORMAL assign register_dbg = register; `endif always_comb begin for (int i = 0; i < NUM_READ_PORTS; i++) begin : gen_read_block rdata_o[i] = (raddr_i[i] == '0) ? '0 : register[raddr_i[i]][slice_sel_i*SLICE_WIDTH +: SLICE_WIDTH]; end : gen_read_block end always_ff @(posedge clk_i) begin if (!rst_ni) begin register <= '0; end else if (wen_i && (waddr_i != '0)) begin /* verilog_lint: waive dff-name-style */ register[waddr_i][slice_sel_i*SLICE_WIDTH +: SLICE_WIDTH] <= wdata_i; end end endmodule : regfile