`timescale 1ns / 1ps
module tb_wrapper;
//
// Test Vectors
//
`include "modexp_fpga_model_vectors.v";
/*
* Settings
*/
localparam USE_OPERAND_ADDR_WIDTH = 7;
localparam USE_SYSTOLIC_ARRAY_POWER = 1;
/*
* Clock (100 MHz)
*/
reg clk;
initial clk = 1'b0;
always #5 clk = ~clk;
/*
* Reset
*/
reg rst_n;
/*
* Access Bus
*/
reg bus_cs;
reg bus_we;
reg [USE_OPERAND_ADDR_WIDTH+3:0] bus_addr;
reg [ 32-1:0] bus_wr_data;
wire [ 32-1:0] bus_rd_data;
modexpa7_wrapper #
(
.OPERAND_ADDR_WIDTH (USE_OPERAND_ADDR_WIDTH),
.SYSTOLIC_ARRAY_POWER (USE_SYSTOLIC_ARRAY_POWER)
)
uut
(
.clk (clk),
.rst_n (rst_n),
.cs (bus_cs),
.we (bus_we),
.address (bus_addr),
.write_data (bus_wr_data),
.read_data (bus_rd_data)
);
integer i;
reg [31: 0] tmp;
reg [383:0] shreg;
reg poll;
initial begin
//
rst_n = 0;
//
bus_cs = 0;
bus_we = 0;
bus_addr = 'bX;
bus_wr_data = 'bX;
//
#200;
//
rst_n = 1;
//
// read common registers to make sure core header reads out ok
//
read_reg('h00, tmp); // NAME0
read_reg('h01, tmp); // NAME1
read_reg('h02, tmp); // VERSION
//
read_reg('h13, tmp); // BUFFER_BITS
read_reg('h14, tmp); // ARRAY_BITS
//
write_reg('h12, 32'd384); // EXPONENT_BITS
read_reg ('h12, tmp);
//
write_reg('h11, 32'd384); // MODULUS_BITS
read_reg ('h11, tmp);
//
write_reg('h10, 32'd0); // MODE
read_reg ('h10, tmp);
//
// fill in 384-bit modulus
//
shreg = N_384;
for (i=0; i<384/32; i=i+1) begin
write_bank(3'b000, i[USE_OPERAND_ADDR_WIDTH-1:0], shreg[31:0]);
shreg = shreg >> 32;
end
//
// start precomputation
//
write_reg('h08, 32'd0); // CONTROL.init = 0
write_reg('h08, 32'd1); // CONTROL.init = 1
//
// wait for precomputation to complete
//
poll = 1;
while (poll) begin
#10;
read_reg('h09, tmp); // tmp = STATUS
poll = ~tmp[0]; // poll = STATUS.ready
end
//
// move modulus-dependent coefficient and Montgomery factor
// from "output" to "input" banks
//
for (i=0; i<384/32; i=i+1) begin
read_bank (3'b100, i[USE_OPERAND_ADDR_WIDTH-1:0], tmp);
write_bank(3'b101, i[USE_OPERAND_ADDR_WIDTH-1:0], tmp);
read_bank (3'b110, i[USE_OPERAND_ADDR_WIDTH-1:0], tmp);
write_bank(3'b111, i[USE_OPERAND_ADDR_WIDTH-1:0], tmp);
end
//
// fill in 384-bit message
//
shreg = M_384;
for (i=0; i<384/32; i=i+1) begin
write_bank(3'b001, i[USE_OPERAND_ADDR_WIDTH-1:0], shreg[31:0]);
shreg = shreg >> 32;
end
//
// fill in 384-bit exponent
//
shreg = D_384;
for (i=0; i<384/32; i=i+1) begin
write_bank(3'b010, i[USE_OPERAND_ADDR_WIDTH-1:0], shreg[31:0]);
shreg = shreg >> 32;
end
//
// start exponentiation
//
write_reg('h08, 32'd0); // CONTROL.next = 0
write_reg('h08, 32'd2); // CONTROL.next = 1
//
// wait for exponentiation to complete
//
poll = 1;
while (poll) begin
#10;
read_reg('h09, tmp); // tmp = STATUS
poll = ~tmp[1]; // poll = STATUS.valid
end
//
// read result
//
for (i=0; i<384/32; i=i+1) begin
read_bank(3'b011, i[USE_OPERAND_ADDR_WIDTH-1:0], tmp);
shreg = {tmp, shreg[383:32]};
end
//
end
task read_reg;
input [USE_OPERAND_ADDR_WIDTH+2:0] addr;
output [ 32-1:0] data;
begin
bus_cs = 1;
bus_addr = {1'b0, addr};
#10;
bus_cs = 0;
bus_addr = 'bX;
data = bus_rd_data;
end
endtask
task read_bank;
input [ 2:0] bank;
input [USE_OPERAND_ADDR_WIDTH-1:0] addr;
output [ 32-1:0] data;
begin
bus_cs = 1;
bus_addr = {1'b1, bank, addr};
#10;
bus_cs = 0;
bus_addr = 'bX;
data = bus_rd_data;
end
endtask
task write_reg;
input [USE_OPERAND_ADDR_WIDTH+2:0] addr;
input [ 32-1:0] data;
begin
bus_cs = 1;
bus_we = 1;
bus_addr = {1'b0, addr};
bus_wr_data = data;
#10;
bus_cs = 0;
bus_we = 0;
bus_addr = 'bX;
end
endtask
task write_bank;
input [ 2:0] bank;
input [USE_OPERAND_ADDR_WIDTH-1:0] addr;
input [ 32-1:0] data;
begin
bus_cs = 1;
bus_we = 1;
bus_addr = {1'b1, bank, addr};
bus_wr_data = data;
#10;
bus_cs = 0;
bus_we = 0;
bus_addr = 'bX;
end
endtask
endmodule