diff --git a/doc/contributing/hw/comportability/README.md b/doc/contributing/hw/comportability/README.md index f050711aceb96..e555f4a115789 100644 --- a/doc/contributing/hw/comportability/README.md +++ b/doc/contributing/hw/comportability/README.md @@ -300,6 +300,7 @@ The following standardised countermeasures are defined: | REGREN | A register write enable is used to protect the asset from read access | CONFIG, MEM | SCRAMBLE | The asset is scrambled | CONFIG, MEM | INTEGRITY | The asset has integrity protection from a computed value such as a checksum | CONFIG, REG, MEM +| READBACK | A readback check is performed to validate that the asset has been correctly modified or fetched | MEM | CONSISTENCY | This asset is checked for consistency other than by associating integrity bits | CTRL, RST | DIGEST | Similar to integrity but more computationally intensive, implying a full hash function | CONFIG, REG, MEM | LC_GATED | Access to the asset is qualified by life-cycle state | REG, MEM, CONSTANTS, CONFIG diff --git a/hw/dv/sv/sim_sram/sim_sram.sv b/hw/dv/sv/sim_sram/sim_sram.sv index 5b8e15ba22263..20d3556ebd6bb 100644 --- a/hw/dv/sv/sim_sram/sim_sram.sv +++ b/hw/dv/sv/sim_sram/sim_sram.sv @@ -71,16 +71,20 @@ module sim_sram #( .tl_i(tl_in_i), .tl_o(tl_in_o), - .req_o (sram_req), - .gnt_i (1'b1), - .we_o (sram_we), - .addr_o (sram_addr), - .wdata_o (sram_wdata), - .wmask_o (sram_wmask), - .rdata_i (sram_rdata), - .rvalid_i (sram_rvalid), - .rerror_i (2'b00), - .rmw_in_progress_o() + .req_o (sram_req), + .gnt_i (1'b1), + .we_o (sram_we), + .addr_o (sram_addr), + .wdata_o (sram_wdata), + .wmask_o (sram_wmask), + .rdata_i (sram_rdata), + .rvalid_i (sram_rvalid), + .rerror_i (2'b00), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); prim_ram_1p #( diff --git a/hw/ip/hmac/rtl/hmac.sv b/hw/ip/hmac/rtl/hmac.sv index 6f41fbdf4a4d8..70e7121ecde4b 100644 --- a/hw/ip/hmac/rtl/hmac.sv +++ b/hw/ip/hmac/rtl/hmac.sv @@ -569,21 +569,26 @@ module hmac ) u_tlul_adapter ( .clk_i, .rst_ni, - .tl_i (tl_win_h2d), - .tl_o (tl_win_d2h), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (msg_fifo_req ), - .req_type_o ( ), - .gnt_i (msg_fifo_gnt ), - .we_o (msg_fifo_we ), - .addr_o ( ), // Doesn't care the address other than sub-word - .wdata_o (msg_fifo_wdata ), - .wmask_o (msg_fifo_wmask ), - .intg_error_o ( ), - .rdata_i (msg_fifo_rdata ), - .rvalid_i (msg_fifo_rvalid), - .rerror_i (msg_fifo_rerror), - .rmw_in_progress_o() + .tl_i (tl_win_h2d), + .tl_o (tl_win_d2h), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (msg_fifo_req ), + .req_type_o ( ), + .gnt_i (msg_fifo_gnt ), + .we_o (msg_fifo_we ), + .addr_o ( ), // Doesn't care the address + // other than sub-word + .wdata_o (msg_fifo_wdata ), + .wmask_o (msg_fifo_wmask ), + .intg_error_o ( ), + .rdata_i (msg_fifo_rdata ), + .rvalid_i (msg_fifo_rvalid), + .rerror_i (msg_fifo_rerror), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); // TL-UL to MSG_FIFO byte write handling diff --git a/hw/ip/kmac/rtl/kmac.sv b/hw/ip/kmac/rtl/kmac.sv index 43a276b8f3d43..4cb66e85717d7 100644 --- a/hw/ip/kmac/rtl/kmac.sv +++ b/hw/ip/kmac/rtl/kmac.sv @@ -1004,22 +1004,26 @@ module kmac ) u_tlul_adapter_msgfifo ( .clk_i, .rst_ni, - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .tl_i (tl_win_h2d[WinMsgFifo]), - .tl_o (tl_win_d2h[WinMsgFifo]), - - .req_o (tlram_req), - .req_type_o (), - .gnt_i (tlram_gnt), - .we_o (tlram_we ), - .addr_o (tlram_addr), - .wdata_o (tlram_wdata), - .wmask_o (tlram_wmask), - .intg_error_o ( ), - .rdata_i (tlram_rdata), - .rvalid_i (tlram_rvalid), - .rerror_i (tlram_rerror), - .rmw_in_progress_o() + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .tl_i (tl_win_h2d[WinMsgFifo]), + .tl_o (tl_win_d2h[WinMsgFifo]), + + .req_o (tlram_req), + .req_type_o (), + .gnt_i (tlram_gnt), + .we_o (tlram_we ), + .addr_o (tlram_addr), + .wdata_o (tlram_wdata), + .wmask_o (tlram_wmask), + .intg_error_o ( ), + .rdata_i (tlram_rdata), + .rvalid_i (tlram_rvalid), + .rerror_i (tlram_rerror), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); assign sw_msg_valid = tlram_req & tlram_we ; diff --git a/hw/ip/kmac/rtl/kmac_staterd.sv b/hw/ip/kmac/rtl/kmac_staterd.sv index 4b9d011bb8e48..f145aea82f96e 100644 --- a/hw/ip/kmac/rtl/kmac_staterd.sv +++ b/hw/ip/kmac/rtl/kmac_staterd.sv @@ -64,19 +64,23 @@ module kmac_staterd .tl_i, .tl_o, - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (tlram_req), - .req_type_o (), - .gnt_i (tlram_gnt), - .we_o (tlram_we ), - .addr_o (tlram_addr), - .wdata_o (unused_tlram_wdata), - .wmask_o (unused_tlram_wmask), - .intg_error_o (), - .rdata_i (tlram_rdata), - .rvalid_i (tlram_rvalid), - .rerror_i (tlram_rerror), - .rmw_in_progress_o() + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (tlram_req), + .req_type_o (), + .gnt_i (tlram_gnt), + .we_o (tlram_we ), + .addr_o (tlram_addr), + .wdata_o (unused_tlram_wdata), + .wmask_o (unused_tlram_wmask), + .intg_error_o (), + .rdata_i (tlram_rdata), + .rvalid_i (tlram_rvalid), + .rerror_i (tlram_rerror), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); always_ff @(posedge clk_i or negedge rst_ni) begin diff --git a/hw/ip/otbn/dv/verilator/otbn_top_sim.sv b/hw/ip/otbn/dv/verilator/otbn_top_sim.sv index 18b09e38ba797..394610a6c827d 100644 --- a/hw/ip/otbn/dv/verilator/otbn_top_sim.sv +++ b/hw/ip/otbn/dv/verilator/otbn_top_sim.sv @@ -256,26 +256,29 @@ module otbn_top_sim ( .EnableParity ( 0 ), .ReplicateKeyStream ( 1 ) ) u_dmem ( - .clk_i ( IO_CLK ), - .rst_ni ( IO_RST_N ), - - .key_valid_i ( 1'b1 ), - .key_i ( TestScrambleKey ), - .nonce_i ( TestScrambleNonce ), - - .req_i ( dmem_req ), - .gnt_o ( ), - .write_i ( dmem_write ), - .addr_i ( dmem_index ), - .wdata_i ( dmem_wdata ), - .wmask_i ( dmem_wmask ), - .intg_error_i ( 1'b0 ), - - .rdata_o ( dmem_rdata ), - .rvalid_o ( dmem_rvalid ), - .raddr_o ( ), - .rerror_o ( ), - .cfg_i ( '0 ) + .clk_i ( IO_CLK ), + .rst_ni ( IO_RST_N ), + + .key_valid_i ( 1'b1 ), + .key_i ( TestScrambleKey ), + .nonce_i ( TestScrambleNonce ), + + .req_i ( dmem_req ), + .gnt_o ( ), + .write_i ( dmem_write ), + .addr_i ( dmem_index ), + .wdata_i ( dmem_wdata ), + .wmask_i ( dmem_wmask ), + .intg_error_i ( 1'b0 ), + + .rdata_o ( dmem_rdata ), + .rvalid_o ( dmem_rvalid ), + .raddr_o ( ), + .rerror_o ( ), + .cfg_i ( '0 ), + + .wr_collision_o ( ), + .write_pending_o ( ) ); // No integrity errors in Verilator testbench @@ -296,26 +299,29 @@ module otbn_top_sim ( .DataBitsPerMask ( 39 ), .EnableParity ( 0 ) ) u_imem ( - .clk_i ( IO_CLK ), - .rst_ni ( IO_RST_N ), - - .key_valid_i ( 1'b1 ), - .key_i ( TestScrambleKey ), - .nonce_i ( TestScrambleNonce ), - - .req_i ( imem_req ), - .gnt_o ( ), - .write_i ( 1'b0 ), - .addr_i ( imem_index ), - .wdata_i ( '0 ), - .wmask_i ( '0 ), - .intg_error_i ( 1'b0 ), - - .rdata_o ( imem_rdata ), - .rvalid_o ( imem_rvalid ), - .raddr_o ( ), - .rerror_o ( ), - .cfg_i ( '0 ) + .clk_i ( IO_CLK ), + .rst_ni ( IO_RST_N ), + + .key_valid_i ( 1'b1 ), + .key_i ( TestScrambleKey ), + .nonce_i ( TestScrambleNonce ), + + .req_i ( imem_req ), + .gnt_o ( ), + .write_i ( 1'b0 ), + .addr_i ( imem_index ), + .wdata_i ( '0 ), + .wmask_i ( '0 ), + .intg_error_i ( 1'b0 ), + + .rdata_o ( imem_rdata ), + .rvalid_o ( imem_rvalid ), + .raddr_o ( ), + .rerror_o ( ), + .cfg_i ( '0 ), + + .wr_collision_o ( ), + .write_pending_o ( ) ); // When OTBN is done let a few more cycles run then finish simulation diff --git a/hw/ip/otbn/rtl/otbn.sv b/hw/ip/otbn/rtl/otbn.sv index 89ad976e0a912..4d8c91ec38079 100644 --- a/hw/ip/otbn/rtl/otbn.sv +++ b/hw/ip/otbn/rtl/otbn.sv @@ -234,6 +234,8 @@ module otbn logic imem_req; logic imem_gnt; logic imem_write; + logic imem_wr_collision; + logic imem_wpending; logic [ImemIndexWidth-1:0] imem_index; logic [38:0] imem_wdata; logic [38:0] imem_wmask; @@ -353,7 +355,10 @@ module otbn .rvalid_o(imem_rvalid), .raddr_o (), .rerror_o(), - .cfg_i (ram_cfg_i) + .cfg_i (ram_cfg_i), + + .wr_collision_o (imem_wr_collision), + .write_pending_o (imem_wpending) ); // We should never see a request that doesn't get granted. A fatal error is raised if this occurs. @@ -374,22 +379,26 @@ module otbn .SecFifoPtr (1) // SEC_CM: TLUL_FIFO.CTR.REDUN ) u_tlul_adapter_sram_imem ( .clk_i, - .rst_ni (rst_n), - .tl_i (tl_win_h2d[TlWinImem]), - .tl_o (tl_win_d2h[TlWinImem]), - .en_ifetch_i (MuBi4False), - .req_o (imem_req_bus), - .req_type_o (), - .gnt_i (imem_gnt_bus), - .we_o (imem_write_bus), - .addr_o (imem_index_bus), - .wdata_o (imem_wdata_bus), - .wmask_o (imem_wmask_bus), - .intg_error_o (imem_bus_intg_violation), - .rdata_i (imem_rdata_bus), - .rvalid_i (imem_rvalid_bus), - .rerror_i (imem_rerror_bus), - .rmw_in_progress_o() + .rst_ni (rst_n), + .tl_i (tl_win_h2d[TlWinImem]), + .tl_o (tl_win_d2h[TlWinImem]), + .en_ifetch_i (MuBi4False), + .req_o (imem_req_bus), + .req_type_o (), + .gnt_i (imem_gnt_bus), + .we_o (imem_write_bus), + .addr_o (imem_index_bus), + .wdata_o (imem_wdata_bus), + .wmask_o (imem_wmask_bus), + .intg_error_o (imem_bus_intg_violation), + .rdata_i (imem_rdata_bus), + .rvalid_i (imem_rvalid_bus), + .rerror_i (imem_rerror_bus), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (imem_wr_collision), + .write_pending_i (imem_wpending) ); @@ -519,6 +528,8 @@ module otbn logic [31:0] dmem_wdata_narrow_bus; logic [top_pkg::TL_DBW-1:0] dmem_byte_mask_bus; logic dmem_rvalid_bus; + logic dmem_wr_collision; + logic dmem_wpending; logic [1:0] dmem_rerror_bus; logic dmem_bus_intg_violation; @@ -556,7 +567,10 @@ module otbn .rvalid_o(dmem_rvalid), .raddr_o (), .rerror_o(), - .cfg_i (ram_cfg_i) + .cfg_i (ram_cfg_i), + + .wr_collision_o (dmem_wr_collision), + .write_pending_o (dmem_wpending) ); // We should never see a request that doesn't get granted. A fatal error is raised if this occurs. @@ -613,22 +627,26 @@ module otbn .SecFifoPtr (1) // SEC_CM: TLUL_FIFO.CTR.REDUN ) u_tlul_adapter_sram_dmem ( .clk_i, - .rst_ni (rst_n), - .tl_i (tl_win_h2d[TlWinDmem]), - .tl_o (tl_win_d2h[TlWinDmem]), - .en_ifetch_i (MuBi4False), - .req_o (dmem_req_bus), - .req_type_o (), - .gnt_i (dmem_gnt_bus), - .we_o (dmem_write_bus), - .addr_o (dmem_index_bus), - .wdata_o (dmem_wdata_bus), - .wmask_o (dmem_wmask_bus), - .intg_error_o (dmem_bus_intg_violation), - .rdata_i (dmem_rdata_bus), - .rvalid_i (dmem_rvalid_bus), - .rerror_i (dmem_rerror_bus), - .rmw_in_progress_o() + .rst_ni (rst_n), + .tl_i (tl_win_h2d[TlWinDmem]), + .tl_o (tl_win_d2h[TlWinDmem]), + .en_ifetch_i (MuBi4False), + .req_o (dmem_req_bus), + .req_type_o (), + .gnt_i (dmem_gnt_bus), + .we_o (dmem_write_bus), + .addr_o (dmem_index_bus), + .wdata_o (dmem_wdata_bus), + .wmask_o (dmem_wmask_bus), + .intg_error_o (dmem_bus_intg_violation), + .rdata_i (dmem_rdata_bus), + .rvalid_i (dmem_rvalid_bus), + .rerror_i (dmem_rerror_bus), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (dmem_wr_collision), + .write_pending_i (dmem_wpending) ); // Mux core and bus access into dmem diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl.sv index 62d440bf6e670..904c4ad9250c1 100644 --- a/hw/ip/otp_ctrl/rtl/otp_ctrl.sv +++ b/hw/ip/otp_ctrl/rtl/otp_ctrl.sv @@ -221,22 +221,26 @@ module otp_ctrl ) u_tlul_adapter_sram ( .clk_i, .rst_ni, - .en_ifetch_i ( MuBi4False ), - .tl_i ( tl_win_h2d ), - .tl_o ( tl_win_d2h ), - .req_o ( tlul_req ), - .gnt_i ( tlul_gnt ), - .we_o ( ), // unused - .addr_o ( tlul_addr ), - .wdata_o ( ), // unused - .wmask_o ( ), // unused + .en_ifetch_i ( MuBi4False ), + .tl_i ( tl_win_h2d ), + .tl_o ( tl_win_d2h ), + .req_o ( tlul_req ), + .gnt_i ( tlul_gnt ), + .we_o ( ), // unused + .addr_o ( tlul_addr ), + .wdata_o ( ), // unused + .wmask_o ( ), // unused // SEC_CM: BUS.INTEGRITY - .intg_error_o ( intg_error[1] ), - .rdata_i ( tlul_rdata ), - .rvalid_i ( tlul_rvalid ), - .rerror_i ( tlul_rerror ), - .req_type_o ( ), - .rmw_in_progress_o( ) + .intg_error_o ( intg_error[1] ), + .rdata_i ( tlul_rdata ), + .rvalid_i ( tlul_rvalid ), + .rerror_i ( tlul_rerror ), + .req_type_o ( ), + .compound_txn_in_progress_o ( ), + .readback_en_i ( MuBi4False ), + .readback_error_o ( ), + .wr_collision_i ( 1'b0 ), + .write_pending_i ( 1'b0 ) ); logic [NumPart-1:0] tlul_part_sel_oh; diff --git a/hw/ip/prim/rtl/prim_ram_1p_scr.sv b/hw/ip/prim/rtl/prim_ram_1p_scr.sv index dba14f102f142..972e7038b6e5c 100644 --- a/hw/ip/prim/rtl/prim_ram_1p_scr.sv +++ b/hw/ip/prim/rtl/prim_ram_1p_scr.sv @@ -83,7 +83,11 @@ module prim_ram_1p_scr import prim_ram_1p_pkg::*; #( output logic [31:0] raddr_o, // Read address for error reporting. // config - input ram_1p_cfg_t cfg_i + input ram_1p_cfg_t cfg_i, + + // Write currently pending inside this module. + output logic wr_collision_o, + output logic write_pending_o ); ////////////////////// @@ -136,6 +140,14 @@ module prim_ram_1p_scr import prim_ram_1p_pkg::*; #( logic rw_collision; assign rw_collision = write_en_q & read_en; + // Write currently processed inside this module. Although we are sending an immediate d_valid + // back to the host, the write could take longer due to the scrambling. + assign write_pending_o = macro_write | write_en_d; + + // When a read is followed after a write with the same address, we return the data from the + // holding register. + assign wr_collision_o = addr_collision_q; + //////////////////////// // Address Scrambling // //////////////////////// diff --git a/hw/ip/rom_ctrl/rtl/rom_ctrl.sv b/hw/ip/rom_ctrl/rtl/rom_ctrl.sv index ff22235b402cc..99567013c575f 100644 --- a/hw/ip/rom_ctrl/rtl/rom_ctrl.sv +++ b/hw/ip/rom_ctrl/rtl/rom_ctrl.sv @@ -187,21 +187,25 @@ module rom_ctrl .clk_i, .rst_ni, - .tl_i (tl_rom_h2d_downstream), - .tl_o (rom_tl_o), - .en_ifetch_i (prim_mubi_pkg::MuBi4True), - .req_o (bus_rom_req), - .req_type_o (), - .gnt_i (bus_rom_gnt), - .we_o (), - .addr_o (bus_rom_rom_index), - .wdata_o (), - .wmask_o (), - .intg_error_o (rom_integrity_error), - .rdata_i (bus_rom_rdata), - .rvalid_i (bus_rom_rvalid), - .rerror_i (2'b00), - .rmw_in_progress_o() + .tl_i (tl_rom_h2d_downstream), + .tl_o (rom_tl_o), + .en_ifetch_i (prim_mubi_pkg::MuBi4True), + .req_o (bus_rom_req), + .req_type_o (), + .gnt_i (bus_rom_gnt), + .we_o (), + .addr_o (bus_rom_rom_index), + .wdata_o (), + .wmask_o (), + .intg_error_o (rom_integrity_error), + .rdata_i (bus_rom_rdata), + .rvalid_i (bus_rom_rvalid), + .rerror_i (2'b00), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); // Snoop on the "upstream" TL transaction to infer the address to pass to the PRINCE cipher. diff --git a/hw/ip/spi_device/rtl/spi_device.sv b/hw/ip/spi_device/rtl/spi_device.sv index 1c5e775c9a0d9..e4d582fe646e3 100644 --- a/hw/ip/spi_device/rtl/spi_device.sv +++ b/hw/ip/spi_device/rtl/spi_device.sv @@ -1638,21 +1638,25 @@ module spi_device .clk_i, .rst_ni, - .tl_i (tl_sram_egress_h2d), - .tl_o (tl_sram_egress_d2h), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (sys_sram_l2m[SysSramFwEgress].req), - .req_type_o (), - .gnt_i (sys_sram_fw_gnt[SPI_DEVICE_EGRESS_BUFFER_IDX]), - .we_o (sys_sram_l2m[SysSramFwEgress].we), - .addr_o (sys_sram_l2m[SysSramFwEgress].addr), - .wdata_o (sys_sram_l2m[SysSramFwEgress].wdata), - .wmask_o (sys_sram_l2m_fw_wmask[SPI_DEVICE_EGRESS_BUFFER_IDX]), // Not used - .intg_error_o (), - .rdata_i (sys_sram_m2l[SysSramFwEgress].rdata), - .rvalid_i (sys_sram_m2l[SysSramFwEgress].rvalid), - .rerror_i (sys_sram_m2l[SysSramFwEgress].rerror), - .rmw_in_progress_o() + .tl_i (tl_sram_egress_h2d), + .tl_o (tl_sram_egress_d2h), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (sys_sram_l2m[SysSramFwEgress].req), + .req_type_o (), + .gnt_i (sys_sram_fw_gnt[SPI_DEVICE_EGRESS_BUFFER_IDX]), + .we_o (sys_sram_l2m[SysSramFwEgress].we), + .addr_o (sys_sram_l2m[SysSramFwEgress].addr), + .wdata_o (sys_sram_l2m[SysSramFwEgress].wdata), + .wmask_o (sys_sram_l2m_fw_wmask[SPI_DEVICE_EGRESS_BUFFER_IDX]), // Not used + .intg_error_o (), + .rdata_i (sys_sram_m2l[SysSramFwEgress].rdata), + .rvalid_i (sys_sram_m2l[SysSramFwEgress].rvalid), + .rerror_i (sys_sram_m2l[SysSramFwEgress].rerror), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); tlul_adapter_sram #( @@ -1665,21 +1669,25 @@ module spi_device .clk_i, .rst_ni, - .tl_i (tl_sram_ingress_h2d), - .tl_o (tl_sram_ingress_d2h), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (sys_sram_l2m[SysSramFwIngress].req), - .req_type_o (), - .gnt_i (sys_sram_fw_gnt[SPI_DEVICE_INGRESS_BUFFER_IDX]), - .we_o (sys_sram_l2m[SysSramFwIngress].we), - .addr_o (sys_sram_l2m[SysSramFwIngress].addr), - .wdata_o (sys_sram_l2m[SysSramFwIngress].wdata), - .wmask_o (sys_sram_l2m_fw_wmask[SPI_DEVICE_INGRESS_BUFFER_IDX]), // Not used - .intg_error_o (), - .rdata_i (sys_sram_m2l[SysSramFwIngress].rdata), - .rvalid_i (sys_sram_m2l[SysSramFwIngress].rvalid), - .rerror_i (sys_sram_m2l[SysSramFwIngress].rerror), - .rmw_in_progress_o() + .tl_i (tl_sram_ingress_h2d), + .tl_o (tl_sram_ingress_d2h), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (sys_sram_l2m[SysSramFwIngress].req), + .req_type_o (), + .gnt_i (sys_sram_fw_gnt[SPI_DEVICE_INGRESS_BUFFER_IDX]), + .we_o (sys_sram_l2m[SysSramFwIngress].we), + .addr_o (sys_sram_l2m[SysSramFwIngress].addr), + .wdata_o (sys_sram_l2m[SysSramFwIngress].wdata), + .wmask_o (sys_sram_l2m_fw_wmask[SPI_DEVICE_INGRESS_BUFFER_IDX]), // Not used + .intg_error_o (), + .rdata_i (sys_sram_m2l[SysSramFwIngress].rdata), + .rvalid_i (sys_sram_m2l[SysSramFwIngress].rvalid), + .rerror_i (sys_sram_m2l[SysSramFwIngress].rerror), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); assign sys_sram_l2m[SysSramFwEgress].wstrb = sram_mask2strb(sys_sram_l2m_fw_wmask[SPI_DEVICE_EGRESS_BUFFER_IDX]); diff --git a/hw/ip/spi_host/rtl/spi_host_window.sv b/hw/ip/spi_host/rtl/spi_host_window.sv index 2794d414c31f1..999c1192086ee 100644 --- a/hw/ip/spi_host/rtl/spi_host_window.sv +++ b/hw/ip/spi_host/rtl/spi_host_window.sv @@ -84,7 +84,11 @@ module spi_host_window ( .rdata_i('0), .rvalid_i('0), .rerror_i('0), - .rmw_in_progress_o() + .compound_txn_in_progress_o(), + .readback_en_i(prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i(1'b0), + .write_pending_i(1'b0) ); endmodule : spi_host_window diff --git a/hw/ip/sram_ctrl/README.md b/hw/ip/sram_ctrl/README.md index 7e329e039f67a..1b5da77eac2ab 100644 --- a/hw/ip/sram_ctrl/README.md +++ b/hw/ip/sram_ctrl/README.md @@ -28,3 +28,4 @@ The SRAM controller contains the SRAM data and address scrambling device and pro - LFSR-based memory initialization feature. - Access controls to allow / disallow code execution from SRAM. - Security hardening when integrity error has been detected. +- Optional memory readback mode for detecting memory integrity errors. diff --git a/hw/ip/sram_ctrl/data/sram_ctrl.hjson b/hw/ip/sram_ctrl/data/sram_ctrl.hjson index 1c27e36b581af..0a3fb9b20d695 100644 --- a/hw/ip/sram_ctrl/data/sram_ctrl.hjson +++ b/hw/ip/sram_ctrl/data/sram_ctrl.hjson @@ -204,6 +204,9 @@ { name: "MEM.INTEGRITY", desc: "End-to-end data/memory integrity scheme." } + { name: "MEM.READBACK", + desc: "Each read and write is checked with a readback." + } { name: "MEM.SCRAMBLE", desc: "Data is scrambled with a keyed reduced-round PRINCE cipher in CTR mode." } @@ -302,6 +305,15 @@ ''', resval: 0, } + { bits: "6" + name: "READBACK_ERROR" + desc: ''' + This bit is set to 1 if a SRAM readback check failed. + This error triggers a fatal_error alert. + This condition is terminal. + ''', + resval: 0, + } ] } { name: "EXEC_REGWEN", @@ -401,6 +413,41 @@ resval: false }, ] + } + { name: "READBACK_REGWEN", + desc: "Lock register for readback enable register.", + swaccess: "rw0c", + hwaccess: "none", + tags: [// Exclude from writes to these field because they cause side affects. + "excl:CsrAllTests:CsrExclAll"] + fields: [ + { bits: "0" + desc: ''' + When cleared to zero, !!READBACK can not be written anymore. + ''', + resval: 1 + } + ] + } + { name: "READBACK", + desc: "readback enable.", + swaccess: "rw", + hwaccess: "hro", + regwen: "READBACK_REGWEN" + tags: [// Exclude from writes to these field because they cause side affects. + "excl:CsrAllTests:CsrExclAll"] + fields: [ + { bits: "3:0", + name: "EN", + mubi: true, + desc: ''' + Write kMultiBitBool4True to this field to enable the readback security feature for the SRAM. + A readback of each memory write or read request will be performed and a comparison happens. + Any other value than kMultiBitBool4False written to this field is interpreted as kMultiBitBool4True. + ''', + resval: false + }, + ] }, ], diff --git a/hw/ip/sram_ctrl/data/sram_ctrl_sec_cm_testplan.hjson b/hw/ip/sram_ctrl/data/sram_ctrl_sec_cm_testplan.hjson index d5853121e56ce..15d4626cda915 100644 --- a/hw/ip/sram_ctrl/data/sram_ctrl_sec_cm_testplan.hjson +++ b/hw/ip/sram_ctrl/data/sram_ctrl_sec_cm_testplan.hjson @@ -91,6 +91,15 @@ stage: V2S tests: ["{name}_passthru_mem_tl_intg_err"] } + { + name: sec_cm_mem_readback + desc: '''Verify the countermeasure(s) MEM.READBACK. + + Test needs to be implemented, see lowRISC/opentitan#23322. + ''' + stage: V2S + tests: ["{name}_smoke"] + } { name: sec_cm_mem_scramble desc: '''Verify the countermeasure(s) MEM.SCRAMBLE. diff --git a/hw/ip/sram_ctrl/doc/interfaces.md b/hw/ip/sram_ctrl/doc/interfaces.md index 679d75f2d6b3e..ee48bf52bea75 100644 --- a/hw/ip/sram_ctrl/doc/interfaces.md +++ b/hw/ip/sram_ctrl/doc/interfaces.md @@ -55,6 +55,7 @@ Referring to the [Comportable guideline for peripheral device functionality](htt | SRAM_CTRL.LC_ESCALATE_EN.INTERSIG.MUBI | The life cycle escalation enable signal is multibit encoded. | | SRAM_CTRL.LC_HW_DEBUG_EN.INTERSIG.MUBI | The life cycle hardware debug enable signal is multibit encoded. | | SRAM_CTRL.MEM.INTEGRITY | End-to-end data/memory integrity scheme. | +| SRAM_CTRL.MEM.READBACK | Each read and write is checked with a readback. | | SRAM_CTRL.MEM.SCRAMBLE | Data is scrambled with a keyed reduced-round PRINCE cipher in CTR mode. | | SRAM_CTRL.ADDR.SCRAMBLE | Address is scrambled with a keyed lightweight permutation/diffusion function. | | SRAM_CTRL.INSTR.BUS.LC_GATED | Prevent code execution from SRAM in non-test lifecycle states. | diff --git a/hw/ip/sram_ctrl/doc/registers.md b/hw/ip/sram_ctrl/doc/registers.md index 8504937afd650..5cd448914cdcf 100644 --- a/hw/ip/sram_ctrl/doc/registers.md +++ b/hw/ip/sram_ctrl/doc/registers.md @@ -12,6 +12,8 @@ | sram_ctrl.[`CTRL_REGWEN`](#ctrl_regwen) | 0x10 | 4 | Lock register for control register. | | sram_ctrl.[`CTRL`](#ctrl) | 0x14 | 4 | SRAM ctrl register. | | sram_ctrl.[`SCR_KEY_ROTATED`](#scr_key_rotated) | 0x18 | 4 | Clearable SRAM key request status. | +| sram_ctrl.[`READBACK_REGWEN`](#readback_regwen) | 0x1c | 4 | Lock register for readback enable register. | +| sram_ctrl.[`READBACK`](#readback) | 0x20 | 4 | readback enable. | ## ALERT_TEST Alert Test Register @@ -34,17 +36,18 @@ Alert Test Register SRAM status register. - Offset: `0x4` - Reset default: `0x0` -- Reset mask: `0x3f` +- Reset mask: `0x7f` ### Fields ```wavejson -{"reg": [{"name": "BUS_INTEG_ERROR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "INIT_ERROR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ESCALATED", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SCR_KEY_VALID", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SCR_KEY_SEED_VALID", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "INIT_DONE", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 26}], "config": {"lanes": 1, "fontsize": 10, "vspace": 200}} +{"reg": [{"name": "BUS_INTEG_ERROR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "INIT_ERROR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "ESCALATED", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SCR_KEY_VALID", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "SCR_KEY_SEED_VALID", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "INIT_DONE", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "READBACK_ERROR", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 25}], "config": {"lanes": 1, "fontsize": 10, "vspace": 200}} ``` | Bits | Type | Reset | Name | |:------:|:------:|:-------:|:--------------------------------------------------| -| 31:6 | | | Reserved | +| 31:7 | | | Reserved | +| 6 | ro | 0x0 | [READBACK_ERROR](#status--readback_error) | | 5 | ro | 0x0 | [INIT_DONE](#status--init_done) | | 4 | ro | 0x0 | [SCR_KEY_SEED_VALID](#status--scr_key_seed_valid) | | 3 | ro | 0x0 | [SCR_KEY_VALID](#status--scr_key_valid) | @@ -52,6 +55,11 @@ SRAM status register. | 1 | ro | 0x0 | [INIT_ERROR](#status--init_error) | | 0 | ro | 0x0 | [BUS_INTEG_ERROR](#status--bus_integ_error) | +### STATUS . READBACK_ERROR +This bit is set to 1 if a SRAM readback check failed. +This error triggers a fatal_error alert. +This condition is terminal. + ### STATUS . INIT_DONE Set to 1 if the hardware initialization triggered via [`CTRL.INIT`](#ctrl) has completed. @@ -201,5 +209,45 @@ SW can use this for a hardened acknowledgement mechanism where it clears the reg kMultiBitBool4True indicates that a valid scrambling key has been obtained from OTP. Write kMultiBitBool4True to clear. +## READBACK_REGWEN +Lock register for readback enable register. +- Offset: `0x1c` +- Reset default: `0x1` +- Reset mask: `0x1` + +### Fields + +```wavejson +{"reg": [{"name": "READBACK_REGWEN", "bits": 1, "attr": ["rw0c"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 170}} +``` + +| Bits | Type | Reset | Name | Description | +|:------:|:------:|:-------:|:----------------|:--------------------------------------------------------------------------| +| 31:1 | | | | Reserved | +| 0 | rw0c | 0x1 | READBACK_REGWEN | When cleared to zero, [`READBACK`](#readback) can not be written anymore. | + +## READBACK +readback enable. +- Offset: `0x20` +- Reset default: `0x9` +- Reset mask: `0xf` +- Register enable: [`READBACK_REGWEN`](#readback_regwen) + +### Fields + +```wavejson +{"reg": [{"name": "EN", "bits": 4, "attr": ["rw"], "rotate": 0}, {"bits": 28}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}} +``` + +| Bits | Type | Reset | Name | +|:------:|:------:|:-------:|:--------------------| +| 31:4 | | | Reserved | +| 3:0 | rw | 0x9 | [EN](#readback--en) | + +### READBACK . EN +Write kMultiBitBool4True to this field to enable the readback security feature for the SRAM. +A readback of each memory write or read request will be performed and a comparison happens. +Any other value than kMultiBitBool4False written to this field is interpreted as kMultiBitBool4True. + This interface does not expose any registers. diff --git a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv index f58a60e7ab85e..293e4b0352b26 100644 --- a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv +++ b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv @@ -11,6 +11,8 @@ class sram_ctrl_base_vseq #(parameter int AddrWidth = `SRAM_ADDR_WIDTH) extends `uvm_object_param_utils(sram_ctrl_base_vseq#(AddrWidth)) `uvm_object_new + rand mubi4_t readback_en; + // various knobs to enable certain routines bit do_sram_ctrl_init = 1'b1; @@ -18,6 +20,10 @@ class sram_ctrl_base_vseq #(parameter int AddrWidth = `SRAM_ADDR_WIDTH) extends int partial_access_pct = 10; + constraint readback_en_c { + soft readback_en inside {MuBi4True, MuBi4False}; + } + virtual task pre_start(); super.pre_start(); void'($value$plusargs("partial_access_pct=%0d", partial_access_pct)); @@ -29,8 +35,40 @@ class sram_ctrl_base_vseq #(parameter int AddrWidth = `SRAM_ADDR_WIDTH) extends virtual task dut_init(string reset_kind = "HARD"); super.dut_init(); if (do_sram_ctrl_init) sram_ctrl_init(); + sram_readback_en(); endtask + // Enable readback feature only for non-throughput and non-sec_cm tests. The + // readback feature is randomly initialized to on/off at the start of the test + // and randomly switched during the tests. + // TODO(#23321) Adapt the troughput tests to take the delay caused by the + // readback feature into account. + virtual task sram_readback_en(); + if (uvm_re_match("*throughput*", get_type_name()) && + uvm_re_match("*sec_cm*", get_type_name()) && + uvm_re_match("*throughput*", common_seq_type) && + uvm_re_match("*sec_cm*", common_seq_type)) begin + // Configure the SRAM TLUL agent to wait at least 2 cycles before dropping + // a request. + cfg.m_tl_agent_cfgs[cfg.sram_ral_name].a_valid_len_min = 2; + // Init the readback enable randomly to true or false. + csr_wr(.ptr(ral.readback), .value(readback_en)); + // Randomly toggle the readback enable during the test. + fork + begin + forever begin + cfg.clk_rst_vif.wait_clks($urandom_range(10, 10_000)); + csr_utils_pkg::wait_no_outstanding_access(); + std::randomize(readback_en) with { + readback_en inside {MuBi4True, MuBi4False};}; + csr_wr(.ptr(ral.readback), .value(readback_en)); + `uvm_info(`gfn, "Update READBACK Value", UVM_LOW) + end + end + join_none + end + endtask : sram_readback_en + virtual task apply_reset(string kind = "HARD"); cfg.lc_vif.init(); cfg.exec_vif.init(); diff --git a/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv b/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv index bd4ace9fbaec0..4423a07a09930 100644 --- a/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv +++ b/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv @@ -550,6 +550,9 @@ class sram_ctrl_scoreboard #(parameter int AddrWidth = 10) extends cip_base_scor "exec": begin // do nothing end + "readback": begin + // do nothing + end "status": begin if (addr_phase_read) begin void'(ral.status.predict(.value(exp_status), .kind(UVM_PREDICT_READ))); diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl.sv index 9a48735fbad6c..d19a136db6f80 100644 --- a/hw/ip/sram_ctrl/rtl/sram_ctrl.sv +++ b/hw/ip/sram_ctrl/rtl/sram_ctrl.sv @@ -140,8 +140,12 @@ module sram_ctrl assign hw2reg.status.init_error.d = 1'b1; assign hw2reg.status.init_error.de = init_error; + logic readback_error; + assign hw2reg.status.readback_error.d = 1'b1; + assign hw2reg.status.readback_error.de = readback_error; + logic alert_req; - assign alert_req = (|bus_integ_error) | init_error; + assign alert_req = (|bus_integ_error) | init_error | readback_error; prim_alert_sender #( .AsyncOn(AlertAsyncOn[0]), @@ -183,15 +187,17 @@ module sram_ctrl logic local_esc, local_esc_reg; // This signal only aggregates registered escalation signals and is used for transaction // blocking further below, which is on a timing-critical path. - assign local_esc_reg = reg2hw.status.escalated.q | - reg2hw.status.init_error.q | - reg2hw.status.bus_integ_error.q; + assign local_esc_reg = reg2hw.status.escalated.q | + reg2hw.status.init_error.q | + reg2hw.status.bus_integ_error.q | + reg2hw.status.readback_error.q; // This signal aggregates all escalation trigger signals, including the ones that are generated in // the same cycle such as init_error and bus_integ_error. It is used for countermeasures that are // not on the critical path (such as clearing the scrambling keys). assign local_esc = escalate | init_error | (|bus_integ_error) | + readback_error | local_esc_reg; // Convert registered, local escalation sources to a multibit signal and combine this with @@ -444,8 +450,14 @@ module sram_ctrl logic sram_intg_error, sram_req, sram_gnt, sram_we, sram_rvalid; logic [AddrWidth-1:0] sram_addr; logic [DataWidth-1:0] sram_wdata, sram_wmask, sram_rdata; + logic sram_wpending, sram_wr_collision; + + logic sram_compound_txn_in_progress; - logic sram_rmw_in_progress; + + // // SEC_CM: MEM.READBACK + mubi4_t reg_readback_en; + assign reg_readback_en = mubi4_t'(reg2hw.readback.q); tlul_adapter_sram #( .SramAw(AddrWidth), @@ -456,26 +468,31 @@ module sram_ctrl .EnableRspIntgGen(1), .EnableDataIntgGen(0), .EnableDataIntgPt(1), // SEC_CM: MEM.INTEGRITY - .SecFifoPtr (1) // SEC_CM: TLUL_FIFO.CTR.REDUN + .SecFifoPtr (1), // SEC_CM: TLUL_FIFO.CTR.REDUN + .EnableReadback (1) // SEC_CM: MEM.READBACK ) u_tlul_adapter_sram ( .clk_i, .rst_ni, - .tl_i (ram_tl_in_gated), - .tl_o (ram_tl_out_gated), - .en_ifetch_i (en_ifetch), - .req_o (tlul_req), - .req_type_o (), - .gnt_i (tlul_gnt), - .we_o (tlul_we), - .addr_o (tlul_addr), - .wdata_o (tlul_wdata), - .wmask_o (tlul_wmask), + .tl_i (ram_tl_in_gated), + .tl_o (ram_tl_out_gated), + .en_ifetch_i (en_ifetch), + .req_o (tlul_req), + .req_type_o (), + .gnt_i (tlul_gnt), + .we_o (tlul_we), + .addr_o (tlul_addr), + .wdata_o (tlul_wdata), + .wmask_o (tlul_wmask), // SEC_CM: BUS.INTEGRITY - .intg_error_o (bus_integ_error[1]), - .rdata_i (sram_rdata), - .rvalid_i (sram_rvalid), - .rerror_i ('0), - .rmw_in_progress_o(sram_rmw_in_progress) + .intg_error_o (bus_integ_error[1]), + .rdata_i (sram_rdata), + .rvalid_i (sram_rvalid), + .rerror_i ('0), + .compound_txn_in_progress_o (sram_compound_txn_in_progress), + .readback_en_i (reg_readback_en), + .readback_error_o (readback_error), + .wr_collision_i (sram_wr_collision), + .write_pending_i (sram_wpending) ); logic key_valid; @@ -500,12 +517,12 @@ module sram_ctrl // reset, where the keys are reset to the default netlist constant. // // If we have escalated, but there is a pending request in the TL gate, we may have a pending - // read-modify-write transaction in the SRAM adapter. In that case we force key_valid high to - // enable that to complete so it returns a response, the TL gate won't accept any new + // read-modify-write transaction or readback in the SRAM adapter. In that case we force key_valid + // high to enable that to complete so it returns a response, the TL gate won't accept any new // transactions and the SRAM keys have been clobbered already. assign key_valid = (key_req_pending_q) ? 1'b0 : - (reg2hw.status.escalated.q) ? (tl_gate_resp_pending & sram_rmw_in_progress) : 1'b1; + (reg2hw.status.escalated.q) ? (tl_gate_resp_pending & sram_compound_txn_in_progress) : 1'b1; // SEC_CM: MEM.SCRAMBLE, ADDR.SCRAMBLE prim_ram_1p_scr #( @@ -517,22 +534,24 @@ module sram_ctrl .clk_i, .rst_ni, - .key_valid_i (key_valid), - .key_i (key_q), - .nonce_i (nonce_q[NonceWidth-1:0]), - - .req_i (sram_req), - .intg_error_i(sram_intg_error), - .gnt_o (sram_gnt), - .write_i (sram_we), - .addr_i (sram_addr), - .wdata_i (sram_wdata), - .wmask_i (sram_wmask), - .rdata_o (sram_rdata), - .rvalid_o (sram_rvalid), - .rerror_o ( ), - .raddr_o ( ), - .cfg_i + .key_valid_i (key_valid), + .key_i (key_q), + .nonce_i (nonce_q[NonceWidth-1:0]), + + .req_i (sram_req), + .intg_error_i (sram_intg_error), + .gnt_o (sram_gnt), + .write_i (sram_we), + .addr_i (sram_addr), + .wdata_i (sram_wdata), + .wmask_i (sram_wmask), + .rdata_o (sram_rdata), + .rvalid_o (sram_rvalid), + .rerror_o ( ), + .raddr_o ( ), + .cfg_i, + .wr_collision_o (sram_wr_collision), + .write_pending_o (sram_wpending) ); logic unused_sram_gnt; @@ -568,6 +587,10 @@ module sram_ctrl u_tlul_adapter_sram.u_rspfifo.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_rptr, alert_tx_o[0]) + // Alert assertions for sparse FSM. + `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(TlSramByteFsm_A, + u_tlul_adapter_sram.u_sram_byte.gen_integ_handling.u_state_regs, alert_tx_o[0]) + // `tlul_gnt` doesn't factor in `sram_gnt` for timing reasons. This assertions checks that // `tlul_gnt` is the same as `sram_gnt` when there's an active `tlul_req` that isn't being ignored // because the SRAM is initializing. diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl_pkg.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl_pkg.sv index 6c92a44ba9638..e3df577b34541 100644 --- a/hw/ip/sram_ctrl/rtl/sram_ctrl_pkg.sv +++ b/hw/ip/sram_ctrl/rtl/sram_ctrl_pkg.sv @@ -31,6 +31,4 @@ package sram_ctrl_pkg; parameter lfsr_perm_t RndCnstLfsrPermDefault = { 160'h438131ae2cb71ffdd2e4c29a1f412231747cd7b2 }; - - endpackage : sram_ctrl_pkg diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv index 9af446e4c0397..3c996230b3b39 100644 --- a/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv +++ b/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv @@ -10,7 +10,7 @@ package sram_ctrl_reg_pkg; parameter int NumAlerts = 1; // Address widths within the block - parameter int RegsAw = 5; + parameter int RegsAw = 6; parameter int RamAw = 1; /////////////////////////////////////////////// @@ -23,6 +23,9 @@ package sram_ctrl_reg_pkg; } sram_ctrl_reg2hw_alert_test_reg_t; typedef struct packed { + struct packed { + logic q; + } readback_error; struct packed { logic q; } init_done; @@ -55,6 +58,10 @@ package sram_ctrl_reg_pkg; } renew_scr_key; } sram_ctrl_reg2hw_ctrl_reg_t; + typedef struct packed { + logic [3:0] q; + } sram_ctrl_reg2hw_readback_reg_t; + typedef struct packed { struct packed { logic d; @@ -80,6 +87,10 @@ package sram_ctrl_reg_pkg; logic d; logic de; } init_done; + struct packed { + logic d; + logic de; + } readback_error; } sram_ctrl_hw2reg_status_reg_t; typedef struct packed { @@ -89,26 +100,29 @@ package sram_ctrl_reg_pkg; // Register -> HW type for regs interface typedef struct packed { - sram_ctrl_reg2hw_alert_test_reg_t alert_test; // [14:13] - sram_ctrl_reg2hw_status_reg_t status; // [12:8] - sram_ctrl_reg2hw_exec_reg_t exec; // [7:4] - sram_ctrl_reg2hw_ctrl_reg_t ctrl; // [3:0] + sram_ctrl_reg2hw_alert_test_reg_t alert_test; // [19:18] + sram_ctrl_reg2hw_status_reg_t status; // [17:12] + sram_ctrl_reg2hw_exec_reg_t exec; // [11:8] + sram_ctrl_reg2hw_ctrl_reg_t ctrl; // [7:4] + sram_ctrl_reg2hw_readback_reg_t readback; // [3:0] } sram_ctrl_regs_reg2hw_t; // HW -> register type for regs interface typedef struct packed { - sram_ctrl_hw2reg_status_reg_t status; // [16:5] + sram_ctrl_hw2reg_status_reg_t status; // [18:5] sram_ctrl_hw2reg_scr_key_rotated_reg_t scr_key_rotated; // [4:0] } sram_ctrl_regs_hw2reg_t; // Register offsets for regs interface - parameter logic [RegsAw-1:0] SRAM_CTRL_ALERT_TEST_OFFSET = 5'h 0; - parameter logic [RegsAw-1:0] SRAM_CTRL_STATUS_OFFSET = 5'h 4; - parameter logic [RegsAw-1:0] SRAM_CTRL_EXEC_REGWEN_OFFSET = 5'h 8; - parameter logic [RegsAw-1:0] SRAM_CTRL_EXEC_OFFSET = 5'h c; - parameter logic [RegsAw-1:0] SRAM_CTRL_CTRL_REGWEN_OFFSET = 5'h 10; - parameter logic [RegsAw-1:0] SRAM_CTRL_CTRL_OFFSET = 5'h 14; - parameter logic [RegsAw-1:0] SRAM_CTRL_SCR_KEY_ROTATED_OFFSET = 5'h 18; + parameter logic [RegsAw-1:0] SRAM_CTRL_ALERT_TEST_OFFSET = 6'h 0; + parameter logic [RegsAw-1:0] SRAM_CTRL_STATUS_OFFSET = 6'h 4; + parameter logic [RegsAw-1:0] SRAM_CTRL_EXEC_REGWEN_OFFSET = 6'h 8; + parameter logic [RegsAw-1:0] SRAM_CTRL_EXEC_OFFSET = 6'h c; + parameter logic [RegsAw-1:0] SRAM_CTRL_CTRL_REGWEN_OFFSET = 6'h 10; + parameter logic [RegsAw-1:0] SRAM_CTRL_CTRL_OFFSET = 6'h 14; + parameter logic [RegsAw-1:0] SRAM_CTRL_SCR_KEY_ROTATED_OFFSET = 6'h 18; + parameter logic [RegsAw-1:0] SRAM_CTRL_READBACK_REGWEN_OFFSET = 6'h 1c; + parameter logic [RegsAw-1:0] SRAM_CTRL_READBACK_OFFSET = 6'h 20; // Reset values for hwext registers and their fields for regs interface parameter logic [0:0] SRAM_CTRL_ALERT_TEST_RESVAL = 1'h 0; @@ -122,18 +136,22 @@ package sram_ctrl_reg_pkg; SRAM_CTRL_EXEC, SRAM_CTRL_CTRL_REGWEN, SRAM_CTRL_CTRL, - SRAM_CTRL_SCR_KEY_ROTATED + SRAM_CTRL_SCR_KEY_ROTATED, + SRAM_CTRL_READBACK_REGWEN, + SRAM_CTRL_READBACK } sram_ctrl_regs_id_e; // Register width information to check illegal writes for regs interface - parameter logic [3:0] SRAM_CTRL_REGS_PERMIT [7] = '{ + parameter logic [3:0] SRAM_CTRL_REGS_PERMIT [9] = '{ 4'b 0001, // index[0] SRAM_CTRL_ALERT_TEST 4'b 0001, // index[1] SRAM_CTRL_STATUS 4'b 0001, // index[2] SRAM_CTRL_EXEC_REGWEN 4'b 0001, // index[3] SRAM_CTRL_EXEC 4'b 0001, // index[4] SRAM_CTRL_CTRL_REGWEN 4'b 0001, // index[5] SRAM_CTRL_CTRL - 4'b 0001 // index[6] SRAM_CTRL_SCR_KEY_ROTATED + 4'b 0001, // index[6] SRAM_CTRL_SCR_KEY_ROTATED + 4'b 0001, // index[7] SRAM_CTRL_READBACK_REGWEN + 4'b 0001 // index[8] SRAM_CTRL_READBACK }; endpackage diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv index f149f31bb720d..d25c911c9f2d4 100644 --- a/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv +++ b/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv @@ -21,7 +21,7 @@ module sram_ctrl_regs_reg_top ( import sram_ctrl_reg_pkg::* ; - localparam int AW = 5; + localparam int AW = 6; localparam int DW = 32; localparam int DBW = DW/8; // Byte Width @@ -52,9 +52,9 @@ module sram_ctrl_regs_reg_top ( // also check for spurious write enables logic reg_we_err; - logic [6:0] reg_we_check; + logic [8:0] reg_we_check; prim_reg_we_check #( - .OneHotWidth(7) + .OneHotWidth(9) ) u_prim_reg_we_check ( .clk_i(clk_i), .rst_ni(rst_ni), @@ -129,6 +129,7 @@ module sram_ctrl_regs_reg_top ( logic status_scr_key_valid_qs; logic status_scr_key_seed_valid_qs; logic status_init_done_qs; + logic status_readback_error_qs; logic exec_regwen_we; logic exec_regwen_qs; logic exec_regwen_wd; @@ -144,6 +145,12 @@ module sram_ctrl_regs_reg_top ( logic scr_key_rotated_we; logic [3:0] scr_key_rotated_qs; logic [3:0] scr_key_rotated_wd; + logic readback_regwen_we; + logic readback_regwen_qs; + logic readback_regwen_wd; + logic readback_we; + logic [3:0] readback_qs; + logic [3:0] readback_wd; // Register instances // R[alert_test]: V(True) @@ -329,6 +336,33 @@ module sram_ctrl_regs_reg_top ( .qs (status_init_done_qs) ); + // F[readback_error]: 6:6 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_readback_error ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.readback_error.de), + .d (hw2reg.status.readback_error.d), + + // to internal hardware + .qe (), + .q (reg2hw.status.readback_error.q), + .ds (), + + // to register interface (read) + .qs (status_readback_error_qs) + ); + // R[exec_regwen]: V(False) prim_subreg #( @@ -517,8 +551,67 @@ module sram_ctrl_regs_reg_top ( ); + // R[readback_regwen]: V(False) + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW0C), + .RESVAL (1'h1), + .Mubi (1'b0) + ) u_readback_regwen ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (readback_regwen_we), + .wd (readback_regwen_wd), + + // from internal hardware + .de (1'b0), + .d ('0), - logic [6:0] addr_hit; + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (readback_regwen_qs) + ); + + + // R[readback]: V(False) + // Create REGWEN-gated WE signal + logic readback_gated_we; + assign readback_gated_we = readback_we & readback_regwen_qs; + prim_subreg #( + .DW (4), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (4'h9), + .Mubi (1'b1) + ) u_readback ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (readback_gated_we), + .wd (readback_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.readback.q), + .ds (), + + // to register interface (read) + .qs (readback_qs) + ); + + + + logic [8:0] addr_hit; always_comb begin addr_hit = '0; addr_hit[0] = (reg_addr == SRAM_CTRL_ALERT_TEST_OFFSET); @@ -528,6 +621,8 @@ module sram_ctrl_regs_reg_top ( addr_hit[4] = (reg_addr == SRAM_CTRL_CTRL_REGWEN_OFFSET); addr_hit[5] = (reg_addr == SRAM_CTRL_CTRL_OFFSET); addr_hit[6] = (reg_addr == SRAM_CTRL_SCR_KEY_ROTATED_OFFSET); + addr_hit[7] = (reg_addr == SRAM_CTRL_READBACK_REGWEN_OFFSET); + addr_hit[8] = (reg_addr == SRAM_CTRL_READBACK_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -541,7 +636,9 @@ module sram_ctrl_regs_reg_top ( (addr_hit[3] & (|(SRAM_CTRL_REGS_PERMIT[3] & ~reg_be))) | (addr_hit[4] & (|(SRAM_CTRL_REGS_PERMIT[4] & ~reg_be))) | (addr_hit[5] & (|(SRAM_CTRL_REGS_PERMIT[5] & ~reg_be))) | - (addr_hit[6] & (|(SRAM_CTRL_REGS_PERMIT[6] & ~reg_be))))); + (addr_hit[6] & (|(SRAM_CTRL_REGS_PERMIT[6] & ~reg_be))) | + (addr_hit[7] & (|(SRAM_CTRL_REGS_PERMIT[7] & ~reg_be))) | + (addr_hit[8] & (|(SRAM_CTRL_REGS_PERMIT[8] & ~reg_be))))); end // Generate write-enables @@ -565,6 +662,12 @@ module sram_ctrl_regs_reg_top ( assign scr_key_rotated_we = addr_hit[6] & reg_we & !reg_error; assign scr_key_rotated_wd = reg_wdata[3:0]; + assign readback_regwen_we = addr_hit[7] & reg_we & !reg_error; + + assign readback_regwen_wd = reg_wdata[0]; + assign readback_we = addr_hit[8] & reg_we & !reg_error; + + assign readback_wd = reg_wdata[3:0]; // Assign write-enables to checker logic vector. always_comb begin @@ -576,6 +679,8 @@ module sram_ctrl_regs_reg_top ( reg_we_check[4] = ctrl_regwen_we; reg_we_check[5] = ctrl_gated_we; reg_we_check[6] = scr_key_rotated_we; + reg_we_check[7] = readback_regwen_we; + reg_we_check[8] = readback_gated_we; end // Read data return @@ -593,6 +698,7 @@ module sram_ctrl_regs_reg_top ( reg_rdata_next[3] = status_scr_key_valid_qs; reg_rdata_next[4] = status_scr_key_seed_valid_qs; reg_rdata_next[5] = status_init_done_qs; + reg_rdata_next[6] = status_readback_error_qs; end addr_hit[2]: begin @@ -616,6 +722,14 @@ module sram_ctrl_regs_reg_top ( reg_rdata_next[3:0] = scr_key_rotated_qs; end + addr_hit[7]: begin + reg_rdata_next[0] = readback_regwen_qs; + end + + addr_hit[8]: begin + reg_rdata_next[3:0] = readback_qs; + end + default: begin reg_rdata_next = '1; end diff --git a/hw/ip/tlul/README.md b/hw/ip/tlul/README.md index 158502b0af699..b795d52545202 100644 --- a/hw/ip/tlul/README.md +++ b/hw/ip/tlul/README.md @@ -692,3 +692,9 @@ The act of storing into the `rspfifo` also pops `sramreqfifo` entry. The `reqfifo` entry is used to construct the TL-UL response. When the response is accepted by an upstream TL-UL host, the `reqfifo` and `rspfifo` entries are both popped. + +#### Readback Mode +When enabled using the [`SRAM_CTRL.READBACK`](../sram_ctrl/doc/registers.md#readback) register, the `tlul_sram_byte` module is capable of reading back and checking each issued read and write. +On an integrity failure, for example caused by a fault injection attack, a fatal alert is raised and the alert register [`STATUS.READBACK_ERROR`](../sram_ctrl/doc/registers.md#status--readback_error) is set. +When the host issues a read, the `tlul_sram_byte` module performs the read, internally stores the received data from the memory, issues a second read, and compares the values of the first and second reads. +Similarily, on a write, the module temporarily stores the data to write, performs the write, issues a readback, and compares the read back value to the temporarily stored write data to ensure that the data correctly got written into the memory. diff --git a/hw/ip/tlul/rtl/tlul_adapter_sram.sv b/hw/ip/tlul/rtl/tlul_adapter_sram.sv index b497ba64a8c49..3a8427a51ce3c 100644 --- a/hw/ip/tlul/rtl/tlul_adapter_sram.sv +++ b/hw/ip/tlul/rtl/tlul_adapter_sram.sv @@ -34,6 +34,7 @@ module tlul_adapter_sram parameter bit EnableDataIntgGen = 0, // 1: Generate response data integrity parameter bit EnableDataIntgPt = 0, // 1: Passthrough command/response data integrity parameter bit SecFifoPtr = 0, // 1: Duplicated fifo pointers + parameter bit EnableReadback = 0, // 1: Readback and check written/read data. localparam int WidthMult = SramDw / top_pkg::TL_DW, localparam int IntgWidth = tlul_pkg::DataIntgWidth * WidthMult, localparam int DataOutW = EnableDataIntgPt ? SramDw + IntgWidth : SramDw @@ -60,7 +61,11 @@ module tlul_adapter_sram input [DataOutW-1:0] rdata_i, input rvalid_i, input [1:0] rerror_i, // 2 bit error [1]: Uncorrectable, [0]: Correctable - output logic rmw_in_progress_o + output logic compound_txn_in_progress_o, + input mubi4_t readback_en_i, + output logic readback_error_o, + input logic wr_collision_i, + input logic write_pending_i ); localparam int SramByte = SramDw/8; @@ -77,6 +82,31 @@ module tlul_adapter_sram logic rsp_fifo_error; logic intg_error; logic tlul_error; + logic readback_error; + logic sram_byte_readback_error; + + // readback check + logic readback_error_q; + if (EnableReadback) begin : gen_cmd_readback_check + assign readback_error = sram_byte_readback_error; + // permanently latch readback error until reset + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + readback_error_q <= '0; + end else if (readback_error) begin + readback_error_q <= 1'b1; + end + end + end else begin : gen_no_readback_check + logic unused_sram_byte_readback_error; + assign unused_sram_byte_readback_error = sram_byte_readback_error; + assign readback_error = '0; + assign readback_error_q = '0; + end + + // readback error output is permanent and should be used for alert generation + // or other downstream effects + assign readback_error_o = readback_error | readback_error_q; // integrity check if (CmdIntgCheck) begin : gen_cmd_intg_check @@ -162,7 +192,8 @@ module tlul_adapter_sram // byte handling for integrity tlul_sram_byte #( .EnableIntg(ByteAccess & EnableDataIntgPt & !ErrOnWrite), - .Outstanding(Outstanding) + .Outstanding(Outstanding), + .EnableReadback(EnableReadback) ) u_sram_byte ( .clk_i, .rst_ni, @@ -172,7 +203,11 @@ module tlul_adapter_sram .tl_sram_i(tl_o_int), .error_i(error_det), .error_o(error_internal), - .rmw_in_progress_o + .alert_o(sram_byte_readback_error), + .compound_txn_in_progress_o, + .readback_en_i, + .wr_collision_i, + .write_pending_i ); typedef struct packed { diff --git a/hw/ip/tlul/rtl/tlul_sram_byte.sv b/hw/ip/tlul/rtl/tlul_sram_byte.sv index 8faaf791e83a8..e7f6098cc1c44 100644 --- a/hw/ip/tlul/rtl/tlul_sram_byte.sv +++ b/hw/ip/tlul/rtl/tlul_sram_byte.sv @@ -16,8 +16,10 @@ * incoming tlul transaction is directly muxed out. */ module tlul_sram_byte import tlul_pkg::*; #( - parameter bit EnableIntg = 0, // Enable integrity handling at byte level - parameter int Outstanding = 1 + parameter bit EnableIntg = 0, // Enable integrity handling at byte level, + parameter int Outstanding = 1, + parameter bit EnableReadback = 0 // Enable readback checks on all transactions must have + // EnableIntg == 1 to enable ) ( input clk_i, input rst_ni, @@ -34,33 +36,72 @@ module tlul_sram_byte import tlul_pkg::*; #( // The error indication is also fed through input error_i, output logic error_o, + output logic alert_o, - output logic rmw_in_progress_o -); + output logic compound_txn_in_progress_o, - if (EnableIntg) begin : gen_integ_handling + input prim_mubi_pkg::mubi4_t readback_en_i, + + input logic wr_collision_i, + input logic write_pending_i +); - // state enumeration - typedef enum logic [1:0] { - StPassThru, - StWaitRd, - StWriteCmd - } state_e; + import prim_mubi_pkg::mubi4_t; + import prim_mubi_pkg::mubi4_test_true_loose; + import prim_mubi_pkg::mubi4_test_false_strict; + import prim_mubi_pkg::MuBi4True; + import prim_mubi_pkg::MuBi4False; + import prim_mubi_pkg::MuBi4Width; + + // Encoding generated with: + // $ ./util/design/sparse-fsm-encode.py -d 3 -m 11 -n 8 \ + // -s 718546395 --language=sv + // + // Hamming distance histogram: + // + // 0: -- + // 1: -- + // 2: -- + // 3: |||||||||||||| (25.45%) + // 4: |||||||||||||||||||| (36.36%) + // 5: |||||||||||| (21.82%) + // 6: ||||||| (12.73%) + // 7: || (3.64%) + // 8: -- + // + // Minimum Hamming distance: 3 + // Maximum Hamming distance: 7 + // Minimum Hamming weight: 1 + // Maximum Hamming weight: 6 + // + localparam int StateWidth = 8; + typedef enum logic [StateWidth-1:0] { + StPassThru = 8'b01111110, + StWaitRd = 8'b00000010, + StWriteCmd = 8'b11110001, + StWrReadBackInit = 8'b10011001, + StWrReadBack = 8'b00001111, + StWrReadBackDWait = 8'b00110000, + StRdReadBack = 8'b10101100, + StRdReadBackDWait = 8'b11000000, + StByteWrReadBackInit = 8'b01010111, + StByteWrReadBack = 8'b11100111, + StByteWrReadBackDWait = 8'b11111111 + } state_e; + if (EnableIntg) begin : gen_integ_handling // state and selection logic stall_host; + logic wait_phase; logic rd_phase; logic rd_wait; logic wr_phase; + logic rdback_phase; + logic rdback_phase_wrreadback; + logic rdback_wait; state_e state_d, state_q; - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - state_q <= StPassThru; - end else begin - state_q <= state_d; - end - end + `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, StPassThru) // transaction qualifying signals logic a_ack; // upstream a channel acknowledgement @@ -70,7 +111,23 @@ module tlul_sram_byte import tlul_pkg::*; #( logic wr_txn; logic byte_wr_txn; logic byte_req_ack; - logic [prim_util_pkg::vbits(Outstanding+1)-1:0] pending_txn_cnt; + logic hold_tx_data; + + localparam int unsigned PendingTxnCntW = prim_util_pkg::vbits(Outstanding+1); + logic [PendingTxnCntW-1:0] pending_txn_cnt; + + // prim fifo for capturing info + typedef struct packed { + logic [2:0] a_param; + logic [top_pkg::TL_SZW-1:0] a_size; + logic [top_pkg::TL_AIW-1:0] a_source; + logic [top_pkg::TL_AW-1:0] a_address; + logic [top_pkg::TL_DBW-1:0] a_mask; + logic [top_pkg::TL_DW-1:0] a_data; + tl_a_user_t a_user; + } tl_txn_data_t; + + tl_txn_data_t held_data; assign a_ack = tl_i.a_valid & tl_o.a_ready; assign d_ack = tl_o.d_valid & tl_i.d_ready; @@ -81,21 +138,147 @@ module tlul_sram_byte import tlul_pkg::*; #( assign byte_req_ack = byte_wr_txn & a_ack & ~error_i; assign byte_wr_txn = tl_i.a_valid & ~&tl_i.a_mask & wr_txn; + logic rdback_chk_ok; + mubi4_t rdback_check_q, rdback_check_d; + mubi4_t rdback_en_q, rdback_en_d; + logic [31:0] rdback_data_exp_q, rdback_data_exp_d; + logic [DataIntgWidth-1:0] rdback_data_exp_intg_q, rdback_data_exp_intg_d; + + if (EnableReadback) begin : gen_readback_logic + logic rdback_chk_ok_unbuf; + + assign rdback_chk_ok_unbuf = (rdback_data_exp_q == tl_sram_i.d_data); + + prim_sec_anchor_buf #( + .Width(1) + ) u_rdback_chk_ok_buf ( + .in_i (rdback_chk_ok_unbuf), + .out_o(rdback_chk_ok) + ); + + prim_flop #( + .Width(MuBi4Width), + .ResetValue(MuBi4Width'(MuBi4False)) + ) u_rdback_check_flop ( + .clk_i, + .rst_ni, + + .d_i(MuBi4Width'(rdback_check_d)), + .q_o({rdback_check_q}) + ); + + prim_flop #( + .Width(MuBi4Width), + .ResetValue(MuBi4Width'(MuBi4False)) + ) u_rdback_en_flop ( + .clk_i, + .rst_ni, + + .d_i(MuBi4Width'(rdback_en_d)), + .q_o({rdback_en_q}) + ); + + prim_flop #( + .Width(32), + .ResetValue(0) + ) u_rdback_data_exp ( + .clk_i, + .rst_ni, + + .d_i(rdback_data_exp_d), + .q_o(rdback_data_exp_q) + ); + + prim_flop #( + .Width(DataIntgWidth), + .ResetValue(0) + ) u_rdback_data_exp_intg ( + .clk_i, + .rst_ni, + + .d_i(rdback_data_exp_intg_d), + .q_o(rdback_data_exp_intg_q) + ); + + // If the readback feature is enabled and we are currently in the readback phase, + // no address collision should happen inside prim_ram_1p_scr. If this would be the + // case, we would read from the holding register inside prim_ram_1p_scr instead of + // actually performing the readback from the memory. + `ASSERT(WRCollisionDuringReadBack_A, (rdback_phase | rdback_phase_wrreadback) & + mubi4_test_true_loose(rdback_en_q) |-> !wr_collision_i) + + + // If the readback feature is enabled, we assume that the write phase takes one extra cycle + // due to the underyling scrambling mechanism. If this additional cycle is not needed anymore + // in the future (e.g. due to the removale of the scrambling mechanism), the readback does not + // need to be delayed by once cylce in the FSM below. + `ASSERT(NoPendingWriteAfterWrite_A, wr_phase & mubi4_test_true_loose(rdback_en_q) + |=> write_pending_i) + + + end else begin: gen_no_readback_logic + assign rdback_chk_ok = 1'b0; + assign rdback_check_q = MuBi4False; + assign rdback_en_q = MuBi4False; + assign rdback_data_exp_q = 1'b0; + assign rdback_data_exp_intg_q = 1'b0; + + logic unused_rdback; + + assign unused_rdback = ^{rdback_check_d, rdback_data_exp_d, rdback_data_exp_intg_d}; + end + // state machine handling always_comb begin rd_wait = 1'b0; + wait_phase = 1'b0; stall_host = 1'b0; wr_phase = 1'b0; rd_phase = 1'b0; + rdback_phase = 1'b0; + rdback_phase_wrreadback = 1'b0; + rdback_wait = 1'b0; state_d = state_q; + hold_tx_data = 1'b0; + alert_o = 1'b0; + rdback_check_d = rdback_check_q; + rdback_en_d = rdback_en_q; + rdback_data_exp_d = rdback_data_exp_q; + rdback_data_exp_intg_d = rdback_data_exp_intg_q; unique case (state_q) StPassThru: begin + if (mubi4_test_true_loose(rdback_en_q) && mubi4_test_true_loose(rdback_check_q)) begin + // When we're expecting a readback check that means we'll see a data response from the + // SRAM this cycle which we need to check against the readback registers. During this + // cycle the data response out (via tl_o) will be squashed to invalid but we can accept + // a new transaction (via tl_i). + rdback_wait = 1'b1; + rdback_check_d = MuBi4False; + + // Perform the readback check. Omit the check if the transaction contains an error. + if (!rdback_chk_ok && !error_i) begin + alert_o = 1'b1; + end + end + if (byte_wr_txn) begin rd_phase = 1'b1; if (byte_req_ack) begin state_d = StWaitRd; end + end else if (a_ack && mubi4_test_true_loose(rdback_en_q) && !error_i) begin + // For reads and full word writes we'll first do the transaction and then do a readback + // check. Setting `hold_tx_data` here will preserve the transaction information in + // u_sync_fifo for doing the readback transaction. + hold_tx_data = 1'b1; + state_d = wr_txn ? StWrReadBackInit : StRdReadBack; + end + + if (!tl_sram_o.a_valid && !tl_o.d_valid && + mubi4_test_false_strict(rdback_check_q)) begin + // Store readback enable into register when bus is idle and no readback is processed. + rdback_en_d = readback_en_i; end end @@ -105,7 +288,7 @@ module tlul_sram_byte import tlul_pkg::*; #( StWaitRd: begin rd_phase = 1'b1; stall_host = 1'b1; - if (pending_txn_cnt == $bits(pending_txn_cnt)'(1)) begin + if (pending_txn_cnt == PendingTxnCntW'(1)) begin rd_wait = 1'b1; if (sram_d_ack) begin state_d = StWriteCmd; @@ -118,30 +301,200 @@ module tlul_sram_byte import tlul_pkg::*; #( wr_phase = 1'b1; if (sram_a_ack) begin - state_d = StPassThru; + state_d = mubi4_test_true_loose(rdback_en_q) ? StByteWrReadBackInit : StPassThru; + rdback_check_d = mubi4_test_true_loose(rdback_en_q) ? MuBi4True : MuBi4False; + rdback_data_exp_d = tl_sram_o.a_data; + rdback_data_exp_intg_d = tl_sram_o.a_user.data_intg; + end + end + + StWrReadBackInit: begin + // Perform readback after full write. To avoid that we read the holding register + // in the readback, wait until the write was processed by the memory module. + if (EnableReadback == 0) begin : gen_inv_state_StWrReadBackInit + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + + // Stall the host to perform the readback in the next cycle. + stall_host = 1'b1; + + // Need to ensure there's no other transactions in flight before we do the readback (the + // initial write we're doing the readback for should be the only one active). + if (pending_txn_cnt == PendingTxnCntW'(1)) begin + wait_phase = 1'b1; + // Data we're checking against the readback is captured from the write transaction that + // was sent. + rdback_check_d = mubi4_test_true_loose(rdback_en_q) ? MuBi4True : MuBi4False; + rdback_data_exp_d = held_data.a_data; + rdback_data_exp_intg_d = held_data.a_user.data_intg; + if (d_ack) begin + // Got an immediate TL-UL write response. Wait for one cycle until the holding + // register is flushed and then perform the readback. + state_d = StWrReadBack; + end else begin + // No response yet to the initial write. + state_d = StWrReadBackDWait; + end + end + end + + StWrReadBack: begin + // Perform readback and check response in StPassThru. + if (EnableReadback == 0) begin : gen_inv_state_StWrReadBack + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + + stall_host = 1'b1; + + rdback_phase = 1'b1; + + state_d = StPassThru; + end + + StWrReadBackDWait: begin + // We have not received the d_valid response of the initial write. Wait + // for the valid signal. + if (EnableReadback == 0) begin : gen_inv_state_StWrReadBackDWait + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + + // Wait until we get write response. + wait_phase = 1'b1; + + stall_host = 1'b1; + + if (d_ack) begin + // Got the TL-UL write response. Wait for one cycle until the holding + // register is flushed and then perform the readback. + state_d = StWrReadBack; + end + end + + StByteWrReadBackInit: begin + // Perform readback after partial write. To avoid that we read the holding register + // in the readback, do the actual readback check in the next FSM state. + if (EnableReadback == 0) begin : gen_inv_state_StByteWrReadBackInit + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + + // Sends out a read to a readback check on a partial write. The host is stalled whilst + // this is happening. + stall_host = 1'b1; + + // Wait until there is a single ongoing transaction. + if (pending_txn_cnt == PendingTxnCntW'(1)) begin + // Wait for one cycle with sending readback request to SRAM to avoid reading from + // holding register. + wait_phase = 1'b1; + + if (d_ack) begin + // Got an immediate TL-UL write response. Wait for one cycle until the holding + // register is flushed and then perform the readback. + state_d = StByteWrReadBack; + end else begin + // No response received for initial write. We already can send the + // request for the readback in the next cycle but we need to wait + // for the response for the initial write before doing the readback + // check. + state_d = StByteWrReadBackDWait; + end + end + end + + StByteWrReadBack: begin + // Wait until the memory module has completed the partial write. + // Perform readback and check response in StPassThru. + if (EnableReadback == 0) begin : gen_inv_state_StByteWrReadBack + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + + stall_host = 1'b1; + + rdback_phase_wrreadback = 1'b1; + + state_d = StPassThru; + end + + StByteWrReadBackDWait: begin + if (EnableReadback == 0) begin : gen_inv_state_StByteWrReadBackDWait + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + + stall_host = 1'b1; + + // Wait for one cycle with sending readback request to SRAM. + wait_phase = 1'b1; + + if (d_ack) begin + // Got the TL-UL write response. Wait for one cycle until the holding + // register is flushed and then perform the readback. + state_d = StByteWrReadBack; + end + end + + StRdReadBack: begin + if (EnableReadback == 0) begin : gen_inv_state_StRdReadBack + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + + // Sends out a read to a readback check on a read. The host is stalled whilst + // this is happening. + stall_host = 1'b1; + + // Need to ensure there's no other transactions in flight before we do the readback (the + // read we're doing the readback for should be the only one active). + if (pending_txn_cnt == PendingTxnCntW'(1)) begin + rdback_phase = 1'b1; + + if (d_ack) begin + state_d = StPassThru; + // Data for the readback check comes from the first read. + rdback_check_d = mubi4_test_true_loose(rdback_en_q) ? MuBi4True : MuBi4False; + rdback_data_exp_d = tl_o.d_data; + rdback_data_exp_intg_d = tl_o.d_user.data_intg; + end else begin + // No response yet to the initial read, so go wait for it. + state_d = StRdReadBackDWait; + end end end - default:; + StRdReadBackDWait : begin + if (EnableReadback == 0) begin : gen_inv_state_StRdReadBackDWait + // If readback is disabled, we shouldn't be in this state. + alert_o = 1'b1; + end + stall_host = 1'b1; + + if (d_ack) begin + // Response received for first read. Now need to await data for the readback check + // which is done in the `StPassThru` state. + state_d = StPassThru; + // Data for the readback check comes from the first read. + rdback_check_d = mubi4_test_true_loose(rdback_en_q) ? MuBi4True : MuBi4False; + rdback_data_exp_d = tl_o.d_data; + rdback_data_exp_intg_d = tl_o.d_user.data_intg; + end + end + + default: begin + alert_o = 1'b1; + end endcase // unique case (state_q) end - // prim fifo for capturing info - typedef struct packed { - logic [2:0] a_param; - logic [top_pkg::TL_SZW-1:0] a_size; - logic [top_pkg::TL_AIW-1:0] a_source; - logic [top_pkg::TL_AW-1:0] a_address; - logic [top_pkg::TL_DBW-1:0] a_mask; - logic [top_pkg::TL_DW-1:0] a_data; - tl_a_user_t a_user; - } tl_txn_data_t; - tl_txn_data_t txn_data; - tl_txn_data_t held_data; logic fifo_rdy; + logic txn_data_wr; localparam int TxnDataWidth = $bits(tl_txn_data_t); assign txn_data = '{ @@ -154,6 +507,9 @@ module tlul_sram_byte import tlul_pkg::*; #( a_user: tl_i.a_user }; + + assign txn_data_wr = hold_tx_data | byte_req_ack; + prim_fifo_sync #( .Width(TxnDataWidth), .Pass(1'b0), @@ -163,7 +519,7 @@ module tlul_sram_byte import tlul_pkg::*; #( .clk_i, .rst_ni, .clr_i(1'b0), - .wvalid_i(byte_req_ack), + .wvalid_i(txn_data_wr), .wready_o(fifo_rdy), .wdata_i(txn_data), .rvalid_o(), @@ -215,8 +571,8 @@ module tlul_sram_byte import tlul_pkg::*; #( always_comb begin // Pass-through by default tl_sram_o = tl_i; - // if we're waiting for an internal read for RMW, we force this to 1. - tl_sram_o.d_ready = tl_i.d_ready | rd_wait; + // If we're waiting for an internal read for RMW, or a readback read, we force this to 1. + tl_sram_o.d_ready = tl_i.d_ready | rd_wait | rdback_wait; // We take over the TL-UL bus if there is a pending read or write for the RMW transaction. // TL-UL signals are selectively muxed below to reduce complexity and remove long timing @@ -224,22 +580,26 @@ module tlul_sram_byte import tlul_pkg::*; #( // to the address and data output since these may feed into RAM scrambling logic further // downstream. - // Write transactions for RMW. - if (wr_phase) begin + // Write transactions for RMW or reads when in readback mode. + if (wr_phase | rdback_phase | rdback_phase_wrreadback) begin tl_sram_o.a_valid = 1'b1; - tl_sram_o.a_opcode = PutFullData; - // Since we are performing a read-modify-write operation, - // we always access the entire word. - tl_sram_o.a_size = top_pkg::TL_SZW'(AccessSize); - tl_sram_o.a_mask = '{default: '1}; + // During a read-modify write, always access the entire word. + tl_sram_o.a_opcode = wr_phase ? PutFullData : Get; + // In either read-modify write or SRAM readback mode, use the mask, size and address + // of the original request. + tl_sram_o.a_size = + (wr_phase | rdback_phase_wrreadback) ? top_pkg::TL_SZW'(AccessSize) : held_data.a_size; + tl_sram_o.a_mask = + (wr_phase | rdback_phase_wrreadback) ? '{default: '1} : held_data.a_mask; // override with held / combined data. // need to use word aligned addresses here. tl_sram_o.a_address = held_data.a_address; - tl_sram_o.a_address[AccessSize-1:0] = '0; + tl_sram_o.a_address[AccessSize-1:0] = + (wr_phase | rdback_phase_wrreadback) ? '0 : held_data.a_address[AccessSize-1:0]; tl_sram_o.a_source = held_data.a_source; tl_sram_o.a_param = held_data.a_param; - tl_sram_o.a_data = combined_data; - tl_sram_o.a_user = combined_user; + tl_sram_o.a_data = wr_phase ? combined_data : '0; + tl_sram_o.a_user = wr_phase ? combined_user : '0; // Read transactions for RMW. end else if (rd_phase) begin // need to use word aligned addresses here. @@ -254,17 +614,16 @@ module tlul_sram_byte import tlul_pkg::*; #( tl_sram_o.a_valid = tl_i.a_valid & ~stall_host; tl_sram_o.a_opcode = Get; end + end else if (wait_phase) begin + // Delay the readback request to avoid that we are reading the holding + // register. + tl_sram_o.a_valid = 1'b0; end end // This assert is necessary for the casting of AccessSize. `ASSERT(TlulSramByteTlSize_A, top_pkg::TL_SZW >= $clog2(AccessSize + 1)) - logic unused_held_data; - assign unused_held_data = ^{held_data.a_address[AccessSize-1:0], - held_data.a_user.data_intg, - held_data.a_size}; - assign error_o = error_i & ~stall_host; logic size_fifo_rdy; @@ -297,7 +656,7 @@ module tlul_sram_byte import tlul_pkg::*; #( // when internal logic has taken over, do not show response to host during // read phase. During write phase, allow the host to see the completion. - tl_o.d_valid = tl_sram_i.d_valid & ~rd_wait; + tl_o.d_valid = tl_sram_i.d_valid & ~rd_wait & ~rdback_wait; // the size returned by tl_sram_i does not always correspond to the actual // transaction size in cases where a read modify write operation is @@ -316,13 +675,43 @@ module tlul_sram_byte import tlul_pkg::*; #( // when in wait for read, a successful response should move to write phase `ASSERT(ReadCompleteStateChange_A, (state_q == StWaitRd) && (pending_txn_cnt == 1) && sram_d_ack |=> state_q == StWriteCmd) - - assign rmw_in_progress_o = wr_phase; + // The readback logic assumes that any request on the readback channel will be instantly granted + // (i.e. after the initial SRAM read or write request from the external requester has been + // granted). This helps simplify the logic. It is guaranteed when connected to an SRAM as it + // produces no back pressure. When connected to a scrambled SRAM the key going invalid will + // cause a_ready to drop. The `compound_txn_in_progress_o` output is provided for this scenario. + // When asserted SRAM should not drop `a_ready` even if there is an invalid scrambling key. + `ASSERT(ReadbackAccessAlwaysGranted_A, (rdback_phase | rdback_phase_wrreadback) && !error_i + |-> tl_sram_i.a_ready) + + // The readback logic assumes the result of a read transaction issues for the readback will get + // an immediate response. This can be guaranteed when connected to a SRAM, see above comment. + `ASSERT(ReadbackDataImmediatelyAvailable_A, (state_q == StPassThru) && + mubi4_test_true_loose(rdback_en_q) && mubi4_test_true_loose(rdback_check_q) && + !error_i|-> tl_sram_i.d_valid) + + assign compound_txn_in_progress_o = wr_phase | rdback_phase | rdback_phase_wrreadback; end else begin : gen_no_integ_handling // In this case we pass everything just through. assign tl_sram_o = tl_i; assign tl_o = tl_sram_i; assign error_o = error_i; - assign rmw_in_progress_o = 1'b0; + assign alert_o = 1'b0; + assign compound_txn_in_progress_o = 1'b0; + + // Signal only used in readback mode. + mubi4_t unused_readback_en; + assign unused_readback_en = readback_en_i; + end + + // Signals only used for SVA. + logic unused_write_pending, unused_wr_collision; + assign unused_write_pending = write_pending_i; + assign unused_wr_collision = wr_collision_i; + + // EnableReadback requires that EnableIntg is on. + // EnableIntg can be used without EnableReadback. + `ASSERT_INIT(SramReadbackAndIntg, + (EnableReadback && EnableIntg) || (!EnableReadback && (EnableIntg || !EnableIntg))) endmodule // tlul_adapter_sram diff --git a/hw/ip/usbdev/rtl/usbdev.sv b/hw/ip/usbdev/rtl/usbdev.sv index f9f989371bd71..05b881846fd87 100644 --- a/hw/ip/usbdev/rtl/usbdev.sv +++ b/hw/ip/usbdev/rtl/usbdev.sv @@ -764,21 +764,25 @@ module usbdev .clk_i, .rst_ni, - .tl_i (tl_sram_h2d), - .tl_o (tl_sram_d2h), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (sw_mem_a_req), - .req_type_o (), - .gnt_i (sw_mem_a_gnt), - .we_o (sw_mem_a_write), - .addr_o (sw_mem_a_addr), - .wdata_o (sw_mem_a_wdata), - .wmask_o (), // Not used - .intg_error_o (), - .rdata_i (sw_mem_a_rdata), - .rvalid_i (sw_mem_a_rvalid), - .rerror_i (sw_mem_a_rerror), - .rmw_in_progress_o() + .tl_i (tl_sram_h2d), + .tl_o (tl_sram_d2h), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (sw_mem_a_req), + .req_type_o (), + .gnt_i (sw_mem_a_gnt), + .we_o (sw_mem_a_write), + .addr_o (sw_mem_a_addr), + .wdata_o (sw_mem_a_wdata), + .wmask_o (), // Not used + .intg_error_o (), + .rdata_i (sw_mem_a_rdata), + .rvalid_i (sw_mem_a_rvalid), + .rerror_i (sw_mem_a_rerror), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); // Single Port RAM implementation, which will award the `usb` port absolute priority and diff --git a/hw/ip_templates/flash_ctrl/rtl/flash_ctrl.sv.tpl b/hw/ip_templates/flash_ctrl/rtl/flash_ctrl.sv.tpl index 96ba41552180c..8ede59fd46986 100644 --- a/hw/ip_templates/flash_ctrl/rtl/flash_ctrl.sv.tpl +++ b/hw/ip_templates/flash_ctrl/rtl/flash_ctrl.sv.tpl @@ -529,21 +529,25 @@ module flash_ctrl ) u_to_prog_fifo ( .clk_i, .rst_ni, - .tl_i (prog_tl_h2d), - .tl_o (prog_tl_d2h), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (sw_wvalid), - .req_type_o (), - .gnt_i (sw_wready), - .we_o (), - .addr_o (), - .wmask_o (), - .intg_error_o (), - .wdata_o (sw_wdata), - .rdata_i ('0), - .rvalid_i (1'b0), - .rerror_i (2'b0), - .rmw_in_progress_o() + .tl_i (prog_tl_h2d), + .tl_o (prog_tl_d2h), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (sw_wvalid), + .req_type_o (), + .gnt_i (sw_wready), + .we_o (), + .addr_o (), + .wmask_o (), + .intg_error_o (), + .wdata_o (sw_wdata), + .rdata_i ('0), + .rvalid_i (1'b0), + .rerror_i (2'b0), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); prim_fifo_sync #( @@ -642,23 +646,27 @@ module flash_ctrl ) u_to_rd_fifo ( .clk_i, .rst_ni, - .tl_i (tl_win_h2d[1]), - .tl_o (tl_win_d2h[1]), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (adapter_req), - .req_type_o (), + .tl_i (tl_win_h2d[1]), + .tl_o (tl_win_d2h[1]), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (adapter_req), + .req_type_o (), // if there is no valid read operation, don't hang the // bus, just let things normally return - .gnt_i (sw_rfifo_rvalid | rd_no_op_d), - .we_o (), - .addr_o (), - .wmask_o (), - .wdata_o (), - .intg_error_o (adapter_fifo_err), - .rdata_i (sw_rfifo_rdata), - .rvalid_i (adapter_rvalid | rd_no_op_q), - .rerror_i ({rd_no_op_q, 1'b0}), - .rmw_in_progress_o() + .gnt_i (sw_rfifo_rvalid | rd_no_op_d), + .we_o (), + .addr_o (), + .wmask_o (), + .wdata_o (), + .intg_error_o (adapter_fifo_err), + .rdata_i (sw_rfifo_rdata), + .rvalid_i (adapter_rvalid | rd_no_op_q), + .rerror_i ({rd_no_op_q, 1'b0}), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); assign sw_rfifo_wen = sw_sel & rd_ctrl_wen; @@ -1302,21 +1310,25 @@ module flash_ctrl ) u_tl_adapter_eflash ( .clk_i, .rst_ni, - .tl_i (gate_tl_h2d), - .tl_o (gate_tl_d2h), - .en_ifetch_i (flash_exec_en), - .req_o (flash_host_req), - .req_type_o (), - .gnt_i (flash_host_req_rdy), - .we_o (), - .addr_o (flash_host_addr), - .wdata_o (), - .wmask_o (), - .intg_error_o (eflash_cmd_intg_err), - .rdata_i (flash_host_rdata), - .rvalid_i (flash_host_req_done), - .rerror_i ({flash_host_rderr,1'b0}), - .rmw_in_progress_o() + .tl_i (gate_tl_h2d), + .tl_o (gate_tl_d2h), + .en_ifetch_i (flash_exec_en), + .req_o (flash_host_req), + .req_type_o (), + .gnt_i (flash_host_req_rdy), + .we_o (), + .addr_o (flash_host_addr), + .wdata_o (), + .wmask_o (), + .intg_error_o (eflash_cmd_intg_err), + .rdata_i (flash_host_rdata), + .rvalid_i (flash_host_req_done), + .rerror_i ({flash_host_rderr,1'b0}), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); flash_phy #( diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson index 4e055df25b096..e787552a8a041 100644 --- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson +++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson @@ -9521,7 +9521,7 @@ [ { base_addr: 0x411c0000 - size_byte: 0x20 + size_byte: 0x40 } ] xbar: false @@ -10341,7 +10341,7 @@ [ { base_addr: 0x40500000 - size_byte: 0x20 + size_byte: 0x40 } ] xbar: false diff --git a/hw/top_earlgrey/dv/autogen/xbar_env_pkg__params.sv b/hw/top_earlgrey/dv/autogen/xbar_env_pkg__params.sv index 9314ccbc3af0d..6f77551fa321d 100644 --- a/hw/top_earlgrey/dv/autogen/xbar_env_pkg__params.sv +++ b/hw/top_earlgrey/dv/autogen/xbar_env_pkg__params.sv @@ -71,7 +71,7 @@ tl_device_t xbar_devices[$] = '{ '{32'h411f0000, 32'h411f00ff} }}, '{"sram_ctrl_main__regs", '{ - '{32'h411c0000, 32'h411c001f} + '{32'h411c0000, 32'h411c003f} }}, '{"sram_ctrl_main__ram", '{ '{32'h10000000, 32'h1001ffff} @@ -140,7 +140,7 @@ tl_device_t xbar_devices[$] = '{ '{32'h40150000, 32'h401507ff} }}, '{"sram_ctrl_ret_aon__regs", '{ - '{32'h40500000, 32'h4050001f} + '{32'h40500000, 32'h4050003f} }}, '{"sram_ctrl_ret_aon__ram", '{ '{32'h40600000, 32'h40600fff} diff --git a/hw/top_earlgrey/dv/autogen/xbar_tgl_excl.cfg b/hw/top_earlgrey/dv/autogen/xbar_tgl_excl.cfg index ea1af34249527..2733827ec12d1 100644 --- a/hw/top_earlgrey/dv/autogen/xbar_tgl_excl.cfg +++ b/hw/top_earlgrey/dv/autogen/xbar_tgl_excl.cfg @@ -105,7 +105,7 @@ -node tb.dut*.u_rv_core_ibex cfg_tl_*i.a_address[23:21] -node tb.dut*.u_rv_core_ibex cfg_tl_*i.a_address[29:25] -node tb.dut*.u_rv_core_ibex cfg_tl_*i.a_address[31:31] --node tb.dut*.u_sram_ctrl_main regs_tl_*i.a_address[17:5] +-node tb.dut*.u_sram_ctrl_main regs_tl_*i.a_address[17:6] -node tb.dut*.u_sram_ctrl_main regs_tl_*i.a_address[23:21] -node tb.dut*.u_sram_ctrl_main regs_tl_*i.a_address[29:25] -node tb.dut*.u_sram_ctrl_main regs_tl_*i.a_address[31:31] @@ -188,7 +188,7 @@ -node tb.dut*.u_alert_handler tl_*i.a_address[19:19] -node tb.dut*.u_alert_handler tl_*i.a_address[29:21] -node tb.dut*.u_alert_handler tl_*i.a_address[31:31] --node tb.dut*.u_sram_ctrl_ret_aon regs_tl_*i.a_address[19:5] +-node tb.dut*.u_sram_ctrl_ret_aon regs_tl_*i.a_address[19:6] -node tb.dut*.u_sram_ctrl_ret_aon regs_tl_*i.a_address[21:21] -node tb.dut*.u_sram_ctrl_ret_aon regs_tl_*i.a_address[29:23] -node tb.dut*.u_sram_ctrl_ret_aon regs_tl_*i.a_address[31:31] diff --git a/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson b/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson index ac17ac83ac3c7..daa2dd492ded1 100644 --- a/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson +++ b/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson @@ -593,7 +593,7 @@ [ { base_addr: 0x411c0000 - size_byte: 0x20 + size_byte: 0x40 } ] xbar: false diff --git a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_cover.cfg b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_cover.cfg index 9d2f9823bf464..528f79c929b33 100644 --- a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_cover.cfg +++ b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_cover.cfg @@ -103,7 +103,7 @@ -node tb.dut tl_rv_core_ibex__cfg_o.a_address[23:21] -node tb.dut tl_rv_core_ibex__cfg_o.a_address[29:25] -node tb.dut tl_rv_core_ibex__cfg_o.a_address[31:31] --node tb.dut tl_sram_ctrl_main__regs_o.a_address[17:5] +-node tb.dut tl_sram_ctrl_main__regs_o.a_address[17:6] -node tb.dut tl_sram_ctrl_main__regs_o.a_address[23:21] -node tb.dut tl_sram_ctrl_main__regs_o.a_address[29:25] -node tb.dut tl_sram_ctrl_main__regs_o.a_address[31:31] diff --git a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv index 07219e05f5c8a..a6c1a5357b391 100644 --- a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv +++ b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv @@ -75,7 +75,7 @@ tl_device_t xbar_devices[$] = '{ '{32'h411f0000, 32'h411f00ff} }}, '{"sram_ctrl_main__regs", '{ - '{32'h411c0000, 32'h411c001f} + '{32'h411c0000, 32'h411c003f} }}, '{"sram_ctrl_main__ram", '{ '{32'h10000000, 32'h1001ffff} diff --git a/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv b/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv index 15f826b745202..22a1a4bcaf6ac 100644 --- a/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv +++ b/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv @@ -59,7 +59,7 @@ package tl_main_pkg; localparam logic [31:0] ADDR_MASK_OTBN = 32'h 0000ffff; localparam logic [31:0] ADDR_MASK_KEYMGR = 32'h 000000ff; localparam logic [31:0] ADDR_MASK_RV_CORE_IBEX__CFG = 32'h 000000ff; - localparam logic [31:0] ADDR_MASK_SRAM_CTRL_MAIN__REGS = 32'h 0000001f; + localparam logic [31:0] ADDR_MASK_SRAM_CTRL_MAIN__REGS = 32'h 0000003f; localparam logic [31:0] ADDR_MASK_SRAM_CTRL_MAIN__RAM = 32'h 0001ffff; localparam int N_HOST = 3; diff --git a/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson b/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson index 08c6fbfb1c274..9563cf0e595c9 100644 --- a/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson +++ b/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson @@ -466,7 +466,7 @@ [ { base_addr: 0x40500000 - size_byte: 0x20 + size_byte: 0x40 } ] xbar: false diff --git a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_cover.cfg b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_cover.cfg index b134e50236140..827fa1a16b512 100644 --- a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_cover.cfg +++ b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_cover.cfg @@ -98,7 +98,7 @@ -node tb.dut tl_alert_handler_o.a_address[19:19] -node tb.dut tl_alert_handler_o.a_address[29:21] -node tb.dut tl_alert_handler_o.a_address[31:31] --node tb.dut tl_sram_ctrl_ret_aon__regs_o.a_address[19:5] +-node tb.dut tl_sram_ctrl_ret_aon__regs_o.a_address[19:6] -node tb.dut tl_sram_ctrl_ret_aon__regs_o.a_address[21:21] -node tb.dut tl_sram_ctrl_ret_aon__regs_o.a_address[29:23] -node tb.dut tl_sram_ctrl_ret_aon__regs_o.a_address[31:31] diff --git a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv index a1847207d1460..66ea147da0ae1 100644 --- a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv +++ b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv @@ -71,7 +71,7 @@ tl_device_t xbar_devices[$] = '{ '{32'h40150000, 32'h401507ff} }}, '{"sram_ctrl_ret_aon__regs", '{ - '{32'h40500000, 32'h4050001f} + '{32'h40500000, 32'h4050003f} }}, '{"sram_ctrl_ret_aon__ram", '{ '{32'h40600000, 32'h40600fff} diff --git a/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv b/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv index 690c8f3e7c277..b9a1399a55274 100644 --- a/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv +++ b/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv @@ -55,7 +55,7 @@ package tl_peri_pkg; localparam logic [31:0] ADDR_MASK_LC_CTRL = 32'h 000000ff; localparam logic [31:0] ADDR_MASK_SENSOR_CTRL_AON = 32'h 0000007f; localparam logic [31:0] ADDR_MASK_ALERT_HANDLER = 32'h 000007ff; - localparam logic [31:0] ADDR_MASK_SRAM_CTRL_RET_AON__REGS = 32'h 0000001f; + localparam logic [31:0] ADDR_MASK_SRAM_CTRL_RET_AON__REGS = 32'h 0000003f; localparam logic [31:0] ADDR_MASK_SRAM_CTRL_RET_AON__RAM = 32'h 00000fff; localparam logic [31:0] ADDR_MASK_AON_TIMER_AON = 32'h 0000003f; localparam logic [31:0] ADDR_MASK_SYSRST_CTRL_AON = 32'h 000000ff; diff --git a/hw/top_earlgrey/ip_autogen/flash_ctrl/rtl/flash_ctrl.sv b/hw/top_earlgrey/ip_autogen/flash_ctrl/rtl/flash_ctrl.sv index d2fec77571f8c..3fc172d93cead 100644 --- a/hw/top_earlgrey/ip_autogen/flash_ctrl/rtl/flash_ctrl.sv +++ b/hw/top_earlgrey/ip_autogen/flash_ctrl/rtl/flash_ctrl.sv @@ -530,21 +530,25 @@ module flash_ctrl ) u_to_prog_fifo ( .clk_i, .rst_ni, - .tl_i (prog_tl_h2d), - .tl_o (prog_tl_d2h), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (sw_wvalid), - .req_type_o (), - .gnt_i (sw_wready), - .we_o (), - .addr_o (), - .wmask_o (), - .intg_error_o (), - .wdata_o (sw_wdata), - .rdata_i ('0), - .rvalid_i (1'b0), - .rerror_i (2'b0), - .rmw_in_progress_o() + .tl_i (prog_tl_h2d), + .tl_o (prog_tl_d2h), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (sw_wvalid), + .req_type_o (), + .gnt_i (sw_wready), + .we_o (), + .addr_o (), + .wmask_o (), + .intg_error_o (), + .wdata_o (sw_wdata), + .rdata_i ('0), + .rvalid_i (1'b0), + .rerror_i (2'b0), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); prim_fifo_sync #( @@ -643,23 +647,27 @@ module flash_ctrl ) u_to_rd_fifo ( .clk_i, .rst_ni, - .tl_i (tl_win_h2d[1]), - .tl_o (tl_win_d2h[1]), - .en_ifetch_i (prim_mubi_pkg::MuBi4False), - .req_o (adapter_req), - .req_type_o (), + .tl_i (tl_win_h2d[1]), + .tl_o (tl_win_d2h[1]), + .en_ifetch_i (prim_mubi_pkg::MuBi4False), + .req_o (adapter_req), + .req_type_o (), // if there is no valid read operation, don't hang the // bus, just let things normally return - .gnt_i (sw_rfifo_rvalid | rd_no_op_d), - .we_o (), - .addr_o (), - .wmask_o (), - .wdata_o (), - .intg_error_o (adapter_fifo_err), - .rdata_i (sw_rfifo_rdata), - .rvalid_i (adapter_rvalid | rd_no_op_q), - .rerror_i ({rd_no_op_q, 1'b0}), - .rmw_in_progress_o() + .gnt_i (sw_rfifo_rvalid | rd_no_op_d), + .we_o (), + .addr_o (), + .wmask_o (), + .wdata_o (), + .intg_error_o (adapter_fifo_err), + .rdata_i (sw_rfifo_rdata), + .rvalid_i (adapter_rvalid | rd_no_op_q), + .rerror_i ({rd_no_op_q, 1'b0}), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); assign sw_rfifo_wen = sw_sel & rd_ctrl_wen; @@ -1303,21 +1311,25 @@ module flash_ctrl ) u_tl_adapter_eflash ( .clk_i, .rst_ni, - .tl_i (gate_tl_h2d), - .tl_o (gate_tl_d2h), - .en_ifetch_i (flash_exec_en), - .req_o (flash_host_req), - .req_type_o (), - .gnt_i (flash_host_req_rdy), - .we_o (), - .addr_o (flash_host_addr), - .wdata_o (), - .wmask_o (), - .intg_error_o (eflash_cmd_intg_err), - .rdata_i (flash_host_rdata), - .rvalid_i (flash_host_req_done), - .rerror_i ({flash_host_rderr,1'b0}), - .rmw_in_progress_o() + .tl_i (gate_tl_h2d), + .tl_o (gate_tl_d2h), + .en_ifetch_i (flash_exec_en), + .req_o (flash_host_req), + .req_type_o (), + .gnt_i (flash_host_req_rdy), + .we_o (), + .addr_o (flash_host_addr), + .wdata_o (), + .wmask_o (), + .intg_error_o (eflash_cmd_intg_err), + .rdata_i (flash_host_rdata), + .rvalid_i (flash_host_req_done), + .rerror_i ({flash_host_rderr,1'b0}), + .compound_txn_in_progress_o (), + .readback_en_i (prim_mubi_pkg::MuBi4False), + .readback_error_o (), + .wr_collision_i (1'b0), + .write_pending_i (1'b0) ); flash_phy #( diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv index 77c1a3ade8ec7..c0bf0ab650faf 100644 --- a/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv +++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey_pkg.sv @@ -299,7 +299,7 @@ package top_earlgrey_pkg; /** * Peripheral size in bytes for regs device on sram_ctrl_ret_aon in top earlgrey. */ - parameter int unsigned TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES = 32'h20; + parameter int unsigned TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES = 32'h40; /** * Peripheral base address for ram device on sram_ctrl_ret_aon in top earlgrey. @@ -469,7 +469,7 @@ package top_earlgrey_pkg; /** * Peripheral size in bytes for regs device on sram_ctrl_main in top earlgrey. */ - parameter int unsigned TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES = 32'h20; + parameter int unsigned TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES = 32'h40; /** * Peripheral base address for ram device on sram_ctrl_main in top earlgrey. diff --git a/hw/top_earlgrey/sw/autogen/chip/top_earlgrey.rs b/hw/top_earlgrey/sw/autogen/chip/top_earlgrey.rs index be8380bdfa2c4..1cdfec44238d0 100644 --- a/hw/top_earlgrey/sw/autogen/chip/top_earlgrey.rs +++ b/hw/top_earlgrey/sw/autogen/chip/top_earlgrey.rs @@ -425,7 +425,7 @@ pub const SRAM_CTRL_RET_AON_REGS_BASE_ADDR: usize = 0x40500000; /// memory-mapped registers associated with this peripheral should have an /// address between #SRAM_CTRL_RET_AON_REGS_BASE_ADDR and /// `SRAM_CTRL_RET_AON_REGS_BASE_ADDR + SRAM_CTRL_RET_AON_REGS_SIZE_BYTES`. -pub const SRAM_CTRL_RET_AON_REGS_SIZE_BYTES: usize = 0x20; +pub const SRAM_CTRL_RET_AON_REGS_SIZE_BYTES: usize = 0x40; /// Peripheral base address for ram device on sram_ctrl_ret_aon in top earlgrey. /// @@ -663,7 +663,7 @@ pub const SRAM_CTRL_MAIN_REGS_BASE_ADDR: usize = 0x411C0000; /// memory-mapped registers associated with this peripheral should have an /// address between #SRAM_CTRL_MAIN_REGS_BASE_ADDR and /// `SRAM_CTRL_MAIN_REGS_BASE_ADDR + SRAM_CTRL_MAIN_REGS_SIZE_BYTES`. -pub const SRAM_CTRL_MAIN_REGS_SIZE_BYTES: usize = 0x20; +pub const SRAM_CTRL_MAIN_REGS_SIZE_BYTES: usize = 0x40; /// Peripheral base address for ram device on sram_ctrl_main in top earlgrey. /// diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.h b/hw/top_earlgrey/sw/autogen/top_earlgrey.h index 8883620a0d407..4bb647d70900b 100644 --- a/hw/top_earlgrey/sw/autogen/top_earlgrey.h +++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.h @@ -545,7 +545,7 @@ extern "C" { * address between #TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_BASE_ADDR and * `TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_BASE_ADDR + TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES`. */ -#define TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES 0x20u +#define TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES 0x40u /** * Peripheral base address for ram device on sram_ctrl_ret_aon in top earlgrey. @@ -851,7 +851,7 @@ extern "C" { * address between #TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_BASE_ADDR and * `TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_BASE_ADDR + TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES`. */ -#define TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES 0x20u +#define TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES 0x40u /** * Peripheral base address for ram device on sram_ctrl_main in top earlgrey. diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h b/hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h index f430969fb6112..ad2b0a1d5a2c0 100644 --- a/hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h +++ b/hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h @@ -555,7 +555,7 @@ * address between #TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_BASE_ADDR and * `TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_BASE_ADDR + TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES`. */ -#define TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES 0x20 +#define TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_SIZE_BYTES 0x40 /** * Peripheral base address for ram device on sram_ctrl_ret_aon in top earlgrey. * @@ -844,7 +844,7 @@ * address between #TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_BASE_ADDR and * `TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_BASE_ADDR + TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES`. */ -#define TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES 0x20 +#define TOP_EARLGREY_SRAM_CTRL_MAIN_REGS_SIZE_BYTES 0x40 /** * Peripheral base address for ram device on sram_ctrl_main in top earlgrey. * diff --git a/hw/vendor/lowrisc_ibex.vendor.hjson b/hw/vendor/lowrisc_ibex.vendor.hjson index f3d531d0ccfd3..c9a2aeb65255a 100644 --- a/hw/vendor/lowrisc_ibex.vendor.hjson +++ b/hw/vendor/lowrisc_ibex.vendor.hjson @@ -19,7 +19,11 @@ patch_dir: "dv" } "lint", - "rtl", + { + from: "rtl", + to: "rtl", + patch_dir: "rtl" + } "syn", "util", "vendor/google_riscv-dv", diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv index 69c7cb7bba38a..df1e607ac4a1e 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv @@ -571,24 +571,26 @@ module ibex_top import ibex_pkg::*; #( .clk_i, .rst_ni, - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_tag_req[way]), - - .gnt_o (), - .write_i (ic_tag_write), - .addr_i (ic_tag_addr), - .wdata_i (ic_tag_wdata), - .wmask_i ({TagSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_tag_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) + .key_valid_i (scramble_key_valid_q), + .key_i (scramble_key_q), + .nonce_i (scramble_nonce_q), + + .req_i (ic_tag_req[way]), + + .gnt_o (), + .write_i (ic_tag_write), + .addr_i (ic_tag_addr), + .wdata_i (ic_tag_wdata), + .wmask_i ({TagSizeECC{1'b1}}), + .intg_error_i (1'b0), + + .rdata_o (ic_tag_rdata[way]), + .rvalid_o (), + .raddr_o (), + .rerror_o (), + .cfg_i (ram_cfg_i), + .wr_collision_o (), + .write_pending_o () ); // Data RAM instantiation @@ -604,24 +606,26 @@ module ibex_top import ibex_pkg::*; #( .clk_i, .rst_ni, - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_data_req[way]), - - .gnt_o (), - .write_i (ic_data_write), - .addr_i (ic_data_addr), - .wdata_i (ic_data_wdata), - .wmask_i ({LineSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_data_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) + .key_valid_i (scramble_key_valid_q), + .key_i (scramble_key_q), + .nonce_i (scramble_nonce_q), + + .req_i (ic_data_req[way]), + + .gnt_o (), + .write_i (ic_data_write), + .addr_i (ic_data_addr), + .wdata_i (ic_data_wdata), + .wmask_i ({LineSizeECC{1'b1}}), + .intg_error_i (1'b0), + + .rdata_o (ic_data_rdata[way]), + .rvalid_o (), + .raddr_o (), + .rerror_o (), + .cfg_i (ram_cfg_i), + .wr_collision_o (), + .write_pending_o () ); `ifdef INC_ASSERT diff --git a/hw/vendor/patches/lowrisc_ibex/rtl/0001-rtl-Add-new-ports-to-prim-ram-1p-scr.patch b/hw/vendor/patches/lowrisc_ibex/rtl/0001-rtl-Add-new-ports-to-prim-ram-1p-scr.patch new file mode 100644 index 0000000000000..03a467c14b9b6 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ibex/rtl/0001-rtl-Add-new-ports-to-prim-ram-1p-scr.patch @@ -0,0 +1,106 @@ +commit ce590553992529dd1ae3e8d984255abe2a8d631d +Author: Pascal Nasahl +Date: Tue May 21 07:45:37 2024 +0000 + + [PATCH] [rtl] Add new output ports to prim_ram_1p_scr + + This patch adds the new output ports `wr_collision_o` and + `write_pending_o` to the `prim_ram_1p_scr` instantiations inside + `ibex_top`. + + Signed-off-by: Pascal Nasahl + +diff --git a/ibex_top.sv b/ibex_top.sv +index 69c7cb7bba..df1e607ac4 100644 +--- a/ibex_top.sv ++++ b/ibex_top.sv +@@ -571,24 +571,26 @@ module ibex_top import ibex_pkg::*; #( + .clk_i, + .rst_ni, + +- .key_valid_i (scramble_key_valid_q), +- .key_i (scramble_key_q), +- .nonce_i (scramble_nonce_q), +- +- .req_i (ic_tag_req[way]), +- +- .gnt_o (), +- .write_i (ic_tag_write), +- .addr_i (ic_tag_addr), +- .wdata_i (ic_tag_wdata), +- .wmask_i ({TagSizeECC{1'b1}}), +- .intg_error_i(1'b0), +- +- .rdata_o (ic_tag_rdata[way]), +- .rvalid_o (), +- .raddr_o (), +- .rerror_o (), +- .cfg_i (ram_cfg_i) ++ .key_valid_i (scramble_key_valid_q), ++ .key_i (scramble_key_q), ++ .nonce_i (scramble_nonce_q), ++ ++ .req_i (ic_tag_req[way]), ++ ++ .gnt_o (), ++ .write_i (ic_tag_write), ++ .addr_i (ic_tag_addr), ++ .wdata_i (ic_tag_wdata), ++ .wmask_i ({TagSizeECC{1'b1}}), ++ .intg_error_i (1'b0), ++ ++ .rdata_o (ic_tag_rdata[way]), ++ .rvalid_o (), ++ .raddr_o (), ++ .rerror_o (), ++ .cfg_i (ram_cfg_i), ++ .wr_collision_o (), ++ .write_pending_o () + ); + + // Data RAM instantiation +@@ -604,24 +606,26 @@ module ibex_top import ibex_pkg::*; #( + .clk_i, + .rst_ni, + +- .key_valid_i (scramble_key_valid_q), +- .key_i (scramble_key_q), +- .nonce_i (scramble_nonce_q), +- +- .req_i (ic_data_req[way]), +- +- .gnt_o (), +- .write_i (ic_data_write), +- .addr_i (ic_data_addr), +- .wdata_i (ic_data_wdata), +- .wmask_i ({LineSizeECC{1'b1}}), +- .intg_error_i(1'b0), +- +- .rdata_o (ic_data_rdata[way]), +- .rvalid_o (), +- .raddr_o (), +- .rerror_o (), +- .cfg_i (ram_cfg_i) ++ .key_valid_i (scramble_key_valid_q), ++ .key_i (scramble_key_q), ++ .nonce_i (scramble_nonce_q), ++ ++ .req_i (ic_data_req[way]), ++ ++ .gnt_o (), ++ .write_i (ic_data_write), ++ .addr_i (ic_data_addr), ++ .wdata_i (ic_data_wdata), ++ .wmask_i ({LineSizeECC{1'b1}}), ++ .intg_error_i (1'b0), ++ ++ .rdata_o (ic_data_rdata[way]), ++ .rvalid_o (), ++ .raddr_o (), ++ .rerror_o (), ++ .cfg_i (ram_cfg_i), ++ .wr_collision_o (), ++ .write_pending_o () + ); + + `ifdef INC_ASSERT diff --git a/util/reggen/countermeasure.py b/util/reggen/countermeasure.py index 8891d5af6f03a..48328ffc9a6e5 100644 --- a/util/reggen/countermeasure.py +++ b/util/reggen/countermeasure.py @@ -44,6 +44,7 @@ 'SHADOW', 'SCRAMBLE', 'INTEGRITY', + 'READBACK', 'CONSISTENCY', 'DIGEST', 'LC_GATED',