Newer
Older

Dimitris Lampridis
committed
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// GN4124 core for PCIe FMC carrier
// http://www.ohwr.org/projects/gn4124-core
//------------------------------------------------------------------------------
//
// unit name: main
//

Dimitris Lampridis
committed
// description: This is a simple example testbench, to demonstrate how to use

Dimitris Lampridis
committed
// the SystemVerilog BFM of the GN4124 to perform simple accesses over wishbone.
//
// The testbench simply connects the wishbone master of the GN4124 to its own

Dimitris Lampridis
committed
// DMA configuration wishbone slave and attaches a pre-initialised dummy RAM
// with a wishbone interface to the pipelined DMA interface in order to perform
// a DMA read.

Dimitris Lampridis
committed
//
//------------------------------------------------------------------------------
// Copyright CERN 2019
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------
`timescale 1ns/1ps
`include "gn4124_bfm.svh"
import wishbone_pkg::*;
module main;
reg clk_125m = 0;

Dimitris Lampridis
committed
logic gn4124_irq;
t_wishbone_master_in wb_in, wb_dma_in, wb_mem_in;
t_wishbone_master_out wb_out, wb_dma_out, wb_mem_out;

Dimitris Lampridis
committed
always #4ns clk_125m <= ~clk_125m;
logic rst_125m_n;
initial begin
rst_125m_n = 0;
#80ns rst_125m_n = 1;
end

Dimitris Lampridis
committed
IGN4124PCIMaster i_gn4124 ();
xwb_gn4124_core
DUT (
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
.rst_n_a_i (i_gn4124.rst_n),
.p2l_clk_p_i (i_gn4124.p2l_clk_p),
.p2l_clk_n_i (i_gn4124.p2l_clk_n),
.p2l_data_i (i_gn4124.p2l_data),
.p2l_dframe_i (i_gn4124.p2l_dframe),
.p2l_valid_i (i_gn4124.p2l_valid),
.p2l_rdy_o (i_gn4124.p2l_rdy),
.p_wr_req_i (i_gn4124.p_wr_req),
.p_wr_rdy_o (i_gn4124.p_wr_rdy),
.rx_error_o (i_gn4124.rx_error),
.vc_rdy_i (i_gn4124.vc_rdy),
.l2p_clk_p_o (i_gn4124.l2p_clk_p),
.l2p_clk_n_o (i_gn4124.l2p_clk_n),
.l2p_data_o (i_gn4124.l2p_data),
.l2p_dframe_o (i_gn4124.l2p_dframe),
.l2p_valid_o (i_gn4124.l2p_valid),
.l2p_edb_o (i_gn4124.l2p_edb),
.l2p_rdy_i (i_gn4124.l2p_rdy),
.l_wr_rdy_i (i_gn4124.l_wr_rdy),
.p_rd_d_rdy_i (i_gn4124.p_rd_d_rdy),
.tx_error_i (i_gn4124.tx_error),
.dma_irq_o (dma_irq),
.irq_p_i (1'b0),
.irq_p_o (gn4124_irq),
.status_o (),
.wb_master_clk_i (clk_125m),
.wb_master_rst_n_i (rst_125m_n),
.wb_master_i (wb_in),
.wb_master_o (wb_out),
.wb_dma_cfg_clk_i (clk_125m),
.wb_dma_cfg_rst_n_i (rst_125m_n),
.wb_dma_cfg_i (wb_out),
.wb_dma_cfg_o (wb_in),
.wb_dma_dat_clk_i (clk_125m),
.wb_dma_dat_rst_n_i (rst_125m_n),
.wb_dma_dat_i (wb_dma_in),
.wb_dma_dat_o (wb_dma_out)
);

Dimitris Lampridis
committed

Dimitris Lampridis
committed
xwb_dpram #
(
.g_size (32),
.g_init_file ("mem_init.bram"),
.g_slave1_interface_mode (1), // 1 = PIPELINED
.g_slave2_interface_mode (1),
.g_slave1_granularity (1), // 1 = WORD
.g_slave2_granularity (1)
)
MEM (
.rst_n_i (1'b1),
.clk_sys_i (clk_125m),
.slave1_i (wb_dma_out),
.slave1_o (wb_dma_in),
.slave2_i (wb_mem_out),
.slave2_o (wb_mem_in)
);

Dimitris Lampridis
committed

Dimitris Lampridis
committed
CBusAccessor acc;
task val_check(string name, uint32_t addr, val, expected);

Dimitris Lampridis
committed
if (val != expected)
begin
$display();
$display("Simulation FAILED");
$fatal(1, "%s error at address 0x%.2x. Expected 0x%.8x, got 0x%.8x",
name, addr, expected, val);
end

Dimitris Lampridis
committed
endtask // val_check
task reg_check(uint32_t addr, expected);

Dimitris Lampridis
committed
uint64_t val;
acc.read(addr, val);
val_check("Register read-back", addr, val, expected);

Dimitris Lampridis
committed
endtask // reg_check
initial begin
automatic int ntest = 1;
const int tests = 6;
uint32_t addr, val, expected;

Dimitris Lampridis
committed
@(posedge i_gn4124.ready);
acc = i_gn4124.get_accessor();
acc.set_default_xfer_size(4);
@(posedge clk_125m);
$write("Test %0d/%0d: simple read/write accesses over Wishbone: ",
ntest++, tests);

Dimitris Lampridis
committed
// Verify simple read/writes over wishbone

Dimitris Lampridis
committed
reg_check('h0, 'h0);
acc.write('h0c, 'hffacce55);
acc.write('h10, 'h1badcafe);

Dimitris Lampridis
committed
reg_check('h0c, 'hffacce55);
reg_check('h10, 'h1badcafe);

Dimitris Lampridis
committed

Dimitris Lampridis
committed
// Reset all DMA config registers

Dimitris Lampridis
committed
for (addr = 'h00; addr <= 'h20; addr += 4)
begin
acc.write(addr, 'h0);
end
$write("PASS\n");
$write("Test %0d/%0d: 32 reads over DMA, abort after first read: ",
ntest++, tests);

Dimitris Lampridis
committed

Dimitris Lampridis
committed
// Perform 32 reads over DMA
reg_check('h00, 'h00000000);
if (dma_irq != 1'b0)
$fatal(1, "dma irq should be 0");
acc.write('h14, 'h80); // count
acc.write('h00, 'h01); // start

Dimitris Lampridis
committed
// Check values read from memory
@(posedge i_gn4124.l2p_valid); // skip header
@(posedge i_gn4124.l2p_valid);
expected = 32'h8000001f;
val = i_gn4124.l2p_data;
@(posedge i_gn4124.l2p_clk_n);
val |= i_gn4124.l2p_data << 16;
val_check("DMA read-back", 'h20, val, expected);
repeat(2) @(posedge clk_125m);
// Test abort feature
acc.write('h00, 'h02);
reg_check('h04, 'h03);
acc.write('h00, 'h00);
repeat(2) @(posedge clk_125m);
$write("PASS\n");
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// Check all four byte swap settings
for (int i = 0; i < 4; i++) begin
$write("Test %0d/%0d: 32 reads over DMA (byte swap = %0d): ",
ntest++, tests, i);
// Restart
acc.write('h14, 'h80); // count
acc.write('h00, (i << 2) | 'h01); // start
@(posedge i_gn4124.l2p_valid); // skip header
@(posedge i_gn4124.l2p_valid);
for (addr = 'h20; addr > 'h00; addr -= 1)
begin
expected = 32'h80000000 + addr - 1;
if (i == 1)
expected = {<<8{expected}};
else if (i == 2)
expected = {<<16{expected}};
else if (i == 3)
expected = {<<16{{<<8{expected}}}};
val = i_gn4124.l2p_data;
@(posedge i_gn4124.l2p_clk_n);
val |= i_gn4124.l2p_data << 16;
val_check("DMA read-back", 'h20-addr, val, expected);
@(posedge i_gn4124.l2p_clk_p);
end
//#1us;
repeat(4) @(posedge clk_125m);
// Check irq status
reg_check('h04, 'h04);
if (dma_irq != 1'b1)
$fatal(1, "dma irq should be 1");
// clear irq
acc.write('h04, 'h04);
reg_check('h04, 'h00);
if (dma_irq != 1'b0)
$fatal(1, "dma irq should be 0");
$write("PASS\n");
#1us;
end

Dimitris Lampridis
committed

Dimitris Lampridis
committed
$display();
$display("Simulation PASSED");
$finish;
end
endmodule // main