testcase framework
This commit is contained in:
14
test/lib/cpuifs/apb3/__init__.py
Normal file
14
test/lib/cpuifs/apb3/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from ..base import CpuifTestMode
|
||||
|
||||
from peakrdl.regblock.cpuif.apb3 import APB3_Cpuif, APB3_Cpuif_flattened
|
||||
|
||||
class APB3(CpuifTestMode):
|
||||
cpuif_cls = APB3_Cpuif
|
||||
tb_files = [
|
||||
"apb3_intf.sv",
|
||||
"apb3_intf_driver.sv",
|
||||
]
|
||||
tb_template = "tb_inst.sv"
|
||||
|
||||
class FlatAPB3(APB3):
|
||||
cpuif_cls = APB3_Cpuif_flattened
|
||||
40
test/lib/cpuifs/apb3/apb3_intf.sv
Normal file
40
test/lib/cpuifs/apb3/apb3_intf.sv
Normal file
@@ -0,0 +1,40 @@
|
||||
interface apb3_intf #(
|
||||
parameter DATA_WIDTH = 32,
|
||||
parameter ADDR_WIDTH = 32
|
||||
);
|
||||
// Command
|
||||
logic PSEL;
|
||||
logic PENABLE;
|
||||
logic PWRITE;
|
||||
logic [ADDR_WIDTH-1:0] PADDR;
|
||||
logic [DATA_WIDTH-1:0] PWDATA;
|
||||
|
||||
// Response
|
||||
logic [DATA_WIDTH-1:0] PRDATA;
|
||||
logic PREADY;
|
||||
logic PSLVERR;
|
||||
|
||||
modport master (
|
||||
output PSEL,
|
||||
output PENABLE,
|
||||
output PWRITE,
|
||||
output PADDR,
|
||||
output PWDATA,
|
||||
|
||||
input PRDATA,
|
||||
input PREADY,
|
||||
input PSLVERR
|
||||
);
|
||||
|
||||
modport slave (
|
||||
input PSEL,
|
||||
input PENABLE,
|
||||
input PWRITE,
|
||||
input PADDR,
|
||||
input PWDATA,
|
||||
|
||||
output PRDATA,
|
||||
output PREADY,
|
||||
output PSLVERR
|
||||
);
|
||||
endinterface
|
||||
109
test/lib/cpuifs/apb3/apb3_intf_driver.sv
Normal file
109
test/lib/cpuifs/apb3/apb3_intf_driver.sv
Normal file
@@ -0,0 +1,109 @@
|
||||
interface apb3_intf_driver #(
|
||||
parameter DATA_WIDTH = 32,
|
||||
parameter ADDR_WIDTH = 32
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
apb3_intf.master m_apb
|
||||
);
|
||||
|
||||
timeunit 1ps;
|
||||
timeprecision 1ps;
|
||||
|
||||
logic PSEL;
|
||||
logic PENABLE;
|
||||
logic PWRITE;
|
||||
logic [ADDR_WIDTH-1:0] PADDR;
|
||||
logic [DATA_WIDTH-1:0] PWDATA;
|
||||
logic [DATA_WIDTH-1:0] PRDATA;
|
||||
logic PREADY;
|
||||
logic PSLVERR;
|
||||
|
||||
assign m_apb.PSEL = PSEL;
|
||||
assign m_apb.PENABLE = PENABLE;
|
||||
assign m_apb.PWRITE = PWRITE;
|
||||
assign m_apb.PADDR = PADDR;
|
||||
assign m_apb.PWDATA = PWDATA;
|
||||
assign PRDATA = m_apb.PRDATA;
|
||||
assign PREADY = m_apb.PREADY;
|
||||
assign PSLVERR = m_apb.PSLVERR;
|
||||
|
||||
default clocking cb @(posedge clk);
|
||||
default input #1step output #1;
|
||||
output PSEL;
|
||||
output PENABLE;
|
||||
output PWRITE;
|
||||
output PADDR;
|
||||
output PWDATA;
|
||||
input PRDATA;
|
||||
input PREADY;
|
||||
input PSLVERR;
|
||||
endclocking
|
||||
|
||||
task reset();
|
||||
cb.PSEL <= '0;
|
||||
cb.PENABLE <= '0;
|
||||
cb.PWRITE <= '0;
|
||||
cb.PADDR <= '0;
|
||||
cb.PWDATA <= '0;
|
||||
endtask
|
||||
|
||||
task write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
|
||||
##0;
|
||||
|
||||
// Initiate transfer
|
||||
cb.PSEL <= '1;
|
||||
cb.PENABLE <= '0;
|
||||
cb.PWRITE <= '1;
|
||||
cb.PADDR <= addr;
|
||||
cb.PWDATA <= data;
|
||||
@(cb);
|
||||
|
||||
// active phase
|
||||
cb.PENABLE <= '1;
|
||||
@(cb);
|
||||
|
||||
// Wait for response
|
||||
while(cb.PREADY !== 1'b1) @(cb);
|
||||
reset();
|
||||
endtask
|
||||
|
||||
task read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
|
||||
##0;
|
||||
|
||||
// Initiate transfer
|
||||
cb.PSEL <= '1;
|
||||
cb.PENABLE <= '0;
|
||||
cb.PWRITE <= '0;
|
||||
cb.PADDR <= addr;
|
||||
cb.PWDATA <= '0;
|
||||
@(cb);
|
||||
|
||||
// active phase
|
||||
cb.PENABLE <= '1;
|
||||
@(cb);
|
||||
|
||||
// Wait for response
|
||||
while(cb.PREADY !== 1'b1) @(cb);
|
||||
assert(!$isunknown(cb.PRDATA)) else $error("Read from 0x%0x returned X's on PRDATA", addr);
|
||||
assert(!$isunknown(cb.PSLVERR)) else $error("Read from 0x%0x returned X's on PSLVERR", addr);
|
||||
data = cb.PRDATA;
|
||||
reset();
|
||||
endtask
|
||||
|
||||
task assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data);
|
||||
logic [DATA_WIDTH-1:0] data;
|
||||
read(addr, data);
|
||||
assert(data == expected_data) else $error("Read from 0x%x returned 0x%x. Expected 0x%x", addr, data, expected_data);
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
reset();
|
||||
end
|
||||
|
||||
initial forever begin
|
||||
@cb;
|
||||
if(!rst) assert(!$isunknown(cb.PREADY)) else $error("Saw X on PREADY!");
|
||||
end
|
||||
|
||||
endinterface
|
||||
30
test/lib/cpuifs/apb3/tb_inst.sv
Normal file
30
test/lib/cpuifs/apb3/tb_inst.sv
Normal file
@@ -0,0 +1,30 @@
|
||||
apb3_intf #(
|
||||
.DATA_WIDTH({{exporter.cpuif.data_width}}),
|
||||
.ADDR_WIDTH({{exporter.cpuif.addr_width}})
|
||||
) s_apb();
|
||||
apb3_intf_driver #(
|
||||
.DATA_WIDTH({{exporter.cpuif.data_width}}),
|
||||
.ADDR_WIDTH({{exporter.cpuif.addr_width}})
|
||||
) cpuif(
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.m_apb(s_apb)
|
||||
);
|
||||
{% if type(cpuif).__name__.startswith("Flat") %}
|
||||
wire s_apb_psel;
|
||||
wire s_apb_penable;
|
||||
wire s_apb_pwrite;
|
||||
wire [{{exporter.cpuif.addr_width - 1}}:0] s_apb_paddr;
|
||||
wire [{{exporter.cpuif.data_width - 1}}:0] s_apb_pwdata;
|
||||
wire s_apb_pready;
|
||||
wire [{{exporter.cpuif.data_width - 1}}:0] s_apb_prdata;
|
||||
wire s_apb_pslverr;
|
||||
assign s_apb_psel = s_apb.PSEL;
|
||||
assign s_apb_penable = s_apb.PENABLE;
|
||||
assign s_apb_pwrite = s_apb.PWRITE;
|
||||
assign s_apb_paddr = s_apb.PADDR;
|
||||
assign s_apb_pwdata = s_apb.PWDATA;
|
||||
assign s_apb.PREADY = s_apb_pready;
|
||||
assign s_apb.PRDATA = s_apb_prdata;
|
||||
assign s_apb.PSLVERR = s_apb_pslverr;
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user