[prim] Add option to not clear the packer FIFO upon read
There are cases where leaving around the data just read doesn't hurt but
instead outputting a deterministic value after read should be avoided.
For example, if the packer FIFO is used to feed pseudo-random data into
an LFSR, having the packer output such a deterministic value most of the
time is bad as it may simplify an attack trying to load the LFSR with
deterministic instead of random values.
For this reason, this commit adds a new parameter to the packer FIFO
primitive to control this behavior on a per-case basis and disables the
clearing when used to feed LFSRs or inside prim_edn_req.
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/ip/aes/rtl/aes_prng_clearing.sv b/hw/ip/aes/rtl/aes_prng_clearing.sv
index 1d1fb0f..db99292 100644
--- a/hw/ip/aes/rtl/aes_prng_clearing.sv
+++ b/hw/ip/aes/rtl/aes_prng_clearing.sv
@@ -100,8 +100,9 @@
assign reseed_ack_o = SecSkipPRNGReseeding ? reseed_req_i : seed_valid;
prim_packer_fifo #(
- .InW ( EntropyWidth ),
- .OutW ( Width )
+ .InW ( EntropyWidth ),
+ .OutW ( Width ),
+ .ClearOnRead ( 1'b0 )
) u_prim_packer_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
diff --git a/hw/ip/aes/rtl/aes_prng_masking.sv b/hw/ip/aes/rtl/aes_prng_masking.sv
index 79c53e8..f11f50e 100644
--- a/hw/ip/aes/rtl/aes_prng_masking.sv
+++ b/hw/ip/aes/rtl/aes_prng_masking.sv
@@ -128,8 +128,9 @@
assign reseed_ack_o = SecSkipPRNGReseeding ? reseed_req_i : seed_valid;
prim_packer_fifo #(
- .InW ( EntropyWidth ),
- .OutW ( Width )
+ .InW ( EntropyWidth ),
+ .OutW ( Width ),
+ .ClearOnRead ( 1'b0 )
) u_prim_packer_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
diff --git a/hw/ip/prim/rtl/prim_edn_req.sv b/hw/ip/prim/rtl/prim_edn_req.sv
index 77f57d4..430594f 100644
--- a/hw/ip/prim/rtl/prim_edn_req.sv
+++ b/hw/ip/prim/rtl/prim_edn_req.sv
@@ -71,7 +71,8 @@
prim_packer_fifo #(
.InW(edn_pkg::ENDPOINT_BUS_WIDTH),
- .OutW(OutWidth)
+ .OutW(OutWidth),
+ .ClearOnRead(1'b0)
) u_prim_packer_fifo (
.clk_i,
.rst_ni,
diff --git a/hw/ip/prim/rtl/prim_packer_fifo.sv b/hw/ip/prim/rtl/prim_packer_fifo.sv
index 472233b..35482c7 100644
--- a/hw/ip/prim/rtl/prim_packer_fifo.sv
+++ b/hw/ip/prim/rtl/prim_packer_fifo.sv
@@ -44,6 +44,7 @@
module prim_packer_fifo #(
parameter int InW = 32,
parameter int OutW = 8,
+ parameter bit ClearOnRead = 1'b1, // if == 1 always output 0 after read
// derived parameters
localparam int MaxW = (InW > OutW) ? InW : OutW,
localparam int MinW = (InW < OutW) ? InW : OutW,
@@ -69,6 +70,7 @@
// signals
logic load_data;
logic clear_data;
+ logic clear_status;
// flops
logic [DepthW:0] depth_q, depth_d;
@@ -96,10 +98,11 @@
logic [MaxW-1:0] wdata_shifted;
assign wdata_shifted = {{OutW - InW{1'b0}}, wdata_i} << (depth_q*InW);
- assign clear_data = (rready_i && rvalid_o) || clr_q;
+ assign clear_status = (rready_i && rvalid_o) || clr_q;
+ assign clear_data = (ClearOnRead && clear_status) || clr_q;
assign load_data = wvalid_i && wready_o;
- assign depth_d = clear_data ? '0 :
+ assign depth_d = clear_status ? '0 :
load_data ? depth_q+1 :
depth_q;
@@ -130,16 +133,17 @@
assign lsb_is_one = {{DepthW{1'b0}},1'b1};
assign max_value = FullDepth;
assign rdata_shifted = data_q >> ptr_q*OutW;
- assign clear_data = (rready_i && (depth_q == lsb_is_one)) || clr_q;
+ assign clear_status = (rready_i && (depth_q == lsb_is_one)) || clr_q;
+ assign clear_data = (ClearOnRead && clear_status) || clr_q;
assign load_data = wvalid_i && wready_o;
assign pull_data = rvalid_o && rready_i;
- assign depth_d = clear_data ? '0 :
+ assign depth_d = clear_status ? '0 :
load_data ? max_value :
pull_data ? depth_q-1 :
depth_q;
- assign ptr_d = clear_data ? '0 :
+ assign ptr_d = clear_status ? '0 :
pull_data ? ptr_q+1 :
ptr_q;