aboutsummaryrefslogtreecommitdiff
path: root/src/tb/tb_modexp.v
diff options
context:
space:
mode:
authorJoachim StroĢˆmbergson <joachim@secworks.se>2015-04-27 11:17:08 +0200
committerJoachim StroĢˆmbergson <joachim@secworks.se>2015-04-27 11:17:08 +0200
commita315223f98fa6f1fdea2b1080c5f3e33352ebb13 (patch)
tree0fb3f6c458df78f58017e9475ff3b0c5cb3b52d0 /src/tb/tb_modexp.v
parent502f0f429a261628fe5e43582280012541c40804 (diff)
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.
Diffstat (limited to 'src/tb/tb_modexp.v')
-rw-r--r--src/tb/tb_modexp.v466
1 files changed, 443 insertions, 23 deletions
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
@@ -207,16 +265,41 @@ module tb_modexp();
//----------------------------------------------------------------
+ // 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. ***");