diff --git a/doc/register_file.rst b/doc/register_file.rst index 8c98879a..c5c4c0fb 100644 --- a/doc/register_file.rst +++ b/doc/register_file.rst @@ -17,10 +17,21 @@ Flip-Flop-Based Register File The flip-flop-based register file uses regular, positive-edge-triggered flip-flops to implement the registers. -This makes it the **first choice for FPGA synthesis** or when simulating the design using Verilator. +This makes it the **first choice when simulating the design using Verilator**. To select the flip-flop-based register file, make sure to use the source file ``ibex_register_file_ff.sv`` in your project. +FPGA Register File +-------------------------- + +The FPGA register file leverages synchronous-write / asynchronous-read RAM design elements, where available on FPGA targets. + +For Xilinx FPGAs, synthesis results in an implementation using RAM32M primitives. Using this design with a Xilinx Artya7-100 FPGA conserves around 600 Logic LUTs and 1000 flip-flops at the expense of 48 LUTRAMs for the 31-entry register file as compared to the flip-flop-based register file. + +This makes it the **first choice for FPGA synthesis**. + +To select the FPGA register file, make sure to use the source file ``ibex_register_file_fpga.sv`` in your project. + Latch-Based Register File ------------------------- diff --git a/ibex_core.core b/ibex_core.core index d9349ac4..0bada042 100644 --- a/ibex_core.core +++ b/ibex_core.core @@ -27,7 +27,8 @@ filesets: # XXX: Figure out the best way to switch these two implementations # dynamically on the target. # - rtl/ibex_register_file_latch.sv # ASIC - - rtl/ibex_register_file_ff.sv # FPGA +# - rtl/ibex_register_file_fpga.sv # FPGA + - rtl/ibex_register_file_ff.sv # generic FF-based - rtl/ibex_core.sv file_type: systemVerilogSource diff --git a/lint/verilator_waiver.vlt b/lint/verilator_waiver.vlt index f31e81f0..3ff0b2bd 100644 --- a/lint/verilator_waiver.vlt +++ b/lint/verilator_waiver.vlt @@ -17,6 +17,7 @@ lint_off -msg PINCONNECTEMPTY // implementation choices for the same module. lint_off -msg DECLFILENAME -file "*/rtl/ibex_register_file_ff.sv" lint_off -msg DECLFILENAME -file "*/rtl/ibex_register_file_latch.sv" +lint_off -msg DECLFILENAME -file "*/rtl/ibex_register_file_fpga.sv" // Bits of signal are not used: boot_addr_i[7:0] // Boot address is 256B aligned, cleaner to pass all bits in @@ -45,6 +46,7 @@ lint_off -msg UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -lines 68 // Signal is not used: test_en_i // testability signal lint_off -msg UNUSED -file "*/rtl/ibex_register_file_ff.sv" -lines 21 +lint_off -msg UNUSED -file "*/rtl/ibex_register_file_fpga.sv" -lines 22 // Signal is not used: clk_i // leaving clk and reset connected in-case we want to add assertions @@ -57,6 +59,7 @@ lint_off -msg UNUSED -file "*/rtl/ibex_decoder.sv" -lines 21 lint_off -msg UNUSED -file "*/rtl/ibex_pmp.sv" -lines 16 lint_off -msg UNUSED -file "*/rtl/ibex_compressed_decoder.sv" -lines 15 lint_off -msg UNUSED -file "*/rtl/ibex_decoder.sv" -lines 22 +lint_off -msg UNUSED -file "*/rtl/ibex_register_file_fpga.sv" -lines 20 // Signal unoptimizable: Feedback to clock or circular logic: // ibex_core.cs_registers_i.mie_q diff --git a/rtl/ibex_register_file_fpga.sv b/rtl/ibex_register_file_fpga.sv new file mode 100644 index 00000000..3ced5d80 --- /dev/null +++ b/rtl/ibex_register_file_fpga.sv @@ -0,0 +1,57 @@ +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * RISC-V register file + * + * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. + * + * This register file is designed to make FPGA synthesis tools infer RAM primitives. For Xilinx + * FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested. + */ +module ibex_register_file #( + parameter bit RV32E = 0, + parameter int unsigned DataWidth = 32 +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_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 ADDR_WIDTH = RV32E ? 4 : 5; + localparam int NUM_WORDS = 2**ADDR_WIDTH; + + logic [DataWidth-1:0] mem[NUM_WORDS]; + logic we; // write enable if writing to any register other than R0 + + // async_read a + assign rdata_a_o = (raddr_a_i == '0) ? '0 : mem[raddr_a_i]; + + // async_read b + assign rdata_b_o = (raddr_b_i == '0) ? '0 : mem[baddr_b_i]; + + // we select + assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i; + + always_ff @(posedge clk_i) begin : sync_write + if (we == 1'b1) begin + mem[waddr_a_i] <= wdata_a_i; + end + end : sync_write + +endmodule : ibex_register_file