From b825de8c9c8711479c29cc42c9c86f2d33c60172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Stro=CC=88mbergson?= Date: Wed, 3 Sep 2014 15:51:17 +0200 Subject: Adding testbenches for core and top. --- src/tb/tb_chacha.v | 761 ++++++++++++++++++++++++++++++++++++++++++++++++ src/tb/tb_chacha_core.v | 689 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1450 insertions(+) create mode 100644 src/tb/tb_chacha.v create mode 100644 src/tb/tb_chacha_core.v diff --git a/src/tb/tb_chacha.v b/src/tb/tb_chacha.v new file mode 100644 index 0000000..4322334 --- /dev/null +++ b/src/tb/tb_chacha.v @@ -0,0 +1,761 @@ +//====================================================================== +// +// tb_chacha.v +// ----------- +// Testbench for the Chacha top level wrapper. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2011, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +//------------------------------------------------------------------ +// Simulator directives. +//------------------------------------------------------------------ +`timescale 1ns/100ps + +module tb_chacha(); + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + parameter DEBUG = 0; + + parameter CLK_HALF_PERIOD = 2; + + parameter TC1 = 1; + parameter TC2 = 2; + parameter TC3 = 3; + parameter TC4 = 4; + parameter TC5 = 5; + parameter TC6 = 6; + parameter TC7 = 7; + parameter TC8 = 8; + parameter TC9 = 9; + parameter TC10 = 10; + + parameter ONE = 1; + parameter TWO = 2; + parameter THREE = 3; + parameter FOUR = 4; + parameter FIVE = 5; + parameter SIX = 6; + parameter SEVEN = 7; + parameter EIGHT = 8; + + parameter KEY_128_BITS = 0; + parameter KEY_256_BITS = 1; + + parameter EIGHT_ROUNDS = 8; + parameter TWELWE_ROUNDS = 12; + parameter TWENTY_ROUNDS = 20; + + parameter DISABLE = 0; + parameter ENABLE = 1; + + // API for the dut. + parameter ADDR_CTRL = 8'h00; + parameter CTRL_INIT_BIT = 0; + parameter CTRL_NEXT_BIT = 1; + + parameter ADDR_STATUS = 8'h01; + parameter STATUS_READY_BIT = 0; + + parameter ADDR_KEYLEN = 8'h08; + parameter KEYLEN_BIT = 0; + parameter ADDR_ROUNDS = 8'h09; + parameter ROUNDS_HIGH_BIT = 4; + parameter ROUNDS_LOW_BIT = 0; + + parameter ADDR_KEY0 = 8'h10; + parameter ADDR_KEY1 = 8'h11; + parameter ADDR_KEY2 = 8'h12; + parameter ADDR_KEY3 = 8'h13; + parameter ADDR_KEY4 = 8'h14; + parameter ADDR_KEY5 = 8'h15; + parameter ADDR_KEY6 = 8'h16; + parameter ADDR_KEY7 = 8'h17; + + parameter ADDR_IV0 = 8'h20; + parameter ADDR_IV1 = 8'h21; + + parameter ADDR_DATA_IN0 = 8'h40; + parameter ADDR_DATA_IN1 = 8'h41; + parameter ADDR_DATA_IN2 = 8'h42; + parameter ADDR_DATA_IN3 = 8'h43; + parameter ADDR_DATA_IN4 = 8'h44; + parameter ADDR_DATA_IN5 = 8'h45; + parameter ADDR_DATA_IN6 = 8'h46; + parameter ADDR_DATA_IN7 = 8'h47; + parameter ADDR_DATA_IN8 = 8'h48; + parameter ADDR_DATA_IN9 = 8'h49; + parameter ADDR_DATA_IN10 = 8'h4a; + parameter ADDR_DATA_IN11 = 8'h4b; + parameter ADDR_DATA_IN12 = 8'h4c; + parameter ADDR_DATA_IN13 = 8'h4d; + parameter ADDR_DATA_IN14 = 8'h4e; + parameter ADDR_DATA_IN15 = 8'h4f; + + parameter ADDR_DATA_OUT0 = 8'h80; + parameter ADDR_DATA_OUT1 = 8'h81; + parameter ADDR_DATA_OUT2 = 8'h82; + parameter ADDR_DATA_OUT3 = 8'h83; + parameter ADDR_DATA_OUT4 = 8'h84; + parameter ADDR_DATA_OUT5 = 8'h85; + parameter ADDR_DATA_OUT6 = 8'h86; + parameter ADDR_DATA_OUT7 = 8'h87; + parameter ADDR_DATA_OUT8 = 8'h88; + parameter ADDR_DATA_OUT9 = 8'h89; + parameter ADDR_DATA_OUT10 = 8'h8a; + parameter ADDR_DATA_OUT11 = 8'h8b; + parameter ADDR_DATA_OUT12 = 8'h8c; + parameter ADDR_DATA_OUT13 = 8'h8d; + parameter ADDR_DATA_OUT14 = 8'h8e; + parameter ADDR_DATA_OUT15 = 8'h8f; + + + //---------------------------------------------------------------- + // Register and Wire declarations. + //---------------------------------------------------------------- + reg tb_clk; + reg tb_reset_n; + + reg tb_cs; + reg tb_write_read; + + reg [7 : 0] tb_address; + reg [31 : 0] tb_data_in; + wire [31 : 0] tb_data_out; + wire tb_error; + + reg [63 : 0] cycle_ctr; + reg [31 : 0] error_ctr; + reg [31 : 0] tc_ctr; + + reg error_found; + reg [31 : 0] read_data; + + reg [511 : 0] extracted_data; + + reg display_cycle_ctr; + reg display_read_write; + + + //---------------------------------------------------------------- + // Chacha device under test. + //---------------------------------------------------------------- + chacha dut( + // Clock and reset. + .clk(tb_clk), + .reset_n(tb_reset_n), + + // Control. + .cs(tb_cs), + .we(tb_write_read), + + // Data ports. + .address(tb_address), + .write_data(tb_data_in), + .read_data(tb_data_out), + .error(tb_error) + ); + + + //---------------------------------------------------------------- + // clk_gen + // + // Clock generator process. + //---------------------------------------------------------------- + always + begin : clk_gen + #CLK_HALF_PERIOD tb_clk = !tb_clk; + end // clk_gen + + + //-------------------------------------------------------------------- + // dut_monitor + // + // Monitor displaying information every cycle. + // Includes the cycle counter. + //-------------------------------------------------------------------- + always @ (posedge tb_clk) + begin : dut_monitor + cycle_ctr = cycle_ctr + 1; + + if (display_cycle_ctr) + begin + $display("cycle = %016x:", cycle_ctr); + end + + if (display_read_write) + begin + + if (dut.cs) + begin + if (dut.we) + begin + $display("*** Write acess: addr 0x%02x = 0x%08x", dut.address, dut.write_data); + end + else + begin + $display("*** Read acess: addr 0x%02x = 0x%08x", dut.address, dut.read_data); + end + end + end + + end // dut_monitor + + + //---------------------------------------------------------------- + // set_display_prefs() + // + // Set the different monitor displays we want to see during + // simulation. + //---------------------------------------------------------------- + task set_display_prefs( + input cycles, + input read_write); + begin + display_cycle_ctr = cycles; + display_read_write = read_write; + end + endtask // set_display_prefs + + + //---------------------------------------------------------------- + // reset_dut + //---------------------------------------------------------------- + task reset_dut(); + begin + tb_reset_n = 0; + #(4 * CLK_HALF_PERIOD); + tb_reset_n = 1; + end + endtask // reset_dut + + + //---------------------------------------------------------------- + // read_reg + // + // Task that reads and display the value of + // a register in the dut. + //---------------------------------------------------------------- + task read_reg(input [7 : 0] addr); + begin + tb_cs = 1; + tb_write_read = 0; + tb_address = addr; + #(2 * CLK_HALF_PERIOD); + tb_cs = 0; + tb_write_read = 0; + tb_address = 8'h00; + tb_data_in = 32'h00000000; + end + endtask // read_reg + + + //---------------------------------------------------------------- + // write_reg + // + // Task that writes to a register in the dut. + //---------------------------------------------------------------- + task write_reg(input [7 : 0] addr, input [31 : 0] data); + begin + tb_cs = 1; + tb_write_read = 1; + tb_address = addr; + tb_data_in = data; + #(2 * CLK_HALF_PERIOD); + tb_cs = 0; + tb_write_read = 0; + tb_address = 8'h00; + tb_data_in = 32'h00000000; + end + endtask // write_reg + + + //---------------------------------------------------------------- + // dump_top_state + // + // Dump the internal state of the top to std out. + //---------------------------------------------------------------- + task dump_top_state(); + begin + $display(""); + $display("Top internal state"); + $display("------------------"); + $display("init_reg = %01x", dut.init_reg); + $display("next_reg = %01x", dut.next_reg); + $display("ready_reg = %01x", dut.ready_reg); + $display("keylen_reg = %01x", dut.keylen_reg); + $display("rounds_reg = %01x", dut.rounds_reg); + $display(""); + + $display("key0_reg = %08x, key1_reg = %08x, key2_reg = %08x, key3_reg = %08x", dut.key0_reg, dut.key1_reg, dut.key2_reg, dut.key3_reg); + $display("key4_reg = %08x, key5_reg = %08x, key6_reg = %08x, key7_reg = %08x", dut.key4_reg, dut.key5_reg, dut.key6_reg, dut.key7_reg); + $display(""); + + $display("iv0_reg = %08x, iv1_reg = %08x", dut.iv0_reg, dut.iv1_reg); + $display(""); + + $display("data_in0_reg = %08x, data_in1_reg = %08x, data_in2_reg = %08x, data_in3_reg = %08x", dut.data_in0_reg, dut.data_in1_reg, dut.data_in2_reg, dut.data_in3_reg); + $display("data_in4_reg = %08x, data_in5_reg = %08x, data_in6_reg = %08x, data_in7_reg = %08x", dut.data_in4_reg, dut.data_in5_reg, dut.data_in6_reg, dut.data_in7_reg); + $display("data_in8_reg = %08x, data_in9_reg = %08x, data_in10_reg = %08x, data_in11_reg = %08x", dut.data_in8_reg, dut.data_in9_reg, dut.data_in10_reg, dut.data_in11_reg); + $display("data_in12_reg = %08x, data_in13_reg = %08x, data_in14_reg = %08x, data_in15_reg = %08x", dut.data_in12_reg, dut.data_in13_reg, dut.data_in14_reg, dut.data_in15_reg); + $display(""); + + $display("data_out_valid_reg = %01x", dut.data_out_valid_reg); + $display("data_out0_reg = %08x, data_out1_reg = %08x, data_out2_reg = %08x, data_out3_reg = %08x", dut.data_out0_reg, dut.data_out1_reg, dut.data_out2_reg, dut.data_out3_reg); + $display("data_out4_reg = %08x, data_out5_reg = %08x, data_out6_reg = %08x, data_out7_reg = %08x", dut.data_out4_reg, dut.data_out5_reg, dut.data_out6_reg, dut.data_out7_reg); + $display("data_out8_reg = %08x, data_out9_reg = %08x, data_out10_reg = %08x, data_out11_reg = %08x", dut.data_out8_reg, dut.data_out9_reg, dut.data_out10_reg, dut.data_out11_reg); + $display("data_out12_reg = %08x, data_out13_reg = %08x, data_out14_reg = %08x, data_out15_reg = %08x", dut.data_out12_reg, dut.data_out13_reg, dut.data_out14_reg, dut.data_out15_reg); + $display(""); + end + endtask // dump_top_state + + + //---------------------------------------------------------------- + // dump_core_state + // + // Dump the internal state of the core to std out. + //---------------------------------------------------------------- + task dump_core_state(); + begin + $display(""); + $display("Core internal state"); + $display("-------------------"); +// $display("Internal data state vector:"); +// $display("0x%064x", dut.core.state_reg); + $display(""); + + $display("Round state X:"); + $display("x0_reg = %08x, x1_reg = %08x", dut.core.x0_reg, dut.core.x1_reg); + $display("x2_reg = %08x, x3_reg = %08x", dut.core.x2_reg, dut.core.x3_reg); + $display("x4_reg = %08x, x5_reg = %08x", dut.core.x4_reg, dut.core.x5_reg); + $display("x6_reg = %08x, x7_reg = %08x", dut.core.x6_reg, dut.core.x7_reg); + $display("x8_reg = %08x, x9_reg = %08x", dut.core.x8_reg, dut.core.x9_reg); + $display("x10_reg = %08x, x11_reg = %08x", dut.core.x10_reg, dut.core.x11_reg); + $display("x12_reg = %08x, x13_reg = %08x", dut.core.x12_reg, dut.core.x13_reg); + $display("x14_reg = %08x, x15_reg = %08x", dut.core.x14_reg, dut.core.x15_reg); + $display(""); + + $display("rounds_reg = %01x", dut.core.rounds_reg); + $display("qr_ctr_reg = %01x, dr_ctr_reg = %01x", dut.core.qr_ctr_reg, dut.core.dr_ctr_reg); + $display("block0_ctr_reg = %08x, block1_ctr_reg = %08x", dut.core.block0_ctr_reg, dut.core.block1_ctr_reg); + + $display(""); + + $display("chacha_ctrl_reg = %02x", dut.core.chacha_ctrl_reg); + $display(""); + + $display("data_in_reg = %064x", dut.core.data_in_reg); + $display("data_out_valid_reg = %01x", dut.core.data_out_valid_reg); + $display(""); + + $display("qr0_a_prim = %08x, qr0_b_prim = %08x", dut.core.qr0_a_prim, dut.core.qr0_b_prim); + $display("qr0_c_prim = %08x, qr0_d_prim = %08x", dut.core.qr0_c_prim, dut.core.qr0_d_prim); + $display(""); + end + endtask // dump_core_state + + + //---------------------------------------------------------------- + // display_test_result() + // + // Display the accumulated test results. + //---------------------------------------------------------------- + task display_test_result(); + begin + if (error_ctr == 0) + begin + $display("*** All %02d test cases completed successfully", tc_ctr); + end + else + begin + $display("*** %02d test cases did not complete successfully.", error_ctr); + end + end + endtask // display_test_result + + + //---------------------------------------------------------------- + // init_dut() + // + // Set the input to the DUT to defined values. + //---------------------------------------------------------------- + task init_dut(); + begin + // Set clock, reset and DUT input signals to + // defined values at simulation start. + cycle_ctr = 0; + error_ctr = 0; + tc_ctr = 0; + tb_clk = 0; + tb_reset_n = 0; + tb_cs = 0; + tb_write_read = 0; + tb_address = 8'h00; + tb_data_in = 32'h00000000; + end + endtask // init_dut + + + //---------------------------------------------------------------- + // read_write_test() + // + // Simple test case that tries to read and write to the + // registers in the dut. + // + // Note: Currently not self testing. No expected values. + //---------------------------------------------------------------- + task read_write_test(); + begin + tc_ctr = tc_ctr + 1; + + write_reg(ADDR_KEY0, 32'h55555555); + read_reg(ADDR_KEY0); + write_reg(ADDR_KEY1, 32'haaaaaaaa); + read_reg(ADDR_KEY1); + read_reg(ADDR_CTRL); + read_reg(ADDR_STATUS); + read_reg(ADDR_KEYLEN); + read_reg(ADDR_ROUNDS); + + read_reg(ADDR_KEY0); + read_reg(ADDR_KEY1); + read_reg(ADDR_KEY2); + read_reg(ADDR_KEY3); + read_reg(ADDR_KEY4); + read_reg(ADDR_KEY5); + read_reg(ADDR_KEY6); + read_reg(ADDR_KEY7); + end + endtask // read_write_test + + + //---------------------------------------------------------------- + // write_parameters() + // + // Write key, iv and other parameters to the dut. + //---------------------------------------------------------------- + task write_parameters(input [256 : 0] key, + input key_length, + input [64 : 0] iv, + input [4 : 0] rounds); + begin + write_reg(ADDR_KEY0, key[255 : 224]); + write_reg(ADDR_KEY1, key[223 : 192]); + write_reg(ADDR_KEY2, key[191 : 160]); + write_reg(ADDR_KEY3, key[159 : 128]); + write_reg(ADDR_KEY4, key[127 : 96]); + write_reg(ADDR_KEY5, key[95 : 64]); + write_reg(ADDR_KEY6, key[63 : 32]); + write_reg(ADDR_KEY7, key[31 : 0]); + write_reg(ADDR_IV0, iv[63 : 32]); + write_reg(ADDR_IV1, iv[31 : 0]); + write_reg(ADDR_KEYLEN, {{31'b0000000000000000000000000000000}, key_length}); + write_reg(ADDR_ROUNDS, {{27'b000000000000000000000000000}, rounds}); + end + endtask // write_parameters + + + //---------------------------------------------------------------- + // start_init_block() + // + // Toggle the init signal in the dut to make it start processing + // the first block available in the data in registers. + // + // Note: It is the callers responsibility to call the function + // when the dut is ready to react on the init signal. + //---------------------------------------------------------------- + task start_init_block(); + begin + write_reg(ADDR_CTRL, 32'h00000001); + #(4 * CLK_HALF_PERIOD); + write_reg(ADDR_CTRL, 32'h00000000); + end + endtask // start_init_block + + + //---------------------------------------------------------------- + // start_next_block() + // + // Toggle the next signal in the dut to make it start processing + // the next block available in the data in registers. + // + // Note: It is the callers responsibility to call the function + // when the dut is ready to react on the next signal. + //---------------------------------------------------------------- + task start_next_block(); + begin + write_reg(ADDR_CTRL, 32'h00000002); + #(4 * CLK_HALF_PERIOD); + write_reg(ADDR_CTRL, 32'h00000000); + + if (DEBUG) + begin + $display("Debug of next state."); + dump_core_state(); + #(4 * CLK_HALF_PERIOD); + dump_core_state(); + end + end + endtask // start_next_block + + + //---------------------------------------------------------------- + // wait_ready() + // + // Wait for the ready flag in the dut to be set. + // + // Note: It is the callers responsibility to call the function + // when the dut is actively processing and will in fact at some + // point set the flag. + //---------------------------------------------------------------- + task wait_ready(); + begin + while (!tb_data_out[STATUS_READY_BIT]) + begin + read_reg(ADDR_STATUS); + end + end + endtask // wait_ready + + + //---------------------------------------------------------------- + // extract_data() + // + // Extracts all 16 data out words and combine them into the + // global extracted_data. + //---------------------------------------------------------------- + task extract_data(); + begin + read_reg(ADDR_DATA_OUT0); + extracted_data[511 : 480] = tb_data_out; + read_reg(ADDR_DATA_OUT1); + extracted_data[479 : 448] = tb_data_out; + read_reg(ADDR_DATA_OUT2); + extracted_data[447 : 416] = tb_data_out; + read_reg(ADDR_DATA_OUT3); + extracted_data[415 : 384] = tb_data_out; + read_reg(ADDR_DATA_OUT4); + extracted_data[383 : 352] = tb_data_out; + read_reg(ADDR_DATA_OUT5); + extracted_data[351 : 320] = tb_data_out; + read_reg(ADDR_DATA_OUT6); + extracted_data[319 : 288] = tb_data_out; + read_reg(ADDR_DATA_OUT7); + extracted_data[287 : 256] = tb_data_out; + read_reg(ADDR_DATA_OUT8); + extracted_data[255 : 224] = tb_data_out; + read_reg(ADDR_DATA_OUT9); + extracted_data[223 : 192] = tb_data_out; + read_reg(ADDR_DATA_OUT10); + extracted_data[191 : 160] = tb_data_out; + read_reg(ADDR_DATA_OUT11); + extracted_data[159 : 128] = tb_data_out; + read_reg(ADDR_DATA_OUT12); + extracted_data[127 : 96] = tb_data_out; + read_reg(ADDR_DATA_OUT13); + extracted_data[95 : 64] = tb_data_out; + read_reg(ADDR_DATA_OUT14); + extracted_data[63 : 32] = tb_data_out; + read_reg(ADDR_DATA_OUT15); + extracted_data[31 : 0] = tb_data_out; + end + endtask // extract_data + + + //---------------------------------------------------------------- + // run_two_blocks_test_vector() + // + // Runs a test case with two blocks based on the given + // test vector. Only the final block is compared. + //---------------------------------------------------------------- + task run_two_blocks_test_vector(input [7 : 0] major, + input [7 : 0] minor, + input [256 : 0] key, + input key_length, + input [64 : 0] iv, + input [4 : 0] rounds, + input [511 : 0] expected); + begin + tc_ctr = tc_ctr + 1; + + $display("***TC%2d-%2d started", major, minor); + $display("***-----------------"); + write_parameters(key, key_length, iv, rounds); + + start_init_block(); + wait_ready(); + extract_data(); + + if (DEBUG) + begin + $display("State after first block:"); + dump_core_state(); + + $display("First block:"); + $display("0x%064x", extracted_data); + end + + start_next_block(); + + if (DEBUG) + begin + $display("State after init of second block:"); + dump_core_state(); + end + + wait_ready(); + extract_data(); + + if (DEBUG) + begin + $display("State after init of second block:"); + dump_core_state(); + + $display("Second block:"); + $display("0x%064x", extracted_data); + end + + if (extracted_data != expected) + begin + error_ctr = error_ctr + 1; + $display("***TC%2d-%2d - ERROR", major, minor); + $display("***-----------------"); + $display("Expected:"); + $display("0x%064x", expected); + $display("Got:"); + $display("0x%064x", extracted_data); + end + else + begin + $display("***TC%2d-%2d - SUCCESS", major, minor); + $display("***-------------------"); + end + $display(""); + end + endtask // run_two_blocks_test_vector + + + //---------------------------------------------------------------- + // run_test_vector() + // + // Runs a test case based on the given test vector. + //---------------------------------------------------------------- + task run_test_vector(input [7 : 0] major, + input [7 : 0] minor, + input [256 : 0] key, + input key_length, + input [64 : 0] iv, + input [4 : 0] rounds, + input [511 : 0] expected); + begin + tc_ctr = tc_ctr + 1; + + $display("***TC%2d-%2d started", major, minor); + $display("***-----------------"); + write_parameters(key, key_length, iv, rounds); + + start_init_block(); + wait_ready(); + extract_data(); + + if (extracted_data != expected) + begin + error_ctr = error_ctr + 1; + $display("***TC%2d-%2d - ERROR", major, minor); + $display("***-----------------"); + $display("Expected:"); + $display("0x%064x", expected); + $display("Got:"); + $display("0x%064x", extracted_data); + end + else + begin + $display("***TC%2d-%2d - SUCCESS", major, minor); + $display("***-------------------"); + end + $display(""); + end + endtask // run_test_vector + + + //---------------------------------------------------------------- + // chacha_test + // The main test functionality. + //---------------------------------------------------------------- + initial + begin : chacha_test + $display(" -- Testbench for chacha started --"); + init_dut(); + set_display_prefs(0, 0); + reset_dut(); + + $display("State at init after reset:"); + dump_top_state(); + + $display("TC1-1: All zero inputs. 128 bit key, 8 rounds."); + run_test_vector(TC1, ONE, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_128_BITS, + 64'h0000000000000000, + EIGHT_ROUNDS, + 512'he28a5fa4a67f8c5defed3e6fb7303486aa8427d31419a729572d777953491120b64ab8e72b8deb85cd6aea7cb6089a101824beeb08814a428aab1fa2c816081b); + + $display("TC7-2: Increasing, decreasing sequences in key and IV. 256 bit key, 8 rounds."); + run_test_vector(TC7, TWO, + 256'h00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100, + KEY_256_BITS, + 64'h0f1e2d3c4b596877, + EIGHT_ROUNDS, + 512'h60fdedbd1a280cb741d0593b6ea0309010acf18e1471f68968f4c9e311dca149b8e027b47c81e0353db013891aa5f68ea3b13dd2f3b8dd0873bf3746e7d6c567); + + + $display("TC7-3: Increasing, decreasing sequences in key and IV. 256 bit key, 8 rounds."); + $display("TC7-3: Testing correct second block."); + run_two_blocks_test_vector(TC7, THREE, + 256'h00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100, + KEY_256_BITS, + 64'h0f1e2d3c4b596877, + EIGHT_ROUNDS, + 512'hfe882395601ce8aded444867fe62ed8741420002e5d28bb573113a418c1f4008e954c188f38ec4f26bb8555e2b7c92bf4380e2ea9e553187fdd42821794416de); + + + display_test_result(); + $display("*** chacha simulation done."); + $finish; + end // chacha_test +endmodule // tb_chacha + +//====================================================================== +// EOF tb_chacha.v +//====================================================================== diff --git a/src/tb/tb_chacha_core.v b/src/tb/tb_chacha_core.v new file mode 100644 index 0000000..a1ddfdc --- /dev/null +++ b/src/tb/tb_chacha_core.v @@ -0,0 +1,689 @@ +//====================================================================== +// +// tb_chacha_core.v +// ----------------- +// Testbench for the Chacha stream cipher core. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2011, NORDUnet A/S All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +//------------------------------------------------------------------ +// Simulator directives. +//------------------------------------------------------------------ +`timescale 1ns/100ps + +module tb_chacha_core(); + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + parameter CLK_HALF_PERIOD = 2; + + parameter TC1 = 1; + parameter TC2 = 2; + parameter TC3 = 3; + parameter TC4 = 4; + parameter TC5 = 5; + parameter TC6 = 6; + parameter TC7 = 7; + parameter TC8 = 8; + parameter TC9 = 9; + parameter TC10 = 10; + + parameter ONE = 1; + parameter TWO = 2; + parameter THREE = 3; + parameter FOUR = 4; + parameter FIVE = 5; + parameter SIX = 6; + parameter SEVEN = 7; + parameter EIGHT = 8; + + parameter KEY_128_BITS = 0; + parameter KEY_256_BITS = 1; + + parameter EIGHT_ROUNDS = 8; + parameter TWELWE_ROUNDS = 12; + parameter TWENTY_ROUNDS = 20; + + parameter DISABLE = 0; + parameter ENABLE = 1; + + parameter DEFAULT_CTR_INIT = 64'h0000000000000000; + + + //---------------------------------------------------------------- + // Register and Wire declarations. + //---------------------------------------------------------------- + reg [31 : 0] cycle_ctr; + reg [31 : 0] error_ctr; + reg [31 : 0] tc_ctr; + + reg tb_clk; + reg tb_reset_n; + + reg tb_core_init; + reg tb_core_next; + reg [255 : 0] tb_core_key; + reg tb_core_keylen; + reg [4 : 0] tb_core_rounds; + reg [63 : 0] tb_core_iv; + wire tb_core_ready; + reg [0 : 511] tb_core_data_in; + wire [0 : 511] tb_core_data_out; + + reg display_cycle_ctr; + reg display_ctrl_and_ctrs; + reg display_qround; + reg display_state; + reg display_x_state; + + + //---------------------------------------------------------------- + // chacha_core device under test. + //---------------------------------------------------------------- + chacha_core dut( + // Clock and reset. + .clk(tb_clk), + .reset_n(tb_reset_n), + + // Control. + .init(tb_core_init), + .next(tb_core_next), + + // Parameters. + .key(tb_core_key), + .keylen(tb_core_keylen), + .iv(tb_core_iv), + .ctr(DEFAULT_CTR_INIT), + .rounds(tb_core_rounds), + + // Data input. + .data_in(tb_core_data_in), + + // Status output. + .ready(tb_core_ready), + + // Data out with valid signal. + .data_out(tb_core_data_out), + .data_out_valid(tb_core_data_out_valid) + ); + + + //---------------------------------------------------------------- + // clk_gen + // + // Clock generator process. + //---------------------------------------------------------------- + always + begin : clk_gen + #CLK_HALF_PERIOD tb_clk = !tb_clk; + end // clk_gen + + + //-------------------------------------------------------------------- + // dut_monitor + // + // Monitor that displays different types of information + // every cycle depending on what flags test cases enable. + // + // The monitor includes a cycle counter for the testbench. + //-------------------------------------------------------------------- + always @ (posedge tb_clk) + begin : dut_monitor + cycle_ctr = cycle_ctr + 1; + + // Display cycle counter. + if (display_cycle_ctr) + begin + $display("cycle = %08x:", cycle_ctr); + $display(""); + end + + // Display FSM control state and QR, DR counters. + if (display_ctrl_and_ctrs) + begin + $display("chacha_ctrl_reg = %01x", dut.chacha_ctrl_reg); + $display("qr_ctr_reg = %01x, dr_ctr_reg = %01x", dut.qr_ctr_reg, dut.dr_ctr_reg); + $display(""); + end + + // Display the internal state register. + if (display_state) + begin +// $display("Internal state:"); +// $display("0x%064x", dut.state_reg); +// $display(""); + end + + // Display the round processing state register X. + if (display_x_state) + begin + $display("Round state X:"); + $display("x0_reg = 0x%08x, x0_new = 0x%08x, x0_we = 0x%01x", dut.x0_reg, dut.x0_new, dut.x0_we); + $display("x1_reg = 0x%08x, x1_new = 0x%08x, x1_we = 0x%01x", dut.x1_reg, dut.x1_new, dut.x1_we); + $display("x2_reg = 0x%08x, x2_new = 0x%08x, x2_we = 0x%01x", dut.x2_reg, dut.x2_new, dut.x2_we); + $display("x3_reg = 0x%08x, x3_new = 0x%08x, x3_we = 0x%01x", dut.x3_reg, dut.x3_new, dut.x3_we); + $display("x4_reg = 0x%08x, x4_new = 0x%08x, x4_we = 0x%01x", dut.x4_reg, dut.x4_new, dut.x4_we); + $display("x5_reg = 0x%08x, x5_new = 0x%08x, x5_we = 0x%01x", dut.x5_reg, dut.x5_new, dut.x5_we); + $display("x6_reg = 0x%08x, x6_new = 0x%08x, x6_we = 0x%01x", dut.x6_reg, dut.x6_new, dut.x6_we); + $display("x7_reg = 0x%08x, x7_new = 0x%08x, x7_we = 0x%01x", dut.x7_reg, dut.x7_new, dut.x7_we); + $display("x8_reg = 0x%08x, x8_new = 0x%08x, x8_we = 0x%01x", dut.x8_reg, dut.x8_new, dut.x8_we); + $display("x9_reg = 0x%08x, x9_new = 0x%08x, x9_we = 0x%01x", dut.x9_reg, dut.x9_new, dut.x9_we); + $display("x10_reg = 0x%08x, x10_new = 0x%08x, x10_we = 0x%01x", dut.x10_reg, dut.x10_new, dut.x10_we); + $display("x11_reg = 0x%08x, x11_new = 0x%08x, x11_we = 0x%01x", dut.x11_reg, dut.x11_new, dut.x11_we); + $display("x12_reg = 0x%08x, x12_new = 0x%08x, x12_we = 0x%01x", dut.x12_reg, dut.x12_new, dut.x12_we); + $display("x13_reg = 0x%08x, x13_new = 0x%08x, x13_we = 0x%01x", dut.x13_reg, dut.x13_new, dut.x13_we); + $display("x14_reg = 0x%08x, x14_new = 0x%08x, x14_we = 0x%01x", dut.x14_reg, dut.x14_new, dut.x14_we); + $display("x15_reg = 0x%08x, x15_new = 0x%08x, x15_we = 0x%01x", dut.x15_reg, dut.x15_new, dut.x15_we); + $display(""); + end + + // Display the qround input and outputs. + if (display_qround) + begin + $display("a = %08x, b = %08x, c = %08x, d = %08x", dut.qr0_a, dut.qr0_b, dut.qr0_c, dut.qr0_d); + $display("qr0_a_prim = %08x, qr0_b_prim = %08x, qr0_c_prim = %08x, qr0_d_prim = %08x", dut.qr0_a_prim, dut.qr0_b_prim, dut.qr0_c_prim, dut.qr0_d_prim); + $display(""); + end + + end // dut_monitor + + + //---------------------------------------------------------------- + // dump_state() + // Dump the internal CHACHA state to std out. + //---------------------------------------------------------------- + task dump_state(); + begin + $display(""); + $display("Internal state:"); + $display("---------------"); +// $display("0x%064x", dut.state_reg); +// $display(""); + + $display("Round state X::"); + $display("x0_reg = %08x, x1_reg = %08x", dut.x0_reg, dut.x1_reg); + $display("x2_reg = %08x, x3_reg = %08x", dut.x2_reg, dut.x3_reg); + $display("x4_reg = %08x, x5_reg = %08x", dut.x4_reg, dut.x5_reg); + $display("x6_reg = %08x, x7_reg = %08x", dut.x6_reg, dut.x7_reg); + $display("x8_reg = %08x, x9_reg = %08x", dut.x8_reg, dut.x9_reg); + $display("x10_reg = %08x, x11_reg = %08x", dut.x10_reg, dut.x11_reg); + $display("x12_reg = %08x, x13_reg = %08x", dut.x12_reg, dut.x13_reg); + $display("x14_reg = %08x, x15_reg = %08x", dut.x14_reg, dut.x15_reg); + $display(""); + + $display("rounds_reg = %01x", dut.rounds_reg); + $display("qr_ctr_reg = %01x, dr_ctr_reg = %01x", dut.qr_ctr_reg, dut.dr_ctr_reg); + $display("block0_ctr_reg = %08x, block1_ctr_reg = %08x", dut.block0_ctr_reg, dut.block1_ctr_reg); + + $display(""); + + $display("chacha_ctrl_reg = %02x", dut.chacha_ctrl_reg); + $display(""); + + $display("data_in_reg = %064x", dut.data_in_reg); + $display("data_out_valid_reg = %01x", dut.data_out_valid_reg); + $display(""); + + $display("qr0_a_prim = %08x, qr0_b_prim = %08x", dut.qr0_a_prim, dut.qr0_b_prim); + $display("qr0_c_prim = %08x, qr0_d_prim = %08x", dut.qr0_c_prim, dut.qr0_d_prim); + $display(""); + end + endtask // dump_state + + + //---------------------------------------------------------------- + // dump_inout() + // Dump the status for input and output ports. + //---------------------------------------------------------------- + task dump_inout(); + begin + $display(""); + $display("State for input and output ports:"); + $display("---------------------------------"); + + $display("init = %01x", dut.init); + $display("next = %01x", dut.next); + $display("keylen = %01x", dut.keylen); + $display(""); + + $display("key = %032x", dut.key); + $display("iv = %016x", dut.iv); + $display(""); + + $display("ready = %01x", dut.ready); + $display("data_in = %064x", dut.data_in); + $display("data_out = %064x", dut.data_out); + $display("data_out_valid = %01x", dut.data_out_valid); + $display(""); + end + endtask // dump_inout + + + //---------------------------------------------------------------- + // test_quarterround() + // + // Test the quarterround by forcing the inputs of the logic + // to known given values and observing the result. + //---------------------------------------------------------------- + task test_quarterround(input [31 : 0] a, input [31 : 0] b, + input [31 : 0] c, input [31 : 0] d); + begin + $display("Test of quarterround."); + $display("a = 0x%08x, b = 0x%08x", a, b); + $display("c = 0x%08x, d = 0x%08x", c, d); + $display(""); + + dut.qr0_a = a; + dut.qr0_b = b; + dut.qr0_c = c; + dut.qr0_d = d; + #(2 * CLK_HALF_PERIOD); + + $display("a0 = 0x%08x, a1 = 0x%08x", dut.qr0.qr.a0, dut.qr0.qr.a1); + $display("b0 = 0x%08x, b1 = 0x%08x", dut.qr0.qr.b0, dut.qr0.qr.b1); + $display("b2 = 0x%08x, b3 = 0x%08x", dut.qr0.qr.b2, dut.qr0.qr.b3); + $display("c0 = 0x%08x, c1 = 0x%08x", dut.qr0.qr.c0, dut.qr0.qr.c1); + $display("d0 = 0x%08x, d1 = 0x%08x", dut.qr0.qr.d0, dut.qr0.qr.d1); + $display("d2 = 0x%08x, d3 = 0x%08x", dut.qr0.qr.d2, dut.qr0.qr.d3); + $display(""); + + $display("a_prim = 0x%08x, b_prim = 0x%08x", dut.qr0_a_prim, dut.qr0_b_prim); + $display("c_prim = 0x%08x, d_prim = 0x%08x", dut.qr0_c_prim, dut.qr0_d_prim); + $display(""); + end + endtask // test_quarterround + + + //---------------------------------------------------------------- + // qr_tests() + // + // Run some simple test on the qr logic. + // Note: Not self testing. No expected value used. + //---------------------------------------------------------------- + task qr_tests(); + begin + $display("*** Test of Quarterround:"); + $display(""); + test_quarterround(32'h11223344, 32'h11223344, 32'h11223344, 32'h11223344); + test_quarterround(32'h55555555, 32'h55555555, 32'h55555555, 32'h55555555); + end + endtask // qr_tests + + + //---------------------------------------------------------------- + // set_core_init() + // + // Set core init flag to given value. + //---------------------------------------------------------------- + task set_core_init(input value); + begin + tb_core_init = value; + end + endtask // set_core_init + + + //---------------------------------------------------------------- + // set_core_next() + // + // Set code next flag to given value. + //---------------------------------------------------------------- + task set_core_next(input value); + begin + tb_core_next = value; + end + endtask // set_core_next + + + //---------------------------------------------------------------- + // set_core_key_iv_rounds() + // + // Sets the core key, iv and rounds indata ports + // to the given values. + //---------------------------------------------------------------- + task set_core_key_iv_rounds(input [255 : 0] key, + input key_length, + input [63 : 0] iv, + input [4 : 0] rounds); + begin + tb_core_key = key; + tb_core_keylen = key_length; + tb_core_iv = iv; + tb_core_rounds = rounds; + end + endtask // set_core_key_iv + + + //---------------------------------------------------------------- + // cycle_reset() + // + // Cycles the reset signal on the dut. + //---------------------------------------------------------------- + task cycle_reset(); + begin + tb_reset_n = 0; + #(2 * CLK_HALF_PERIOD); + + @(negedge tb_clk) + + tb_reset_n = 1; + #(2 * CLK_HALF_PERIOD); + end + endtask // cycle_reset + + + //---------------------------------------------------------------- + // run_test_case + // + // Runs a test case based on the given key, keylenght, IV and + // expected data out from the DUT. + //---------------------------------------------------------------- + task run_test_case(input [7 : 0] major, + input [7 : 0] minor, + input [255 : 0] key, + input key_length, + input [63 : 0] iv, + input [4 : 0] rounds, + input [511 : 0] expected); + begin + $display("*** TC %0d-%0d started.", major, minor); + $display(""); + + tc_ctr = tc_ctr + 1; + + cycle_reset(); + set_core_key_iv_rounds(key, key_length, iv, rounds); + set_core_init(1); + + #(2 * CLK_HALF_PERIOD); + set_core_init(0); + dump_state(); + + // Wait for valid flag and check results. + @(posedge dut.data_out_valid); + dump_state(); + + if (tb_core_data_out == expected) + begin + $display("*** TC %0d-%0d successful", major, minor); + $display(""); + end + else + begin + $display("*** ERROR: TC %0d-%0d not successful", major, minor); + $display("Expected: 0x%064x", expected); + $display("Got: 0x%064x", tb_core_data_out); + $display(""); + + error_ctr = error_ctr + 1; + end + end + endtask // run_test_case + + + //---------------------------------------------------------------- + // display_test_result() + // + // Display the accumulated test results. + //---------------------------------------------------------------- + task display_test_result(); + begin + if (error_ctr == 0) + begin + $display("*** All %d test cases completed successfully", tc_ctr); + end + else + begin + $display("*** %02d test cases did not complete successfully.", error_ctr); + end + end + endtask // display_test_result + + + //---------------------------------------------------------------- + // init_dut() + // + // Set the input to the DUT to defined values. + //---------------------------------------------------------------- + task init_dut(); + begin + cycle_ctr = 0; + tb_clk = 0; + tb_reset_n = 0; + error_ctr = 0; + tc_ctr = 0; + set_core_key_iv_rounds(256'h0000000000000001000000000000000100000000000000010000000000000001, + 1'b0, + 64'h0000000000000001, + 5'b01000); + + tb_core_init = 0; + tb_core_next = 0; + tb_core_data_in = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; + end + endtask // init_dut + + + //---------------------------------------------------------------- + // set_display_prefs() + // + // Set the different monitor displays we want to see during + // simulation. + //---------------------------------------------------------------- + task set_display_prefs( + input cycles, + input ctrl_ctr, + input state, + input x_state, + input qround); + begin + display_cycle_ctr = cycles; + display_ctrl_and_ctrs = ctrl_ctr; + display_state = state; + display_x_state = x_state; + display_qround = qround; + end + endtask // set_display_prefs + + + //---------------------------------------------------------------- + // chacha_core_test + // + // The main test functionality. + //---------------------------------------------------------------- + initial + begin : chacha_core_test + $display(" -- Testbench for chacha_core started --"); + $display(""); + + set_display_prefs(0, 0, 1, 1, 0); + qr_tests(); + init_dut(); + $display("*** State at init:"); + $display(""); + dump_state(); + + #(4 * CLK_HALF_PERIOD); + @(negedge tb_clk) + tb_reset_n = 1; + #(2 * CLK_HALF_PERIOD); + $display("*** State after release of reset:"); + $display(""); + dump_state(); + + $display("TC1-1: All zero inputs. 128 bit key, 8 rounds."); + run_test_case(TC1, ONE, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_128_BITS, + 64'h0000000000000000, + EIGHT_ROUNDS, + 512'he28a5fa4a67f8c5defed3e6fb7303486aa8427d31419a729572d777953491120b64ab8e72b8deb85cd6aea7cb6089a101824beeb08814a428aab1fa2c816081b); + + + $display("TC1-2: All zero inputs. 128 bit key, 12 rounds."); + run_test_case(TC1, TWO, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_128_BITS, + 64'h0000000000000000, + TWELWE_ROUNDS, + 512'he1047ba9476bf8ff312c01b4345a7d8ca5792b0ad467313f1dc412b5fdce32410dea8b68bd774c36a920f092a04d3f95274fbeff97bc8491fcef37f85970b450); + + + $display("TC1-3: All zero inputs. 128 bit key, 20 rounds."); + run_test_case(TC1, THREE, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_128_BITS, + 64'h0000000000000000, + TWENTY_ROUNDS, + 512'h89670952608364fd00b2f90936f031c8e756e15dba04b8493d00429259b20f46cc04f111246b6c2ce066be3bfb32d9aa0fddfbc12123d4b9e44f34dca05a103f); + + + $display("TC1-4: All zero inputs. 256 bit key, 8 rounds."); + run_test_case(TC1, FOUR, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_256_BITS, + 64'h0000000000000000, + EIGHT_ROUNDS, + 512'h3e00ef2f895f40d67f5bb8e81f09a5a12c840ec3ce9a7f3b181be188ef711a1e984ce172b9216f419f445367456d5619314a42a3da86b001387bfdb80e0cfe42); + + + $display("TC1-5: All zero inputs. 256 bit key, 12 rounds."); + run_test_case(TC1, FIVE, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_256_BITS, + 64'h0000000000000000, + TWELWE_ROUNDS, + 512'h9bf49a6a0755f953811fce125f2683d50429c3bb49e074147e0089a52eae155f0564f879d27ae3c02ce82834acfa8c793a629f2ca0de6919610be82f411326be); + + + $display("TC1-6: All zero inputs. 256 bit key, 20 rounds."); + run_test_case(TC1, SIX, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_256_BITS, + 64'h0000000000000000, + TWENTY_ROUNDS, + 512'h76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586); + + + $display("TC2-1: One bit in key set, all zero IV. 128 bit key, 8 rounds."); + run_test_case(TC2, ONE, + 256'h0100000000000000000000000000000000000000000000000000000000000000, + KEY_128_BITS, + 64'h0000000000000000, + EIGHT_ROUNDS, + 512'h03a7669888605a0765e8357475e58673f94fc8161da76c2a3aa2f3caf9fe5449e0fcf38eb882656af83d430d410927d55c972ac4c92ab9da3713e19f761eaa14); + + + $display("TC2-2: One bit in key set, all zero IV. 256 bit key, 8 rounds."); + run_test_case(TC2, ONE, + 256'h0100000000000000000000000000000000000000000000000000000000000000, + KEY_256_BITS, + 64'h0000000000000000, + EIGHT_ROUNDS, + 512'hcf5ee9a0494aa9613e05d5ed725b804b12f4a465ee635acc3a311de8740489ea289d04f43c7518db56eb4433e498a1238cd8464d3763ddbb9222ee3bd8fae3c8); + + + $display("TC3-1: All zero key, one bit in IV set. 128 bit key, 8 rounds."); + run_test_case(TC3, ONE, + 256'h0000000000000000000000000000000000000000000000000000000000000000, + KEY_128_BITS, + 64'h0100000000000000, + EIGHT_ROUNDS, + 512'h25f5bec6683916ff44bccd12d102e692176663f4cac53e719509ca74b6b2eec85da4236fb29902012adc8f0d86c8187d25cd1c486966930d0204c4ee88a6ab35); + + + $display("TC4-1: All bits in key and IV are set. 128 bit key, 8 rounds."); + run_test_case(TC4, ONE, + 256'hffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, + KEY_128_BITS, + 64'hffffffffffffffff, + EIGHT_ROUNDS, + 512'h2204d5b81ce662193e00966034f91302f14a3fb047f58b6e6ef0d721132304163e0fb640d76ff9c3b9cd99996e6e38fad13f0e31c82244d33abbc1b11e8bf12d); + + + $display("TC5-1: Even bits in key, IV are set. 128 bit key, 8 rounds."); + run_test_case(TC5, ONE, + 256'h5555555555555555555555555555555555555555555555555555555555555555, + KEY_128_BITS, + 64'h5555555555555555, + EIGHT_ROUNDS, + 512'hf0a23bc36270e18ed0691dc384374b9b2c5cb60110a03f56fa48a9fbbad961aa6bab4d892e96261b6f1a0919514ae56f86e066e17c71a4176ac684af1c931996); + + + $display("TC6-1: Odd bits in key, IV are set. 128 bit key, 8 rounds."); + run_test_case(TC6, ONE, + 256'haaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + KEY_128_BITS, + 64'haaaaaaaaaaaaaaaa, + EIGHT_ROUNDS, + 512'h312d95c0bc38eff4942db2d50bdc500a30641ef7132db1a8ae838b3bea3a7ab03815d7a4cc09dbf5882a3433d743aced48136ebab73299506855c0f5437a36c6); + + + $display("TC7-1: Increasing, decreasing sequences in key and IV. 128 bit key, 8 rounds"); + run_test_case(TC7, ONE, + 256'h00112233445566778899aabbccddeeff00000000000000000000000000000000, + KEY_128_BITS, + 64'h0f1e2d3c4b596877, + EIGHT_ROUNDS, + 512'ha7a6c81bd8ac106e8f3a46a1bc8ec702e95d18c7e0f424519aeafb54471d83a2bf888861586b73d228eaaf82f9665a5a155e867f93731bfbe24fab495590b231); + + + $display("TC7-2: Increasing, decreasing sequences in key and IV. 256 bit key, 8 rounds."); + run_test_case(TC7, TWO, + 256'h00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100, + KEY_256_BITS, + 64'h0f1e2d3c4b596877, + EIGHT_ROUNDS, + 512'h60fdedbd1a280cb741d0593b6ea0309010acf18e1471f68968f4c9e311dca149b8e027b47c81e0353db013891aa5f68ea3b13dd2f3b8dd0873bf3746e7d6c567); + + + $display("TC8-128-8: Random inputs. 128 bit key, 8 rounds."); + run_test_case(TC8, ONE, + 256'hc46ec1b18ce8a878725a37e780dfb73500000000000000000000000000000000, + KEY_128_BITS, + 64'h1ada31d5cf688221, + EIGHT_ROUNDS, + 512'h6a870108859f679118f3e205e2a56a6826ef5a60a4102ac8d4770059fcb7c7bae02f5ce004a6bfbbea53014dd82107c0aa1c7ce11b7d78f2d50bd3602bbd2594); + + + // Finish in style. + $display("*** chacha_core simulation done ***"); + display_test_result(); + $finish; + end // chacha_core_test + +endmodule // tb_chacha_core + +//====================================================================== +// EOF tb_chacha_core.v +//====================================================================== -- cgit v1.2.3