From 1a02289102362a0e826f739048e9649fd3d8820d Mon Sep 17 00:00:00 2001 From: "Pavel V. Shatov (Meister)" Date: Mon, 12 Apr 2021 17:35:49 +0300 Subject: New testbench (basically the same as tb_curve_multiplier_256.v, but tests entire core starting from the wrapper) --- bench/tb_ecdsa256_wrapper.v | 443 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 443 insertions(+) create mode 100644 bench/tb_ecdsa256_wrapper.v (limited to 'bench') diff --git a/bench/tb_ecdsa256_wrapper.v b/bench/tb_ecdsa256_wrapper.v new file mode 100644 index 0000000..2e11d83 --- /dev/null +++ b/bench/tb_ecdsa256_wrapper.v @@ -0,0 +1,443 @@ +//------------------------------------------------------------------------------ +// +// tb_ecdsa256_wrapper.v +// ----------------------------------------------------------------------------- +// Testbench for 256-bit curve base point scalar multiplier. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2016, 2018-2019, 2021 NORDUnet A/S +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//------------------------------------------------------------------------------ + +module tb_ecdsa256_wrapper; + + + // + // Test Vectors + // + `include "ecdsa256_test_vector_nsa.vh" + `include "ecdsa_test_vector_randomized.vh" + + + // + // Core Parameters + // + localparam WORD_COUNTER_WIDTH = 3; + localparam OPERAND_NUM_WORDS = 8; + + + // + // Register Offsets + // + localparam CORE_ADDR_NAME0 = 24'h000000; + localparam CORE_ADDR_NAME1 = 24'h000001; + localparam CORE_ADDR_VERSION = 24'h000002; + localparam CORE_ADDR_CONTROL = 24'h000008; + localparam CORE_ADDR_STATUS = 24'h000009; + + localparam CORE_ADDR_BUF_K = 24'h000020; + localparam CORE_ADDR_BUF_X = 24'h000028; + localparam CORE_ADDR_BUF_Y = 24'h000030; + + localparam CORE_CONTROL_BIT_NEXT = 32'h00000002; + localparam CORE_STATUS_BIT_VALID = 32'h00000002; + + + // + // STM32 Settings + // + localparam STM32_FMC_LATENCY = 6; + + + // + // P-256 Domain Parameters + // + localparam ECDSA_P256_N = + {32'hffffffff, 32'h00000000, 32'hffffffff, 32'hffffffff, + 32'hbce6faad, 32'ha7179e84, 32'hf3b9cac2, 32'hfc632551}; + + localparam ECDSA_P256_GX = + {32'h6b17d1f2, 32'he12c4247, 32'hf8bce6e5, 32'h63a440f2, + 32'h77037d81, 32'h2deb33a0, 32'hf4a13945, 32'hd898c296}; + + localparam ECDSA_P256_GY = + {32'h4fe342e2, 32'hfe1a7f9b, 32'h8ee7eb4a, 32'h7c0f9e16, + 32'h2bce3357, 32'h6b315ece, 32'hcbb64068, 32'h37bf51f5}; + + localparam ECDSA_P256_HX = + {32'h7cf27b18, 32'h8d034f7e, 32'h8a523803, 32'h04b51ac3, + 32'hc08969e2, 32'h77f21b35, 32'ha60b48fc, 32'h47669978}; + + localparam ECDSA_P256_HY = + {32'h07775510, 32'hdb8ed040, 32'h293d9ac6, 32'h9f7430db, + 32'hba7dade6, 32'h3ce98229, 32'h9e04b79d, 32'h227873d1}; + + + // + // FMC Clock (50 MHz) + // + localparam FMC_CLOCK_PERIOD = 20.0; + localparam FMC_CLOCK_PERIOD_HALF = 0.5 * FMC_CLOCK_PERIOD; + localparam FMC_CLOCK_PERIOD_QUARTER = 0.5 * FMC_CLOCK_PERIOD_HALF; + + reg fmc_clk = 1'b0; + + initial forever #FMC_CLOCK_PERIOD_HALF fmc_clk = ~fmc_clk; + + + // + // Clock Manager + // + wire io_clk; // i/o clock + wire sys_clk; // system clock + wire sys_rst_n; // active-low reset + + alpha_clkmgr clkmgr_inst + ( + .fmc_clk (fmc_clk), + + .io_clk (io_clk), + .sys_clk (sys_clk), + .sys_rst_n (sys_rst_n), + .core_clk () + ); + + + // + // FMC Arbiter - FPGA Side + // + wire [23: 0] sys_fmc_addr; + wire sys_fmc_wren; + wire sys_fmc_rden; + wire [31: 0] sys_fmc_dout; + wire [31: 0] sys_fmc_din; + + + // + // FMC Arbiter - STM32 Side + // + reg [23: 0] fmc_a = {24{1'bX}}; + reg [31: 0] fmc_d_drive; + wire [31: 0] fmc_d_bidir; + reg fmc_ne1 = 1'b1; + reg fmc_noe = 1'b1; + reg fmc_nwe = 1'b1; + reg fmc_nl = 1'b1; + wire fmc_nwait_dummy; + + assign fmc_d_bidir = fmc_noe ? fmc_d_drive : 32'hZZZZZZZZ; + + fmc_arbiter #(.NUM_ADDR_BITS(24)) + fmc_arbiter_inst + ( + // fmc bus + .fmc_a (fmc_a), + .fmc_d (fmc_d_bidir), + .fmc_ne1 (fmc_ne1), + .fmc_nl (fmc_nl), + .fmc_nwe (fmc_nwe), + .fmc_noe (fmc_noe), + .fmc_nwait (fmc_nwait_dummy), + + // system clock, i/o clock + .io_clk (io_clk), + .sys_clk (sys_clk), + + // user bus + .sys_addr (sys_fmc_addr), + .sys_wr_en (sys_fmc_wren), + .sys_data_out (sys_fmc_dout), + .sys_rd_en (sys_fmc_rden), + .sys_data_in (sys_fmc_din) + ); + + ecdsa256_wrapper uut + ( + .clk (sys_clk), + .reset_n (sys_rst_n), + + .cs (sys_fmc_wren | sys_fmc_rden), + .we (sys_fmc_wren), + + .address (sys_fmc_addr[5:0]), + .write_data (sys_fmc_dout), + .read_data (sys_fmc_din) + ); + + + // + // Testbench Routine + // + reg ok = 1; + + reg [31:0] core_name0; + reg [31:0] core_name1; + reg [31:0] core_version; + + initial begin + + /* wait for some time */ + #4000; + + /* sanity checks */ + fmc_read(CORE_ADDR_NAME0, core_name0); + fmc_read(CORE_ADDR_NAME1, core_name1); + fmc_read(CORE_ADDR_VERSION, core_version); + + $display("CORE_NAME0: %x", core_name0); + $display("CORE_NAME1: %x", core_name1); + $display("CORE_VERSION: %x", core_version); + + /* run tests */ + $display("1. Q1 = d1 * G..."); + test_curve_multiplier(ECDSA_P256_D_NSA, ECDSA_P256_QX_NSA, ECDSA_P256_QY_NSA); + + $display("2. R = k * G..."); + test_curve_multiplier(ECDSA_P256_K_NSA, ECDSA_P256_RX_NSA, ECDSA_P256_RY_NSA); + + $display("3. Q2 = d2 * G..."); + test_curve_multiplier(ECDSA_P256_D_RANDOM, ECDSA_P256_QX_RANDOM, ECDSA_P256_QY_RANDOM); + + $display("4. O = n * G..."); + test_curve_multiplier(ECDSA_P256_N, 256'd0, 256'd0); + + $display("5. G = (n + 1) * G..."); + test_curve_multiplier(ECDSA_P256_N + 256'd1, ECDSA_P256_GX, ECDSA_P256_GY); + + $display("6. H = 2 * G..."); + test_curve_multiplier(256'd2, ECDSA_P256_HX, ECDSA_P256_HY); + + $display("7. H = (n + 2) * G..."); + test_curve_multiplier(ECDSA_P256_N + 256'd2, ECDSA_P256_HX, ECDSA_P256_HY); + + /* print result */ + if (ok) $display("tb_curve_multiplier_256: SUCCESS"); + else $display("tb_curve_multiplier_256: FAILURE"); + + $finish; + + end + + + // + // Test Task + // + reg p_ok; + integer w; + reg busy; + reg [31:0] reg_control; + reg [31:0] reg_status; + task test_curve_multiplier; + + input [255:0] k; + input [255:0] px; + input [255:0] py; + + reg [255:0] k_shreg; + reg [255:0] px_shreg; + reg [255:0] py_shreg; + + begin + + // initialize shift registers + k_shreg = k; + + // write all the words + for (w=0; w