From c8c3c550711481862b4e080830830bc3b5f2d45f Mon Sep 17 00:00:00 2001 From: Greg Chadwick Date: Fri, 15 Jan 2021 16:29:08 +0000 Subject: [PATCH] [dv] Fix race condition in cs_registers testbench The `driver_tick` DPI call drove inputs directly but was being scheduled in an undefined order with other always_ff blocks. This results in a race condition where some always_ff blocks see old inputs and others see new in the same clock tick. Instead use values from `driver_tick` to perform NBA updates and avoid the race condition. --- dv/cs_registers/tb/tb_cs_registers.sv | 29 ++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/dv/cs_registers/tb/tb_cs_registers.sv b/dv/cs_registers/tb/tb_cs_registers.sv index 57be8a7df0..23e706e092 100644 --- a/dv/cs_registers/tb/tb_cs_registers.sv +++ b/dv/cs_registers/tb/tb_cs_registers.sv @@ -33,6 +33,11 @@ module tb_cs_registers #( logic illegal_csr_insn_o; + logic csr_access_d; + ibex_pkg::csr_num_e csr_addr_d; + logic [31:0] csr_wdata_d; + ibex_pkg::csr_op_e csr_op_d; + logic csr_op_en_d; //----------------- // Reset generation //----------------- @@ -121,12 +126,26 @@ module tb_cs_registers #( csr_addr_i, csr_wdata_i, csr_rdata_o); + reg_dpi::driver_tick("reg_driver", - csr_access_i, - csr_op_i, - csr_op_en_i, - csr_addr_i, - csr_wdata_i); + csr_access_d, + csr_op_d, + csr_op_en_d, + csr_addr_d, + csr_wdata_d); + + // Use NBA to drive inputs to ensure correct scheduling. + // This always_ff block will be executed on the positive edge of the clock with undefined order + // vs all other always_ff triggered on the positive edge of the clock. If `driver_tick` drives + // the inputs directly some of the always_ff blocks will see the old version of the inputs and + // others will see the new version depending on scheduling order. This schedules all the inputs + // to be NBA updates to avoid the race condition (in effect acting like any other always_ff + // block with the _d values being computed via DPI rather than combinational logic). + csr_access_i <= csr_access_d; + csr_addr_i <= csr_addr_d; + csr_wdata_i <= csr_wdata_d; + csr_op_i <= csr_op_d; + csr_op_en_i <= csr_op_en_d; end endmodule