//====================================================================== // // Copyright (c) 2019, NORDUnet A/S All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // - Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // - Neither the name of the NORDUnet nor the names of its contributors may // be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //====================================================================== `timescale 1ns / 1ps module tb_wrapper; // // Clocks // `define CLK_FREQUENCY_MHZ (100.0) `define CLK_PERIOD_NS (1000.0 / `CLK_FREQUENCY_MHZ) `define CLK_PERIOD_HALF_NS (0.5 * `CLK_PERIOD_NS) `define CLK_PERIOD_QUARTER_NS (0.5 * `CLK_PERIOD_HALF_NS) `define CLK_BUS_FREQUENCY_MHZ (25.0) `define CLK_BUS_PERIOD_NS (1000.0 / `CLK_BUS_FREQUENCY_MHZ) `define CLK_BUS_PERIOD_HALF_NS (0.5 * `CLK_BUS_PERIOD_NS) reg clk = 1'b1; reg clk_bus = 1'b1; reg clk_bus_dly = 1'b0; wire clk_bus_idle = clk_bus & clk_bus_dly; always #`CLK_PERIOD_HALF_NS clk <= ~clk; always #`CLK_BUS_PERIOD_HALF_NS clk_bus <= ~clk_bus; always @(clk_bus) clk_bus_dly <= #(`CLK_BUS_PERIOD_HALF_NS - `CLK_PERIOD_QUARTER_NS) clk_bus; // // Clock Sync // task sync_clk_bus; while (clk_bus_idle !== 1) _wait_quarter_clk_tick; endtask // // Reset // reg rst_n = 1'b0; // // System Bus // reg bus_cs = 1'b0; reg bus_we = 1'b0; reg [11:0] bus_addr; reg [31:0] bus_data_wr; wire [31:0] bus_data_rd; // // UUT // modexpng_wrapper uut ( .clk (clk_bus), .rst_n (rst_n), .clk_core (clk), .cs (bus_cs), .we (bus_we), .address (bus_addr), .write_data (bus_data_wr), .read_data (bus_data_rd) ); // // Script // initial main; // // Main Routine (Control/Status, Bus) // reg [31:0] ti, to; task main; begin sync_clk_bus; wait_clk_bus_ticks(100); rst_n = 1'b1; wait_clk_bus_ticks(100); // use the following code to observe how the core handles invalid parameter settings... /* bus_read('h11, to); $display("modulus_bits = %0d", to); ti = 100; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 510; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 511; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 512; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 513; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 514; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 1022; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 1023; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 1024; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 1025; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 1026; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 4094; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 4095; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 4096; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 4097; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); ti = 4098; bus_write('h11, ti); bus_read('h11, to); $display("modulus_bits = %0d -> %0d", ti, to); bus_read('h12, to); $display("exponent_bits = %0d", to); ti = 0; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 1; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 2; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 3; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 4; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 5; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 6; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 7; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 8; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 100; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 510; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 511; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 512; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 513; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 514; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 1022; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 1023; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 1024; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 1025; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 1026; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 4094; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 4095; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 4096; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 4097; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to); ti = 4098; bus_write('h12, ti); bus_read('h12, to); $display("exponent_bits = %0d -> %0d", ti, to);*/ // use the following to observe how the core handles "next" bit rising edge //ti = 0; bus_write('h08, ti); //ti = 2; bus_write('h08, ti); //ti = 0; bus_write('h08, ti); //ti = 2; bus_write('h08, ti); //ti = 0; bus_write('h08, ti); //ti = 2; bus_write('h08, ti); end endtask // // _bus_drive() // task _bus_drive; input cs; input we; input [11:0] addr; input [31:0] data; {bus_cs, bus_we, bus_addr, bus_data_wr} <= {cs, we, addr, data}; endtask // // bus_write() // task bus_write; input [ 9:0] offset; input [31:0] data; begin _bus_drive(1'b1, 1'b1, {2'b00, offset}, data); wait_clk_bus_tick; _bus_drive(1'b0, 1'b0, 12'hXXX, 32'hXXXXXXXX); end endtask // // bus_read() // task bus_read; input [ 9:0] offset; output [31:0] data; begin _bus_drive(1'b1, 1'b0, {2'b00, offset}, 32'hXXXXXXXX); wait_clk_bus_tick; data = bus_data_rd; _bus_drive(1'b0, 1'b0, 12'hXXX, 32'hXXXXXXXX); end endtask // // Variables // integer _n; // // _wait_quarter_clk_tick() // task _wait_quarter_clk_tick; #`CLK_PERIOD_QUARTER_NS; endtask // // wait_clk_bus_tick() // task wait_clk_bus_tick; #`CLK_BUS_PERIOD_NS; endtask // // wait_clk_bus_ticks() // task wait_clk_bus_ticks; input integer num_ticks; for (_n=0; _n