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

Subversion Repositories ftdi_wb_bridge

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

Compare with Previous | Blame | View Log

//-----------------------------------------------------------------
// Module
//-----------------------------------------------------------------
module wb_slave
(
    input                               clk_i /*verilator public*/, 
    input                               rst_i /*verilator public*/, 

    // Wishbone I/F
    input [31:0]                        addr_i /*verilator public*/,
    input [31:0]                        data_i /*verilator public*/,
    output reg [31:0]                   data_o /*verilator public*/,
    input [3:0]                         sel_i /*verilator public*/,
    input                               cyc_i /*verilator public*/,
    input                               stb_i /*verilator public*/,
    input [2:0]                         cti_i /*verilator public*/,
    input                               we_i /*verilator public*/,
    output reg                          ack_o /*verilator public*/,
    output reg                          stall_o /*verilator public*/
);

//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter MAX_RESP_RATE     = 0;
parameter RESP_DELAY_RATE   = 3;

parameter RANDOM_STALLS     = 1;
parameter STALL_RATE        = 3;

`include "simulation.svh"

//-----------------------------------------------------------------
// Request Queue
//-----------------------------------------------------------------
typedef struct
{
    reg [31:0] address;
    reg [31:0] data;
    reg [3:0]  sel;
    reg        we;
} request_t;

request_t requests[$];

//-----------------------------------------------------------------
// Memory
//-----------------------------------------------------------------
reg [31:0] mem[*];

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

//-----------------------------------------------------------------
// read
//-----------------------------------------------------------------
task automatic read(input [31:0] addr, output [31:0] data);
begin
    if (mem.exists(addr[31:2]))
        data = mem[addr[31:2]];
    else
        data = 32'bx;
end
endtask
//-----------------------------------------------------------------
// read8
//-----------------------------------------------------------------
task automatic read8(input [31:0] addr, output [7:0] data);
begin
    if (mem.exists(addr[31:2]))
    begin
        reg [31:0] tmp_data;
        tmp_data = mem[addr[31:2]];

        case (addr[1:0])
            0: data = tmp_data[7:0];
            1: data = tmp_data[15:8];
            2: data = tmp_data[23:16];
            3: data = tmp_data[31:24];
        endcase
    end
    else
        data = 8'bx;
end
endtask
//-----------------------------------------------------------------
// write_bytes
//-----------------------------------------------------------------
task automatic write_bytes(input [31:0] addr, input [31:0] data, input [31:0] sel);
begin
    reg [31:0] new_data;

    read(addr, new_data);

    if (sel[3])
        new_data[31:24] = data[31:24];
    if (sel[2])
        new_data[23:16] = data[23:16];
    if (sel[1])
        new_data[15:8]  = data[15:8];
    if (sel[0])
        new_data[7:0]   = data[7:0];

    write(addr, new_data);
end
endtask

//-----------------------------------------------------------------
// response
//-----------------------------------------------------------------
initial
begin
    request_t  req;

    ack_o  = 1'b0;
    data_o = 32'bz;

    forever
    begin
        @(posedge clk_i);

        ack_o  = 1'b0;
        data_o = 32'bz;

        if (!MAX_RESP_RATE)
        begin
            repeat ($urandom_range(RESP_DELAY_RATE,0)) @(posedge clk_i);
        end

        if (requests.size() > 0)
        begin
            req = requests.pop_front();

            // Write
            if (req.we)
            begin
                ack_o  = 1'b1;
                data_o = 32'bz;
        
                write_bytes(req.address, req.data, req.sel);
            end
            // Read
            else
            begin
                ack_o  = 1'b1;
                read(req.address, data_o);
            end
        end
    end
end

//-----------------------------------------------------------------
// request
//-----------------------------------------------------------------
always @(posedge clk_i)
begin
    // Request presented and accepted
    if (stb_i && cyc_i && !stall_o)
    begin
        request_t req;

        req.address = addr_i;
        req.data    = data_i;
        req.sel     = sel_i;
        req.we      = we_i;

        requests.push_back(req);
    end
end

always @(posedge rst_i or posedge clk_i)
if (rst_i)
    stall_o <= 1'b0;
else
begin
    if (RANDOM_STALLS)
        stall_o <= ($urandom_range(STALL_RATE,0) == 0);
end

//-----------------------------------------------------------------
// CTI
//-----------------------------------------------------------------
initial
begin
    reg        burst;
    reg [2:0]  burst_cnt;

    burst  = 1'b0;
    burst_cnt = 0;

    forever
    begin
        @(posedge clk_i);

        // Start of burst
        if (stb_i && cyc_i && !stall_o && cti_i == 3'b010)
        begin
            burst_cnt = 7;
            burst = 1;

            while (burst_cnt != 0)
            begin
                @(posedge clk_i);

                if (stb_i && cyc_i && !stall_o)
                begin
                    if (burst_cnt == 1)
                    begin
                        `ASSERT(cti_i == 3'b111);
                    end

                    burst_cnt = burst_cnt - 1;
                end
            end

            burst = 0;
        end
        else if (stb_i && cyc_i && !stall_o)
        begin
            `ASSERT(cti_i == 3'b111);
        end
    end
end

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.