From a315223f98fa6f1fdea2b1080c5f3e33352ebb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Mon, 27 Apr 2015 11:17:08 +0200 Subject: Updating modexp core to v 0.50. This version contains a working core that can perform sign and verify with big keys/values. The core builds ok in Altera and Xilinx FPGA tools. This commit also includes a new testgenerator capable of generating testbench for modexp with autgenerated test data of different lengths. The README has been updated with status and implementation results in for different FPGA devices. --- src/tb/tb_modexp.v | 466 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 443 insertions(+), 23 deletions(-) (limited to 'src/tb/tb_modexp.v') diff --git a/src/tb/tb_modexp.v b/src/tb/tb_modexp.v index c07d3d5..a7159b7 100644 --- a/src/tb/tb_modexp.v +++ b/src/tb/tb_modexp.v @@ -50,19 +50,43 @@ module tb_modexp(); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- - parameter DEBUG = 0; + parameter DEBUG = 0; + parameter DEBUG_EI = 1; localparam CLK_HALF_PERIOD = 1; localparam CLK_PERIOD = 2 * CLK_HALF_PERIOD; // The DUT address map. - localparam ADDR_NAME0 = 8'h00; - localparam ADDR_NAME1 = 8'h01; - localparam ADDR_VERSION = 8'h02; + localparam GENERAL_PREFIX = 4'h0; + localparam ADDR_NAME0 = 8'h00; + localparam ADDR_NAME1 = 8'h01; + localparam ADDR_VERSION = 8'h02; - localparam ADDR_CTRL = 8'h08; - localparam CTRL_INIT_BIT = 0; - localparam CTRL_NEXT_BIT = 1; + localparam ADDR_CTRL = 8'h08; + localparam CTRL_START_BIT = 0; + + localparam ADDR_STATUS = 8'h09; + localparam STATUS_READY_BIT = 0; + + localparam ADDR_MODULUS_LENGTH = 8'h20; + localparam ADDR_MESSAGE_LENGTH = 8'h21; + localparam ADDR_EXPONENT_LENGTH = 8'h22; + + localparam MODULUS_PREFIX = 4'h1; + localparam ADDR_MODULUS_START = 8'h00; + localparam ADDR_MODULUS_END = 8'hff; + + localparam EXPONENT_PREFIX = 4'h2; + localparam ADDR_EXPONENT_START = 8'h00; + localparam ADDR_EXPONENT_END = 8'hff; + + localparam MESSAGE_PREFIX = 4'h3; + localparam MESSAGE_START = 8'h00; + localparam MESSAGE_END = 8'hff; + + localparam RESULT_PREFIX = 4'h4; + localparam RESULT_START = 8'h00; + localparam RESULT_END = 8'hff; //---------------------------------------------------------------- @@ -79,7 +103,7 @@ module tb_modexp(); reg tb_reset_n; reg tb_cs; reg tb_we; - reg [11 : 0] tb_address; + reg [11 : 0] tb_address; reg [31 : 0] tb_write_data; wire [31 : 0] tb_read_data; wire tb_error; @@ -129,6 +153,25 @@ module tb_modexp(); end end + //---------------------------------------------------------------- + // ei_monitor() + // + // Displays ei_new, the most important variable for determining + // what modexp will do (i.e. should Z=MONTPROD( Z, P, M) be + // performed + //---------------------------------------------------------------- + always @* + begin : ei_monitor + if (DEBUG_EI) + if (dut.modexp_ctrl_reg == dut.CTRL_ITERATE_Z_P) + $display("loop counter %d: ei = %d", dut.loop_counter_reg, dut.ei_reg); + end + + always @* + begin : z_monitor + $display("result_mem[0][1] = %x %x",dut.result_mem.mem[0],dut.result_mem.mem[1]); + end + //---------------------------------------------------------------- // dump_dut_state() @@ -140,8 +183,23 @@ module tb_modexp(); $display("cycle: 0x%016x", cycle_ctr); $display("State of DUT"); $display("------------"); + $display("Inputs and outputs:"); + $display("cs = 0x%01x, we = 0x%01x", tb_cs, tb_we); + $display("addr = 0x%08x, read_data = 0x%08x, write_data = 0x%08x", + tb_address, tb_read_data, tb_write_data); $display(""); + $display("State:"); + $display("ready_reg = 0x%01x, start_reg = 0x%01x, start_new = 0x%01x, start_we = 0x%01x", + dut.ready_reg, dut.start_reg, dut.start_new, dut.start_we); + $display("residue_valid = 0x%01x", dut.residue_valid_reg); + $display("loop_counter_reg = 0x%08x", dut.loop_counter_reg); + $display("exponent_length_reg = 0x%02x, modulus_length_reg = 0x%02x", + dut.exponent_length_reg, dut.modulus_length_reg); + $display("length_reg = 0x%02x, length_m1_reg = 0x%02x", + dut.length_reg, dut.length_m1_reg); + $display("ctrl_reg = 0x%04x", dut.modexp_ctrl_reg); + $display(""); end endtask // dump_dut_state @@ -206,17 +264,42 @@ module tb_modexp(); endtask // init_sim + //---------------------------------------------------------------- + // read_word() + // + // Read a data word from the given address in the DUT. + // the word read will be available in the global variable + // read_data. + //---------------------------------------------------------------- + task read_word(input [11 : 0] address); + begin + tb_address = address; + tb_cs = 1; + tb_we = 0; + #(CLK_PERIOD); + read_data = tb_read_data; + tb_cs = 0; + + if (DEBUG) + begin + $display("*** (read_word) Reading 0x%08x from 0x%02x.", read_data, address); + $display(""); + end + end + endtask // read_word + + //---------------------------------------------------------------- // write_word() // // Write the given word to the DUT using the DUT interface. //---------------------------------------------------------------- - task write_word(input [11 : 0] address, + task write_word(input [11 : 0] address, input [31 : 0] word); begin if (DEBUG) begin - $display("*** Writing 0x%08x to 0x%02x.", word, address); + $display("*** (write_word) Writing 0x%08x to 0x%02x.", word, address); $display(""); end @@ -232,28 +315,359 @@ module tb_modexp(); //---------------------------------------------------------------- - // read_word() + // wait_ready() // - // Read a data word from the given address in the DUT. - // the word read will be available in the global variable - // read_data. + // Wait until the ready flag in the core is set. //---------------------------------------------------------------- - task read_word(input [11 : 0] address); + task wait_ready(); begin - tb_address = address; - tb_cs = 1; - tb_we = 0; - #(CLK_PERIOD); - read_data = tb_read_data; - tb_cs = 0; + while (tb_read_data != 32'h00000001) + read_word({GENERAL_PREFIX, ADDR_STATUS}); if (DEBUG) + $display("*** (wait_ready) Ready flag has been set."); + end + endtask // wait_ready + + + //---------------------------------------------------------------- + // dump_message_mem() + // + // Dump the contents of the message memory. + //---------------------------------------------------------------- + task dump_message_mem(); + reg [8 : 0] i; + begin + $display("Contents of the message memory:"); + for (i = 0 ; i < 256 ; i = i + 8) + begin + $display("message_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", + i[7 : 0], (i[7 : 0] + 8'h07), + dut.message_mem.mem[(i[7 : 0] + 0)], dut.message_mem.mem[(i[7 : 0] + 1)], + dut.message_mem.mem[(i[7 : 0] + 2)], dut.message_mem.mem[(i[7 : 0] + 3)], + dut.message_mem.mem[(i[7 : 0] + 4)], dut.message_mem.mem[(i[7 : 0] + 5)], + dut.message_mem.mem[(i[7 : 0] + 6)], dut.message_mem.mem[(i[7 : 0] + 7)], + ); + end + $display(""); + end + endtask // dump_message_mem + + + //---------------------------------------------------------------- + // dump_exponent_mem() + // + // Dump the contents of the exponent memory. + //---------------------------------------------------------------- + task dump_exponent_mem(); + reg [8 : 0] i; + begin + $display("Contents of the exponent memory:"); + for (i = 0 ; i < 256 ; i = i + 8) + begin + $display("exponent_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", + i[7 : 0], (i[7 : 0] + 8'h07), + dut.exponent_mem.mem[(i[7 : 0] + 0)], dut.exponent_mem.mem[(i[7 : 0] + 1)], + dut.exponent_mem.mem[(i[7 : 0] + 2)], dut.exponent_mem.mem[(i[7 : 0] + 3)], + dut.exponent_mem.mem[(i[7 : 0] + 4)], dut.exponent_mem.mem[(i[7 : 0] + 5)], + dut.exponent_mem.mem[(i[7 : 0] + 6)], dut.exponent_mem.mem[(i[7 : 0] + 7)], + ); + end + $display(""); + end + endtask // dump_exponent_mem + + + //---------------------------------------------------------------- + // dump_modulus_mem() + // + // Dump the contents of the modulus memory. + //---------------------------------------------------------------- + task dump_modulus_mem(); + reg [8 : 0] i; + begin + $display("Contents of the modulus memory:"); + for (i = 0 ; i < 256 ; i = i + 8) + begin + $display("modulus_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", + i[7 : 0], (i[7 : 0] + 8'h07), + dut.modulus_mem.mem[(i[7 : 0] + 0)], dut.modulus_mem.mem[(i[7 : 0] + 1)], + dut.modulus_mem.mem[(i[7 : 0] + 2)], dut.modulus_mem.mem[(i[7 : 0] + 3)], + dut.modulus_mem.mem[(i[7 : 0] + 4)], dut.modulus_mem.mem[(i[7 : 0] + 5)], + dut.modulus_mem.mem[(i[7 : 0] + 6)], dut.modulus_mem.mem[(i[7 : 0] + 7)], + ); + end + $display(""); + end + endtask // dump_modulus_mem + + + //---------------------------------------------------------------- + // dump_residue_mem() + // + // Dump the contents of the residue memory. + //---------------------------------------------------------------- + task dump_residue_mem(); + reg [8 : 0] i; + begin + $display("Contents of the residue memory:"); + for (i = 0 ; i < 256 ; i = i + 8) + begin + $display("residue_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", + i[7 : 0], (i[7 : 0] + 8'h07), + dut.residue_mem.mem[(i[7 : 0] + 0)], dut.residue_mem.mem[(i[7 : 0] + 1)], + dut.residue_mem.mem[(i[7 : 0] + 2)], dut.residue_mem.mem[(i[7 : 0] + 3)], + dut.residue_mem.mem[(i[7 : 0] + 4)], dut.residue_mem.mem[(i[7 : 0] + 5)], + dut.residue_mem.mem[(i[7 : 0] + 6)], dut.residue_mem.mem[(i[7 : 0] + 7)], + ); + end + $display(""); + end + endtask // dump_residue_mem + + + //---------------------------------------------------------------- + // dump_result_mem() + // + // Dump the contents of the result memory. + //---------------------------------------------------------------- + task dump_result_mem(); + reg [8 : 0] i; + begin + $display("Contents of the result memory:"); + for (i = 0 ; i < 256 ; i = i + 8) begin - $display("*** Reading 0x%08x from 0x%02x.", read_data, address); + $display("result_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", + i[7 : 0], (i[7 : 0] + 8'h07), + dut.result_mem.mem[(i[7 : 0] + 0)], dut.result_mem.mem[(i[7 : 0] + 1)], + dut.result_mem.mem[(i[7 : 0] + 2)], dut.result_mem.mem[(i[7 : 0] + 3)], + dut.result_mem.mem[(i[7 : 0] + 4)], dut.result_mem.mem[(i[7 : 0] + 5)], + dut.result_mem.mem[(i[7 : 0] + 6)], dut.result_mem.mem[(i[7 : 0] + 7)], + ); + end + $display(""); + end + endtask // dump_result_mem + + + //---------------------------------------------------------------- + // dump_memories() + // + // Dump the contents of the memories in the dut. + //---------------------------------------------------------------- + task dump_memories(); + begin + dump_message_mem(); + dump_exponent_mem(); + dump_modulus_mem(); + dump_residue_mem(); + dump_result_mem(); + end + endtask // dump_memories + + + //---------------------------------------------------------------- + // tc1 + // + // A first, very simple testcase where we want to do: + // c = m ** e % N with the following (decimal) test values: + // m = 3 + // e = 7 + // n = 11 + // c = 3 ** 7 % 11 = 9 + //---------------------------------------------------------------- + task tc1(); + reg [31 : 0] read_data; + + begin + tc_ctr = tc_ctr + 1; + $display("TC1: Trying to calculate 3**7 mod 11 = 9"); + + // Write 3 to message memory. + write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000003); + + // Write 7 to exponent memory and set length to one word. + write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000007); + write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001); + + // Write 11 to modulus memory and set length to one word. + write_word({MODULUS_PREFIX, 8'h00}, 32'h0000000b); + write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001); + + // Start processing and wait for ready. + write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001); + wait_ready(); + + // Read out result word and check result. + read_word({RESULT_PREFIX, 8'h00}); + read_data = tb_read_data; + + if (read_data == 32'h00000009) + begin + $display("*** TC1 successful."); $display(""); end + else + begin + $display("*** ERROR: TC1 NOT successful."); + $display("Expected: 0x09, got 0x%08x", read_data); + error_ctr = error_ctr + 1; + dump_memories(); + end end - endtask // read_word + endtask // tc1 + + + //---------------------------------------------------------------- + // tc2 + // + // c = m ** e % N with the following (decimal) test values: + // m = 251 + // e = 251 + // n = 257 + // c = 251 ** 251 % 257 = 183 + //---------------------------------------------------------------- + task tc2(); + reg [31 : 0] read_data; + + begin + tc_ctr = tc_ctr + 1; + $display("TC2: Trying to calculate 251**251 mod 257 = 183"); + + // Write 13 to (m)esaage memory. + write_word({MESSAGE_PREFIX, 8'h00}, 32'h000000fb); + + // Write 11 to exponent memory and set length to one word. + write_word({EXPONENT_PREFIX, 8'h00}, 32'h000000fb); + write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001); + + // Write 7 to modulus memory and set length to one word. + write_word({MODULUS_PREFIX, 8'h00}, 32'h00000101); + write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001); + + // Start processing and wait for ready. + write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001); + wait_ready(); + + // Read out result word and check result. + read_word({RESULT_PREFIX, 8'h00}); + read_data = tb_read_data; + + if (read_data == 32'h000000b7) + begin + $display("*** TC2 successful."); + $display(""); + end + else + begin + $display("*** ERROR: TC2 NOT successful."); + $display("Expected: 0x06, got 0x%08x", read_data); + error_ctr = error_ctr + 1; + end + end + endtask // tc2 + + + //---------------------------------------------------------------- + // tc3 + // + // c = m ** e % N with the following (decimal) test values: + // m = 0x81 + // e = 0x41 + // n = 0x87 + // c = 0x81 ** 0x41 % 0x87 = 0x36 + //---------------------------------------------------------------- + task tc3(); + reg [31 : 0] read_data; + + begin + tc_ctr = tc_ctr + 1; + $display("TC3: Trying to calculate 0x81 ** 0x41 mod 0x87 = 0x36"); + + write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000081); + + // Write 11 to exponent memory and set length to one word. + write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000041); + write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001); + + // Write 7 to modulus memory and set length to one word. + write_word({MODULUS_PREFIX, 8'h00}, 32'h00000087); + write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001); + + // Start processing and wait for ready. + write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001); + wait_ready(); + + // Read out result word and check result. + read_word({RESULT_PREFIX, 8'h00}); + read_data = tb_read_data; + + if (read_data == 32'h00000036) + begin + $display("*** TC3 successful."); + $display(""); + end + else + begin + $display("*** ERROR: TC3 NOT successful."); + $display("Expected: 0x06, got 0x%08x", read_data); + error_ctr = error_ctr + 1; + end + end + endtask // tc3 + + function assertEquals( + input [31:0] expected, + input [31:0] actual + ); + begin + if (expected === actual) + begin + assertEquals = 1; // success + end + else + begin + $display("Expected: 0x%08x, got 0x%08x", expected, actual); + assertEquals = 0; // failure + end + end + endfunction // assertEquals + + integer success; + + task autogenerated_BASIC_M4962768465676381896(); + reg [31 : 0] read_data; + begin + success = 32'h1; + tc_ctr = tc_ctr + 1; + $display("autogenerated_BASIC_M4962768465676381896: 00000001946473e1 ** h000000010e85e74f mod 0000000170754797 "); + + write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001); //TEMPLATE_MESSAGE_VALES + write_word({MESSAGE_PREFIX, 8'h01}, 32'h946473e1); //TEMPLATE_MESSAGE_VALES + write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001); //TEMPLATE_EXPONENT_VALES + write_word({EXPONENT_PREFIX, 8'h01}, 32'h0e85e74f); //TEMPLATE_EXPONENT_VALES + write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001); //TEMPLATE_MODULUS_VALUES + write_word({MODULUS_PREFIX, 8'h01}, 32'h70754797); //TEMPLATE_MODULUS_VALUES + + write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002); //TEMPLATE_MESSAGE_LENGTH + write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002); //TEMPLATE_MODULUS_LENGTH + + // Start processing and wait for ready. + write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001); + wait_ready(); + + read_word({RESULT_PREFIX, 8'h00}); read_data = tb_read_data; success = success & assertEquals(32'h00000000, read_data); //TEMPLATE_EXPECTED_VALUES + read_word({RESULT_PREFIX, 8'h01}); read_data = tb_read_data; success = success & assertEquals(32'h7761ed4f, read_data); //TEMPLATE_EXPECTED_VALUES + + if (success !== 1) + begin + $display("*** ERROR: autogenerated_BASIC_M4962768465676381896 was NOT successful."); + error_ctr = error_ctr + 1; + end + else + $display("*** autogenerated_BASIC_M4962768465676381896 success."); + end + endtask // autogenerated_BASIC_M4962768465676381896 //---------------------------------------------------------------- @@ -273,7 +687,13 @@ module tb_modexp(); reset_dut(); dump_dut_state(); + tc1(); + tc2(); + tc3(); + autogenerated_BASIC_M4962768465676381896(); // add a broken random test for debugging + display_test_results(); +// dump_memories(); $display(""); $display("*** modexp simulation done. ***"); -- cgit v1.2.3