From 0d772757e9ca1eda37486c1ed36bb9c34b6001a8 Mon Sep 17 00:00:00 2001 From: Pirmin Vogel Date: Fri, 1 Mar 2024 16:22:03 +0100 Subject: [PATCH 1/4] [entropy_src] Fix FIFO controls, move drop point to before postht FIFO This commit cleans up and documents the control signals for the main FIFOs of the pipeline including the esrng, esbit, postht, precon and esfinal FIFOs. Most of the changes simplify the code but don't alter the behavior of the design as the used FIFO primitives already implement the logic to not accept pushes when full internally. However, there are some important changes that are necessary: 1. The esrng FIFO handles no backpressure anymore. This wasn't spec compliant. 2. The sample drop point in case of backpressure is moved to after the health tests in case we are not in firmware overide insert mode and the window counter controls are updated. This means in case of backpressure, samples are tested but they're not pushed into the postht FIFO (or the esbit FIFO in case of single-bit mode). The window timer doesn't increment to keep the number of samples ending up in the conditioner fixed, independent of backpressure. This is required by the spec. Signed-off-by: Pirmin Vogel --- .../entropy_src/dv/env/entropy_src_env_cfg.sv | 5 +- .../entropy_src/dv/env/entropy_src_env_pkg.sv | 22 +++--- .../dv/env/seq_lib/entropy_src_err_vseq.sv | 14 ++-- hw/ip/entropy_src/rtl/entropy_src_core.sv | 79 +++++++++++++++---- 4 files changed, 78 insertions(+), 42 deletions(-) diff --git a/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv b/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv index c1aa36156d265..0e020b10f31cd 100644 --- a/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv +++ b/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv @@ -182,12 +182,11 @@ class entropy_src_env_cfg extends cip_base_env_cfg #(.RAL_T(entropy_src_reg_bloc constraint which_err_code_c { which_err_code dist { sfifo_esrng_err :/ 2, - sfifo_observe_err :/ 3, + sfifo_observe_err :/ 2, sfifo_esfinal_err :/ 2, es_ack_sm_err :/ 2, es_main_sm_err :/ 2, es_cntr_err :/ 60, - fifo_write_err :/ 2, fifo_read_err :/ 3, fifo_state_err :/ 3};} @@ -209,13 +208,11 @@ class entropy_src_env_cfg extends cip_base_env_cfg #(.RAL_T(entropy_src_reg_bloc constraint which_fifo_err_c { which_err_code inside {sfifo_esrng_err, sfifo_esfinal_err} -> which_fifo_err inside {read, state}; - which_err_code == fifo_write_err -> which_fifo_err == write; which_err_code == fifo_read_err -> which_fifo_err == read; which_err_code == fifo_state_err -> which_fifo_err == state; } constraint which_fifo_c { - which_err_code == fifo_write_err -> which_fifo == sfifo_observe; which_err_code == sfifo_observe_err -> which_fifo == sfifo_observe; which_err_code == sfifo_esrng_err -> which_fifo == sfifo_esrng; which_err_code == sfifo_esfinal_err -> which_fifo == sfifo_esfinal; diff --git a/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv b/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv index c5b44065473ac..1e830c9aea29c 100644 --- a/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv +++ b/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv @@ -61,18 +61,16 @@ package entropy_src_env_pkg; es_ack_sm_err = 3, es_main_sm_err = 4, es_cntr_err = 5, - fifo_write_err = 6, - fifo_read_err = 7, - fifo_state_err = 8, - sfifo_esrng_err_test = 9, - sfifo_observe_err_test = 10, - sfifo_esfinal_err_test = 11, - es_ack_sm_err_test = 12, - es_main_sm_err_test = 13, - es_cntr_err_test = 14, - fifo_write_err_test = 15, - fifo_read_err_test = 16, - fifo_state_err_test = 17 + fifo_read_err = 6, + fifo_state_err = 7, + sfifo_esrng_err_test = 8, + sfifo_observe_err_test = 9, + sfifo_esfinal_err_test = 10, + es_ack_sm_err_test = 11, + es_main_sm_err_test = 12, + es_cntr_err_test = 13, + fifo_read_err_test = 14, + fifo_state_err_test = 15 } err_code_e; typedef enum int { diff --git a/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv b/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv index 86d05d4e5fb60..27ef8f28e4588 100644 --- a/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv +++ b/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv @@ -126,7 +126,7 @@ class entropy_src_err_vseq extends entropy_src_base_vseq; `DV_CHECK(uvm_hdl_read(sm_state_path, sm_state)) `DV_CHECK_EQ(sm_state, entropy_src_ack_sm_pkg::Error) end - fifo_write_err, fifo_read_err, fifo_state_err: begin + fifo_read_err, fifo_state_err: begin fifo_name = cfg.which_fifo.name(); path_key = fld_name.substr(first_index+1, last_index-1); @@ -141,16 +141,12 @@ class entropy_src_err_vseq extends entropy_src_base_vseq; fifo_forced_paths[i] = cfg.entropy_src_path_vif.fifo_err_path("sfifo_esrng", path_exts[i]); end - if (cfg.which_err_code == fifo_write_err && cfg.which_fifo == sfifo_esrng) begin - force_fifo_err_exception(fifo_forced_paths, fifo_forced_values, fld, 1'b1); - end else begin - force_fifo_err(path1, path2, value1, value2, fld, 1'b1); - end + force_fifo_err(path1, path2, value1, value2, fld, 1'b1); cov_vif.cg_fifo_err_sample(cfg.which_fifo_err, cfg.which_fifo); end - sfifo_esrng_err_test ,sfifo_observe_err_test, sfifo_esfinal_err_test, es_ack_sm_err_test, - es_main_sm_err_test, es_cntr_err_test, fifo_write_err_test, fifo_read_err_test, - fifo_state_err_test: begin + sfifo_esrng_err_test, sfifo_observe_err_test, sfifo_esfinal_err_test, + es_ack_sm_err_test, es_main_sm_err_test, es_cntr_err_test, + fifo_read_err_test, fifo_state_err_test: begin // First turn off module_enable to write registers csr_wr(.ptr(ral.module_enable), .value(prim_mubi_pkg::MuBi4False)); // Get the register field name diff --git a/hw/ip/entropy_src/rtl/entropy_src_core.sv b/hw/ip/entropy_src/rtl/entropy_src_core.sv index 74d5c4749381e..ab8fa0b96dd55 100644 --- a/hw/ip/entropy_src/rtl/entropy_src_core.sv +++ b/hw/ip/entropy_src/rtl/entropy_src_core.sv @@ -139,7 +139,6 @@ module entropy_src_core import entropy_src_pkg::*; #( logic [Clog2EsFifoDepth:0] sfifo_esfinal_depth; logic [(1+SeedLen)-1:0] sfifo_esfinal_wdata; logic [(1+SeedLen)-1:0] sfifo_esfinal_rdata; - logic sfifo_esfinal_push_enable; logic sfifo_esfinal_push; logic sfifo_esfinal_pop; logic sfifo_esfinal_clr; @@ -416,6 +415,7 @@ module entropy_src_core import entropy_src_pkg::*; #( logic [32:0] sha3_err; logic cs_aes_halt_req; logic [WINDOW_CNTR_WIDTH-1:0] window_cntr; + logic window_cntr_incr_en; logic [sha3_pkg::StateW-1:0] sha3_state[Sha3Share]; logic [PreCondWidth-1:0] msg_data[Sha3Share]; @@ -450,6 +450,7 @@ module entropy_src_core import entropy_src_pkg::*; #( logic unused_entropy_data; logic unused_fw_ov_rd_data; logic unused_sfifo_esrng_not_full; + logic unused_sfifo_esfinal_not_full; prim_mubi_pkg::mubi8_t en_entropy_src_fw_read; prim_mubi_pkg::mubi8_t en_entropy_src_fw_over; @@ -1023,28 +1024,40 @@ module entropy_src_core import entropy_src_pkg::*; #( ); // fifo controls + // We can't handle any backpressure at this point. Unless the ENTROPY_SRC block is turned off, + // the input coming from the noise source / RNG needs to be accepted without dropping samples. assign sfifo_esrng_push = es_enable_fo[5] && es_delayed_enable && es_rng_src_valid && rng_enable_q; assign sfifo_esrng_clr = ~es_delayed_enable; assign sfifo_esrng_wdata = es_rng_bus; - assign sfifo_esrng_pop = sfifo_esrng_not_empty & (rng_bit_en ? pfifo_esbit_not_full : - pfifo_postht_not_full); + // We can't apply any backpressure at this point. Every sample is presented to the health tests + // for exactly one clock cycle. If the receiving FIFO is full, the sample is dropped but the + // health tests are still performed and the results accumulated. + assign sfifo_esrng_pop = sfifo_esrng_not_empty; // fifo err - // Note: for prim_fifo_sync is not an error to push to a fifo that is full. In fact, the - // backpressure mechanism applied to the RNG inputs counts on this. + // The esnrg FIFO must never be pushed when it's full as no backpressure can be applied to the + // noise source / RNG. However, we can't raise an error and abort operation of the ENTROPY_SRC + // block as this would mean a catastrophic failure of the whole chip. Instead we need to catch + // this in simulation only. assign sfifo_esrng_err = {1'b0, (sfifo_esrng_pop && !sfifo_esrng_not_empty), (sfifo_esrng_full && !sfifo_esrng_not_empty)}; - + `ASSERT(RngBackpressureNotAllowed_A, sfifo_esrng_push |-> sfifo_esrng_not_full) // Read the health test data from the esrng FIFO. assign health_test_esbus = sfifo_esrng_rdata; - // Set the valid signal to true whenever data is pushed into the next FIFO. - assign health_test_esbus_vld = rng_bit_en ? pfifo_esbit_push && !pfifo_esbit_clr : - pfifo_postht_push && !pfifo_postht_clr; + // Perform the health tests whenever data is valid and the receiving FIFO is not being cleared. + // This doesn't mean the receiving FIFO is pushed. The receiving FIFO is only pushed if it has + // indeed space. This means in case of heavy backpressure, we keep testing the noise source + // samples, but we drop them before the postht FIFO. If this happens, the window counter isn't + // incremented. This way we can keep the number of bits going into the conditioner constant, + // independent of potential backpressure within the pipeline. + assign health_test_esbus_vld = + rng_bit_en ? sfifo_esrng_not_empty && !pfifo_esbit_clr : + sfifo_esrng_not_empty && !pfifo_postht_clr; // Health test any data that comes in on the RNG interface. assign repcnt_active = 1'b1; @@ -1499,6 +1512,16 @@ module entropy_src_core import entropy_src_pkg::*; #( // Window counter // SEC_CM: CTR.REDUN + + // We only increment the counter if the currently tested sample can be pushed to the correct FIFO + // following the health tests. This is required to keep the number of samples passed to the + // conditioner constant also when experiencing backpressure from the conditioner. At the same + // time, we're not allowed to drop samples before the health testing. This means the number of + // tested samples might be slightly bigger than the number of samples fed into the conditioner. + assign window_cntr_incr_en = + rng_bit_en ? pfifo_esbit_push && pfifo_esbit_not_full && !pfifo_esbit_clr : + pfifo_postht_push && pfifo_postht_not_full && !pfifo_postht_clr; + prim_count #( .Width(WINDOW_CNTR_WIDTH) ) u_prim_count_window_cntr ( @@ -1507,7 +1530,7 @@ module entropy_src_core import entropy_src_pkg::*; #( .clr_i(!es_delayed_enable), .set_i(health_test_done_pulse), .set_cnt_i(WINDOW_CNTR_WIDTH'(0)), - .incr_en_i(health_test_esbus_vld), + .incr_en_i(window_cntr_incr_en), .decr_en_i(1'b0), .step_i(WINDOW_CNTR_WIDTH'(1)), .commit_i(1'b1), @@ -2336,6 +2359,13 @@ module entropy_src_core import entropy_src_pkg::*; #( .depth_o () ); + // The prim_packer_fifo primitive is constructed to only accept pushes if there is indeed space + // available. The pop signal of the preceeding esrng FIFO is unconditional, meaning samples can + // be dropped before the esbit FIFO in case of backpressure. The samples are however still + // tested. Regardless, these drops should only happen when we are not + // in firmware overide insert mode. In firmware overide insert mode the postht FIFO gets popped + // as soon as data is available and the entropy should come in slow enough such that we won't + // drop entropy. assign pfifo_esbit_push = rng_bit_en && sfifo_esrng_not_empty; assign pfifo_esbit_clr = ~es_delayed_enable; assign pfifo_esbit_pop = rng_bit_en && pfifo_esbit_not_empty && pfifo_postht_not_full; @@ -2367,6 +2397,15 @@ module entropy_src_core import entropy_src_pkg::*; #( .depth_o () ); + // The prim_packer_fifo primitive is constructed to only accept pushes if there is indeed space + // available. In case the single-bit mode is enabled, the pop signal of the preceeding esbit FIFO + // is conditional on the full status of the postht FIFO, meaning backpressure can be handled. In + // case the single-bit mode is disabled, the pop signal of the preceeding esrng FIFO is + // unconditional, meaning samples can be dropped before the esbit in case of backpressure. The + // samples are however still tested. Regardless, these drops should only happen when we are not + // in firmware overide insert mode. In firmware overide insert mode the postht FIFO gets popped + // as soon as data is available and the entropy should come in slow enough such that we won't + // drop entropy. assign pfifo_postht_push = rng_bit_en ? pfifo_esbit_not_empty : sfifo_esrng_not_empty; assign pfifo_postht_wdata = rng_bit_en ? pfifo_esbit_rdata : @@ -2446,7 +2485,7 @@ module entropy_src_core import entropy_src_pkg::*; #( assign hw2reg.observe_fifo_depth.d = sfifo_observe_depth; // fifo controls - assign sfifo_observe_push = fw_ov_mode && pfifo_postht_pop && !sfifo_observe_full && + assign sfifo_observe_push = fw_ov_mode && pfifo_postht_pop && (sfifo_observe_gate_q || !sfifo_observe_not_empty); assign sfifo_observe_clr = ~es_enable_fo[9]; @@ -2457,8 +2496,11 @@ module entropy_src_core import entropy_src_pkg::*; #( (fw_ov_mode && fw_ov_fifo_rd_pulse); // fifo err + // Note that for the used prim_fifo_sync and prim_packer_fifo primitives it is not an error to + // push to a FIFO that is full. The primitives simply don't accept the data when full. The + // backpressure needs to be handled at the sender. assign sfifo_observe_err = - {(sfifo_observe_push && sfifo_observe_full), + {1'b0, (sfifo_observe_pop && !sfifo_observe_not_empty), (sfifo_observe_full && !sfifo_observe_not_empty)}; @@ -2788,11 +2830,12 @@ module entropy_src_core import entropy_src_pkg::*; #( assign fips_compliance = es_enable_fo[13] && fips_flag_pfe; // fifo controls - assign sfifo_esfinal_push_enable = + // No backpressure is possible at this point. If the esfinal FIFO is already full and a new seed + // is pushed, the push is ignored and the seed is lost. + assign sfifo_esfinal_push = fw_ov_mode_entropy_insert && es_bypass_mode ? pfifo_bypass_not_empty : main_stage_push; - assign sfifo_esfinal_push = sfifo_esfinal_not_full && sfifo_esfinal_push_enable; assign sfifo_esfinal_clr = !es_enable_fo[14]; assign sfifo_esfinal_wdata = {fips_compliance,final_es_data}; assign sfifo_esfinal_pop = es_route_to_sw ? pfifo_swread_push : @@ -2800,8 +2843,9 @@ module entropy_src_core import entropy_src_pkg::*; #( assign {esfinal_fips_flag,esfinal_data} = sfifo_esfinal_rdata; // fifo err - // Note: for prim_fifo_sync is not an error to push to a fifo that is full. In fact, the - // backpressure mechanism applied to the previous FIFO counts on this. + // Note that for the used prim_fifo_sync and prim_packer_fifo primitives it is not an error to + // push to a FIFO that is full. The primitives simply don't accept the data when full. The + // backpressure needs to be handled at the sender. assign sfifo_esfinal_err = {1'b0, (sfifo_esfinal_pop && !sfifo_esfinal_not_empty), @@ -2907,7 +2951,8 @@ module entropy_src_core import entropy_src_pkg::*; #( assign unused_sha3_state = (|sha3_state[0][sha3_pkg::StateW-1:SeedLen]); assign unused_entropy_data = (|reg2hw.entropy_data.q); assign unused_fw_ov_rd_data = (|reg2hw.fw_ov_rd_data.q); - assign unused_sfifo_esrng_not_full = (|sfifo_esrng_not_full); + assign unused_sfifo_esrng_not_full = sfifo_esrng_not_full; + assign unused_sfifo_esfinal_not_full = sfifo_esfinal_not_full; //-------------------------------------------- // Assertions From d3feaa575a0b3828ebc95ec1a0506b0848a28a92 Mon Sep 17 00:00:00 2001 From: Pirmin Vogel Date: Fri, 1 Mar 2024 17:25:54 +0100 Subject: [PATCH 2/4] [entropy_src] Align prim_fifo_sync instantation parameters This commit switches all instances of prim_fifo_sync to use hardened counters for the pointers. Signed-off-by: Pirmin Vogel --- hw/ip/entropy_src/data/entropy_src.hjson | 12 ++--- hw/ip/entropy_src/doc/registers.md | 12 ++--- hw/ip/entropy_src/rtl/entropy_src.sv | 22 +++++++++ hw/ip/entropy_src/rtl/entropy_src_core.sv | 58 +++++++++++++---------- 4 files changed, 61 insertions(+), 43 deletions(-) diff --git a/hw/ip/entropy_src/data/entropy_src.hjson b/hw/ip/entropy_src/data/entropy_src.hjson index b9b5ccee44183..fa3a8acf2790b 100644 --- a/hw/ip/entropy_src/data/entropy_src.hjson +++ b/hw/ip/entropy_src/data/entropy_src.hjson @@ -1679,27 +1679,21 @@ { bits: "28", name: "FIFO_WRITE_ERR", desc: ''' - This bit will be set to one when any of the source bits (bits 0 through 1 of this - this register) are asserted as a result of an error pulse generated from - any full FIFO that has been recieved a write pulse. + This bit will be set to one when any of the source bits (bits 0 through 1 of this register) are asserted as a result of an error pulse generated from any full FIFO that has been received a write pulse. This bit will stay set until the next reset. ''' } { bits: "29", name: "FIFO_READ_ERR", desc: ''' - This bit will be set to one when any of the source bits (bits 0 through 1 of this - this register) are asserted as a result of an error pulse generated from - any empty FIFO that has recieved a read pulse. + This bit will be set to one when any of the source bits (bits 0 through 1 of this register) are asserted as a result of an error pulse generated from any empty FIFO that has received a read pulse. This bit will stay set until the next reset. ''' } { bits: "30", name: "FIFO_STATE_ERR", desc: ''' - This bit will be set to one when any of the source bits (bits 0 through 1 of this - this register) are asserted as a result of an error pulse generated from - any FIFO where both the empty and full status bits are set. + This bit will be set to one when any of the source bits (bits 0 through 1 of this register) are asserted as a result of an error pulse generated from any FIFO where either both the empty and full status bits are set or in case of error conditions inside the hardened counters. This bit will stay set until the next reset. ''' } diff --git a/hw/ip/entropy_src/doc/registers.md b/hw/ip/entropy_src/doc/registers.md index 549931403bee8..837e34b6d4ac1 100644 --- a/hw/ip/entropy_src/doc/registers.md +++ b/hw/ip/entropy_src/doc/registers.md @@ -1494,21 +1494,15 @@ Hardware detection of error conditions status register | 0 | ro | 0x0 | [SFIFO_ESRNG_ERR](#err_code--sfifo_esrng_err) | ### ERR_CODE . FIFO_STATE_ERR -This bit will be set to one when any of the source bits (bits 0 through 1 of this -this register) are asserted as a result of an error pulse generated from -any FIFO where both the empty and full status bits are set. +This bit will be set to one when any of the source bits (bits 0 through 1 of this register) are asserted as a result of an error pulse generated from any FIFO where either both the empty and full status bits are set or in case of error conditions inside the hardened counters. This bit will stay set until the next reset. ### ERR_CODE . FIFO_READ_ERR -This bit will be set to one when any of the source bits (bits 0 through 1 of this -this register) are asserted as a result of an error pulse generated from -any empty FIFO that has recieved a read pulse. +This bit will be set to one when any of the source bits (bits 0 through 1 of this register) are asserted as a result of an error pulse generated from any empty FIFO that has received a read pulse. This bit will stay set until the next reset. ### ERR_CODE . FIFO_WRITE_ERR -This bit will be set to one when any of the source bits (bits 0 through 1 of this -this register) are asserted as a result of an error pulse generated from -any full FIFO that has been recieved a write pulse. +This bit will be set to one when any of the source bits (bits 0 through 1 of this register) are asserted as a result of an error pulse generated from any full FIFO that has been received a write pulse. This bit will stay set until the next reset. ### ERR_CODE . SHA3_RST_STORAGE_ERR diff --git a/hw/ip/entropy_src/rtl/entropy_src.sv b/hw/ip/entropy_src/rtl/entropy_src.sv index 5a5b904e5a49d..83dd74b6c281b 100644 --- a/hw/ip/entropy_src/rtl/entropy_src.sv +++ b/hw/ip/entropy_src/rtl/entropy_src.sv @@ -403,6 +403,28 @@ module entropy_src u_entropy_src_core.u_entropy_src_cntr_reg_extht_lo_alert_fails.u_prim_count_cntr_reg, alert_tx_o[1]) + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(EsrngFifoWptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_esrng.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_wptr, + alert_tx_o[1]) + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(EsrngFifoRptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_esrng.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_rptr, + alert_tx_o[1]) + + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(ObserveFifoWptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_observe.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_wptr, + alert_tx_o[1]) + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(ObserveFifoRptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_observe.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_rptr, + alert_tx_o[1]) + + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(EsfinalFifoWptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_esfinal.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_wptr, + alert_tx_o[1]) + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(EsfinalFifoRptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_esfinal.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_rptr, + alert_tx_o[1]) + // Alert assertions for reg_we onehot check `ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(RegWeOnehotCheck_A, u_reg, alert_tx_o[1]) + endmodule diff --git a/hw/ip/entropy_src/rtl/entropy_src_core.sv b/hw/ip/entropy_src/rtl/entropy_src_core.sv index ab8fa0b96dd55..fc16d6b2a9419 100644 --- a/hw/ip/entropy_src/rtl/entropy_src_core.sv +++ b/hw/ip/entropy_src/rtl/entropy_src_core.sv @@ -124,28 +124,32 @@ module entropy_src_core import entropy_src_pkg::*; #( logic sfifo_esrng_full; logic sfifo_esrng_not_empty; logic sfifo_esrng_not_full; + logic sfifo_esrng_int_err; logic [2:0] sfifo_esrng_err; - logic [ObserveFifoWidth-1:0] sfifo_observe_wdata; - logic [ObserveFifoWidth-1:0] sfifo_observe_rdata; - logic sfifo_observe_push; - logic sfifo_observe_pop; - logic sfifo_observe_full; - logic sfifo_observe_clr; - logic sfifo_observe_not_empty; + logic [ObserveFifoWidth-1:0] sfifo_observe_wdata; + logic [ObserveFifoWidth-1:0] sfifo_observe_rdata; + logic sfifo_observe_push; + logic sfifo_observe_pop; + logic sfifo_observe_full; + logic sfifo_observe_clr; + logic sfifo_observe_not_empty; logic [Clog2ObserveFifoDepth:0] sfifo_observe_depth; + logic sfifo_observe_int_err; logic [2:0] sfifo_observe_err; logic [Clog2EsFifoDepth:0] sfifo_esfinal_depth; - logic [(1+SeedLen)-1:0] sfifo_esfinal_wdata; - logic [(1+SeedLen)-1:0] sfifo_esfinal_rdata; - logic sfifo_esfinal_push; - logic sfifo_esfinal_pop; - logic sfifo_esfinal_clr; - logic sfifo_esfinal_not_full; - logic sfifo_esfinal_full; - logic sfifo_esfinal_not_empty; - logic [2:0] sfifo_esfinal_err; + logic [(1+SeedLen)-1:0] sfifo_esfinal_wdata; + logic [(1+SeedLen)-1:0] sfifo_esfinal_rdata; + logic sfifo_esfinal_push; + logic sfifo_esfinal_pop; + logic sfifo_esfinal_clr; + logic sfifo_esfinal_not_full; + logic sfifo_esfinal_full; + logic sfifo_esfinal_not_empty; + logic sfifo_esfinal_int_err; + logic [2:0] sfifo_esfinal_err; + logic [SeedLen-1:0] esfinal_data; logic esfinal_fips_flag; @@ -1007,7 +1011,8 @@ module entropy_src_core import entropy_src_pkg::*; #( .Width(RngBusWidth), .Pass(0), .Depth(2), - .OutputZeroIfEmpty(1'b0) + .OutputZeroIfEmpty(0), + .Secure(1) ) u_prim_fifo_sync_esrng ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -1020,7 +1025,7 @@ module entropy_src_core import entropy_src_pkg::*; #( .rready_i (sfifo_esrng_pop), .full_o (sfifo_esrng_full), .depth_o (), - .err_o () + .err_o (sfifo_esrng_int_err) ); // fifo controls @@ -1044,7 +1049,7 @@ module entropy_src_core import entropy_src_pkg::*; #( assign sfifo_esrng_err = {1'b0, (sfifo_esrng_pop && !sfifo_esrng_not_empty), - (sfifo_esrng_full && !sfifo_esrng_not_empty)}; + (sfifo_esrng_full && !sfifo_esrng_not_empty) || sfifo_esrng_int_err}; `ASSERT(RngBackpressureNotAllowed_A, sfifo_esrng_push |-> sfifo_esrng_not_full) // Read the health test data from the esrng FIFO. @@ -2441,7 +2446,9 @@ module entropy_src_core import entropy_src_pkg::*; #( prim_fifo_sync #( .Width(ObserveFifoWidth), .Pass(0), - .Depth(ObserveFifoDepth) + .Depth(ObserveFifoDepth), + .OutputZeroIfEmpty(1), // Prevent SVA from firing due unknown module outputs. + .Secure(1) ) u_prim_fifo_sync_observe ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -2454,7 +2461,7 @@ module entropy_src_core import entropy_src_pkg::*; #( .rready_i (sfifo_observe_pop), .full_o (sfifo_observe_full), .depth_o (sfifo_observe_depth), - .err_o () + .err_o (sfifo_observe_int_err) ); // The Observe fifo is intended to hold kilobits of contiguous data, yet still gracefully @@ -2502,7 +2509,7 @@ module entropy_src_core import entropy_src_pkg::*; #( assign sfifo_observe_err = {1'b0, (sfifo_observe_pop && !sfifo_observe_not_empty), - (sfifo_observe_full && !sfifo_observe_not_empty)}; + (sfifo_observe_full && !sfifo_observe_not_empty) || sfifo_observe_int_err}; //-------------------------------------------- @@ -2807,7 +2814,8 @@ module entropy_src_core import entropy_src_pkg::*; #( .Width(1+SeedLen), .Pass(0), .Depth(EsFifoDepth), - .OutputZeroIfEmpty(1'b0) + .OutputZeroIfEmpty(0), + .Secure(1) ) u_prim_fifo_sync_esfinal ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -2820,7 +2828,7 @@ module entropy_src_core import entropy_src_pkg::*; #( .rdata_o (sfifo_esfinal_rdata), .full_o (sfifo_esfinal_full), .depth_o (sfifo_esfinal_depth), - .err_o () + .err_o (sfifo_esfinal_int_err) ); // The FIPS flag is fully determined in SW. This has to be the case since we don't know @@ -2849,7 +2857,7 @@ module entropy_src_core import entropy_src_pkg::*; #( assign sfifo_esfinal_err = {1'b0, (sfifo_esfinal_pop && !sfifo_esfinal_not_empty), - (sfifo_esfinal_full && !sfifo_esfinal_not_empty)}; + (sfifo_esfinal_full && !sfifo_esfinal_not_empty) || sfifo_esfinal_int_err}; // drive out hw interface assign es_hw_if_req = entropy_src_hw_if_i.es_req; From 331128be6ba131b74f4efcce80ff17b8ba34c3f6 Mon Sep 17 00:00:00 2001 From: Pirmin Vogel Date: Fri, 1 Mar 2024 19:00:29 +0100 Subject: [PATCH 3/4] [entropy_src] Add FIFO to deal with backpressure from the conditioner This commit adds a 32-bit wide distribution FIFO of configurable depth. The FIFO is added between the postht FIFO, the observe FIFO, the bypass FIFO and the precon FIFO. Its main purpose is to buffer entropy bits while the conditioner is busy such that we don't have to drop entropy bits from the hardware pipeline. Dropping entropy bits is not a big issue per se during normal operation as it's allowed by the spec (when done after the health tests and in a way such that number of samples going into the conditioner is fixed). Also, under normal operating conditions, noise source samples arrive at very low rate and dropping bits should not be needed. However, verifying that the `correct` entropy bits are dropped is hard and seems impossible for our current DV environment as it requires to very accurately model the hardware pipeline which is undesirable. Thus, the safest approach is to add this new distribution FIFO and tune its depth parameter to handle potential backpressure from the conditioner such that dropping bits is not necessary. Signed-off-by: Pirmin Vogel --- hw/ip/entropy_src/data/entropy_src.hjson | 17 ++- hw/ip/entropy_src/doc/registers.md | 16 +- .../entropy_src/dv/env/entropy_src_env_cfg.sv | 8 +- .../entropy_src/dv/env/entropy_src_env_pkg.sv | 51 ++++--- .../dv/env/seq_lib/entropy_src_err_vseq.sv | 4 +- hw/ip/entropy_src/rtl/entropy_src.sv | 13 +- hw/ip/entropy_src/rtl/entropy_src_core.sv | 140 +++++++++++++++--- .../rtl/entropy_src_enable_delay.sv | 16 +- hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv | 84 ++++++----- hw/ip/entropy_src/rtl/entropy_src_reg_top.sv | 37 ++++- .../data/autogen/top_earlgrey.gen.hjson | 8 + hw/top_earlgrey/rtl/autogen/top_earlgrey.sv | 2 + sw/device/lib/dif/dif_entropy_src_unittest.cc | 2 +- 13 files changed, 287 insertions(+), 111 deletions(-) diff --git a/hw/ip/entropy_src/data/entropy_src.hjson b/hw/ip/entropy_src/data/entropy_src.hjson index fa3a8acf2790b..ee5133e1d0b34 100644 --- a/hw/ip/entropy_src/data/entropy_src.hjson +++ b/hw/ip/entropy_src/data/entropy_src.hjson @@ -100,6 +100,13 @@ local: "false", expose: "true" }, + { name: "DistrFifoDepth", + type: "int unsigned", + default: "2", + desc: "Number of 32-bit entries in the distr FIFO", + local: "false", + expose: "true" + }, { name: "Stub", type: "bit", default: "0", @@ -1615,6 +1622,14 @@ ''' } { bits: "1", + name: "SFIFO_DISTR_ERR", + desc: ''' + This bit will be set to one when an error has been detected for the distribution FIFO. + The type of error is reflected in the type status bits (bits 28 through 30 of this register). + This bit will stay set until the next reset. + ''' + } + { bits: "2", name: "SFIFO_OBSERVE_ERR", desc: ''' This bit will be set to one when an error has been detected for the @@ -1623,7 +1638,7 @@ This bit will stay set until the next reset. ''' } - { bits: "2", + { bits: "3", name: "SFIFO_ESFINAL_ERR", desc: ''' This bit will be set to one when an error has been detected for the diff --git a/hw/ip/entropy_src/doc/registers.md b/hw/ip/entropy_src/doc/registers.md index 837e34b6d4ac1..713748b02e2d8 100644 --- a/hw/ip/entropy_src/doc/registers.md +++ b/hw/ip/entropy_src/doc/registers.md @@ -1468,12 +1468,12 @@ Writing a zero resets this status bit. Hardware detection of error conditions status register - Offset: `0xd8` - Reset default: `0x0` -- Reset mask: `0x71f00007` +- Reset mask: `0x71f0000f` ### Fields ```wavejson -{"reg": [{"name": "SFIFO_ESRNG_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SFIFO_OBSERVE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SFIFO_ESFINAL_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 17}, {"name": "ES_ACK_SM_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ES_MAIN_SM_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ES_CNTR_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SHA3_STATE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SHA3_RST_STORAGE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 3}, {"name": "FIFO_WRITE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "FIFO_READ_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "FIFO_STATE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 1}], "config": {"lanes": 1, "fontsize": 10, "vspace": 220}} +{"reg": [{"name": "SFIFO_ESRNG_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SFIFO_DISTR_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SFIFO_OBSERVE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SFIFO_ESFINAL_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 16}, {"name": "ES_ACK_SM_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ES_MAIN_SM_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ES_CNTR_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SHA3_STATE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SHA3_RST_STORAGE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 3}, {"name": "FIFO_WRITE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "FIFO_READ_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "FIFO_STATE_ERR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 1}], "config": {"lanes": 1, "fontsize": 10, "vspace": 220}} ``` | Bits | Type | Reset | Name | @@ -1488,9 +1488,10 @@ Hardware detection of error conditions status register | 22 | ro | 0x0 | [ES_CNTR_ERR](#err_code--es_cntr_err) | | 21 | ro | 0x0 | [ES_MAIN_SM_ERR](#err_code--es_main_sm_err) | | 20 | ro | 0x0 | [ES_ACK_SM_ERR](#err_code--es_ack_sm_err) | -| 19:3 | | | Reserved | -| 2 | ro | 0x0 | [SFIFO_ESFINAL_ERR](#err_code--sfifo_esfinal_err) | -| 1 | ro | 0x0 | [SFIFO_OBSERVE_ERR](#err_code--sfifo_observe_err) | +| 19:4 | | | Reserved | +| 3 | ro | 0x0 | [SFIFO_ESFINAL_ERR](#err_code--sfifo_esfinal_err) | +| 2 | ro | 0x0 | [SFIFO_OBSERVE_ERR](#err_code--sfifo_observe_err) | +| 1 | ro | 0x0 | [SFIFO_DISTR_ERR](#err_code--sfifo_distr_err) | | 0 | ro | 0x0 | [SFIFO_ESRNG_ERR](#err_code--sfifo_esrng_err) | ### ERR_CODE . FIFO_STATE_ERR @@ -1546,6 +1547,11 @@ observe FIFO. The type of error is reflected in the type status bits (bits 28 through 30 of this register). This bit will stay set until the next reset. +### ERR_CODE . SFIFO_DISTR_ERR +This bit will be set to one when an error has been detected for the distribution FIFO. +The type of error is reflected in the type status bits (bits 28 through 30 of this register). +This bit will stay set until the next reset. + ### ERR_CODE . SFIFO_ESRNG_ERR This bit will be set to one when an error has been detected for the esrng FIFO. The type of error is reflected in the type status diff --git a/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv b/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv index 0e020b10f31cd..9e9ef5d840b60 100644 --- a/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv +++ b/hw/ip/entropy_src/dv/env/entropy_src_env_cfg.sv @@ -182,13 +182,14 @@ class entropy_src_env_cfg extends cip_base_env_cfg #(.RAL_T(entropy_src_reg_bloc constraint which_err_code_c { which_err_code dist { sfifo_esrng_err :/ 2, + sfifo_distr_err :/ 2, sfifo_observe_err :/ 2, sfifo_esfinal_err :/ 2, es_ack_sm_err :/ 2, es_main_sm_err :/ 2, es_cntr_err :/ 60, - fifo_read_err :/ 3, - fifo_state_err :/ 3};} + fifo_read_err :/ 4, + fifo_state_err :/ 4};} constraint which_cntr_replicate_c {which_cntr_replicate inside {[0:RNG_BUS_WIDTH-1]};} int num_bins = 2**RNG_BUS_WIDTH; @@ -206,7 +207,7 @@ class entropy_src_env_cfg extends cip_base_env_cfg #(.RAL_T(entropy_src_reg_bloc // Write errors no longer apply to the esfinal or esrng fifos // so exclude those combinations when targetting a specific fifo or error condition constraint which_fifo_err_c { - which_err_code inside {sfifo_esrng_err, sfifo_esfinal_err} -> + which_err_code inside {sfifo_esrng_err, sfifo_distr_err, sfifo_esfinal_err} -> which_fifo_err inside {read, state}; which_err_code == fifo_read_err -> which_fifo_err == read; which_err_code == fifo_state_err -> which_fifo_err == state; @@ -215,6 +216,7 @@ class entropy_src_env_cfg extends cip_base_env_cfg #(.RAL_T(entropy_src_reg_bloc constraint which_fifo_c { which_err_code == sfifo_observe_err -> which_fifo == sfifo_observe; which_err_code == sfifo_esrng_err -> which_fifo == sfifo_esrng; + which_err_code == sfifo_distr_err -> which_fifo == sfifo_distr; which_err_code == sfifo_esfinal_err -> which_fifo == sfifo_esfinal; } diff --git a/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv b/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv index 1e830c9aea29c..31fcd347e07e5 100644 --- a/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv +++ b/hw/ip/entropy_src/dv/env/entropy_src_env_pkg.sv @@ -56,30 +56,33 @@ package entropy_src_env_pkg; typedef enum int { sfifo_esrng_err = 0, - sfifo_observe_err = 1, - sfifo_esfinal_err = 2, - es_ack_sm_err = 3, - es_main_sm_err = 4, - es_cntr_err = 5, - fifo_read_err = 6, - fifo_state_err = 7, - sfifo_esrng_err_test = 8, - sfifo_observe_err_test = 9, - sfifo_esfinal_err_test = 10, - es_ack_sm_err_test = 11, - es_main_sm_err_test = 12, - es_cntr_err_test = 13, - fifo_read_err_test = 14, - fifo_state_err_test = 15 + sfifo_distr_err = 1, + sfifo_observe_err = 2, + sfifo_esfinal_err = 3, + es_ack_sm_err = 4, + es_main_sm_err = 5, + es_cntr_err = 6, + fifo_read_err = 7, + fifo_state_err = 8, + sfifo_esrng_err_test = 9, + sfifo_distr_err_test = 10, + sfifo_observe_err_test = 11, + sfifo_esfinal_err_test = 12, + es_ack_sm_err_test = 13, + es_main_sm_err_test = 14, + es_cntr_err_test = 15, + fifo_read_err_test = 16, + fifo_state_err_test = 17 } err_code_e; typedef enum int { sfifo_observe_error = 0, sfifo_esrng_error = 1, - sfifo_esfinal_error = 2, - es_ack_sm_error = 3, - es_main_sm_error = 4, - es_cntr_error = 5 + sfifo_distr_error = 2, + sfifo_esfinal_error = 3, + es_ack_sm_error = 4, + es_main_sm_error = 5, + es_cntr_error = 6 } fatal_err_e; typedef enum int { @@ -119,8 +122,9 @@ package entropy_src_env_pkg; typedef enum int { sfifo_esrng = 0, - sfifo_observe = 1, - sfifo_esfinal = 2 + sfifo_distr = 1, + sfifo_observe = 2, + sfifo_esfinal = 3 } which_fifo_e; typedef enum int { @@ -130,8 +134,9 @@ package entropy_src_env_pkg; typedef enum bit [4:0] { sfifo_esrng_err_code = 0, - sfifo_observe_err_code = 1, - sfifo_esfinal_err_code = 2, + sfifo_distr_err_code = 1, + sfifo_observe_err_code = 2, + sfifo_esfinal_err_code = 3, es_ack_sm_err_code = 20, es_main_sm_err_code = 21, es_cntr_err_code = 22, diff --git a/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv b/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv index 27ef8f28e4588..b575c93dca22e 100644 --- a/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv +++ b/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_err_vseq.sv @@ -66,7 +66,7 @@ class entropy_src_err_vseq extends entropy_src_base_vseq; cfg.entropy_src_assert_vif.assert_off_err(); case (cfg.which_err_code) inside - sfifo_esrng_err, sfifo_observe_err, sfifo_esfinal_err: begin + sfifo_esrng_err, sfifo_distr_err, sfifo_observe_err, sfifo_esfinal_err: begin path_name = cfg.which_fifo_err.name(); path1 = cfg.entropy_src_path_vif.fifo_err_path(fifo_base_path, @@ -144,7 +144,7 @@ class entropy_src_err_vseq extends entropy_src_base_vseq; force_fifo_err(path1, path2, value1, value2, fld, 1'b1); cov_vif.cg_fifo_err_sample(cfg.which_fifo_err, cfg.which_fifo); end - sfifo_esrng_err_test, sfifo_observe_err_test, sfifo_esfinal_err_test, + sfifo_esrng_err_test, sfifo_distr_err_test, sfifo_observe_err_test, sfifo_esfinal_err_test, es_ack_sm_err_test, es_main_sm_err_test, es_cntr_err_test, fifo_read_err_test, fifo_state_err_test: begin // First turn off module_enable to write registers diff --git a/hw/ip/entropy_src/rtl/entropy_src.sv b/hw/ip/entropy_src/rtl/entropy_src.sv index 83dd74b6c281b..4ac24093c3720 100644 --- a/hw/ip/entropy_src/rtl/entropy_src.sv +++ b/hw/ip/entropy_src/rtl/entropy_src.sv @@ -14,7 +14,8 @@ module entropy_src #( parameter bit Stub = 1'b0, parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, - parameter int EsFifoDepth = 4 + parameter int EsFifoDepth = 4, + parameter int DistrFifoDepth = 2 ) ( input logic clk_i, input logic rst_ni, @@ -130,7 +131,8 @@ module entropy_src ); entropy_src_core #( - .EsFifoDepth(EsFifoDepth) + .EsFifoDepth(EsFifoDepth), + .DistrFifoDepth(DistrFifoDepth) ) u_entropy_src_core ( .clk_i, .rst_ni(core_rst_n), @@ -410,6 +412,13 @@ module entropy_src u_entropy_src_core.u_prim_fifo_sync_esrng.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_rptr, alert_tx_o[1]) + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(DistrFifoWptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_distr.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_wptr, + alert_tx_o[1]) + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(DistrFifoRptrCheck_A, + u_entropy_src_core.u_prim_fifo_sync_distr.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_rptr, + alert_tx_o[1]) + `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(ObserveFifoWptrCheck_A, u_entropy_src_core.u_prim_fifo_sync_observe.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_wptr, alert_tx_o[1]) diff --git a/hw/ip/entropy_src/rtl/entropy_src_core.sv b/hw/ip/entropy_src/rtl/entropy_src_core.sv index fc16d6b2a9419..004e3586ca1c6 100644 --- a/hw/ip/entropy_src/rtl/entropy_src_core.sv +++ b/hw/ip/entropy_src/rtl/entropy_src_core.sv @@ -6,7 +6,8 @@ // module entropy_src_core import entropy_src_pkg::*; #( - parameter int EsFifoDepth = 4 + parameter int EsFifoDepth = 4, + parameter int DistrFifoDepth = 2 ) ( input logic clk_i, input logic rst_ni, @@ -62,10 +63,11 @@ module entropy_src_core import entropy_src_pkg::*; #( localparam int FullRegWidth = 32; localparam int EighthRegWidth = 4; localparam int SeedLen = 384; + localparam int DistrFifoWidth = 32; localparam int ObserveFifoWidth = 32; localparam int PreCondWidth = 64; localparam int Clog2ObserveFifoDepth = $clog2(ObserveFifoDepth); - localparam int EsEnableCopies = 20; + localparam int EsEnableCopies = 21; localparam int EsEnPulseCopies = 1; //----------------------- @@ -127,6 +129,17 @@ module entropy_src_core import entropy_src_pkg::*; #( logic sfifo_esrng_int_err; logic [2:0] sfifo_esrng_err; + logic [DistrFifoWidth-1:0] sfifo_distr_wdata; + logic [DistrFifoWidth-1:0] sfifo_distr_rdata; + logic sfifo_distr_push; + logic sfifo_distr_pop; + logic sfifo_distr_clr; + logic sfifo_distr_not_full; + logic sfifo_distr_full; + logic sfifo_distr_not_empty; + logic sfifo_distr_int_err; + logic [2:0] sfifo_distr_err; + logic [ObserveFifoWidth-1:0] sfifo_observe_wdata; logic [ObserveFifoWidth-1:0] sfifo_observe_rdata; logic sfifo_observe_push; @@ -387,6 +400,7 @@ module entropy_src_core import entropy_src_pkg::*; #( logic es_hw_if_ack; logic es_hw_if_fifo_pop; logic sfifo_esrng_err_sum; + logic sfifo_distr_err_sum; logic sfifo_observe_err_sum; logic sfifo_esfinal_err_sum; // For fifo errors that are generated through the @@ -618,6 +632,7 @@ module entropy_src_core import entropy_src_pkg::*; #( .esrng_fifo_not_empty_i(sfifo_esrng_not_empty), .esbit_fifo_not_empty_i(pfifo_esbit_not_empty), .postht_fifo_not_empty_i(pfifo_postht_not_empty), + .distr_fifo_not_empty_i(sfifo_distr_not_empty), .cs_aes_halt_req_i(cs_aes_halt_req), .sha3_done_i(sha3_done), .bypass_mode_i(es_bypass_mode), @@ -868,6 +883,7 @@ module entropy_src_core import entropy_src_pkg::*; #( // set the interrupt sources assign event_es_fatal_err = (es_enable_fo[3] && (sfifo_esrng_err_sum || + sfifo_distr_err_sum || sfifo_observe_err_sum || sfifo_esfinal_err_sum || sfifo_test_err_sum) ) || @@ -880,10 +896,12 @@ module entropy_src_core import entropy_src_pkg::*; #( // set fifo errors that are single instances of source assign sfifo_esrng_err_sum = (|sfifo_esrng_err) || err_code_test_bit[0]; - assign sfifo_observe_err_sum = (|sfifo_observe_err) || + assign sfifo_distr_err_sum = (|sfifo_distr_err) || err_code_test_bit[1]; - assign sfifo_esfinal_err_sum = (|sfifo_esfinal_err) || + assign sfifo_observe_err_sum = (|sfifo_observe_err) || err_code_test_bit[2]; + assign sfifo_esfinal_err_sum = (|sfifo_esfinal_err) || + err_code_test_bit[3]; // The following test bits help normally diagnose the _type_ of // error when they are triggred by the fifo. However when @@ -924,6 +942,9 @@ module entropy_src_core import entropy_src_pkg::*; #( assign hw2reg.err_code.sfifo_esrng_err.d = 1'b1; assign hw2reg.err_code.sfifo_esrng_err.de = sfifo_esrng_err_sum; + assign hw2reg.err_code.sfifo_distr_err.d = 1'b1; + assign hw2reg.err_code.sfifo_distr_err.de = sfifo_distr_err_sum; + assign hw2reg.err_code.sfifo_observe_err.d = 1'b1; assign hw2reg.err_code.sfifo_observe_err.de = sfifo_observe_err_sum; @@ -2425,19 +2446,68 @@ module entropy_src_core import entropy_src_pkg::*; #( // Also, there is no association between SHA data and health test windows in FW_OV mode, so there // is no benefit in this mode to clearing the SHA FIFOs at the same time we clear the HT // statistics. - assign pfifo_postht_clr = fw_ov_mode_entropy_insert ? !es_enable_fo[7] : !es_delayed_enable; + // Pop whenever the distribution FIFO is not full. The distribution FIFO can be sized such that + // it's never going to be full even under pessimistic operating conditions. + assign pfifo_postht_pop = sfifo_distr_push & sfifo_distr_not_full; + + //-------------------------------------------- + // buffer entropy in ditribution FIFO + //-------------------------------------------- + + // The purpose of this FIFO is to buffer postht entropy bits in case the conditioner cannot + // accept them at the moment, i.e., because it's busy or because it's waiting on the CS AES halt + // interface before it can run. By properly sizing this FIFO, it can be guaranteed that even + // under pessimistic operating conditions (see entropy_src_rng_max_rate test), entropy bits never + // need to be dropped from the hardware pipeline. + + prim_fifo_sync #( + .Width(DistrFifoWidth), + .Pass(1), + .Depth(DistrFifoDepth), + .OutputZeroIfEmpty(0), + .Secure(1) + ) u_prim_fifo_sync_distr ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .clr_i (sfifo_distr_clr), + .wvalid_i (sfifo_distr_push), + .wdata_i (sfifo_distr_wdata), + .wready_o (sfifo_distr_not_full), + .rvalid_o (sfifo_distr_not_empty), + .rdata_o (sfifo_distr_rdata), + .rready_i (sfifo_distr_pop), + .full_o (sfifo_distr_full), + .depth_o (), + .err_o (sfifo_distr_int_err) + ); + + // The prim_fifo_sync primitive is constructed to only accept pushes if there is indeed space + // available. Backpressure is handled at the sender. + assign sfifo_distr_push = pfifo_postht_not_empty; + assign sfifo_distr_wdata = pfifo_postht_rdata; + + assign sfifo_distr_clr = fw_ov_mode_entropy_insert ? !es_enable_fo[20] : !es_delayed_enable; + // In firmware override mode with extract & insert enabled, post-health test entropy bits can // only move into the observe FIFO. Once the observe FIFO is full, post-health test entropy is // just discarded. - assign pfifo_postht_pop = fw_ov_mode_entropy_insert ? pfifo_postht_not_empty : - // In firmware override mode (observe only) or during normal - // operation, post-health test entropy bits continue to flow - // through the hardware pipeline. - es_bypass_mode ? pfifo_bypass_push : - pfifo_precon_push & pfifo_precon_not_full; + assign sfifo_distr_pop = fw_ov_mode_entropy_insert ? sfifo_distr_not_empty : + // In firmware override mode (observe only) or during normal + // operation, post-health test entropy bits continue to flow + // through the hardware pipeline. + es_bypass_mode ? pfifo_bypass_push : + pfifo_precon_push & pfifo_precon_not_full; + // fifo err + // Note that for the used prim_fifo_sync and prim_packer_fifo primitives it is not an error to + // push to a FIFO that is full. The primitives simply don't accept the data when full. The + // backpressure needs to be handled at the sender. + assign sfifo_distr_err = + {1'b0, + (sfifo_distr_pop && !sfifo_distr_not_empty), + (sfifo_distr_full && !sfifo_distr_not_empty) || sfifo_distr_int_err}; //-------------------------------------------- // store entropy into a 64 entry deep FIFO @@ -2471,8 +2541,8 @@ module entropy_src_core import entropy_src_pkg::*; #( // contiguous as possible. logic sfifo_observe_gate_d, sfifo_observe_gate_q; - assign sfifo_observe_gate_d = (pfifo_postht_pop && sfifo_observe_full) ? 1'b0 : - !sfifo_observe_not_empty ? 1'b1 : + assign sfifo_observe_gate_d = (sfifo_distr_pop && sfifo_observe_full) ? 1'b0 : + !sfifo_observe_not_empty ? 1'b1 : sfifo_observe_gate_q; always_ff @(posedge clk_i or negedge rst_ni) begin @@ -2492,12 +2562,12 @@ module entropy_src_core import entropy_src_pkg::*; #( assign hw2reg.observe_fifo_depth.d = sfifo_observe_depth; // fifo controls - assign sfifo_observe_push = fw_ov_mode && pfifo_postht_pop && + assign sfifo_observe_push = fw_ov_mode && sfifo_distr_pop && (sfifo_observe_gate_q || !sfifo_observe_not_empty); assign sfifo_observe_clr = ~es_enable_fo[9]; - assign sfifo_observe_wdata = pfifo_postht_rdata; + assign sfifo_observe_wdata = sfifo_distr_rdata; assign sfifo_observe_pop = (fw_ov_mode && fw_ov_fifo_rd_pulse); @@ -2542,10 +2612,10 @@ module entropy_src_core import entropy_src_pkg::*; #( fw_ov_mode_entropy_insert ? fw_ov_fifo_wr_pulse : // Otherwise post-health test entropy bits continue to flow // downstream. This includes observe-only firmware override mode. - pfifo_postht_not_empty; + sfifo_distr_not_empty; assign pfifo_precon_wdata = fw_ov_mode_entropy_insert ? fw_ov_wr_data : - pfifo_postht_rdata; + sfifo_distr_rdata; // For verification purposes, let post-disable data continue through to the SHA engine if it has // made it past the health checks, when in standard (non-fw_ov) mode. This allows scoreboards @@ -2696,10 +2766,10 @@ module entropy_src_core import entropy_src_pkg::*; #( fw_ov_mode_entropy_insert ? fw_ov_fifo_wr_pulse : // Otherwise post-health test entropy bits continue to flow // downstream. This includes observe-only firmware override mode. - pfifo_postht_not_empty; + sfifo_distr_not_empty; assign pfifo_bypass_wdata = fw_ov_mode_entropy_insert ? fw_ov_wr_data : - pfifo_postht_rdata; + sfifo_distr_rdata; assign pfifo_bypass_clr = !es_enable_fo[11]; @@ -2955,7 +3025,7 @@ module entropy_src_core import entropy_src_pkg::*; #( // unused signals //-------------------------------------------- - assign unused_err_code_test_bit = (|{err_code_test_bit[27:25],err_code_test_bit[19:3]}); + assign unused_err_code_test_bit = (|{err_code_test_bit[27:25],err_code_test_bit[19:4]}); assign unused_sha3_state = (|sha3_state[0][sha3_pkg::StateW-1:SeedLen]); assign unused_entropy_data = (|reg2hw.entropy_data.q); assign unused_fw_ov_rd_data = (|reg2hw.fw_ov_rd_data.q); @@ -3076,6 +3146,26 @@ module entropy_src_core import entropy_src_pkg::*; #( postht_non_bypass_pop_bit_cnt_q + PostHTWidth : postht_non_bypass_pop_bit_cnt_q; + // Count number of bits pushed into distr FIFO (DistrFifoWidth wide input and output). + logic [63:0] distr_non_bypass_push_bit_cnt_d, distr_non_bypass_push_bit_cnt_q; + assign distr_non_bypass_push_bit_cnt_d = + sfifo_distr_push & sfifo_distr_not_full & ~es_bypass_mode ? + distr_non_bypass_push_bit_cnt_q + DistrFifoWidth : + distr_non_bypass_push_bit_cnt_q; + + // Assert that as many bits got pushed into the distr FIFO (destination) as got popped from the + // postht FIFO when bypass mode was disabled (source). + `ASSERT_AT_RESET_AND_FINAL(PosthtFifoPushedIntoDistrFifo_A, + distr_non_bypass_push_bit_cnt_q == postht_non_bypass_pop_bit_cnt_q) + + // Count number of bits popped from distr FIFO (DistrFifoWidth wide output) when bypass mode was + // disabled. + logic [63:0] distr_non_bypass_pop_bit_cnt_d, distr_non_bypass_pop_bit_cnt_q; + assign distr_non_bypass_pop_bit_cnt_d = + sfifo_distr_pop & sfifo_distr_not_empty & ~es_bypass_mode ? + distr_non_bypass_pop_bit_cnt_q + DistrFifoWidth : + distr_non_bypass_pop_bit_cnt_q; + // Count number of bits pushed into precon FIFO (ObserveFifoWidth wide input, PreCondWidth wide // output). logic [63:0] precon_push_bit_cnt_d, precon_push_bit_cnt_q; @@ -3084,9 +3174,9 @@ module entropy_src_core import entropy_src_pkg::*; #( precon_push_bit_cnt_q; // Assert that as many bits got pushed into the precon FIFO (destination) as got popped from the - // postht FIFO when bypass mode was disabled (source). - `ASSERT_AT_RESET_AND_FINAL(PosthtFifoPushedIntoPreconFifo_A, - precon_push_bit_cnt_q == postht_non_bypass_pop_bit_cnt_q) + // distr FIFO when bypass mode was disabled (source). + `ASSERT_AT_RESET_AND_FINAL(DistrFifoPushedIntoPreconFifo_A, + precon_push_bit_cnt_q == distr_non_bypass_pop_bit_cnt_q) // Track when boot and startup checks are completing. logic boot_startup_checks_completing; @@ -3275,6 +3365,8 @@ module entropy_src_core import entropy_src_pkg::*; #( postht_from_esrng_push_bit_cnt_q <= '0; postht_non_bypass_pop_bit_cnt_q <= '0; postht_push_bit_cnt_q <= '0; + distr_non_bypass_pop_bit_cnt_q <= '0; + distr_non_bypass_push_bit_cnt_q <= '0; precon_post_startup_push_bit_cnt_q <= '0; precon_push_bit_cnt_q <= '0; rng_valid_bit_cnt_q <= '0; @@ -3290,6 +3382,8 @@ module entropy_src_core import entropy_src_pkg::*; #( postht_from_esrng_push_bit_cnt_q <= postht_from_esrng_push_bit_cnt_d; postht_non_bypass_pop_bit_cnt_q <= postht_non_bypass_pop_bit_cnt_d; postht_push_bit_cnt_q <= postht_push_bit_cnt_d; + distr_non_bypass_pop_bit_cnt_q <= distr_non_bypass_pop_bit_cnt_d; + distr_non_bypass_push_bit_cnt_q <= distr_non_bypass_push_bit_cnt_d; precon_post_startup_push_bit_cnt_q <= precon_post_startup_push_bit_cnt_d; precon_push_bit_cnt_q <= precon_push_bit_cnt_d; rng_valid_bit_cnt_q <= rng_valid_bit_cnt_d; diff --git a/hw/ip/entropy_src/rtl/entropy_src_enable_delay.sv b/hw/ip/entropy_src/rtl/entropy_src_enable_delay.sv index dc23fbc45f075..953b95509ecab 100644 --- a/hw/ip/entropy_src/rtl/entropy_src_enable_delay.sv +++ b/hw/ip/entropy_src/rtl/entropy_src_enable_delay.sv @@ -21,9 +21,9 @@ // back to idle. // // This block creates a modified version of the enable pulse which: -// 1. Postpones the disable event until any flowing data has passed through the RNG, ESBIT and -// POSTHT FIFOs. If packpressure is encountered at the Precon FIFO, the stalled data can -// be discarded, and so a has a maximum time limit of MaxFifoWait=3 clocks is given for this +// 1. Postpones the disable event until any flowing data has passed through the RNG, ESBIT, POSTHT +// and DISTR FIFOs. If back pressure is encountered at the Precon FIFO, the stalled data can +// be discarded, and so a has a maximum time limit of MaxFifoWait=4 clocks is given for this // check. // 2. Once the disable signal is received, the rising edge does not occur until: // 2a. One clock after the falling edge OR @@ -40,6 +40,7 @@ module entropy_src_enable_delay import prim_mubi_pkg::*; ( input logic esrng_fifo_not_empty_i, input logic esbit_fifo_not_empty_i, input logic postht_fifo_not_empty_i, + input logic distr_fifo_not_empty_i, // SHA3 conditioner inputs input logic cs_aes_halt_req_i, @@ -51,14 +52,14 @@ module entropy_src_enable_delay import prim_mubi_pkg::*; ( ); // Maximum number of cycles to wait for FIFOs to clear out. - // Set to 3 to allow one cycle for each FIFO in the pipeline. - localparam int MaxFifoWait = 3; + // Set to 4 to allow one cycle for each FIFO in the pipeline. + localparam int MaxFifoWait = 4; logic suppress_reenable; logic extend_enable; logic data_in_flight; - logic [2:0] fifos_not_empty; + logic [3:0] fifos_not_empty; // Flops logic [MaxFifoWait - 1:0] fifo_timer_d, fifo_timer_q; @@ -89,7 +90,8 @@ module entropy_src_enable_delay import prim_mubi_pkg::*; ( // register. assign fifo_timer_d = enable_i ? {MaxFifoWait{1'b1}} : {fifo_timer_q[MaxFifoWait-2:0], 1'b0}; assign fifos_not_empty = {esrng_fifo_not_empty_i, esbit_fifo_not_empty_i, - !bypass_mode_i & postht_fifo_not_empty_i}; + !bypass_mode_i & postht_fifo_not_empty_i, + !bypass_mode_i & distr_fifo_not_empty_i}; assign data_in_flight = |fifo_timer_q && |fifos_not_empty; // Extend the enable by at least one clock to give the FSM time to receive any last diff --git a/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv b/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv index 0a4b5ffbefa31..51f1b536f747e 100644 --- a/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv +++ b/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv @@ -655,6 +655,10 @@ package entropy_src_reg_pkg; logic d; logic de; } sfifo_esrng_err; + struct packed { + logic d; + logic de; + } sfifo_distr_err; struct packed { logic d; logic de; @@ -734,46 +738,46 @@ package entropy_src_reg_pkg; // HW -> register type typedef struct packed { - entropy_src_hw2reg_intr_state_reg_t intr_state; // [1077:1070] - entropy_src_hw2reg_regwen_reg_t regwen; // [1069:1068] - entropy_src_hw2reg_entropy_data_reg_t entropy_data; // [1067:1036] - entropy_src_hw2reg_repcnt_thresholds_reg_t repcnt_thresholds; // [1035:1004] - entropy_src_hw2reg_repcnts_thresholds_reg_t repcnts_thresholds; // [1003:972] - entropy_src_hw2reg_adaptp_hi_thresholds_reg_t adaptp_hi_thresholds; // [971:940] - entropy_src_hw2reg_adaptp_lo_thresholds_reg_t adaptp_lo_thresholds; // [939:908] - entropy_src_hw2reg_bucket_thresholds_reg_t bucket_thresholds; // [907:876] - entropy_src_hw2reg_markov_hi_thresholds_reg_t markov_hi_thresholds; // [875:844] - entropy_src_hw2reg_markov_lo_thresholds_reg_t markov_lo_thresholds; // [843:812] - entropy_src_hw2reg_extht_hi_thresholds_reg_t extht_hi_thresholds; // [811:780] - entropy_src_hw2reg_extht_lo_thresholds_reg_t extht_lo_thresholds; // [779:748] - entropy_src_hw2reg_repcnt_hi_watermarks_reg_t repcnt_hi_watermarks; // [747:716] - entropy_src_hw2reg_repcnts_hi_watermarks_reg_t repcnts_hi_watermarks; // [715:684] - entropy_src_hw2reg_adaptp_hi_watermarks_reg_t adaptp_hi_watermarks; // [683:652] - entropy_src_hw2reg_adaptp_lo_watermarks_reg_t adaptp_lo_watermarks; // [651:620] - entropy_src_hw2reg_extht_hi_watermarks_reg_t extht_hi_watermarks; // [619:588] - entropy_src_hw2reg_extht_lo_watermarks_reg_t extht_lo_watermarks; // [587:556] - entropy_src_hw2reg_bucket_hi_watermarks_reg_t bucket_hi_watermarks; // [555:524] - entropy_src_hw2reg_markov_hi_watermarks_reg_t markov_hi_watermarks; // [523:492] - entropy_src_hw2reg_markov_lo_watermarks_reg_t markov_lo_watermarks; // [491:460] - entropy_src_hw2reg_repcnt_total_fails_reg_t repcnt_total_fails; // [459:428] - entropy_src_hw2reg_repcnts_total_fails_reg_t repcnts_total_fails; // [427:396] - entropy_src_hw2reg_adaptp_hi_total_fails_reg_t adaptp_hi_total_fails; // [395:364] - entropy_src_hw2reg_adaptp_lo_total_fails_reg_t adaptp_lo_total_fails; // [363:332] - entropy_src_hw2reg_bucket_total_fails_reg_t bucket_total_fails; // [331:300] - entropy_src_hw2reg_markov_hi_total_fails_reg_t markov_hi_total_fails; // [299:268] - entropy_src_hw2reg_markov_lo_total_fails_reg_t markov_lo_total_fails; // [267:236] - entropy_src_hw2reg_extht_hi_total_fails_reg_t extht_hi_total_fails; // [235:204] - entropy_src_hw2reg_extht_lo_total_fails_reg_t extht_lo_total_fails; // [203:172] - entropy_src_hw2reg_alert_summary_fail_counts_reg_t alert_summary_fail_counts; // [171:156] - entropy_src_hw2reg_alert_fail_counts_reg_t alert_fail_counts; // [155:128] - entropy_src_hw2reg_extht_fail_counts_reg_t extht_fail_counts; // [127:120] - entropy_src_hw2reg_fw_ov_wr_fifo_full_reg_t fw_ov_wr_fifo_full; // [119:119] - entropy_src_hw2reg_fw_ov_rd_fifo_overflow_reg_t fw_ov_rd_fifo_overflow; // [118:117] - entropy_src_hw2reg_fw_ov_rd_data_reg_t fw_ov_rd_data; // [116:85] - entropy_src_hw2reg_observe_fifo_depth_reg_t observe_fifo_depth; // [84:78] - entropy_src_hw2reg_debug_status_reg_t debug_status; // [77:66] - entropy_src_hw2reg_recov_alert_sts_reg_t recov_alert_sts; // [65:32] - entropy_src_hw2reg_err_code_reg_t err_code; // [31:10] + entropy_src_hw2reg_intr_state_reg_t intr_state; // [1079:1072] + entropy_src_hw2reg_regwen_reg_t regwen; // [1071:1070] + entropy_src_hw2reg_entropy_data_reg_t entropy_data; // [1069:1038] + entropy_src_hw2reg_repcnt_thresholds_reg_t repcnt_thresholds; // [1037:1006] + entropy_src_hw2reg_repcnts_thresholds_reg_t repcnts_thresholds; // [1005:974] + entropy_src_hw2reg_adaptp_hi_thresholds_reg_t adaptp_hi_thresholds; // [973:942] + entropy_src_hw2reg_adaptp_lo_thresholds_reg_t adaptp_lo_thresholds; // [941:910] + entropy_src_hw2reg_bucket_thresholds_reg_t bucket_thresholds; // [909:878] + entropy_src_hw2reg_markov_hi_thresholds_reg_t markov_hi_thresholds; // [877:846] + entropy_src_hw2reg_markov_lo_thresholds_reg_t markov_lo_thresholds; // [845:814] + entropy_src_hw2reg_extht_hi_thresholds_reg_t extht_hi_thresholds; // [813:782] + entropy_src_hw2reg_extht_lo_thresholds_reg_t extht_lo_thresholds; // [781:750] + entropy_src_hw2reg_repcnt_hi_watermarks_reg_t repcnt_hi_watermarks; // [749:718] + entropy_src_hw2reg_repcnts_hi_watermarks_reg_t repcnts_hi_watermarks; // [717:686] + entropy_src_hw2reg_adaptp_hi_watermarks_reg_t adaptp_hi_watermarks; // [685:654] + entropy_src_hw2reg_adaptp_lo_watermarks_reg_t adaptp_lo_watermarks; // [653:622] + entropy_src_hw2reg_extht_hi_watermarks_reg_t extht_hi_watermarks; // [621:590] + entropy_src_hw2reg_extht_lo_watermarks_reg_t extht_lo_watermarks; // [589:558] + entropy_src_hw2reg_bucket_hi_watermarks_reg_t bucket_hi_watermarks; // [557:526] + entropy_src_hw2reg_markov_hi_watermarks_reg_t markov_hi_watermarks; // [525:494] + entropy_src_hw2reg_markov_lo_watermarks_reg_t markov_lo_watermarks; // [493:462] + entropy_src_hw2reg_repcnt_total_fails_reg_t repcnt_total_fails; // [461:430] + entropy_src_hw2reg_repcnts_total_fails_reg_t repcnts_total_fails; // [429:398] + entropy_src_hw2reg_adaptp_hi_total_fails_reg_t adaptp_hi_total_fails; // [397:366] + entropy_src_hw2reg_adaptp_lo_total_fails_reg_t adaptp_lo_total_fails; // [365:334] + entropy_src_hw2reg_bucket_total_fails_reg_t bucket_total_fails; // [333:302] + entropy_src_hw2reg_markov_hi_total_fails_reg_t markov_hi_total_fails; // [301:270] + entropy_src_hw2reg_markov_lo_total_fails_reg_t markov_lo_total_fails; // [269:238] + entropy_src_hw2reg_extht_hi_total_fails_reg_t extht_hi_total_fails; // [237:206] + entropy_src_hw2reg_extht_lo_total_fails_reg_t extht_lo_total_fails; // [205:174] + entropy_src_hw2reg_alert_summary_fail_counts_reg_t alert_summary_fail_counts; // [173:158] + entropy_src_hw2reg_alert_fail_counts_reg_t alert_fail_counts; // [157:130] + entropy_src_hw2reg_extht_fail_counts_reg_t extht_fail_counts; // [129:122] + entropy_src_hw2reg_fw_ov_wr_fifo_full_reg_t fw_ov_wr_fifo_full; // [121:121] + entropy_src_hw2reg_fw_ov_rd_fifo_overflow_reg_t fw_ov_rd_fifo_overflow; // [120:119] + entropy_src_hw2reg_fw_ov_rd_data_reg_t fw_ov_rd_data; // [118:87] + entropy_src_hw2reg_observe_fifo_depth_reg_t observe_fifo_depth; // [86:80] + entropy_src_hw2reg_debug_status_reg_t debug_status; // [79:68] + entropy_src_hw2reg_recov_alert_sts_reg_t recov_alert_sts; // [67:34] + entropy_src_hw2reg_err_code_reg_t err_code; // [33:10] entropy_src_hw2reg_main_sm_state_reg_t main_sm_state; // [9:0] } entropy_src_hw2reg_t; diff --git a/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv b/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv index c7ef9a6fb6ee8..8ea8b0f735c44 100644 --- a/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv +++ b/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv @@ -369,6 +369,7 @@ module entropy_src_reg_top ( logic recov_alert_sts_rng_fips_field_alert_qs; logic recov_alert_sts_rng_fips_field_alert_wd; logic err_code_sfifo_esrng_err_qs; + logic err_code_sfifo_distr_err_qs; logic err_code_sfifo_observe_err_qs; logic err_code_sfifo_esfinal_err_qs; logic err_code_es_ack_sm_err_qs; @@ -2999,7 +3000,34 @@ module entropy_src_reg_top ( .qs (err_code_sfifo_esrng_err_qs) ); - // F[sfifo_observe_err]: 1:1 + // F[sfifo_distr_err]: 1:1 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_err_code_sfifo_distr_err ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.err_code.sfifo_distr_err.de), + .d (hw2reg.err_code.sfifo_distr_err.d), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (err_code_sfifo_distr_err_qs) + ); + + // F[sfifo_observe_err]: 2:2 prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessRO), @@ -3026,7 +3054,7 @@ module entropy_src_reg_top ( .qs (err_code_sfifo_observe_err_qs) ); - // F[sfifo_esfinal_err]: 2:2 + // F[sfifo_esfinal_err]: 3:3 prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessRO), @@ -4024,8 +4052,9 @@ module entropy_src_reg_top ( addr_hit[54]: begin reg_rdata_next[0] = err_code_sfifo_esrng_err_qs; - reg_rdata_next[1] = err_code_sfifo_observe_err_qs; - reg_rdata_next[2] = err_code_sfifo_esfinal_err_qs; + reg_rdata_next[1] = err_code_sfifo_distr_err_qs; + reg_rdata_next[2] = err_code_sfifo_observe_err_qs; + reg_rdata_next[3] = err_code_sfifo_esfinal_err_qs; reg_rdata_next[20] = err_code_es_ack_sm_err_qs; reg_rdata_next[21] = err_code_es_main_sm_err_qs; reg_rdata_next[22] = err_code_es_cntr_err_qs; diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson index ab7bf5f6a50b3..857cf13ccbb39 100644 --- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson +++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson @@ -6757,6 +6757,14 @@ expose: "true" name_top: EntropySrcEsFifoDepth } + { + name: DistrFifoDepth + desc: Number of 32-bit entries in the distr FIFO + type: int unsigned + default: "2" + expose: "true" + name_top: EntropySrcDistrFifoDepth + } { name: Stub desc: Stub out the core of entropy_src logic diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv index 6082629d380d2..4c805c33c587b 100644 --- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv +++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv @@ -87,6 +87,7 @@ module top_earlgrey #( parameter aes_pkg::sbox_impl_e CsrngSBoxImpl = aes_pkg::SBoxImplCanright, // parameters for entropy_src parameter int EntropySrcEsFifoDepth = 4, + parameter int unsigned EntropySrcDistrFifoDepth = 2, parameter bit EntropySrcStub = 0, // parameters for edn0 // parameters for edn1 @@ -2415,6 +2416,7 @@ module top_earlgrey #( entropy_src #( .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[54:53]), .EsFifoDepth(EntropySrcEsFifoDepth), + .DistrFifoDepth(EntropySrcDistrFifoDepth), .Stub(EntropySrcStub) ) u_entropy_src ( diff --git a/sw/device/lib/dif/dif_entropy_src_unittest.cc b/sw/device/lib/dif/dif_entropy_src_unittest.cc index 23ea6ca6ea56a..7f8b8deeded30 100644 --- a/sw/device/lib/dif/dif_entropy_src_unittest.cc +++ b/sw/device/lib/dif/dif_entropy_src_unittest.cc @@ -836,7 +836,7 @@ TEST_F(GetErrorsTest, NullArgs) { TEST_F(GetErrorsTest, Success) { uint32_t errors; - EXPECT_READ32(ENTROPY_SRC_ERR_CODE_REG_OFFSET, 0x30000003); + EXPECT_READ32(ENTROPY_SRC_ERR_CODE_REG_OFFSET, 0x30000005); EXPECT_DIF_OK(dif_entropy_src_get_errors(&entropy_src_, &errors)); EXPECT_EQ(errors, kDifEntropySrcErrorRngFifoWrite | kDifEntropySrcErrorRngFifoRead | From 94c73ad4310e01989e48a6086b7142576e3e8ce8 Mon Sep 17 00:00:00 2001 From: Pirmin Vogel Date: Tue, 5 Mar 2024 02:09:13 +0100 Subject: [PATCH 4/4] [entropy_src/dv] Reduce max delay for CS AES Halt IF in max rate test This is useful to reduce the backpressure in the pipeline as this leads to entropy bits being dropped eventually which the scoreboard cannot handle at the moment. Signed-off-by: Pirmin Vogel --- hw/ip/entropy_src/dv/env/entropy_src_env.sv | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/ip/entropy_src/dv/env/entropy_src_env.sv b/hw/ip/entropy_src/dv/env/entropy_src_env.sv index 3166ff21f4747..f69a269255f2a 100644 --- a/hw/ip/entropy_src/dv/env/entropy_src_env.sv +++ b/hw/ip/entropy_src/dv/env/entropy_src_env.sv @@ -58,10 +58,13 @@ class entropy_src_env extends cip_base_env #( cfg.m_aes_halt_agent_cfg.agent_type = push_pull_agent_pkg::PullAgent; cfg.m_aes_halt_agent_cfg.if_mode = dv_utils_pkg::Device; cfg.m_aes_halt_agent_cfg.pull_handshake_type = push_pull_agent_pkg::FourPhase; - // When CSRNG has just started operating its AES, it may take up to 48 cycles to acknowledge the - // request. + // When CSRNG has just started operating its AES, it may take up to 48 cycles to acknowledge + // the request. When running ast/rng at the maximum rate (this is an unrealistic scenario + // primarily used for reaching coverage metrics) we reduce the max acknowledge delay to + // reduce backpressure and avoid entropy bits from being dropped from the pipeline as our + // scoreboard cannot handle this. cfg.m_aes_halt_agent_cfg.zero_delays = 0; - cfg.m_aes_halt_agent_cfg.device_delay_max = 48; + cfg.m_aes_halt_agent_cfg.device_delay_max = (cfg.rng_max_delay == 1) ? 8 : 48; // CSRNG drops its ack in the cycle after entropy_src has dropped its req. cfg.m_aes_halt_agent_cfg.ack_lo_delay_max = 1;