//====================================================================== // // Copyright (c) 2016, NORDUnet A/S All rights reserved. // // 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. // //====================================================================== `timescale 1ns / 1ps module tb_modexpa7_top; // // Settings // localparam MAX_MODULUS_WIDTH = 256; // // Control Registers // reg use_public_mode; reg [ 8: 0] modulus_width; reg [ 8: 0] exponent_width; // // Test Vectors (128-bit) // localparam [127:0] M_TEST_128 = 128'h0001FF00544553545445535454455354; localparam [127:0] M_ABC_128 = 128'h0001FFFFFFFF00414243414243414243; localparam [127:0] M_XYZ_128 = 128'h0001FFFFFFFF0058595A58595A58595A; localparam [127:0] N_1_128 = 128'h56247F8A1582CD1C96ED0ECD3E60FCB1; localparam [127:0] N_2_128 = 128'h708CC1BEA087DCA3D0999E3AC033A50B; localparam [127:0] D_1_128 = 128'h40C9E4AEEB6CDC6D12E4526089BCB8FD; localparam [127:0] D_2_128 = 128'h1ADFF16F74639CB28976EEC528C866C1; localparam [127:0] S_TEST_1_128 = 128'h310AB3124D4CB1DEE1CFA4694DC8BCA2; localparam [127:0] S_TEST_2_128 = 128'h5D621FC2642AEB705FDB7B90693FE3BF; localparam [127:0] S_ABC_1_128 = 128'h235EA2712140F90344DFE2BF74B13075; localparam [127:0] S_XYZ_1_128 = 128'h1A501D80B1F8648DE08C1AE673E13770; localparam [127:0] S_ABC_2_128 = 128'h2258423C6CDB0E1AA73F70CA41BC6633; localparam [127:0] S_XYZ_2_128 = 128'h5B278DEB75C055C8DA8E2993A791F3C2; // // Test Vectors (256-bit) // localparam [255:0] M_TEST_256 = 256'h0001FF0054455354544553545445535454455354544553545445535454455354; localparam [255:0] M_ABC_256 = 256'h0001FFFFFFFFFF00414243414243414243414243414243414243414243414243; localparam [255:0] M_XYZ_256 = 256'h0001FFFFFFFFFF0058595A58595A58595A58595A58595A58595A58595A58595A; localparam [255:0] N_1_256 = 256'h624341A8670845B4AA39CC2C08437E2568E11441CB5461CB49162EAC2E751FC5; localparam [255:0] N_2_256 = 256'h772F7C4A4D8C92CE59D8688897795F7208D3B1D3B5C7D83BF0E1A2A59D879A13; localparam [255:0] D_1_256 = 256'h41D555B401F3A4DFF9FC673249070F08247EF8A52A270F283FFAA7EA65B25F01; localparam [255:0] D_2_256 = 256'h1606E0A19AD3700E52EC7BE542995BDA26AA386DD677A74B7B2846AC44BCAD81; localparam [255:0] S_TEST_1_256 = 256'h07EFB60CF6E6F2350E8D2D5C5261F36CF0B2B71833386AC6E7958A8F39DAD331; localparam [255:0] S_TEST_2_256 = 256'h5C18F857BF6E4D6A013F554A680329BDC14C31FF38D0EEAD1DE02CFD85337A53; localparam [255:0] S_ABC_1_256 = 256'h2AA0A5D3B2AE1FFD23640714F652DD147B6C202905B4D273E837313FB392487C; localparam [255:0] S_XYZ_1_256 = 256'h27850A998B867CB67146EEFF15147668D7CF6B7BD5B048D9735D5767EB6D68CB; localparam [255:0] S_ABC_2_256 = 256'h56A0DA5F9987DF4E921A771CCC8A1D68F8DD7D9244A0DD37A4095D61F455489D; localparam [255:0] S_XYZ_2_256 = 256'h08A7AF13E058754278EE6582626A6675D09A08C0C898E218FCDF7FFA37C9876C; // // Locals // localparam [ 1: 0] BANK_MODULUS = 2'b00; localparam [ 1: 0] BANK_MESSAGE = 2'b01; localparam [ 1: 0] BANK_EXPONENT = 2'b10; localparam [ 1: 0] BANK_RESULT = 2'b11; // // Integers // integer addr; // // Inputs, Outputs // reg init; reg next; wire ready; wire valid; // // Bus // reg bus_cs; reg bus_we; reg [ 4: 0] bus_addr; reg [31: 0] bus_data_wr; wire [31: 0] bus_data_rd; // // Clock (100 MHz) // reg clk = 1'b0; always #5 clk = ~clk; // // UUT // modexpa7_top # ( .MAX_MODULUS_WIDTH (MAX_MODULUS_WIDTH) ) uut ( .clk (clk), .init (init), .ready (ready), .next (next), .valid (valid), .modulus_width (modulus_width), .exponent_width (exponent_width), .fast_public_mode (use_public_mode), .bus_cs (bus_cs), .bus_we (bus_we), .bus_addr (bus_addr), .bus_data_wr (bus_data_wr), .bus_data_rd (bus_data_rd) ); // // Script // initial begin // $display("Testbench started."); // init = 0; next = 0; // bus_cs = 0; bus_we = 0; bus_addr = 5'd0; bus_data_wr = 32'h00000000; // #200; // $display("Running in public (unsafe, faster) mode..."); use_public_mode = 1; // run_tests_128(); run_tests_256(); // $display("Running in private (safe, slower) mode..."); use_public_mode = 0; // run_tests_128(); run_tests_256(); // $display("All tests passed."); $display("Testbench finished."); // $finish; // end // // run_tests_128() // task run_tests_128; begin // $display("Testing 128-bit mode..."); // $display("Setting modulus #1..."); set_modulus_128(N_1_128); $display("Signing TEST message..."); test_vector_128(M_TEST_128, D_1_128, S_TEST_1_128); // $display("Setting modulus #2..."); set_modulus_128(N_2_128); $display("Signing TEST message..."); test_vector_128(M_TEST_128, D_2_128, S_TEST_2_128); // $display("Setting modulus #1..."); set_modulus_128(N_1_128); $display("Signing ABC message..."); test_vector_128(M_ABC_128, D_1_128, S_ABC_1_128); $display("Signing XYZ message..."); test_vector_128(M_XYZ_128, D_1_128, S_XYZ_1_128); // $display("Setting modulus #2..."); set_modulus_128(N_2_128); $display("Signing ABC message..."); test_vector_128(M_ABC_128, D_2_128, S_ABC_2_128); $display("Signing XYZ message..."); test_vector_128(M_XYZ_128, D_2_128, S_XYZ_2_128); // end endtask // // run_tests_256() // task run_tests_256; begin // $display("Testing 256-bit mode..."); // $display("Setting modulus #1..."); set_modulus_256(N_1_256); $display("Signing TEST message..."); test_vector_256(M_TEST_256, D_1_256, S_TEST_1_256); // $display("Setting modulus #2..."); set_modulus_256(N_2_256); $display("Signing TEST message..."); test_vector_256(M_TEST_256, D_2_256, S_TEST_2_256); // $display("Setting modulus #1..."); set_modulus_256(N_1_256); $display("Signing ABC message..."); test_vector_256(M_ABC_256, D_1_256, S_ABC_1_256); $display("Signing XYZ message..."); test_vector_256(M_XYZ_256, D_1_256, S_XYZ_1_256); // $display("Setting modulus #2..."); set_modulus_256(N_2_256); $display("Signing ABC message..."); test_vector_256(M_ABC_256, D_2_256, S_ABC_2_256); $display("Signing XYZ message..."); test_vector_256(M_XYZ_256, D_2_256, S_XYZ_2_256); // end endtask // // set_modulus_128() // task set_modulus_128; input [127:0] modulus; begin // modulus_width = 9'd128; // bank_write_128(BANK_MODULUS, modulus); #100; init = 1; wait_ready(); init = 0; #100; // end endtask // // set_modulus_256() // task set_modulus_256; input [255:0] modulus; begin // modulus_width = 9'd256; // bank_write_256(BANK_MODULUS, modulus); #100; init = 1; wait_ready(); init = 0; #100; // end endtask // // test_vector_128() // task test_vector_128; input [127:0] message; input [127:0] exponent; input [127:0] signature; reg [127:0] readback; begin // exponent_width = 9'd128; // bank_write_128(BANK_MESSAGE, message); #100; bank_write_128(BANK_EXPONENT, exponent); #100; // next = 1; wait_valid(); next = 0; #100; // bank_read_128(BANK_RESULT, readback); // $display(" signature: %032x", signature); $display(" readback: %032x", readback); // if (readback == signature) $display("Got correct S = M ** E mod N [OK]"); else begin $display("Got wrong S = M ** E mod N [ERROR]"); $finish; end // end endtask // // test_vector_256() // task test_vector_256; input [255:0] message; input [255:0] exponent; input [255:0] signature; reg [255:0] readback; begin // exponent_width = 9'd256; // bank_write_256(BANK_MESSAGE, message); #100; bank_write_256(BANK_EXPONENT, exponent); #100; // next = 1; wait_valid(); next = 0; #100; // bank_read_256(BANK_RESULT, readback); // $display(" signature: %064x", signature); $display(" readback: %064x", readback); // if (readback == signature) $display("Got correct S = M ** E mod N [OK]"); else begin $display("Got wrong S = M ** E mod N [ERROR]"); $finish; end // end endtask // // bus_write_reg() // task bus_write_reg; input [ 1: 0] bank; input [ 2: 0] offset; input [31: 0] data; begin // bus_cs = 1; bus_we = 1; bus_addr = {bank, offset}; bus_data_wr = data; // #10; // bus_cs = 0; bus_we = 0; // #10; // end endtask // // bus_read_reg() // task bus_read_reg; input [ 1: 0] bank; input [ 2: 0] offset; output [31: 0] data; begin // bus_cs = 1; bus_we = 0; bus_addr = {bank, offset}; // #10; // bus_cs = 0; bus_we = 0; data = bus_data_rd; // #10; // end endtask // // bank_write_128() // task bank_write_128; input [ 1:0] bank; input [127:0] value; reg [127:0] shreg; begin // shreg = value; // for (addr=0; addr<4; addr=addr+1) begin bus_write_reg(bank, addr[2:0], shreg[31:0]); shreg = {{32{1'b0}}, shreg[127:32]}; end // end endtask // // bank_write_256() // task bank_write_256; input [ 1:0] bank; input [255:0] value; reg [255:0] shreg; begin // shreg = value; // for (addr=0; addr<8; addr=addr+1) begin bus_write_reg(bank, addr[2:0], shreg[31:0]); shreg = {{32{1'b0}}, shreg[255:32]}; end // end endtask // // bank_read_128() // task bank_read_128; input [ 1:0] bank; output [127:0] value; reg [ 31:0] shreg; begin // for (addr=0; addr<4; addr=addr+1) begin bus_read_reg(bank, addr[2:0], shreg); value = {shreg, value[127:32]}; end // end endtask // // bank_read_256() // task bank_read_256; input [ 1:0] bank; output [255:0] value; reg [ 31:0] shreg; begin // for (addr=0; addr<8; addr=addr+1) begin bus_read_reg(bank, addr[2:0], shreg); value = {shreg, value[255:32]}; end // end endtask // // wait_ready() // task wait_ready; begin while (!ready) #10; end endtask // // wait_valid() // task wait_valid; begin while (!valid) #10; end endtask endmodule