aboutsummaryrefslogblamecommitdiff
path: root/bench/tb_wrapper.v
blob: 161bff4340218b53b4db6bd2f859f38329b79d17 (plain) (tree)































                                                                           



























































                                                                                                   
                          























                                         
                                    
                         
                                    
            

                                                                                                   
              







                                                                                                              






                                                                                                              

                                                                                                              


                                                                                                              

























                                                                                                               

                                                                                                               
                                                                                                               



                                                                                                                 





                                          














































































                                                                        
//======================================================================
//
// 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<num_ticks; _n=_n+1)
            wait_clk_bus_tick;
    endtask


endmodule