[kmac] State Window

This commit implements the Keccak storage FW read port. KMAC has 512B of
TL window port to allow FW to read the keccak state 1600bits. If
EnMasking is turned on, FW should read 1600b x 2 (3200b) and XORed
together to get the unmasked state value.

Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/ip/kmac/kmac.core b/hw/ip/kmac/kmac.core
index 03429f5..7327fe9 100644
--- a/hw/ip/kmac/kmac.core
+++ b/hw/ip/kmac/kmac.core
@@ -17,6 +17,7 @@
       - rtl/sha3pad.sv
       - rtl/sha3core.sv
       - rtl/kmac_msgfifo.sv
+      - rtl/kmac_staterd.sv
       - rtl/kmac_reg_pkg.sv
       - rtl/kmac_reg_top.sv
       - rtl/kmac.sv
diff --git a/hw/ip/kmac/rtl/kmac_staterd.sv b/hw/ip/kmac/rtl/kmac_staterd.sv
new file mode 100644
index 0000000..66ae239
--- /dev/null
+++ b/hw/ip/kmac/rtl/kmac_staterd.sv
@@ -0,0 +1,121 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Keccak state read
+
+`include "prim_assert.sv"
+
+module kmac_staterd
+  import kmac_pkg::*;
+#(
+  // TL-UL Address Width. Should be bigger than
+  // $clog2(kmac_pkg::StateW) * Share
+  parameter int AddrW = 9,
+
+  // EnMasking: Enable masking security hardening inside keccak_round
+  // If it is enabled, the result digest will be two set of 1600bit.
+  parameter  int EnMasking = 0,
+  localparam int Share = (EnMasking) ? 2 : 1  // derived parameter
+) (
+  input clk_i,
+  input rst_ni,
+
+  input  tlul_pkg::tl_h2d_t tl_i,
+  output tlul_pkg::tl_d2h_t tl_o,
+
+  // State in
+  input valid_i,
+  input [StateW-1:0] state_i [Share],
+
+  // Config
+  input endian_swap_i
+);
+
+  localparam int StateAddrW = $clog2(kmac_pkg::StateW/32);
+  localparam int SelAddrW   = AddrW-2-StateAddrW;
+
+  /////////////
+  // Signals //
+  /////////////
+
+  // TL-UL Adapter signals
+  logic             tlram_req;
+  logic             tlram_gnt;
+  logic             tlram_we;
+  logic [AddrW-3:0] tlram_addr;   // Word base
+  logic [31:0]      unused_tlram_wdata;
+  logic [31:0]      unused_tlram_wmask;
+  logic [31:0]      tlram_rdata;
+  logic             tlram_rvalid;
+  logic [1:0]       tlram_rerror;
+  logic [31:0]      tlram_rdata_endian;
+
+  // TL Adapter
+  tlul_adapter_sram #(
+    .SramAw (AddrW-2),
+    .SramDw (323),
+    .Outstanding (1),
+    .ByteAccess  (1),
+    .ErrOnWrite  (1),
+    .ErrOnRead   (0)
+  ) u_tlul_adapter (
+    .clk_i,
+    .rst_ni,
+
+    .tl_i,
+    .tl_o,
+
+    .req_o    (tlram_req),
+    .gnt_i    (tlram_gnt),
+    .we_o     (tlram_we ),
+    .addr_o   (tlram_addr),
+    .wdata_o  (unused_tlram_wdata),
+    .wmask_o  (unused_tlram_wmask),
+    .rdata_i  (tlram_rdata),
+    .rvalid_i (tlram_rvalid),
+    .rerror_i (tlram_rerror)
+  );
+
+  assign tlram_rdata = conv_endian32(tlram_rdata_endian, endian_swap_i);
+
+  // Always grant
+  assign tlram_gnt = tlram_req & ~tlram_we;
+
+  // always no error on reading
+  assign tlram_rerror = '0;
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) tlram_rvalid <= 1'b0;
+    else         tlram_rvalid <= tlram_req & !tlram_we;
+  end
+
+  logic [31:0] muxed_state [Share];
+
+
+  for (genvar i = 0 ; i < Share ; i++) begin : gen_slicer
+    prim_slicer #(
+      .InW (kmac_pkg::StateW),
+      .OutW (32),
+      .IndexW (StateAddrW)
+    ) u_state_slice (
+      .sel_i (tlram_addr[StateAddrW-1:0]),
+      .data_i (state_i[i]),
+      .data_o (muxed_state[i])
+    );
+  end : gen_slicer
+
+  logic [SelAddrW-1:0] addr_sel;
+  assign addr_sel = tlram_addr[StateAddrW+:SelAddrW];
+
+  always_comb begin
+    tlram_rdata_endian = '0;
+    for (int i = 0 ; i < Share ; i++) begin
+      if ($unsigned(i) == addr_sel) begin
+        tlram_rdata_endian = muxed_state[i];
+      end
+    end
+  end
+
+endmodule
+