From d249e50588e28375946b14cac5ac4e4bfed000db Mon Sep 17 00:00:00 2001 From: Pascal Nasahl Date: Fri, 29 Nov 2024 18:58:35 +0100 Subject: [PATCH] [rtl] Fix non-DSP reset in ibex_counter When targeting Xilinx FPGAs, we utilize a DSP for counters with a width of less than 49-bit. In this case, a sync. reset is needed. However, currently, there is a bug in the RTL where also a sync. reset is used for the non-DSP counters on the FPGA. Signed-off-by: Pascal Nasahl --- dv/uvm/core_ibex/ibex_dv.f | 1 + ibex_core.core | 1 + rtl/ibex_core.f | 1 + rtl/ibex_counter.sv | 44 +++++++++++++++++++-------------- rtl/ibex_counter_flop_xilinx.sv | 43 ++++++++++++++++++++++++++++++++ src_files.yml | 1 + 6 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 rtl/ibex_counter_flop_xilinx.sv diff --git a/dv/uvm/core_ibex/ibex_dv.f b/dv/uvm/core_ibex/ibex_dv.f index c8ec489eb2..0b1ef67bdb 100644 --- a/dv/uvm/core_ibex/ibex_dv.f +++ b/dv/uvm/core_ibex/ibex_dv.f @@ -84,6 +84,7 @@ ${PRJ_DIR}/rtl/ibex_csr.sv ${PRJ_DIR}/rtl/ibex_cs_registers.sv ${PRJ_DIR}/rtl/ibex_counter.sv +${PRJ_DIR}/rtl/ibex_counter_flop_xilinx.sv ${PRJ_DIR}/rtl/ibex_decoder.sv ${PRJ_DIR}/rtl/ibex_dummy_instr.sv ${PRJ_DIR}/rtl/ibex_ex_block.sv diff --git a/ibex_core.core b/ibex_core.core index 15fb327869..0abee1fbab 100644 --- a/ibex_core.core +++ b/ibex_core.core @@ -23,6 +23,7 @@ filesets: - rtl/ibex_cs_registers.sv - rtl/ibex_csr.sv - rtl/ibex_counter.sv + - rtl/ibex_counter_flop_xilinx.sv - rtl/ibex_decoder.sv - rtl/ibex_ex_block.sv - rtl/ibex_fetch_fifo.sv diff --git a/rtl/ibex_core.f b/rtl/ibex_core.f index cde47fca2c..eaf925d9c1 100644 --- a/rtl/ibex_core.f +++ b/rtl/ibex_core.f @@ -7,6 +7,7 @@ ibex_compressed_decoder.sv ibex_controller.sv ibex_counter.sv +ibex_counter_flop_xilinx.sv ibex_cs_registers.sv ibex_decoder.sv ibex_ex_block.sv diff --git a/rtl/ibex_counter.sv b/rtl/ibex_counter.sv index c78e510ee4..6fac98728e 100644 --- a/rtl/ibex_counter.sv +++ b/rtl/ibex_counter.sv @@ -51,26 +51,37 @@ module ibex_counter #( end `ifdef FPGA_XILINX - // Set DSP pragma for supported xilinx FPGAs - localparam int DspPragma = CounterWidth < 49 ? "yes" : "no"; - (* use_dsp = DspPragma *) logic [CounterWidth-1:0] counter_q; - - // DSP output register requires synchronous reset. - `define COUNTER_FLOP_RST posedge clk_i + // On Xilinx FPGAs, 48-bit DSPs are available that can be used for the + // counter. Hence, use Xilinx specific flop implementation. + localparam int UseDsp = CounterWidth < 49 ? "yes" : "no"; + (* use_dsp = UseDsp *) logic [CounterWidth-1:0] counter_q; `else + localparam string UseDsp = "no"; logic [CounterWidth-1:0] counter_q; - - `define COUNTER_FLOP_RST posedge clk_i or negedge rst_ni `endif - // Counter flop - always_ff @(`COUNTER_FLOP_RST) begin - if (!rst_ni) begin - counter_q <= '0; - end else begin - counter_q <= counter_d; + generate + if (UseDsp == "yes") begin : g_cnt_dsp + // Use sync. reset for DSP. + always_ff @(posedge clk_i) begin + if (!rst_ni) begin + counter_q <= '0; + end else begin + counter_q <= counter_d; + end + end + end else begin : g_cnt_no_dsp + // Use async. reset for flop. + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + counter_q <= '0; + end else begin + counter_q <= counter_d; + end + end end - end + endgenerate + if (CounterWidth < 64) begin : g_counter_narrow logic [63:CounterWidth] unused_counter_load; @@ -98,6 +109,3 @@ module ibex_counter #( assign counter_val_o = counter; endmodule - -// Keep helper defines file-local. -`undef COUNTER_FLOP_RST diff --git a/rtl/ibex_counter_flop_xilinx.sv b/rtl/ibex_counter_flop_xilinx.sv new file mode 100644 index 0000000000..57f6041ae3 --- /dev/null +++ b/rtl/ibex_counter_flop_xilinx.sv @@ -0,0 +1,43 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Generic Counter Flop + * + * Counter flop implementation for non-Xilinx targets + */ +module ibex_counter_flop_xilinx #( + parameter int CounterWidth = 32, + parameter logic [CounterWidth-1:0] ResetValue = 0 +) ( + input logic clk_i, + input logic rst_ni, + input logic [CounterWidth-1:0] d_i, + output logic [CounterWidth-1:0] q_o +); + // On Xilinx FPGAs, 48-bit DSPs are available that can be used for the + // counter. When using a DSP, a sync. reset is needed for the flop. + localparam string ResetType = CounterWidth < 49 ? "SYNC" : "ASYNC"; + + generate + if(ResetType == "ASYNC") begin : g_async_reset_ff + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + q_o <= ResetValue; + end else begin + q_o <= d_i; + end + end + end else begin : g_sync_reset_ff + always_ff @(posedge clk_i) begin + if (!rst_ni) begin + q_o <= ResetValue; + end else begin + q_o <= d_i; + end + end + end + endgenerate + +endmodule diff --git a/src_files.yml b/src_files.yml index 3149b3be71..246f346967 100644 --- a/src_files.yml +++ b/src_files.yml @@ -10,6 +10,7 @@ ibex: rtl/ibex_controller.sv, rtl/ibex_cs_registers.sv, rtl/ibex_counters.sv, + rtl/ibex_counter_flop_xilinx.sv, rtl/ibex_decoder.sv, rtl/ibex_ex_block.sv, rtl/ibex_id_stage.sv,