[otbn, rtl] Only calculate CRC for 32-bit aligned writes Signed-off-by: Greg Chadwick <gac@lowrisc.org>
diff --git a/hw/ip/otbn/doc/_index.md b/hw/ip/otbn/doc/_index.md index ab5c626..a9cd68f 100644 --- a/hw/ip/otbn/doc/_index.md +++ b/hw/ip/otbn/doc/_index.md
@@ -940,6 +940,7 @@ Here, `imem` is a single bit flag which is one for writes to IMEM and zero for writes to DMEM. The `idx` value is the index of the word within the memory, zero extended from 10b to 15b. Finally, `wdata` is the 32b word that was written. +Writes that are less than 32b or not aligned on a 32b boundary are ignored and not factored into the CRC calculation. The host processor can also write to the register. Typically, this will be to clear the value to `32'h00000000`, the traditional starting value for a 32-bit CRC.
diff --git a/hw/ip/otbn/rtl/otbn.sv b/hw/ip/otbn/rtl/otbn.sv index 5fb0dfe..c28dc4d 100644 --- a/hw/ip/otbn/rtl/otbn.sv +++ b/hw/ip/otbn/rtl/otbn.sv
@@ -191,6 +191,7 @@ logic [38:0] imem_wdata_bus; logic [38:0] imem_wmask_bus; logic [38:0] imem_rdata_bus; + logic [top_pkg::TL_DBW-1:0] imem_byte_mask_bus; logic imem_rvalid_bus; logic [1:0] imem_rerror_bus; @@ -355,6 +356,8 @@ assign imem_rvalid_bus = (~imem_access_core & imem_rvalid) | imem_dummy_response_q; assign imem_rvalid_core = imem_access_core ? imem_rvalid : 1'b0; + assign imem_byte_mask_bus = tl_win_h2d[TlWinImem].a_mask; + // No imem errors reported for bus reads. Integrity is carried through on the bus so integrity // checking on TL responses will pick up any errors. assign imem_rerror_bus = 2'b00; @@ -397,6 +400,7 @@ logic [ExtWLEN-1:0] dmem_rdata_bus; logic [top_pkg::TL_AW-1:0] dmem_addr_bus; logic [31:0] dmem_wdata_narrow_bus; + logic [top_pkg::TL_DBW-1:0] dmem_byte_mask_bus; logic dmem_rvalid_bus; logic [1:0] dmem_rerror_bus; @@ -543,11 +547,16 @@ assign dmem_addr_bus = tl_win_h2d[TlWinDmem].a_address; assign dmem_wdata_narrow_bus = tl_win_h2d[TlWinDmem].a_data[31:0]; + assign dmem_byte_mask_bus = tl_win_h2d[TlWinDmem].a_mask; // Memory Load Integrity ===================================================== + // CRC logic below assumes a incoming data bus width of 32 bits + `ASSERT_INIT(TLDWIs32Bit_A, top_pkg::TL_DW == 32) - assign mem_crc_data_in_valid = (imem_req_bus | dmem_req_bus) & - ~(dmem_access_core | imem_access_core); + // Only advance CRC calculation on full 32-bit writes; + assign mem_crc_data_in_valid = ~(dmem_access_core | imem_access_core) & + ((imem_req_bus & (imem_byte_mask_bus == 4'hf)) | + (dmem_req_bus & (dmem_byte_mask_bus == 4'hf))); assign mem_crc_data_in.wr_data = imem_req_bus ? imem_wdata_bus[31:0] : dmem_wdata_narrow_bus[31:0];