aboutsummaryrefslogblamecommitdiff
path: root/bench/tb_core_selector.v
blob: 0b2691c0f1a262af85a2ad9c45df978cdfb1931d (plain) (tree)




































                                                                           































































































































































































                                                                                                                  
//======================================================================
//
// tb_core_selector.v
// ------------------
//
// Author: Pavel Shatov
// Copyright 2020 The Commons Conservancy Cryptech Project
// SPDX-License-Identifier: BSD-3-Clause
//
// 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 copyright holder 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_core_selector;


    //
    // System Clock, System Reset
    //
    `define SYS_CLK_FREQUENCY_MHZ     ( 100.0                         )
    `define SYS_CLK_PERIOD_NS         (1000.0 / `SYS_CLK_FREQUENCY_MHZ)
    `define SYS_CLK_PERIOD_HALF_NS    (   0.5 * `SYS_CLK_PERIOD_NS    )
    
	reg sys_clk = 1'b0;
    initial forever #`SYS_CLK_PERIOD_HALF_NS sys_clk = ~sys_clk;
    
    `define SYS_RST_N_ACTIVE   1'b0
    `define SYS_RST_N_INACTIVE 1'b1
    
    reg sys_rst_n = `SYS_RST_N_ACTIVE;
    
    
    //
    // System Bus
    //
    reg  [23: 0] sys_fmc_addr;
    reg          sys_fmc_wr = 1'b0;
    reg          sys_fmc_rd = 1'b0;
    wire [31: 0] sys_read_data;
    reg  [31: 0] sys_write_data;
    wire         sys_error;
    

    //
	// UUT
    //
    core_selector uut
    (
        .sys_clk        (sys_clk),
        .sys_rst_n      (sys_rst_n),
        
        .sys_fmc_addr   (sys_fmc_addr),
        .sys_fmc_wr     (sys_fmc_wr),
        .sys_fmc_rd     (sys_fmc_rd),
        .sys_read_data  (sys_read_data),
        .sys_write_data (sys_write_data),
        .sys_error      (sys_error),
        
        .mkm_sclk       (),
        .mkm_cs_n       (),
        .mkm_do         (1'b0),
        .mkm_di         (),
        
        .core_clk       (1'b0),
        
        .noise          (1'b0),
        .debug          ()
    );
    
    
    //
    // Script
    //
    
    //
    // Here's what the following routine does. We know that at address 0 there's always a BOARD_REGS core, which
    // has a 32-bit dummy register at offset 255. ECDSA cores also have a 32-bit dummy register at offset 15.
    // We write some values into the two dummy registers to test the address decoding logic (we write to two cores
    // with different numbers, the offsets of registers are also different). Then we do a readback and compare
    // the read value with the written one. The code assumes, that the default "hsm" core configuration is used,
    // where the number of ECDSA-256 is 0x37. If this is not the case, adapt the first parameter passed to the
    // sys_bus_write() calls.  
    //
    
    localparam [31:0] MAGIC_1 = 32'hCCAA5533; 
    localparam [31:0] MAGIC_2 = 32'hCA5335AC;
    
    reg [31:0] wr, rd;
    initial begin
        
        wait_sys_clk_ticks(200);
        sys_rst_n = `SYS_RST_N_INACTIVE;
        wait_sys_clk_ticks(100);
        
        wr = MAGIC_1;
        sys_bus_write(16'h0000, 8'd255, wr);
        wait_sys_clk_ticks(10);
        
        wr = MAGIC_2;
        sys_bus_write(16'h0037, 8'd15, wr);
        wait_sys_clk_ticks(10);

        wr = MAGIC_1;         
        sys_bus_read(16'h0000, 8'd255, rd);
        wait_sys_clk_ticks(10);
        if (rd !== wr) begin
            $display("ERROR: wr = 0x%08x, rd = 0x%08x", wr, rd);
            wait_sys_clk_ticks(100);
            $finish;
        end
        
        wr = MAGIC_2;
        sys_bus_read(16'h0037, 8'd15, rd);
        wait_sys_clk_ticks(10);
        if (rd !== wr) begin
            $display("ERROR: wr = 0x%08x, rd = 0x%08x", wr, rd);
            wait_sys_clk_ticks(100);
            $finish;
        end
        
        $display("Test passed.");
        $finish;
        
    end


    //
    // _wait_half_sys_clk_tick()
    //
    task _wait_half_sys_clk_tick;
        #`SYS_CLK_PERIOD_HALF_NS;
    endtask
    

    //
    // wait_sys_clk_tick()
    //
    task wait_sys_clk_tick;
        begin
            _wait_half_sys_clk_tick;
            _wait_half_sys_clk_tick;
        end
    endtask


    //
    // wait_sys_clk_ticks()
    //    
    task wait_sys_clk_ticks;
        input integer _num_ticks;
        integer _n;
        for (_n=0; _n<_num_ticks; _n=_n+1)
            wait_sys_clk_tick;
    endtask
    
    
    //
    // _sys_bus_drive()
    //    
    task _sys_bus_drive;
        input [23: 0] _addr;
        input         _wr;
        input         _rd;
        input [31: 0] _write_data;
        {sys_fmc_addr, sys_fmc_wr, sys_fmc_rd, sys_write_data} <=
        {       _addr,        _wr,        _rd,    _write_data} ;
    endtask
    
    
    //
    // sys_bus_read()
    //
    task sys_bus_read;
        input  [15:0] _num;
        input  [ 7:0] _reg;
        output [31:0] _data;
        begin
            _sys_bus_drive({_num, _reg}, 1'b0, 1'b1, {32{1'bX}});
            wait_sys_clk_tick;
            _sys_bus_drive(24'hXXXX, 1'b0, 1'b0, {32{1'bX}});
            wait_sys_clk_ticks(3);
            _data = sys_read_data;
            _sys_bus_drive(24'hXXXX, 1'b0, 1'b0, {32{1'bX}});
        end
    endtask

    
    //
    // sys_bus_write()
    //
    task sys_bus_write;
        input [15:0] _num;
        input [ 7:0] _reg;
        input [31:0] _data;
        begin
            _sys_bus_drive({_num, _reg}, 1'b1, 1'b0, _data);
            wait_sys_clk_tick;
            _sys_bus_drive(24'hXXXX, 1'b0, 1'b0, {32{1'bX}});
        end
    endtask

      
endmodule