OpenCores
URL https://opencores.org/ocsvn/ftdi_wb_bridge/ftdi_wb_bridge/trunk

Subversion Repositories ftdi_wb_bridge

[/] [ftdi_wb_bridge/] [trunk/] [testbench/] [top_tb.sv] - Rev 2

Compare with Previous | Blame | View Log

`timescale 100ps/100ps

//-----------------------------------------------------------------
// Module
//-----------------------------------------------------------------
module top_tb ;

//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter MAX_DELAY      = 0;

//-----------------------------------------------------------------
// Simulation
//-----------------------------------------------------------------
`include "simulation.svh"

`CLOCK_GEN(clk, 100)
`RESET_GEN(rst, 100)

`ifdef TRACE
    `TB_VCD(top_tb, "waveform.vcd")
`endif

`TB_RUN_FOR(10ms)

//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
wire [31:0]         mem_addr;
wire [31:0]         mem_data_w;
wire [31:0]         mem_data_r;
wire [3:0]          mem_sel;
wire                mem_stb;
wire                mem_cyc;
wire                mem_we;
wire                mem_stall;
wire                mem_ack;

reg                 ftdi_rxf;
reg                 ftdi_txe;
wire                ftdi_rd;
wire                ftdi_wr;
reg [7:0]           ftdi_data;

wire [7:0]          ftdi_data_io_w;

reg [7:0]           mem[*];

reg [7:0]           gpio_in;
wire [7:0]          gpio_out;

//-----------------------------------------------------------------
// mem_write
//-----------------------------------------------------------------
task automatic mem_write(input [31:0] addr, input [7:0] data);
begin
    mem[addr] = data;
end
endtask

//-----------------------------------------------------------------
// mem_read
//-----------------------------------------------------------------
task automatic mem_read(input [31:0] addr, output [7:0] data);
begin
    if (mem.exists(addr))
        data = mem[addr];
    else
        data = 8'bx;
end
endtask
//-----------------------------------------------------------------
// write_to_ftdi
//-----------------------------------------------------------------
task automatic write_to_ftdi(input [31:0] addr, input [11:0] len);
begin
    integer i;
    reg [7:0] data;
    reg [31:0] addr_tmp;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_rxf        <= 1'b0;
    ftdi_data       <= {len[11:8], 4'h1}; // WRITE

    @(posedge ftdi_rd);
    ftdi_rxf        <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_rxf        <= 1'b0;
    ftdi_data       <= len[7:0]; // LEN

    @(posedge ftdi_rd);
    ftdi_rxf        <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    // ADDR
    addr_tmp = addr;
    for (i=0;i<4;i=i+1)
    begin
        ftdi_rxf   <= 1'b0;

        data = addr_tmp[31:24];
        addr_tmp = {addr_tmp[23:0], 8'b0};

        $display("ADDR%d: %x", i, data);
        ftdi_data  <= data; // DATA

        @(posedge ftdi_rd);
        ftdi_rxf        <= 1'b1;

        repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
    end

    // DATA
    addr_tmp = addr;
    for (i=0;i<len;i=i+1)
    begin
        ftdi_rxf   <= 1'b0;

        data = $urandom;

        $display("BYTE%d: %x", i, data);
        ftdi_data  <= data; // DATA

        mem_write(addr_tmp, data);
        addr_tmp += 1;

        @(posedge ftdi_rd);
        ftdi_rxf    <= 1'b1;

        repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
    end 
end
endtask
//-----------------------------------------------------------------
// write_gp
//-----------------------------------------------------------------
task automatic write_gp(input [7:0] gp);
begin
    integer i;
    reg [7:0] data;
    reg [31:0] addr_tmp;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_rxf        <= 1'b0;
    ftdi_data       <= {4'b0, 4'h3}; // GP_WR

    @(posedge ftdi_rd);
    ftdi_rxf        <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_rxf   <= 1'b0;

    data = $urandom;

    ftdi_data  <= data; // DATA

    mem_write(addr_tmp, data);
    addr_tmp += 1;

    @(posedge ftdi_rd);
    ftdi_rxf    <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    repeat (2) @(posedge clk);
    `ASSERT(gpio_out == data);
end
endtask
//-----------------------------------------------------------------
// read_gp
//-----------------------------------------------------------------
task automatic read_gp(output [7:0] gp);
begin
    integer i;
    reg [7:0] data;
    reg [31:0] addr_tmp;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_rxf        <= 1'b0;
    ftdi_data       <= {4'b0, 4'h4}; // GP_RD

    @(posedge ftdi_rd);
    ftdi_rxf        <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_txe   <= 1'b0;

    @(posedge ftdi_wr);

    $display("GPIO_IN: %x", u_dut.u_sync.tx_data_q);
    
    ftdi_txe    <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
end
endtask
//-----------------------------------------------------------------
// check_mem
//-----------------------------------------------------------------
task automatic check_mem(input [31:0] addr, input [31:0] len);
begin
    integer   i;
    reg [7:0] data;
    reg [7:0] actual_data;

    // Compare
    for (i=0;i<len;i=i+1)
    begin

        mem_read(addr, data);
        u_wbs.read8(addr, actual_data);

        if (data !== actual_data)
        begin
            $display("Error @ %x: %x != %x", addr, data, actual_data);
            $finish;
        end

        addr += 1;

    end   
end
endtask
//-----------------------------------------------------------------
// read_from_ftdi
//-----------------------------------------------------------------
task automatic read_from_ftdi(input [31:0] addr, input [11:0] len);
begin
    integer i;
    reg [7:0] data;
    reg [31:0] addr_tmp;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_rxf        <= 1'b0;
    ftdi_data       <= {len[11:8], 4'h2}; // READ

    @(posedge ftdi_rd);
    ftdi_rxf        <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    ftdi_rxf        <= 1'b0;
    ftdi_data       <= len[7:0]; // LEN

    @(posedge ftdi_rd);
    ftdi_rxf        <= 1'b1;

    repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);

    // ADDR
    addr_tmp = addr;
    for (i=0;i<4;i=i+1)
    begin
        ftdi_rxf   <= 1'b0;

        data = addr_tmp[31:24];
        addr_tmp = {addr_tmp[23:0], 8'b0};

        $display("ADDR%d: %x", i, data);
        ftdi_data  <= data; // DATA

        @(posedge ftdi_rd);
        ftdi_rxf        <= 1'b1;

        repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
    end

    // DATA
    addr_tmp = addr;
    for (i=0;i<len;i=i+1)
    begin
        ftdi_txe   <= 1'b0;

        @(posedge ftdi_wr);

        data = $urandom;

        $display("READ%d: %x", i, u_dut.u_sync.tx_data_q);
        // TODO: COMP
        mem_write(addr_tmp, u_dut.u_sync.tx_data_q);
        addr_tmp += 1;
        
        ftdi_txe    <= 1'b1;

        repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
    end 
end
endtask

//-----------------------------------------------------------------
// Testbench
//-----------------------------------------------------------------
initial
begin
    reg [7:0] tmp;

    ftdi_rxf        = 1'b1;
    ftdi_data       = 8'bz;
    ftdi_txe        = 1'b1;

    gpio_in         = 8'h55;

    forever
    begin
        repeat (10) @(posedge clk);

        write_to_ftdi(32'h00000000, 16);
        write_gp(4'ha);
        write_to_ftdi(32'h00000010, 16);

        read_gp(tmp);
        `ASSERT(tmp == 8'h55);

        repeat (100) @(posedge clk);
        check_mem(32'h00000000, 32);

        read_from_ftdi(32'h00000000, 16);

        repeat (100) @(posedge clk);
        check_mem(32'h00000000, 16);

        write_to_ftdi(32'h00000100, 15);
        repeat (100) @(posedge clk);
        check_mem(32'h00000100, 15);

        write_to_ftdi(32'h00000201, 14);
        repeat (100) @(posedge clk);
        check_mem(32'h00000201, 14);

        write_to_ftdi(32'h00000001, 1);
        repeat (100) @(posedge clk);
        check_mem(32'h00000001, 1);        

        $finish;
    end
end

//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
assign ftdi_data_io_w = !ftdi_rd ? ftdi_data : 8'bz;

ftdi_if
u_dut
(
    .clk_i(clk),
    .rst_i(rst),

    // FTDI (async FIFO interface)
    .ftdi_rxf_i(ftdi_rxf),
    .ftdi_txe_i(ftdi_txe),
    .ftdi_siwua_o(),
    .ftdi_wr_o(ftdi_wr),
    .ftdi_rd_o(ftdi_rd),
    .ftdi_d_io(ftdi_data_io_w),

    // General Purpose
    .gp_o(gpio_out),
    .gp_i(gpio_in),

    // Wishbone Interface
    .mem_addr_o(mem_addr),
    .mem_data_o(mem_data_w),
    .mem_data_i(mem_data_r),
    .mem_sel_o(mem_sel),
    .mem_we_o(mem_we),
    .mem_cyc_o(mem_cyc),
    .mem_stb_o(mem_stb),
    .mem_stall_i(mem_stall),
    .mem_ack_i(mem_ack)
);

wb_slave
#(
    .RANDOM_STALLS(1),
    .MAX_RESP_RATE(0)
)
u_wbs
(
    .clk_i(clk),
    .rst_i(rst),
    
    .addr_i(mem_addr), 
    .data_i(mem_data_w), 
    .data_o(mem_data_r), 
    .sel_i(mem_sel), 
    .cyc_i(mem_cyc), 
    .stb_i(mem_stb), 
    .cti_i(3'b111),
    .we_i(mem_we), 
    .stall_o(mem_stall),
    .ack_o(mem_ack)         
);

endmodule

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.