diff options
author | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2018-12-19 15:34:55 +0300 |
---|---|---|
committer | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2018-12-19 15:41:00 +0300 |
commit | c617c0c711620f58eb3ead22edcdfe57fed06088 (patch) | |
tree | 8c15184d5ca6403ea01843560394f6d909a0986f /bench | |
parent | ea4d251c81c8b53e0bbc71cd1719dfea4d0517c1 (diff) |
core for better timing performance
* Removed custom modular inversion sub-module, now uses micro-coded modular
inversion routine based on Fermat's little theorem (~10% faster)
* Uses math primitives from core/lib
* Added randomized test vector
(see user/shatov/ecdsa_fpga_model/test_vectors/)
Diffstat (limited to 'bench')
-rw-r--r-- | bench/ecdsa256_test_vector_nsa.vh | 26 | ||||
-rw-r--r-- | bench/ecdsa_test_vector_randomized.vh | 29 | ||||
-rw-r--r-- | bench/tb_curve_adder_256.v | 420 | ||||
-rw-r--r-- | bench/tb_curve_doubler_256.v | 409 | ||||
-rw-r--r-- | bench/tb_curve_multiplier_256.v | 525 | ||||
-rw-r--r-- | bench/tb_lowlevel_adder32.v | 175 | ||||
-rw-r--r-- | bench/tb_lowlevel_adder47.v | 151 | ||||
-rw-r--r-- | bench/tb_lowlevel_subtractor32.v | 174 | ||||
-rw-r--r-- | bench/tb_modular_adder.v | 357 | ||||
-rw-r--r-- | bench/tb_modular_invertor.v | 225 | ||||
-rw-r--r-- | bench/tb_modular_multiplier_256.v | 366 | ||||
-rw-r--r-- | bench/tb_modular_subtractor.v | 356 | ||||
-rw-r--r-- | bench/tb_mw_comparator.v | 322 | ||||
-rw-r--r-- | bench/tb_mw_mover.v | 282 |
14 files changed, 322 insertions, 3495 deletions
diff --git a/bench/ecdsa256_test_vector_nsa.vh b/bench/ecdsa256_test_vector_nsa.vh new file mode 100644 index 0000000..e62b657 --- /dev/null +++ b/bench/ecdsa256_test_vector_nsa.vh @@ -0,0 +1,26 @@ +/* Values from "Suite B Implementer's Guide to FIPS 186-3 (ECDSA)" */ + +localparam [255:0] ECDSA_P256_D_NSA = + {32'h70a12c2d, 32'hb16845ed, 32'h56ff68cf, 32'hc21a472b, + 32'h3f04d7d6, 32'h851bf634, 32'h9f2d7d5b, 32'h3452b38a}; + +localparam [255:0] ECDSA_P256_QX_NSA = + {32'h8101ece4, 32'h7464a6ea, 32'hd70cf69a, 32'h6e2bd3d8, + 32'h8691a326, 32'h2d22cba4, 32'hf7635eaf, 32'hf26680a8}; + +localparam [255:0] ECDSA_P256_QY_NSA = + {32'hd8a12ba6, 32'h1d599235, 32'hf67d9cb4, 32'hd58f1783, + 32'hd3ca43e7, 32'h8f0a5aba, 32'ha6240799, 32'h36c0c3a9}; + +localparam [255:0] ECDSA_P256_K_NSA = + {32'h580ec00d, 32'h85643433, 32'h4cef3f71, 32'hecaed496, + 32'h5b12ae37, 32'hfa47055b, 32'h1965c7b1, 32'h34ee45d0}; + +localparam [255:0] ECDSA_P256_RX_NSA = + {32'h7214bc96, 32'h47160bbd, 32'h39ff2f80, 32'h533f5dc6, + 32'hddd70ddf, 32'h86bb8156, 32'h61e805d5, 32'hd4e6f27c}; + +localparam [255:0] ECDSA_P256_RY_NSA = + {32'h8b81e3e9, 32'h77597110, 32'hc7cf2633, 32'h435b2294, + 32'hb7264298, 32'h7defd3d4, 32'h007e1cfc, 32'h5df84541}; + diff --git a/bench/ecdsa_test_vector_randomized.vh b/bench/ecdsa_test_vector_randomized.vh new file mode 100644 index 0000000..6c5cf80 --- /dev/null +++ b/bench/ecdsa_test_vector_randomized.vh @@ -0,0 +1,29 @@ +/* Generated automatically, do not edit. */ + +localparam [255:0] ECDSA_P256_D_RANDOM = + {32'h503e58af, 32'hcf3af333, 32'h7bf53409, 32'h445012b8, + 32'h1fb4548c, 32'h4d2b1302, 32'ha617f9b1, 32'hd00d7de0}; + +localparam [255:0] ECDSA_P256_QX_RANDOM = + {32'hd9349b48, 32'hb0ee8c36, 32'h139b1d78, 32'hedc1911b, + 32'h250877fb, 32'h7ad44ae1, 32'h8bb2f8a6, 32'hf4dccae5}; + +localparam [255:0] ECDSA_P256_QY_RANDOM = + {32'he0a056e8, 32'hb5092a6c, 32'h728f4bc8, 32'h9043fbe2, + 32'h7c262744, 32'hdfbdaf17, 32'h83fc2e01, 32'hb060771b}; + +localparam [383:0] ECDSA_P384_D_RANDOM = + {32'hbb4a09d8, 32'he527f062, 32'h665eb4d0, 32'hb39a1dce, + 32'h94daa2c5, 32'h935b3163, 32'hb090f079, 32'h3ee36a5a, + 32'h62a7055d, 32'h5d850d1b, 32'h15dc656d, 32'h65d8b3a2}; + +localparam [383:0] ECDSA_P384_QX_RANDOM = + {32'hb8023e60, 32'hae42ea14, 32'h6330f2c3, 32'h883096ca, + 32'h961b11f5, 32'hdfea4a1d, 32'h65e98e64, 32'hb33527fb, + 32'h57226db4, 32'h8a514325, 32'h1ef06bde, 32'hf78eb57a}; + +localparam [383:0] ECDSA_P384_QY_RANDOM = + {32'hd3c66469, 32'h625aaaad, 32'ha347e103, 32'h3c1474b6, + 32'h343a9368, 32'hff294501, 32'hbbd53b1c, 32'hc49fd972, + 32'hda439c9d, 32'ha827e230, 32'h2720e2b7, 32'h8dd14f9e}; + diff --git a/bench/tb_curve_adder_256.v b/bench/tb_curve_adder_256.v deleted file mode 100644 index c9b50ce..0000000 --- a/bench/tb_curve_adder_256.v +++ /dev/null @@ -1,420 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_curve_adder_256.v -// ----------------------------------------------------------------------------- -// Testbench for 256-bit curve point adder. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2016, 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. -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_curve_adder_256; - - - // - // Test Vectors - // - localparam [255:0] PX_1 = 256'ha536512112e4bb911ae72744a914761ddc53700f889c88e583e0edd45c179b08; - localparam [255:0] PY_1 = 256'h239e73bf40f4831ab71ccea072291893ac8582982ea6fec6bd6aaf36ac32d22e; - localparam [255:0] PZ_1 = 256'h32258ae04c5498bb34b29c54a7f95afc10c009540c51731eae164750ca385029; - - localparam [255:0] RX_1 = 256'he4fcdd1a151b405b2a567d20d7674031c6d5b207b0b5dcf277015d81784492d5; - localparam [255:0] RY_1 = 256'h4782c540b58988b07bb8e0c5ad3ff562dd45c075a39ee71896d5eb33702dd656; - localparam [255:0] RZ_1 = 256'hae637ff2fd5468780241afb3a8ebaeb8618e86b4a1a211b350546c9e6fea93d4; - - localparam [255:0] PX_2 = 256'he58a6470e038f6b261d5a9a72fb2bd96b6bad433ff7baea6a40b5facf5085189; - localparam [255:0] PY_2 = 256'h03dd8785b592307811ee5512e2d713c5dc65f60f01883340fe0f56f858a39474; - localparam [255:0] PZ_2 = 256'h1b4657b1e79c9074fbf7f63f96ce2854db4808afc72841fac623dc68d9bff64d; - - localparam [255:0] RX_2 = 256'hc354e99a827a3f1c30f29f6b1d72273eb0daaeb06bb373ed315e305b89d857ca; - localparam [255:0] RY_2 = 256'h0cb054f95589c1fcbe763df3b8d7badd568d5e93a667076dddfc70dcfab74948; - localparam [255:0] RZ_2 = 256'hd79d9170dd628aee82d149715a6ec6cc44426ccae236d2a146edbd15a564ea53; - - localparam [255:0] PX_3 = 256'hbf5fe30c79025a0b638b0fd62bf1349aee0a9fc7fc2719291b0c23535c16eb52; - localparam [255:0] PY_3 = 256'h8a637c7c0b9459de664d40a717e1abc0f843f03169fae943e0835cbe767da06b; - localparam [255:0] PZ_3 = 256'h0871d93601d654216912866514a788a92e8a9b6047611bf185d459e204727377; - - localparam [255:0] RX_3 = 256'h1ba6259b5b750e4d6e4f490f661646cd9491be16965f47044ac2688048e567c5; - localparam [255:0] RY_3 = 256'h80e55c16f403f8d7282bca628477771a45330567caa5aaab9a54919dbe05e3e4; - localparam [255:0] RZ_3 = 256'hb99663f045c9602b05f23aaaa508e6167d15740be900175dbeceb957a9dad951; - - localparam [255:0] PX_4 = 256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; - localparam [255:0] PY_4 = 256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; - localparam [255:0] PZ_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - - localparam [255:0] RX_4 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; // G.x - localparam [255:0] RY_4 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; // G.y - localparam [255:0] RZ_4 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - - localparam [255:0] PX_5 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; // G.x - localparam [255:0] PY_5 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; // G.y - localparam [255:0] PZ_5 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - - localparam [255:0] RX_5 = 256'h29d05c193da77b710e86323538b77e1b11f904fea42998be16bd8d744ece7ad0; // H.x - localparam [255:0] RY_5 = 256'hb01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae07; // H.y - localparam [255:0] RZ_5 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - - localparam [255:0] PX_6 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; // G.x - localparam [255:0] PY_6 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; // G.y - localparam [255:0] PZ_6 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - - localparam [255:0] RX_6 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - localparam [255:0] RY_6 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - localparam [255:0] RZ_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - - localparam [255:0] Q = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (PX, PY, PZ, RX, RY, RZ, Q) - // - wire [WORD_COUNTER_WIDTH-1:0] core_px_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_py_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_pz_addr; - - wire [WORD_COUNTER_WIDTH-1:0] core_rx_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_ry_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_rz_addr; - - wire [WORD_COUNTER_WIDTH-1:0] core_q_addr; - - wire core_rx_wren; - wire core_ry_wren; - wire core_rz_wren; - - wire [ 32-1:0] core_px_data; - wire [ 32-1:0] core_py_data; - wire [ 32-1:0] core_pz_data; - - wire [ 32-1:0] core_rx_data_wr; - wire [ 32-1:0] core_ry_data_wr; - wire [ 32-1:0] core_rz_data_wr; - - wire [ 32-1:0] core_rx_data_rd; - wire [ 32-1:0] core_ry_data_rd; - wire [ 32-1:0] core_rz_data_rd; - - wire [ 32-1:0] core_q_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_xyzq_addr; - reg tb_xyzq_wren; - - reg [ 31:0] tb_px_data; - reg [ 31:0] tb_py_data; - reg [ 31:0] tb_pz_data; - wire [ 31:0] tb_rx_data; - wire [ 31:0] tb_ry_data; - wire [ 31:0] tb_rz_data; - reg [ 31:0] tb_q_data; - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_px - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_px_data), .a_out(), - .b_addr(core_px_addr), .b_out(core_px_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_py - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_py_data), .a_out(), - .b_addr(core_py_addr), .b_out(core_py_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_pz - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_pz_data), .a_out(), - .b_addr(core_pz_addr), .b_out(core_pz_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_q - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_q_data), .a_out(), - .b_addr(core_q_addr), .b_out(core_q_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_rx - ( .clk(clk), - .a_addr(core_rx_addr), .a_wr(core_rx_wren), .a_in(core_rx_data_wr), .a_out(core_rx_data_rd), - .b_addr(tb_xyzq_addr), .b_out(tb_rx_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_ry - ( .clk(clk), - .a_addr(core_ry_addr), .a_wr(core_ry_wren), .a_in(core_ry_data_wr), .a_out(core_ry_data_rd), - .b_addr(tb_xyzq_addr), .b_out(tb_ry_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_rz - ( .clk(clk), - .a_addr(core_rz_addr), .a_wr(core_rz_wren), .a_in(core_rz_data_wr), .a_out(core_rz_data_rd), - .b_addr(tb_xyzq_addr), .b_out(tb_rz_data) - ); - - - // - // Opcode - // - wire [ 5: 0] add_uop_addr; - wire [19: 0] add_uop; - - uop_add_rom add_rom - ( - .clk (clk), - .addr (add_uop_addr), - .data (add_uop) - ); - - // - // UUT - // - curve_dbl_add_256 uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .uop_addr (add_uop_addr), - .uop (add_uop), - - .px_addr (core_px_addr), - .py_addr (core_py_addr), - .pz_addr (core_pz_addr), - .rx_addr (core_rx_addr), - .ry_addr (core_ry_addr), - .rz_addr (core_rz_addr), - .q_addr (core_q_addr), - - .rx_wren (core_rx_wren), - .ry_wren (core_ry_wren), - .rz_wren (core_rz_wren), - - .px_din (core_px_data), - .py_din (core_py_data), - .pz_din (core_pz_data), - .rx_din (core_rx_data_rd), - .ry_din (core_ry_data_rd), - .rz_din (core_rz_data_rd), - .rx_dout (core_rx_data_wr), - .ry_dout (core_ry_data_wr), - .rz_dout (core_rz_data_wr), - .q_din (core_q_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_curve_adder(PX_1, PY_1, PZ_1, RX_1, RY_1, RZ_1); - test_curve_adder(PX_2, PY_2, PZ_2, RX_2, RY_2, RZ_2); - test_curve_adder(PX_3, PY_3, PZ_3, RX_3, RY_3, RZ_3); - test_curve_adder(PX_4, PY_4, PZ_4, RX_4, RY_4, RZ_4); - test_curve_adder(PX_5, PY_5, PZ_5, RX_5, RY_5, RZ_5); - test_curve_adder(PX_6, Q - PY_6, PZ_6, RX_6, RY_6, RZ_6); - - /* print result */ - if (ok) $display("tb_curve_adder_256: SUCCESS"); - else $display("tb_curve_adder_256: FAILURE"); - // - $finish; - // - end - - - // - // Test Task - // - reg t_ok; - - integer w; - - task test_curve_adder; - - input [255:0] px; - input [255:0] py; - input [255:0] pz; - - input [255:0] rx; - input [255:0] ry; - input [255:0] rz; - - reg [255:0] px_shreg; - reg [255:0] py_shreg; - reg [255:0] pz_shreg; - - reg [255:0] rx_shreg; - reg [255:0] ry_shreg; - reg [255:0] rz_shreg; - - reg [255:0] q_shreg; - - begin - - /* start filling memories */ - tb_xyzq_wren = 1; - - /* initialize shift registers */ - px_shreg = px; - py_shreg = py; - pz_shreg = pz; - q_shreg = Q; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_px_data = px_shreg[31:0]; - tb_py_data = py_shreg[31:0]; - tb_pz_data = pz_shreg[31:0]; - tb_q_data = q_shreg[31:0]; - - /* shift inputs */ - px_shreg = {{32{1'bX}}, px_shreg[255:32]}; - py_shreg = {{32{1'bX}}, py_shreg[255:32]}; - pz_shreg = {{32{1'bX}}, pz_shreg[255:32]}; - q_shreg = {{32{1'bX}}, q_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_xyzq_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_px_data = {32{1'bX}}; - tb_py_data = {32{1'bX}}; - tb_pz_data = {32{1'bX}}; - tb_q_data = {32{1'bX}}; - - /* stop filling memories */ - tb_xyzq_wren = 0; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set address */ - tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - rx_shreg = {tb_rx_data, rx_shreg[255:32]}; - ry_shreg = {tb_ry_data, ry_shreg[255:32]}; - rz_shreg = {tb_rz_data, rz_shreg[255:32]}; - - end - - /* compare */ - t_ok = (rx_shreg == rx) && - (ry_shreg == ry) && - (rz_shreg == rz); - - /* display results */ - $display("test_curve_adder(): %s", t_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && t_ok; - - end - - endtask - -endmodule - - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_curve_doubler_256.v b/bench/tb_curve_doubler_256.v deleted file mode 100644 index c7a1c0f..0000000 --- a/bench/tb_curve_doubler_256.v +++ /dev/null @@ -1,409 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_curve_doubler_256.v -// ----------------------------------------------------------------------------- -// Testbench for 256-bit curve point doubler. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2016, 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. -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_curve_doubler_256; - - - // - // Test Vectors - // - localparam [255:0] PX_1 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; - localparam [255:0] PY_1 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; - localparam [255:0] PZ_1 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - - localparam [255:0] RX_1 = 256'h9a978f59acd1b5ad570e7d52dcfcde43804b42274f61ddcf1e7d848391d6c70f; - localparam [255:0] RY_1 = 256'h4126885e7f786af905338238e5346d5fe77fc46388668bd0fd59be3190d2f5d1; - localparam [255:0] RZ_1 = 256'h9fc685c5fc34ff371dcfd694f81f3c2c579c66aed662bd9d976c80d06f7ea3ea; - - localparam [255:0] PX_2 = 256'h0ec88440c8b00a9e572bf1bceb7d0c5906bd65990a9b7081130bd72e2c136ca0; - localparam [255:0] PY_2 = 256'hc0bc77e1339e899101f8e8eccf79c3f7f4bbdd1bf96f6446199bd423026a60d6; - localparam [255:0] PZ_2 = 256'hdd27cb52a31d1f6e041accf1103de05ba0a5edd74b738d51fe3397de0e3fc306; - - localparam [255:0] RX_2 = 256'he6afae63e774df21244609cb4c35d17d28b36b8b9fb7c58929af247f34ac72f9; - localparam [255:0] RY_2 = 256'h061076db7a5745adc90b2e9eebe0ad6482309690f50b60835c265cf83a1b34eb; - localparam [255:0] RZ_2 = 256'h1b6bfd04f2a41d68e85423655db1142d97ebaec0c67c450408f427e35c4f054f; - - localparam [255:0] PX_3 = 256'hb0f824c88ec62df89912ca9ffbcbbb4ffb4d80f8a7d7b4a992273261a2f7be7f; - localparam [255:0] PY_3 = 256'h403e34c78c2b816fce2b1f8d73cfeef28113b8de8bda4a447d17b619bef73705; - localparam [255:0] PZ_3 = 256'h0e3e81bb8e954f3164ae54a6cffa7fcc9631dfddee55fac61e46415f1f5fe5e2; - - localparam [255:0] RX_3 = 256'hd4e725920c88cc2f57847a315f3b6c180abb278b8fa2a47da3d1a191a8c29e19; - localparam [255:0] RY_3 = 256'ha798ad8dbd66c98b53414ab1d04b0f871929a90fea996c88b96d9d68eb8eb0dc; - localparam [255:0] RZ_3 = 256'ha7ead72c01294eaf2899bb6b84f7d26417e6758e3db29f3b5c2ca8e9911067f5; - - localparam [255:0] PX_4 = 256'hXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; - localparam [255:0] PY_4 = 256'hXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; - localparam [255:0] PZ_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - - localparam [255:0] RX_4 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - localparam [255:0] RY_4 = 256'h0000000000000000000000000000000000000000000000000000000000000001; - localparam [255:0] RZ_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - - localparam [255:0] Q = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; - - - - // - // TODO: Test special cases! - // - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (PX, PY, PZ, RX, RY, RZ, Q) - // - wire [WORD_COUNTER_WIDTH-1:0] core_px_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_py_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_pz_addr; - - wire [WORD_COUNTER_WIDTH-1:0] core_rx_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_ry_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_rz_addr; - - wire [WORD_COUNTER_WIDTH-1:0] core_q_addr; - - wire core_rx_wren; - wire core_ry_wren; - wire core_rz_wren; - - wire [ 32-1:0] core_px_data; - wire [ 32-1:0] core_py_data; - wire [ 32-1:0] core_pz_data; - - wire [ 32-1:0] core_rx_data_wr; - wire [ 32-1:0] core_ry_data_wr; - wire [ 32-1:0] core_rz_data_wr; - - wire [ 32-1:0] core_rx_data_rd; - wire [ 32-1:0] core_ry_data_rd; - wire [ 32-1:0] core_rz_data_rd; - - wire [ 32-1:0] core_q_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_xyzq_addr; - reg tb_xyzq_wren; - - reg [ 31:0] tb_px_data; - reg [ 31:0] tb_py_data; - reg [ 31:0] tb_pz_data; - wire [ 31:0] tb_rx_data; - wire [ 31:0] tb_ry_data; - wire [ 31:0] tb_rz_data; - reg [ 31:0] tb_q_data; - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_px - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_px_data), .a_out(), - .b_addr(core_px_addr), .b_out(core_px_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_py - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_py_data), .a_out(), - .b_addr(core_py_addr), .b_out(core_py_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_pz - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_pz_data), .a_out(), - .b_addr(core_pz_addr), .b_out(core_pz_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_q - ( .clk(clk), - .a_addr(tb_xyzq_addr), .a_wr(tb_xyzq_wren), .a_in(tb_q_data), .a_out(), - .b_addr(core_q_addr), .b_out(core_q_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_rx - ( .clk(clk), - .a_addr(core_rx_addr), .a_wr(core_rx_wren), .a_in(core_rx_data_wr), .a_out(core_rx_data_rd), - .b_addr(tb_xyzq_addr), .b_out(tb_rx_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_ry - ( .clk(clk), - .a_addr(core_ry_addr), .a_wr(core_ry_wren), .a_in(core_ry_data_wr), .a_out(core_ry_data_rd), - .b_addr(tb_xyzq_addr), .b_out(tb_ry_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_rz - ( .clk(clk), - .a_addr(core_rz_addr), .a_wr(core_rz_wren), .a_in(core_rz_data_wr), .a_out(core_rz_data_rd), - .b_addr(tb_xyzq_addr), .b_out(tb_rz_data) - ); - - - // - // Opcode - // - wire [ 5: 0] dbl_uop_addr; - wire [19: 0] dbl_uop; - - uop_dbl_rom dbl_rom - ( - .clk (clk), - .addr (dbl_uop_addr), - .data (dbl_uop) - ); - - - // - // UUT - // - curve_dbl_add_256 uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .uop_addr (dbl_uop_addr), - .uop (dbl_uop), - - .px_addr (core_px_addr), - .py_addr (core_py_addr), - .pz_addr (core_pz_addr), - .rx_addr (core_rx_addr), - .ry_addr (core_ry_addr), - .rz_addr (core_rz_addr), - .q_addr (core_q_addr), - - .rx_wren (core_rx_wren), - .ry_wren (core_ry_wren), - .rz_wren (core_rz_wren), - - .px_din (core_px_data), - .py_din (core_py_data), - .pz_din (core_pz_data), - .rx_din (core_rx_data_rd), - .ry_din (core_ry_data_rd), - .rz_din (core_rz_data_rd), - .rx_dout (core_rx_data_wr), - .ry_dout (core_ry_data_wr), - .rz_dout (core_rz_data_wr), - .q_din (core_q_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_curve_doubler(PX_1, PY_1, PZ_1, RX_1, RY_1, RZ_1); - test_curve_doubler(PX_2, PY_2, PZ_2, RX_2, RY_2, RZ_2); - test_curve_doubler(PX_3, PY_3, PZ_3, RX_3, RY_3, RZ_3); - test_curve_doubler(PX_4, PY_4, PZ_4, RX_4, RY_4, RZ_4); - - /* print result */ - if (ok) $display("tb_curve_doubler_256: SUCCESS"); - else $display("tb_curve_doubler_256: FAILURE"); - // - // $finish; - // - end - - - // - // Test Task - // - reg t_ok; - - integer w; - - task test_curve_doubler; - - input [255:0] px; - input [255:0] py; - input [255:0] pz; - - input [255:0] rx; - input [255:0] ry; - input [255:0] rz; - - reg [255:0] px_shreg; - reg [255:0] py_shreg; - reg [255:0] pz_shreg; - - reg [255:0] rx_shreg; - reg [255:0] ry_shreg; - reg [255:0] rz_shreg; - - reg [255:0] q_shreg; - - begin - - /* start filling memories */ - tb_xyzq_wren = 1; - - /* initialize shift registers */ - px_shreg = px; - py_shreg = py; - pz_shreg = pz; - q_shreg = Q; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_px_data = px_shreg[31:0]; - tb_py_data = py_shreg[31:0]; - tb_pz_data = pz_shreg[31:0]; - tb_q_data = q_shreg[31:0]; - - /* shift inputs */ - px_shreg = {{32{1'bX}}, px_shreg[255:32]}; - py_shreg = {{32{1'bX}}, py_shreg[255:32]}; - pz_shreg = {{32{1'bX}}, pz_shreg[255:32]}; - q_shreg = {{32{1'bX}}, q_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_xyzq_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_px_data = {32{1'bX}}; - tb_py_data = {32{1'bX}}; - tb_pz_data = {32{1'bX}}; - tb_q_data = {32{1'bX}}; - - /* stop filling memories */ - tb_xyzq_wren = 0; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set address */ - tb_xyzq_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - rx_shreg = {tb_rx_data, rx_shreg[255:32]}; - ry_shreg = {tb_ry_data, ry_shreg[255:32]}; - rz_shreg = {tb_rz_data, rz_shreg[255:32]}; - - end - - /* compare */ - t_ok = (rx_shreg == rx) && - (ry_shreg == ry) && - (rz_shreg == rz); - - /* display results */ - $display("test_curve_doubler(): %s", t_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && t_ok; - - end - - endtask - - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_curve_multiplier_256.v b/bench/tb_curve_multiplier_256.v index c7839e0..a2a6769 100644 --- a/bench/tb_curve_multiplier_256.v +++ b/bench/tb_curve_multiplier_256.v @@ -2,11 +2,11 @@ // // tb_curve_multiplier_256.v // ----------------------------------------------------------------------------- -// Testbench for 256-bit curve point scalar multiplier. +// Testbench for 256-bit curve base point scalar multiplier. // // Authors: Pavel Shatov // -// Copyright (c) 2016, NORDUnet A/S +// Copyright (c) 2016, 2018 NORDUnet A/S // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: @@ -36,265 +36,274 @@ // //------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - module tb_curve_multiplier_256; - // - // Test Vectors - // - - /* Q = d * G */ - localparam [255:0] K_1 = 256'h70a12c2db16845ed56ff68cfc21a472b3f04d7d6851bf6349f2d7d5b3452b38a; - localparam [255:0] PX_1 = 256'h8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8; - localparam [255:0] PY_1 = 256'hd8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9; - - /* R = k * G */ - localparam [255:0] K_2 = 256'h580ec00d856434334cef3f71ecaed4965b12ae37fa47055b1965c7b134ee45d0; - localparam [255:0] PX_2 = 256'h7214bc9647160bbd39ff2f80533f5dc6ddd70ddf86bb815661e805d5d4e6f27c; - localparam [255:0] PY_2 = 256'h8b81e3e977597110c7cf2633435b2294b72642987defd3d4007e1cfc5df84541; - - /* O = n * G */ - localparam [255:0] K_3 = 256'hffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551; - localparam [255:0] PX_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - localparam [255:0] PY_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - - /* H = 2 * G */ - localparam [255:0] K_4 = 256'h0000000000000000000000000000000000000000000000000000000000000002; - localparam [255:0] PX_4 = 256'h7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978; - localparam [255:0] PY_4 = 256'h07775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1; - - /* G = (n + 1) * G */ - localparam [255:0] K_5 = 256'hffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + 'd1; - localparam [255:0] PX_5 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; - localparam [255:0] PY_5 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; - - /* H = (n + 2) * G */ - localparam [255:0] K_6 = 256'hffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + 'd2; - localparam [255:0] PX_6 = 256'h7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978; - localparam [255:0] PY_6 = 256'h07775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1; - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (K, PX, PY) - // - wire [WORD_COUNTER_WIDTH-1:0] core_k_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_px_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_py_addr; - - wire core_px_wren; - wire core_py_wren; - - wire [ 32-1:0] core_k_data; - wire [ 32-1:0] core_px_data; - wire [ 32-1:0] core_py_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_k_addr; - reg [WORD_COUNTER_WIDTH-1:0] tb_pxy_addr; - - reg tb_k_wren; - - reg [ 31:0] tb_k_data; - wire [ 31:0] tb_px_data; - wire [ 31:0] tb_py_data; - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_k - ( .clk(clk), - .a_addr(tb_k_addr), .a_wr(tb_k_wren), .a_in(tb_k_data), .a_out(), - .b_addr(core_k_addr), .b_out(core_k_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_px - ( .clk(clk), - .a_addr(core_px_addr), .a_wr(core_px_wren), .a_in(core_px_data), .a_out(), - .b_addr(tb_pxy_addr), .b_out(tb_px_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_py - ( .clk(clk), - .a_addr(core_py_addr), .a_wr(core_py_wren), .a_in(core_py_data), .a_out(), - .b_addr(tb_pxy_addr), .b_out(tb_py_data) - ); - - - // - // UUT - // - curve_mul_256 uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .k_addr (core_k_addr), - .rx_addr (core_px_addr), - .ry_addr (core_py_addr), - - .rx_wren (core_px_wren), - .ry_wren (core_py_wren), - - .k_din (core_k_data), - - .rx_dout (core_px_data), - .ry_dout (core_py_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - //test_curve_multiplier(K_1, PX_1, PY_1); - //test_curve_multiplier(K_2, PX_2, PY_2); - //test_curve_multiplier(K_3, PX_3, PY_3); - //test_curve_multiplier(K_4, PX_4, PY_4); - //test_curve_multiplier(K_5, PX_5, PY_5); - test_curve_multiplier(K_6, PX_6, PY_6); - - /* 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; - - 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 - - /* start filling memories */ - tb_k_wren = 1; - - /* initialize shift registers */ - k_shreg = k; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_k_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_k_data = k_shreg[31:0]; - - /* shift inputs */ - k_shreg = {{32{1'bX}}, k_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_k_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_k_data = {32{1'bX}}; - - /* stop filling memories */ - tb_k_wren = 0; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set address */ - tb_pxy_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - px_shreg = {tb_px_data, px_shreg[255:32]}; - py_shreg = {tb_py_data, py_shreg[255:32]}; - - end - - /* compare */ - p_ok = (px_shreg == px) && - (py_shreg == py); - - /* display results */ - $display("test_curve_multiplier(): %s", p_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && p_ok; - - end - - endtask - + // + // 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; + + + // + // 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}; + + + // + // Clock (100 MHz) + // + reg clk = 1'b0; + always #5 clk = ~clk; + + + // + // Inputs, Outputs + // + reg rst_n; + reg ena; + wire rdy; + + + // + // Buffers (K, PX, PY) + // + wire [WORD_COUNTER_WIDTH-1:0] core_k_addr; + wire [WORD_COUNTER_WIDTH-1:0] core_pxy_addr; + + wire core_px_wren; + wire core_py_wren; + + wire [ 32-1:0] core_k_data; + wire [ 32-1:0] core_pxy_data; + + reg [WORD_COUNTER_WIDTH-1:0] tb_k_addr; + reg [WORD_COUNTER_WIDTH-1:0] tb_pxy_addr; + + reg tb_k_wren; + + reg [ 31:0] tb_k_data; + wire [ 31:0] tb_px_data; + wire [ 31:0] tb_py_data; + + bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) + bram_k + ( .clk(clk), + .a_addr(tb_k_addr), .a_wr(tb_k_wren), .a_in(tb_k_data), .a_out(), + .b_addr(core_k_addr), .b_out(core_k_data) + ); + + bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) + bram_px + ( .clk(clk), + .a_addr(core_pxy_addr), .a_wr(core_px_wren), .a_in(core_pxy_data), .a_out(), + .b_addr(tb_pxy_addr), .b_out(tb_px_data) + ); + + bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) + bram_py + ( .clk(clk), + .a_addr(core_pxy_addr), .a_wr(core_py_wren), .a_in(core_pxy_data), .a_out(), + .b_addr(tb_pxy_addr), .b_out(tb_py_data) + ); + + + // + // UUT + // + ecdsa256_base_point_multiplier uut + ( + .clk (clk), + .rst_n (rst_n), + + .ena (ena), + .rdy (rdy), + + .k_addr (core_k_addr), + .rxy_addr (core_pxy_addr), + + .rx_wren (core_px_wren), + .ry_wren (core_py_wren), + + .k_din (core_k_data), + + .rxy_dout (core_pxy_data) + ); + + + // + // Testbench Routine + // + reg ok = 1; + initial begin + + /* initialize control inputs */ + rst_n = 0; + ena = 0; + + /* wait for some time */ + #200; + + /* de-assert reset */ + rst_n = 1; + + /* wait for some time */ + #100; + + /* 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; + + 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 + + /* start filling memories */ + tb_k_wren = 1; + + /* initialize shift registers */ + k_shreg = k; + + /* write all the words */ + for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin + + /* set addresses */ + tb_k_addr = w[WORD_COUNTER_WIDTH-1:0]; + + /* set data words */ + tb_k_data = k_shreg[31:0]; + + /* shift inputs */ + k_shreg = {{32{1'bX}}, k_shreg[255:32]}; + + /* wait for 1 clock tick */ + #10; + + end + + /* wipe addresses */ + tb_k_addr = {WORD_COUNTER_WIDTH{1'bX}}; + + /* wipe data words */ + tb_k_data = {32{1'bX}}; + + /* stop filling memories */ + tb_k_wren = 0; + + /* start operation */ + ena = 1; + + /* clear flag */ + #10 ena = 0; + + /* wait for operation to complete */ + while (!rdy) #10; + + /* read result */ + for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin + + /* set address */ + tb_pxy_addr = w[WORD_COUNTER_WIDTH-1:0]; + + /* wait for 1 clock tick */ + #10; + + /* store data word */ + px_shreg = {tb_px_data, px_shreg[255:32]}; + py_shreg = {tb_py_data, py_shreg[255:32]}; + + end + + /* compare */ + p_ok = (px_shreg === px) && + (py_shreg === py); + + /* display results */ + if (p_ok) $display("test_curve_multiplier(): OK"); + else begin + $display("test_curve_multiplier(): ERROR"); + $display("ref_px == %x", px); + $display("calc_px == %x", px_shreg); + $display("ref_py == %x", py); + $display("calc_py == %x", py_shreg); + end + + /* update global flag */ + ok = ok && p_ok; + + end + + endtask + endmodule diff --git a/bench/tb_lowlevel_adder32.v b/bench/tb_lowlevel_adder32.v deleted file mode 100644 index 70fbb15..0000000 --- a/bench/tb_lowlevel_adder32.v +++ /dev/null @@ -1,175 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_lowlevel_adder32.v -// ----------------------------------------------------------------------------- -// Testbench for 32-bit adder. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2015-2016, 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. -// -//------------------------------------------------------------------------------ - - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - - -module tb_lowlevel_adder32; - - // - // Inputs - // - reg clk; - reg [31: 0] a; - reg [31: 0] b; - reg c_in; - - // - // Outputs - // - wire [31: 0] s; - wire c_out; - - // - // Test Vectors {a, b, c_in} - // - wire [64: 0] vec_0 = {32'h00000000, 32'h00000000, 1'b0}; // all zeroes, no carry - wire [64: 0] vec_1 = {32'h00000000, 32'h00000000, 1'b1}; // all zeroes with carry - wire [64: 0] vec_2 = {32'h00000000, 32'hFFFFFFFF, 1'b0}; // zeroes and ones, no carry - wire [64: 0] vec_3 = {32'h00000000, 32'hFFFFFFFF, 1'b1}; // zeroes and ones with carry - wire [64: 0] vec_4 = {32'hFFFFFFFF, 32'h00000000, 1'b0}; // ones and zeroes, no carry - wire [64: 0] vec_5 = {32'hFFFFFFFF, 32'h00000000, 1'b1}; // ones and zeroes with carry - wire [64: 0] vec_6 = {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b0}; // all ones, no carry - wire [64: 0] vec_7 = {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b1}; // all ones with carry - - wire [64: 0] vec_8 = {32'hd898c296, 32'h37bf51f5, 1'b0}; // random values, no carry - wire [64: 0] vec_9 = {32'hf4a13945, 32'hcbb64068, 1'b0}; // random values, no carry - wire [64: 0] vec_10 = {32'h2deb33a0, 32'h6b315ece, 1'b0}; // random values, no carry - wire [64: 0] vec_11 = {32'h77037d81, 32'h2bce3357, 1'b0}; // random values, no carry - wire [64: 0] vec_12 = {32'h63a440f2, 32'h7c0f9e16, 1'b1}; // random values with carry - wire [64: 0] vec_13 = {32'hf8bce6e5, 32'h8ee7eb4a, 1'b1}; // random values with carry - wire [64: 0] vec_14 = {32'he12c4247, 32'hfe1a7f9b, 1'b1}; // random values with carry - wire [64: 0] vec_15 = {32'h6b17d1f2, 32'h4fe342e2, 1'b1}; // random values with carry - - - // - // UUT - // - adder32_wrapper uut - ( - .clk (clk), - .a (a), - .b (b), - .s (s), - .c_in (c_in), - .c_out (c_out) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - // - clk = 0; - // - #100; - // - test_adder32(vec_0); - test_adder32(vec_1); - test_adder32(vec_2); - test_adder32(vec_3); - test_adder32(vec_4); - test_adder32(vec_5); - test_adder32(vec_6); - test_adder32(vec_7); - // - test_adder32(vec_8); - test_adder32(vec_9); - test_adder32(vec_10); - test_adder32(vec_11); - test_adder32(vec_12); - test_adder32(vec_13); - test_adder32(vec_14); - test_adder32(vec_15); - // - if (ok) $display("tb_lowlevel_adder32: SUCCESS"); - else $display("tb_lowlevel_adder32: FAILURE"); - // - $finish; - // - end - - - // - // Test Routine - // - reg [31: 0] ss; // reference value of sum - reg cc; // reference value of carry - reg ss_ok; // result matches reference value - - task test_adder32; - - input [64: 0] vec; - - begin - - /* break down test vector */ - a = vec[64:33]; - b = vec[32: 1]; - c_in = vec[ 0: 0]; - - /* calculate reference values */ - {cc, ss} = {1'b0, a} + {1'b0, b} + {32'd0, c_in}; - - /* send one clock tick */ - #10 clk = 1; - #10 clk = 0; - - /* check outputs */ - ss_ok = (s == ss) && (c_out == cc); - - /* display results */ - $display("test_adder32(): 0x%08X + 0x%08X + %01d = {%01d, 0x%08X} [%0s]", a, b, c_in, c_out, s, ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && ss_ok; - - end - - endtask - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_lowlevel_adder47.v b/bench/tb_lowlevel_adder47.v deleted file mode 100644 index 663e8f9..0000000 --- a/bench/tb_lowlevel_adder47.v +++ /dev/null @@ -1,151 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_lowlevel_adder47.v -// ----------------------------------------------------------------------------- -// Testbench for 47-bit adder. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2016, 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. -// -//------------------------------------------------------------------------------ - - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - - -module tb_lowlevel_adder47; - - // - // Inputs - // - reg clk; - reg [46: 0] a; - reg [46: 0] b; - - // - // Outputs - // - wire [46: 0] s; - - // - // Test Vectors {a, b} - // - wire [93: 0] vec_0 = {47'h2a87ca22be8b, 47'h05378eb1c71e}; - wire [93: 0] vec_1 = {47'h7320ad746e1d, 47'h3b628ba79b98}; - wire [93: 0] vec_2 = {47'h59f741e08254, 47'h2a385502f25d}; - wire [93: 0] vec_3 = {47'h3f55296c3a54, 47'h5e3872760ab7}; - wire [93: 0] vec_4 = {47'h3617de4a9626, 47'h2c6f5d9e98bf}; - wire [93: 0] vec_5 = {47'h1292dc29f8f4, 47'h1dbd289a147c}; - wire [93: 0] vec_6 = {47'h69da3113b5f0, 47'h38c00a60b1ce}; - wire [93: 0] vec_7 = {47'h1d7e819d7a43, 47'h1d7c90ea0e5f}; - - // - // UUT - // - adder47_wrapper uut - ( - .clk (clk), - .a (a), - .b (b), - .s (s) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - // - clk = 0; - // - #100; - // - test_adder47(vec_0); - test_adder47(vec_1); - test_adder47(vec_2); - test_adder47(vec_3); - test_adder47(vec_4); - test_adder47(vec_5); - test_adder47(vec_6); - test_adder47(vec_7); - // - if (ok) $display("tb_lowlevel_adder47: SUCCESS"); - else $display("tb_lowlevel_adder47: FAILURE"); - // - $finish; - // - end - - - // - // Test Routine - // - reg [46: 0] ss; // reference value of sum - reg cc; // reference value of carry - reg ss_ok; // result matches reference value - - task test_adder47; - - input [93: 0] vec; - - begin - - /* break down test vector */ - a = vec[93:47]; - b = vec[46: 0]; - - /* calculate reference values */ - ss = a + b; - - /* send one clock tick */ - #10 clk = 1; - #10 clk = 0; - - /* check outputs */ - ss_ok = (s == ss); - - /* display results */ - $display("test_adder47(): %s", ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && ss_ok; - - end - - endtask - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_lowlevel_subtractor32.v b/bench/tb_lowlevel_subtractor32.v deleted file mode 100644 index fd96000..0000000 --- a/bench/tb_lowlevel_subtractor32.v +++ /dev/null @@ -1,174 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_lowlevel_subtractor32.v -// ----------------------------------------------------------------------------- -// Testbench for 32-bit subtractor. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2015-2016, 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. -// -//------------------------------------------------------------------------------ - - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_lowlevel_subtractor32; - - // - // Inputs - // - reg clk; - reg [31: 0] a; - reg [31: 0] b; - reg b_in; - - // - // Outputs - // - wire [31: 0] d; - wire b_out; - - // - // Test Vectors {a, b, b_in} - // - wire [64: 0] vec_0 = {32'h00000000, 32'h00000000, 1'b0}; // all zeroes, no borrow - wire [64: 0] vec_1 = {32'h00000000, 32'h00000000, 1'b1}; // all zeroes with borrow - wire [64: 0] vec_2 = {32'h00000000, 32'hFFFFFFFF, 1'b0}; // zeroes and ones, no borrow - wire [64: 0] vec_3 = {32'h00000000, 32'hFFFFFFFF, 1'b1}; // zeroes and ones with borrow - wire [64: 0] vec_4 = {32'hFFFFFFFF, 32'h00000000, 1'b0}; // ones and zeroes, no borrow - wire [64: 0] vec_5 = {32'hFFFFFFFF, 32'h00000000, 1'b1}; // ones and zeroes with borrow - wire [64: 0] vec_6 = {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b0}; // all ones, no borrow - wire [64: 0] vec_7 = {32'hFFFFFFFF, 32'hFFFFFFFF, 1'b1}; // all ones with borrow - - wire [64: 0] vec_8 = {32'hd898c296, 32'h37bf51f5, 1'b0}; // random values, no borrow - wire [64: 0] vec_9 = {32'hf4a13945, 32'hcbb64068, 1'b0}; // random values, no borrow - wire [64: 0] vec_10 = {32'h2deb33a0, 32'h6b315ece, 1'b0}; // random values, no borrow - wire [64: 0] vec_11 = {32'h77037d81, 32'h2bce3357, 1'b0}; // random values, no borrow - wire [64: 0] vec_12 = {32'h63a440f2, 32'h7c0f9e16, 1'b1}; // random values with borrow - wire [64: 0] vec_13 = {32'hf8bce6e5, 32'h8ee7eb4a, 1'b1}; // random values with borrow - wire [64: 0] vec_14 = {32'he12c4247, 32'hfe1a7f9b, 1'b1}; // random values with borrow - wire [64: 0] vec_15 = {32'h6b17d1f2, 32'h4fe342e2, 1'b1}; // random values with borrow - - - // - // UUT - // - subtractor32_wrapper uut - ( - .clk (clk), - .a (a), - .b (b), - .d (d), - .b_in (b_in), - .b_out (b_out) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - // - clk = 0; - // - #100; - // - test_subtractor32(vec_0); - test_subtractor32(vec_1); - test_subtractor32(vec_2); - test_subtractor32(vec_3); - test_subtractor32(vec_4); - test_subtractor32(vec_5); - test_subtractor32(vec_6); - test_subtractor32(vec_7); - // - test_subtractor32(vec_8); - test_subtractor32(vec_9); - test_subtractor32(vec_10); - test_subtractor32(vec_11); - test_subtractor32(vec_12); - test_subtractor32(vec_13); - test_subtractor32(vec_14); - test_subtractor32(vec_15); - // - if (ok) $display("tb_lowlevel_subtractor32: SUCCESS"); - else $display("tb_lowlevel_subtractor32: FAILURE"); - // - $finish; - // - end - - - // - // Test Routine - // - reg [31: 0] dd; // reference value of difference - reg bb; // reference value of borrow - reg dd_ok; // result matches reference value - - task test_subtractor32; - - input [64: 0] vec; - - begin - - /* break down test vector */ - a = vec[64:33]; - b = vec[32: 1]; - b_in = vec[ 0: 0]; - - /* calculate reference values */ - {bb, dd} = {1'b0, a} - {1'b0, b} - {32'd0, b_in}; - - /* send one clock tick */ - #10 clk = 1; - #10 clk = 0; - - /* check outputs */ - dd_ok = (d == dd) && (b_out == bb); - - /* display results */ - $display("test_subtractor32(): 0x%08X - (0x%08X + %01d) = {%01d, 0x%08X} [%0s]", a, b, b_in, b_out, d, dd_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && dd_ok; - - end - - endtask - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_modular_adder.v b/bench/tb_modular_adder.v deleted file mode 100644 index 713ff22..0000000 --- a/bench/tb_modular_adder.v +++ /dev/null @@ -1,357 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_modular_adder_256.v -// ----------------------------------------------------------------------------- -// Testbench for modular multi-word adder. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2016, 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. -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_modular_adder_256; - - - // - // Test Vectors - // - localparam [255:0] N = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; - - localparam [255:0] X_1 = 256'h1ddbd0769df27bab1e234019dad09dccce1e87e2193b417ffa1a3465d7439ecd; - localparam [255:0] Y_1 = 256'h1f67cdc34bac91a072945d212f0a03442fc4855788583ecb7b2e375ad3848210; - - localparam [255:0] X_2 = 256'hff563f653b1392a6fa6b0295a280f7a904a11e22d8ae468e220301d8ac232fcf; - localparam [255:0] Y_2 = 256'hf6f53c4b57b25453b68e923fb118e4f753d74af01fc58476dd15a80933453899; - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (X, Y, N) - // - wire [WORD_COUNTER_WIDTH-1:0] core_xy_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_n_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_s_addr; - wire core_s_wren; - - wire [ 31:0] core_x_data; - wire [ 31:0] core_y_data; - wire [ 31:0] core_n_data; - wire [ 31:0] core_s_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_xyn_addr; - reg [WORD_COUNTER_WIDTH-1:0] tb_s_addr; - reg tb_xyn_wren; - - reg [ 31:0] tb_x_data; - reg [ 31:0] tb_y_data; - reg [ 31:0] tb_n_data; - wire [ 31:0] tb_s_data; - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_x - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_x_data), - .a_out (), - - .b_addr (core_xy_addr), - .b_out (core_x_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_y - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_y_data), - .a_out (), - - .b_addr (core_xy_addr), - .b_out (core_y_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_n - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_n_data), - .a_out (), - - .b_addr (core_n_addr), - .b_out (core_n_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_s - ( - .clk (clk), - - .a_addr (core_s_addr), - .a_wr (core_s_wren), - .a_in (core_s_data), - .a_out (), - - .b_addr (tb_s_addr), - .b_out (tb_s_data) - ); - - - // - // UUT - // - modular_adder # - ( - .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), - .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) - ) - uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .ab_addr (core_xy_addr), - .n_addr (core_n_addr), - .s_addr (core_s_addr), - .s_wren (core_s_wren), - - .a_din (core_x_data), - .b_din (core_y_data), - .n_din (core_n_data), - .s_dout (core_s_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - tb_xyn_wren = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_modular_adder(X_1, Y_1, N); - test_modular_adder(X_2, Y_2, N); - test_modular_adder(Y_1, X_1, N); - test_modular_adder(Y_2, X_2, N); - - test_modular_adder(X_1, X_2, N); - test_modular_adder(X_2, X_1, N); - test_modular_adder(Y_1, Y_2, N); - test_modular_adder(Y_2, Y_1, N); - - test_modular_adder(X_1, Y_2, N); - test_modular_adder(Y_2, X_1, N); - test_modular_adder(X_2, Y_1, N); - test_modular_adder(Y_1, X_2, N); - - /* print result */ - if (ok) $display("tb_modular_adder_256: SUCCESS"); - else $display("tb_modular_adder_256: FAILURE"); - // - $finish; - // - end - - - // - // Test Task - // - reg [256:0] s; - wire [255:0] s_dummy = s[255:0]; - reg s_ok; - - integer w; - - reg [255:0] x_shreg; - reg [255:0] y_shreg; - reg [255:0] n_shreg; - reg [255:0] s_shreg; - - task test_modular_adder; - - input [255:0] x; - input [255:0] y; - input [255:0] n; - - begin - - /* start filling memories */ - tb_xyn_wren = 1; - - /* initialize shift registers */ - x_shreg = x; - y_shreg = y; - n_shreg = n; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_xyn_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_x_data = x_shreg[31:0]; - tb_y_data = y_shreg[31:0]; - tb_n_data = n_shreg[31:0]; - - /* shift inputs */ - x_shreg = {{32{1'bX}}, x_shreg[255:32]}; - y_shreg = {{32{1'bX}}, y_shreg[255:32]}; - n_shreg = {{32{1'bX}}, n_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_xyn_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_x_data = {32{1'bX}}; - tb_y_data = {32{1'bX}}; - tb_n_data = {32{1'bX}}; - - /* stop filling memories */ - tb_xyn_wren = 0; - - /* calculate reference value */ - s = {1'b0, x} + {1'b0, y}; - if (s >= {1'b0, n}) - s = s - {1'b0, n}; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set address */ - tb_s_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - s_shreg = {tb_s_data, s_shreg[255:32]}; - - end - - /* compare */ - s_ok = (s_shreg == s[255:0]); - - /* display results */ - $display("test_modular_adder(): %s", s_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && s_ok; - - end - - endtask - - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_modular_invertor.v b/bench/tb_modular_invertor.v deleted file mode 100644 index 24f6db1..0000000 --- a/bench/tb_modular_invertor.v +++ /dev/null @@ -1,225 +0,0 @@ -`timescale 1ns / 1ps - -module tb_modular_invertor; - - - // - // Test Vectors - // - localparam [255:0] Q = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; - - localparam [255:0] A_1 = 256'hd3e73ccd63a5b10da308c615bb9ebd3f76e2c5fccc256fd9f629dcc956bf2382; - localparam [255:0] A1_1 = 256'h93fb26d5d199bbb7232a4b7c98e97ba9bb7530d304b5f07736ea4027bbb57ecd; - - localparam [255:0] A_2 = 256'h57b6c628a5c4e870740b2517975ace2216acbe094ac54568b53212ef45e69d22; - localparam [255:0] A1_2 = 256'hcd2af4766642d7d2f3f3f67d92c575c496772ef7d55c75eb46bd07e8d5f9a4aa; - - - // - // Clock - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (A, A1, Q) - // - wire [ 2: 0] core_a_addr; - wire [ 2: 0] core_q_addr; - wire [ 2: 0] core_a1_addr; - wire core_a1_wren; - - wire [31: 0] core_a_data; - wire [31: 0] core_q_data; - wire [31: 0] core_a1_data; - - reg [ 2: 0] tb_aq_addr; - reg tb_aq_wren; - reg [ 2: 0] tb_a1_addr; - - reg [31: 0] tb_a_data; - reg [31: 0] tb_q_data; - wire [31: 0] tb_a1_data; - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3)) - bram_a - ( .clk(clk), - .a_addr(tb_aq_addr), .a_wr(tb_aq_wren), .a_in(tb_a_data), .a_out(), - .b_addr(core_a_addr), .b_out(core_a_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3)) - bram_q - ( .clk(clk), - .a_addr(tb_aq_addr), .a_wr(tb_aq_wren), .a_in(tb_q_data), .a_out(), - .b_addr(core_q_addr), .b_out(core_q_data) - ); - - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(3)) - bram_a1 - ( .clk(clk), - .a_addr(core_a1_addr), .a_wr(core_a1_wren), .a_in(core_a1_data), .a_out(), - .b_addr(tb_a1_addr), .b_out(tb_a1_data) - ); - - - // - // UUT - // - modular_invertor # - ( - .MAX_OPERAND_WIDTH (256) - ) - uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .a_addr (core_a_addr), - .q_addr (core_q_addr), - .a1_addr (core_a1_addr), - .a1_wren (core_a1_wren), - - .a_din (core_a_data), - .q_din (core_q_data), - .a1_dout (core_a1_data) - ); - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_modular_invertor(A_1, A1_1, Q); - test_modular_invertor(A_2, A1_2, Q); - - /* print result */ - if (ok) $display("tb_modular_invertor: SUCCESS"); - else $display("tb_modular_invertor: FAILURE"); - // - //$finish; - // - - end - - - // - // Test Task - // - reg a1_ok; - - integer w; - - task test_modular_invertor; - - input [255:0] a; - input [255:0] a1; - input [255:0] q; - - reg [255:0] a_shreg; - reg [255:0] a1_shreg; - reg [255:0] q_shreg; - - begin - - /* start filling memories */ - tb_aq_wren = 1; - - /* initialize shift registers */ - a_shreg = a; - q_shreg = q; - - /* write all the words */ - for (w=0; w<8; w=w+1) begin - - /* set addresses */ - tb_aq_addr = w[2:0]; - - /* set data words */ - tb_a_data = a_shreg[31:0]; - tb_q_data = q_shreg[31:0]; - - /* shift inputs */ - a_shreg = {{32{1'bX}}, a_shreg[255:32]}; - q_shreg = {{32{1'bX}}, q_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_aq_addr = {3{1'bX}}; - - /* wipe data words */ - tb_a_data = {32{1'bX}}; - tb_q_data = {32{1'bX}}; - - /* stop filling memories */ - tb_aq_wren = 0; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<8; w=w+1) begin - - /* set address */ - tb_a1_addr = w[2:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - a1_shreg = {tb_a1_data, a1_shreg[255:32]}; - - end - - /* compare */ - a1_ok = (a1_shreg == a1); - - /* display results */ - $display("test_modular_invertor(): %s", a1_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && a1_ok; - - end - - endtask - - -endmodule diff --git a/bench/tb_modular_multiplier_256.v b/bench/tb_modular_multiplier_256.v deleted file mode 100644 index 676a183..0000000 --- a/bench/tb_modular_multiplier_256.v +++ /dev/null @@ -1,366 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_modular_multiplier_256.v -// ----------------------------------------------------------------------------- -// Testbench for modular multi-word multiplier. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2015-2016, 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. -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_modular_multiplier_256; - - - // - // Test Vectors - // - localparam [255:0] N = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; - - localparam [255:0] X_1 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; - localparam [255:0] Y_1 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; - localparam [255:0] P_1 = 256'h823cd15f6dd3c71933565064513a6b2bd183e554c6a08622f713ebbbface98be; - - localparam [255:0] X_2 = 256'h29d05c193da77b710e86323538b77e1b11f904fea42998be16bd8d744ece7ad0; - localparam [255:0] Y_2 = 256'hb01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae07; - localparam [255:0] P_2 = 256'h76b2571d1d009ab0e7d1cc086c7d3648f08755b2e2585e780d11f053b06fb6ec; - - localparam [255:0] X_3 = 256'h8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8; - localparam [255:0] Y_3 = 256'hd8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9; - localparam [255:0] P_3 = 256'h944fea6a4fac7ae475a6bb211db4bbd394bd9b3ee9a038f6c17125a00b3a5375; - - localparam [255:0] X_4 = 256'h7214bc9647160bbd39ff2f80533f5dc6ddd70ddf86bb815661e805d5d4e6f27c; - localparam [255:0] Y_4 = 256'h8b81e3e977597110c7cf2633435b2294b72642987defd3d4007e1cfc5df84541; - localparam [255:0] P_4 = 256'h78d3e33c81ab9c652679363c76df004ea6f9a9e3a242a0fb71a4e8fdf41ab519; - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (X, Y, N, P) - // - wire [WORD_COUNTER_WIDTH-1:0] core_x_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_y_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_n_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_p_addr; - - wire core_p_wren; - - wire [ 31:0] core_x_data; - wire [ 31:0] core_y_data; - wire [ 31:0] core_n_data; - wire [ 31:0] core_p_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_xyn_addr; - reg [WORD_COUNTER_WIDTH-1:0] tb_p_addr; - - reg tb_xyn_wren; - - reg [ 31:0] tb_x_data; - reg [ 31:0] tb_y_data; - reg [ 31:0] tb_n_data; - wire [ 31:0] tb_p_data; - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_x - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_x_data), - .a_out (), - - .b_addr (core_x_addr), - .b_out (core_x_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_y - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_y_data), - .a_out (), - - .b_addr (core_y_addr), - .b_out (core_y_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_n - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_n_data), - .a_out (), - - .b_addr (core_n_addr), - .b_out (core_n_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_s - ( - .clk (clk), - - .a_addr (core_p_addr), - .a_wr (core_p_wren), - .a_in (core_p_data), - .a_out (), - - .b_addr (tb_p_addr), - .b_out (tb_p_data) - ); - - - // - // UUT - // - modular_multiplier_256 uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .a_addr (core_x_addr), - .b_addr (core_y_addr), - .n_addr (core_n_addr), - .p_addr (core_p_addr), - .p_wren (core_p_wren), - - .a_din (core_x_data), - .b_din (core_y_data), - .n_din (core_n_data), - .p_dout (core_p_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - tb_xyn_wren = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_modular_multiplier(X_1, Y_1, N, P_1); - test_modular_multiplier(X_2, Y_2, N, P_2); - test_modular_multiplier(X_3, Y_3, N, P_3); - test_modular_multiplier(X_4, Y_4, N, P_4); - - /* print result */ - if (ok) $display("tb_modular_multiplier_256: SUCCESS"); - else $display("tb_modular_multiplier_256: FAILURE"); - // - //$finish; - // - end - - - // - // Test Task - // - reg [255:0] p; - reg p_ok; - - integer w; - - reg [511:0] pp_full; - reg [255:0] pp_ref; - - task test_modular_multiplier; - - input [255:0] x; - input [255:0] y; - input [255:0] n; - input [255:0] pp; - - reg [255:0] x_shreg; - reg [255:0] y_shreg; - reg [255:0] n_shreg; - reg [255:0] p_shreg; - - begin - - /* start filling memories */ - tb_xyn_wren = 1; - - /* initialize shift registers */ - x_shreg = x; - y_shreg = y; - n_shreg = n; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_xyn_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_x_data = x_shreg[31:0]; - tb_y_data = y_shreg[31:0]; - tb_n_data = n_shreg[31:0]; - - /* shift inputs */ - x_shreg = {{32{1'bX}}, x_shreg[255:32]}; - y_shreg = {{32{1'bX}}, y_shreg[255:32]}; - n_shreg = {{32{1'bX}}, n_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_xyn_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_x_data = {32{1'bX}}; - tb_y_data = {32{1'bX}}; - tb_n_data = {32{1'bX}}; - - /* stop filling memories */ - tb_xyn_wren = 0; - - /* calculate reference value */ - pp_full = {{256{1'b0}}, x} * {{256{1'b0}}, y}; - pp_ref = pp_full % {{256{1'b0}}, n}; - - /* compare reference value against hard-coded one */ - if (pp_ref != pp) begin - $display("ERROR: pp_ref != pp"); - $finish; - end - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set address */ - tb_p_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - p_shreg = {tb_p_data, p_shreg[255:32]}; - - end - - /* compare */ - p_ok = (p_shreg == pp); - - /* display results */ - $display("test_modular_multiplier_256(): %s", p_ok ? "OK" : "ERROR"); - - /* update flag */ - ok = ok && p_ok; - - end - - endtask - - - - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_modular_subtractor.v b/bench/tb_modular_subtractor.v deleted file mode 100644 index 6cf0e01..0000000 --- a/bench/tb_modular_subtractor.v +++ /dev/null @@ -1,356 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_modular_subtractor_256.v -// ----------------------------------------------------------------------------- -// Testbench for modular multi-word subtractor. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2016, 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. -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_modular_subtractor_256; - - - // - // Test Vectors - // - localparam [255:0] N = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; - - localparam [255:0] X_1 = 256'h1ddbd0769df27bab1e234019dad09dccce1e87e2193b417ffa1a3465d7439ecd; - localparam [255:0] Y_1 = 256'h1f67cdc34bac91a072945d212f0a03442fc4855788583ecb7b2e375ad3848210; - - localparam [255:0] X_2 = 256'hff563f653b1392a6fa6b0295a280f7a904a11e22d8ae468e220301d8ac232fcf; - localparam [255:0] Y_2 = 256'hf6f53c4b57b25453b68e923fb118e4f753d74af01fc58476dd15a80933453899; - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (X, Y, N) - // - wire [WORD_COUNTER_WIDTH-1:0] core_xy_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_n_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_d_addr; - wire core_d_wren; - - wire [ 31:0] core_x_data; - wire [ 31:0] core_y_data; - wire [ 31:0] core_n_data; - wire [ 31:0] core_d_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_xyn_addr; - reg [WORD_COUNTER_WIDTH-1:0] tb_d_addr; - reg tb_xyn_wren; - - reg [ 31:0] tb_x_data; - reg [ 31:0] tb_y_data; - reg [ 31:0] tb_n_data; - wire [ 31:0] tb_d_data; - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_x - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_x_data), - .a_out (), - - .b_addr (core_xy_addr), - .b_out (core_x_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_y - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_y_data), - .a_out (), - - .b_addr (core_xy_addr), - .b_out (core_y_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_n - ( - .clk (clk), - - .a_addr (tb_xyn_addr), - .a_wr (tb_xyn_wren), - .a_in (tb_n_data), - .a_out (), - - .b_addr (core_n_addr), - .b_out (core_n_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_s - ( - .clk (clk), - - .a_addr (core_d_addr), - .a_wr (core_d_wren), - .a_in (core_d_data), - .a_out (), - - .b_addr (tb_d_addr), - .b_out (tb_d_data) - ); - - - // - // UUT - // - modular_subtractor # - ( - .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), - .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) - ) - uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .ab_addr (core_xy_addr), - .n_addr (core_n_addr), - .d_addr (core_d_addr), - .d_wren (core_d_wren), - - .a_din (core_x_data), - .b_din (core_y_data), - .n_din (core_n_data), - .d_dout (core_d_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - tb_xyn_wren = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_modular_subtractor(X_1, Y_1, N); - test_modular_subtractor(X_2, Y_2, N); - test_modular_subtractor(Y_1, X_1, N); - test_modular_subtractor(Y_2, X_2, N); - - test_modular_subtractor(X_1, X_2, N); - test_modular_subtractor(X_2, X_1, N); - test_modular_subtractor(Y_1, Y_2, N); - test_modular_subtractor(Y_2, Y_1, N); - - test_modular_subtractor(X_1, Y_2, N); - test_modular_subtractor(Y_2, X_1, N); - test_modular_subtractor(X_2, Y_1, N); - test_modular_subtractor(Y_1, X_2, N); - - /* print result */ - if (ok) $display("tb_modular_subtractor_256: SUCCESS"); - else $display("tb_modular_subtractor_256: FAILURE"); - // - $finish; - // - end - - - // - // Test Task - // - reg [256:0] d; - wire [255:0] d_dummy = d[255:0]; - reg d_ok; - - integer w; - - reg [255:0] x_shreg; - reg [255:0] y_shreg; - reg [255:0] n_shreg; - reg [255:0] d_shreg; - - task test_modular_subtractor; - - input [255:0] x; - input [255:0] y; - input [255:0] n; - - begin - - /* start filling memories */ - tb_xyn_wren = 1; - - /* initialize shift registers */ - x_shreg = x; - y_shreg = y; - n_shreg = n; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_xyn_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_x_data = x_shreg[31:0]; - tb_y_data = y_shreg[31:0]; - tb_n_data = n_shreg[31:0]; - - /* shift inputs */ - x_shreg = {{32{1'bX}}, x_shreg[255:32]}; - y_shreg = {{32{1'bX}}, y_shreg[255:32]}; - n_shreg = {{32{1'bX}}, n_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_xyn_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_x_data = {32{1'bX}}; - tb_y_data = {32{1'bX}}; - tb_n_data = {32{1'bX}}; - - /* stop filling memories */ - tb_xyn_wren = 0; - - /* calculate reference value */ - d = {1'b0, (x < y) ? n : {256{1'b0}}}; - d = d + {1'b0, x} - {1'b0, y}; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set address */ - tb_d_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - d_shreg = {tb_d_data, d_shreg[255:32]}; - - end - - /* compare */ - d_ok = (d_shreg == d[255:0]); - - /* display results */ - $display("test_modular_subtractor(): %s", d_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && d_ok; - - end - - endtask - - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_mw_comparator.v b/bench/tb_mw_comparator.v deleted file mode 100644 index ed830a8..0000000 --- a/bench/tb_mw_comparator.v +++ /dev/null @@ -1,322 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_mw_comparator.v -// ----------------------------------------------------------------------------- -// Testbench for multi-word comparator. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2016, 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. -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_mw_comparator; - - - // - // Test Vectors - // - localparam [383:0] A_0 = 384'hBDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F76; - - localparam [383:0] A_1 = 384'hBDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F75; - localparam [383:0] A_2 = 384'hBDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F77; - - localparam [383:0] A_3 = 384'hBDC7B53C_616B13B5_77622510_75BA95FC_375D568B_79E730D4_18A9143C_18905F76; - localparam [383:0] A_4 = 384'hBDC7B53C_616B13B5_77622510_75BA95FC_575D568B_79E730D4_18A9143C_18905F76; - - localparam [383:0] A_5 = 384'hBDC7B53C_616B13B5_77622510_75BA95FB_475D568B_79E730D4_18A9143C_18905F76; - localparam [383:0] A_6 = 384'hBDC7B53C_616B13B5_77622510_75BA95FD_475D568B_79E730D4_18A9143C_18905F76; - - localparam [383:0] A_7 = 384'hADC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F76; - localparam [383:0] A_8 = 384'hCDC7B53C_616B13B5_77622510_75BA95FC_475D568B_79E730D4_18A9143C_18905F76; - - localparam [383:0] B_0 = 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E5; - - localparam [383:0] B_1 = 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E4; - localparam [383:0] B_2 = 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E6; - - localparam [383:0] B_3 = 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_9D784F98_850046D4_10DDD64D_F6BB32E5; - localparam [383:0] B_4 = 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C0_BD784F98_850046D4_10DDD64D_F6BB32E5; - - localparam [383:0] B_5 = 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3BF_AD784F98_850046D4_10DDD64D_F6BB32E5; - localparam [383:0] B_6 = 384'h348A6D1F_7C66D21E_8D1490D9_AA6AE3C1_AD784F98_850046D4_10DDD64D_F6BB32E5; - - localparam [383:0] B_7 = 384'h248A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E5; - localparam [383:0] B_8 = 384'h448A6D1F_7C66D21E_8D1490D9_AA6AE3C0_AD784F98_850046D4_10DDD64D_F6BB32E5; - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - parameter OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - wire core_cmp_l; - wire core_cmp_e; - wire core_cmp_g; - - - // - // Buffers (X, Y) - // - wire [WORD_COUNTER_WIDTH-1:0] core_xy_addr; - - wire [ 32-1:0] core_x_data; - wire [ 32-1:0] core_y_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_xy_addr; - reg tb_xy_wren; - - reg [ 32-1:0] tb_x_data; - reg [ 32-1:0] tb_y_data; - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_x - ( - .clk (clk), - - .a_addr (tb_xy_addr), - .a_wr (tb_xy_wren), - .a_in (tb_x_data), - .a_out (), - - .b_addr (core_xy_addr), - .b_out (core_x_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_y - ( - .clk (clk), - - .a_addr (tb_xy_addr), - .a_wr (tb_xy_wren), - .a_in (tb_y_data), - .a_out (), - - .b_addr (core_xy_addr), - .b_out (core_y_data) - ); - - - // - // UUT - // - mw_comparator # - ( - .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), - .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) - ) - uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .xy_addr (core_xy_addr), - .x_din (core_x_data), - .y_din (core_y_data), - - .cmp_l (core_cmp_l), - .cmp_e (core_cmp_e), - .cmp_g (core_cmp_g) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - tb_xy_wren = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_mw_comparator(A_0, A_0); - - test_mw_comparator(A_0, A_1); - test_mw_comparator(A_0, A_2); - test_mw_comparator(A_0, A_3); - test_mw_comparator(A_0, A_4); - test_mw_comparator(A_0, A_5); - test_mw_comparator(A_0, A_6); - test_mw_comparator(A_0, A_7); - test_mw_comparator(A_0, A_8); - - test_mw_comparator(B_0, B_0); - - test_mw_comparator(B_0, B_1); - test_mw_comparator(B_0, B_2); - test_mw_comparator(B_0, B_3); - test_mw_comparator(B_0, B_4); - test_mw_comparator(B_0, B_5); - test_mw_comparator(B_0, B_6); - test_mw_comparator(B_0, B_7); - test_mw_comparator(B_0, B_8); - - /* print result */ - if (ok) $display("tb_mw_comparator: SUCCESS"); - else $display("tb_mw_comparator: FAILURE"); - // - $finish; - // - end - - - // - // Test Task - // - reg cmp_l; - reg cmp_e; - reg cmp_g; - reg cmp_ok; - - integer w; - - task test_mw_comparator; - - input [255:0] x; - input [255:0] y; - - reg [255:0] x_shreg; - reg [255:0] y_shreg; - - begin - - /* start filling memories */ - tb_xy_wren = 1; - - /* initialize shift registers */ - x_shreg = x; - y_shreg = y; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_xy_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_x_data = x_shreg[31:0]; - tb_y_data = y_shreg[31:0]; - - /* shift inputs */ - x_shreg = {{32{1'bX}}, x_shreg[255:32]}; - y_shreg = {{32{1'bX}}, y_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_xy_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_x_data = {32{1'bX}}; - tb_y_data = {32{1'bX}}; - - /* stop filling memories */ - tb_xy_wren = 0; - - /* calculate reference values */ - cmp_l = (x < y) ? 1 : 0; - cmp_e = (x == y) ? 1 : 0; - cmp_g = (x > y) ? 1 : 0; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* compare */ - cmp_ok = (cmp_l == core_cmp_l) && (cmp_e == core_cmp_e) && (cmp_g == core_cmp_g); - - /* display results */ - $display("test_mw_comparator(): %s", cmp_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && cmp_ok; - - end - - endtask - -endmodule - - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ diff --git a/bench/tb_mw_mover.v b/bench/tb_mw_mover.v deleted file mode 100644 index 08bdb9e..0000000 --- a/bench/tb_mw_mover.v +++ /dev/null @@ -1,282 +0,0 @@ -//------------------------------------------------------------------------------ -// -// tb_modular_mover.v -// ----------------------------------------------------------------------------- -// Testbench for multi-word data mover. -// -// Authors: Pavel Shatov -// -// Copyright (c) 2016, 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. -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -`timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_mw_mover; - - - // - // Test Vectors - // - localparam [255:0] X_1 = 256'h1ddbd0769df27bab1e234019dad09dccce1e87e2193b417ffa1a3465d7439ecd; - localparam [255:0] X_2 = 256'h1f67cdc34bac91a072945d212f0a03442fc4855788583ecb7b2e375ad3848210; - localparam [255:0] X_3 = 256'hff563f653b1392a6fa6b0295a280f7a904a11e22d8ae468e220301d8ac232fcf; - localparam [255:0] X_4 = 256'hf6f53c4b57b25453b68e923fb118e4f753d74af01fc58476dd15a80933453899; - - - // - // Core Parameters - // - localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - - // - // Buffers (X, Y) - // - wire [WORD_COUNTER_WIDTH-1:0] core_x_addr; - wire [WORD_COUNTER_WIDTH-1:0] core_y_addr; - wire core_y_wren; - - wire [ 32-1:0] core_x_data; - wire [ 32-1:0] core_y_data; - - reg [WORD_COUNTER_WIDTH-1:0] tb_x_addr; - reg [WORD_COUNTER_WIDTH-1:0] tb_y_addr; - reg tb_x_wren; - - reg [ 32-1:0] tb_x_data; - wire [ 32-1:0] tb_y_data; - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_x - ( - .clk (clk), - - .a_addr (tb_x_addr), - .a_wr (tb_x_wren), - .a_in (tb_x_data), - .a_out (), - - .b_addr (core_x_addr), - .b_out (core_x_data) - ); - - bram_1rw_1ro_readfirst # - ( - .MEM_WIDTH (32), - .MEM_ADDR_BITS (WORD_COUNTER_WIDTH) - ) - bram_d - ( - .clk (clk), - - .a_addr (core_y_addr), - .a_wr (core_y_wren), - .a_in (core_y_data), - .a_out (), - - .b_addr (tb_y_addr), - .b_out (tb_y_data) - ); - - - // - // UUT - // - mw_mover # - ( - .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), - .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) - ) - uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .x_addr (core_x_addr), - .y_addr (core_y_addr), - .y_wren (core_y_wren), - - .x_din (core_x_data), - .y_dout (core_y_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - tb_x_wren = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_modular_mover(X_1); - test_modular_mover(X_2); - test_modular_mover(X_3); - test_modular_mover(X_4); - - /* print result */ - if (ok) $display("tb_modular_mover: SUCCESS"); - else $display("tb_modular_mover: FAILURE"); - // - $finish; - // - end - - - // - // Test Task - // - reg [255:0] y; - reg y_ok; - - integer w; - - reg [255:0] x_shreg; - reg [255:0] y_shreg; - - task test_modular_mover; - - input [255:0] x; - - begin - - /* start filling memories */ - tb_x_wren = 1; - - /* initialize shift registers */ - x_shreg = x; - - /* write all the words */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set addresses */ - tb_x_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* set data words */ - tb_x_data = x_shreg[31:0]; - - /* shift inputs */ - x_shreg = {{32{1'bX}}, x_shreg[255:32]}; - - /* wait for 1 clock tick */ - #10; - - end - - /* wipe addresses */ - tb_x_addr = {WORD_COUNTER_WIDTH{1'bX}}; - - /* wipe data words */ - tb_x_data = {32{1'bX}}; - - /* stop filling memories */ - tb_x_wren = 0; - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - - /* read result */ - for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin - - /* set address */ - tb_y_addr = w[WORD_COUNTER_WIDTH-1:0]; - - /* wait for 1 clock tick */ - #10; - - /* store data word */ - y_shreg = {tb_y_data, y_shreg[255:32]}; - - end - - /* compare */ - y_ok = (y_shreg == x); - - /* display results */ - $display("test_modular_mover(): %s", y_ok ? "OK" : "ERROR"); - - /* update global flag */ - ok = ok && y_ok; - - end - - endtask - - -endmodule - -//------------------------------------------------------------------------------ -// End-of-File -//------------------------------------------------------------------------------ |