//------------------------------------------------------------------------------ // // 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