Files
Andrew Moch 8cb9bdd331 fpga: lib: Add AXI4 (full) interface
Add a SystemVerilog interface for connecting AXI4 ports, and an
associated header file with helper macros.


Original-commit: 04d29e85b0c0698e3de96b54fd3f6e04eb439f74
2021-06-03 11:26:54 -05:00

330 lines
7.9 KiB
Systemverilog

//
// Copyright 2021 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Interface: AxiIf
// Description:
// AXI4 is an ARM standard for bursting memory mapped transfers
// For more information on the spec see
// - https://developer.arm.com/docs/ihi0022/d
//
// The interface contains methods for
// (1) Writing an address
// (2) Reading an address
//
// Parameters:
// - DATA_WIDTH - Width of the data on AXI4 bus
// - ADDR_WIDTH - Width of the address on AXI4 bus
//
//-----------------------------------------------------------------------------
// AXI4 interface
//-----------------------------------------------------------------------------
interface AxiIf #(
int DATA_WIDTH = 64,
int ADDR_WIDTH = 1
) (
input logic clk,
input logic rst = 1'b0
);
import PkgAxi::*;
localparam BYTES_PER_WORD = DATA_WIDTH/8;
// local type defs
typedef logic [DATA_WIDTH-1:0] data_t;
typedef logic [ADDR_WIDTH-1:0] addr_t;
typedef logic [BYTES_PER_WORD-1:0] strb_t;
typedef logic [7:0] len_t;
typedef logic [2:0] size_t;
typedef logic [1:0] burst_t;
typedef logic [0:0] lock_t;
typedef logic [3:0] cache_t;
typedef logic [2:0] prot_t;
typedef logic [3:0] qos_t;
// Signals that make up an Axi interface
// Write Address Channel
addr_t awaddr;
len_t awlen;
size_t awsize;
burst_t awburst;
lock_t awlock;
cache_t awcache;
prot_t awprot;
qos_t awqos;
logic awvalid;
logic awready;
// Write Data Channel
data_t wdata;
strb_t wstrb = '1;
logic wlast;
logic wvalid;
logic wready;
// Write Response Channel
axi_resp_t bresp;
logic bvalid;
logic bready;
// Read Address Channel
addr_t araddr;
len_t arlen;
size_t arsize;
burst_t arburst;
lock_t arlock;
cache_t arcache;
prot_t arprot;
qos_t arqos;
logic arvalid;
logic arready;
// Read Data Channel
data_t rdata;
axi_resp_t rresp;
logic rlast;
logic rvalid;
logic rready;
// Master Functions
task automatic drive_aw(input addr_t addr,
input len_t len,
input size_t size,
input burst_t burst,
input lock_t lock,
input cache_t cache,
input prot_t prot,
input qos_t qos);
awaddr = addr;
awlen = len;
awsize = size;
awburst = burst;
awlock = lock;
awcache = cache;
awprot = prot;
awqos = qos;
awvalid = 1;
endtask
task automatic drive_w(input data_t data,
input logic last,
input strb_t strb = '1);
wdata = data;
wstrb = strb;
wlast = last;
wvalid = 1;
endtask
task automatic drive_aw_idle();
awaddr = 'X;
awlen = 'X;
awsize = 'X;
awburst = 'X;
awlock = 'X;
awcache = 'X;
awprot = 'X;
awqos = 'X;
awvalid = 0;
endtask
task automatic drive_w_idle();
wdata = 'X;
wstrb = 'X;
wlast = 1'bX;
wvalid = 0;
endtask
task automatic drive_read(input addr_t addr,
input len_t len,
input size_t size,
input burst_t burst,
input lock_t lock,
input cache_t cache,
input prot_t prot,
input qos_t qos);
araddr = addr;
arlen = len;
arsize = size;
arburst = burst;
arlock = lock;
arcache = cache;
arprot = prot;
arqos = qos;
arvalid = 1;
endtask
task automatic drive_read_idle();
araddr = 'X;
araddr = 'X;
arlen = 'X;
arsize = 'X;
arburst = 'X;
arlock = 'X;
arcache = 'X;
arprot = 'X;
arqos = 'X;
arvalid = 0;
endtask
// Slave Functions
task automatic drive_write_resp(input axi_resp_t resp=OKAY);
bresp = resp;
bvalid = 1;
endtask
task automatic drive_write_resp_idle();
bresp = OKAY;
bvalid = 0;
endtask
task automatic drive_read_resp(input data_t data,
input logic last,
input axi_resp_t resp=OKAY);
rdata = data;
rresp = resp;
rlast = last;
rvalid = 1;
endtask
task automatic drive_read_resp_idle();
rdata = 'X;
rresp = OKAY;
rlast = 1'bX;
rvalid = 0;
endtask
// View from the master side
modport master (
input clk, rst,
output awaddr,awlen,awsize,awburst,awlock,awcache,awprot,awqos,awvalid,
wdata,wstrb,wlast,wvalid,
bready,
araddr,arlen,arsize,arburst,arlock,arcache,arprot,arqos,arvalid,
rready,
input awready,wready,bresp,bvalid,arready,rdata,rresp,rlast,rvalid,
import drive_aw,
import drive_w,
import drive_w_idle,
import drive_aw_idle,
import drive_read,
import drive_read_idle
);
// View from the slave side
modport slave (
input clk, rst,
input awaddr,awlen,awsize,awburst,awlock,awcache,awprot,awqos,awvalid,
wdata,wstrb,wlast,wvalid,
bready,
araddr,arlen,arsize,arburst,arlock,arcache,arprot,arqos,arvalid,
rready,
output awready,wready,bresp,bvalid,arready,rdata,rresp,rlast,rvalid,
import drive_write_resp,
import drive_write_resp_idle,
import drive_read_resp,
import drive_read_resp_idle
);
endinterface : AxiIf
// The _v version of the interface does not assign any signals so it may be used
// in a continuous context. The most common example is when associating members
// to a regular verilog output port.
interface AxiIf_v #(
int DATA_WIDTH = 64,
int ADDR_WIDTH = 1
) (
input logic clk,
input logic rst = 1'b0
);
import PkgAxi::*;
localparam BYTES_PER_WORD = DATA_WIDTH/8;
// local type defs
typedef logic [DATA_WIDTH-1:0] data_t;
typedef logic [ADDR_WIDTH-1:0] addr_t;
typedef logic [BYTES_PER_WORD-1:0] strb_t;
typedef logic [7:0] len_t;
typedef logic [2:0] size_t;
typedef logic [1:0] burst_t;
typedef logic [0:0] lock_t;
typedef logic [3:0] cache_t;
typedef logic [2:0] prot_t;
typedef logic [3:0] qos_t;
// Signals that make up an Axi interface
// Write Address Channel
addr_t awaddr;
len_t awlen;
size_t awsize;
burst_t awburst;
lock_t awlock;
cache_t awcache;
prot_t awprot;
qos_t awqos;
logic awvalid;
logic awready;
// Write Data Channel
data_t wdata;
strb_t wstrb;
logic wlast;
logic wvalid;
logic wready;
// Write Response Channel
axi_resp_t bresp;
logic bvalid;
logic bready;
// Read Address Channel
addr_t araddr;
len_t arlen;
size_t arsize;
burst_t arburst;
lock_t arlock;
cache_t arcache;
prot_t arprot;
qos_t arqos;
logic arvalid;
logic arready;
// Read Data Channel
data_t rdata;
axi_resp_t rresp;
logic rlast;
logic rvalid;
logic rready;
// View from the master side
modport master (
input clk, rst,
output awaddr,awlen,awsize,awburst,awlock,awcache,awprot,awqos,awvalid,
wdata,wstrb,wlast,wvalid,
bready,
araddr,arlen,arsize,arburst,arlock,arcache,arprot,arqos,arvalid,
rready,
input awready,wready,bresp,bvalid,arready,rdata,rresp,rlast,rvalid
);
// View from the slave side
modport slave (
input clk, rst,
input awaddr,awlen,awsize,awburst,awlock,awcache,awprot,awqos,awvalid,
wdata,wstrb,wlast,wvalid,
bready,
araddr,arlen,arsize,arburst,arlock,arcache,arprot,arqos,arvalid,
rready,
output awready,wready,bresp,bvalid,arready,rdata,rresp,rlast,rvalid
);
endinterface : AxiIf_v