[fpv/keccak] FPV wrapper for Keccak This commit implements simple FPV testbench that checks keccak permutation. It assumes the keccak logic is used in SHA3-256 algorithm and the given input value is NULL (zero length message). So the bitstring feeded into the keccak is "" || 01 ||10*(1084)1 || 0*(512), which are respectively M, SHA3 domain, pad10*1, and capacity. More concrete tests are necessary to confirm the logic works. Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/ip/prim/fpv/prim_keccak_fpv.core b/hw/ip/prim/fpv/prim_keccak_fpv.core new file mode 100644 index 0000000..348342f --- /dev/null +++ b/hw/ip/prim/fpv/prim_keccak_fpv.core
@@ -0,0 +1,23 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:fpv:prim_keccak_fpv:0.1" +description: "Keccak_f FPV target" +filesets: + files_fpv: + depend: + - lowrisc:prim:all + files: + - tb/prim_keccak_fpv.sv + file_type: systemVerilogSource + +targets: + default: + # note, this setting is just used + # to generate a file list for jg + default_tool: icarus + filesets: + - files_fpv + toplevel: + - prim_keccak_fpv
diff --git a/hw/ip/prim/fpv/tb/prim_keccak_fpv.sv b/hw/ip/prim/fpv/tb/prim_keccak_fpv.sv new file mode 100644 index 0000000..78cb994 --- /dev/null +++ b/hw/ip/prim/fpv/tb/prim_keccak_fpv.sv
@@ -0,0 +1,74 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Testbench module for prim_keccak. Intended to be used with a formal tool. + +module prim_keccak_fpv #( + parameter int Width = 1600 +) ( + input clk_i, + input rst_ni, + input valid_i, + input [Width-1:0] state_i, + output logic done_o, + output logic [Width-1:0] state_o +); + + localparam int W = Width/25; + localparam int L = $clog2(W); + localparam int NumRound = 12 + 2*L; // Keccak-f only + localparam int RndW = $clog2(NumRound+1); + logic [RndW-1:0] round; + logic active; + logic [Width-1:0] state, state_d; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) state <= '0; + else if (valid_i) state <= state_i; + else if (active) state <= state_d; + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) round <= '0; + else if (valid_i) round <= '0; + else if (active) round <= round + 1'b 1; + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) active <= 1'b 0; + else if (valid_i) active <= 1'b 1; + else if (round == (NumRound -1)) active <= 1'b 0; + end + + assign done_o = (round == NumRound); + assign state_o = state; + + prim_keccak #( + .Width (Width) + ) u_keccak ( + .rnd_i (round), + .s_i (state), + .s_o (state_d) + ); + + + `ASSUME_FPV(ValidSequence_A, ##1 valid_i |=> !valid_i) + `ASSUME_FPV(ValidValid_A, active |-> !valid_i) + + // Test with value 0 + logic [1599:0] data_0 ; + always_comb begin + data_0 = '0; + // SHA3-256 ==> r : 1088 + data_0[1087] = 1'b 1; + data_0[2:0] = 3'b 110; + end + logic [255:0] digest_0; + // Big-Endian a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a + assign digest_0 = 256'h 4a43_f880_4b0a_d882_fa49_3be4_4dff_80f5_62d6_61a0_5647_c151_66d7_1ebf_f8c6_ffa7; + `ASSUME_FPV(Data0TestSHA3_256_A, state_i == data_0) + `ASSERT(DigestForData0TestSHA3_256_A, done_o |-> state_o[255:0] == digest_0) + +endmodule +