fpga: rfnoc: Enable blocks with no inputs/outputs
The following modifications are applied to allow RFNoC blocks with zero input- or output ports (or none at all): - The backend interface will no longer synthesize any flushing logic if there are no streaming ports - The Mako templates are modified to allow generating code for blocks without streaming ports - The BFM for RFNoC blocks (RfnocBlockCtrlBfm) is partially factored out into a parent class (RfnocBlockCtrlBfmCtrlOnly) which allows the simulation of such RFNoC blocks Original-commit: 878cfcf48f125826e9d48b7c61a4ee7fd19e9a94
This commit is contained in:
@@ -30,9 +30,6 @@ module backend_iface #(
|
|||||||
// Input clock
|
// Input clock
|
||||||
input wire rfnoc_chdr_clk,
|
input wire rfnoc_chdr_clk,
|
||||||
input wire rfnoc_ctrl_clk,
|
input wire rfnoc_ctrl_clk,
|
||||||
// Backend interface (sync. to rfnoc_ctrl_clk)
|
|
||||||
input wire [511:0] rfnoc_core_config,
|
|
||||||
output wire [511:0] rfnoc_core_status,
|
|
||||||
// Output reset
|
// Output reset
|
||||||
output wire rfnoc_chdr_rst,
|
output wire rfnoc_chdr_rst,
|
||||||
output wire rfnoc_ctrl_rst,
|
output wire rfnoc_ctrl_rst,
|
||||||
@@ -44,7 +41,10 @@ module backend_iface #(
|
|||||||
output wire data_o_flush_en,
|
output wire data_o_flush_en,
|
||||||
output wire [31:0] data_o_flush_timeout,
|
output wire [31:0] data_o_flush_timeout,
|
||||||
input wire [63:0] data_o_flush_active,
|
input wire [63:0] data_o_flush_active,
|
||||||
input wire [63:0] data_o_flush_done
|
input wire [63:0] data_o_flush_done,
|
||||||
|
// Backend interface (sync. to rfnoc_ctrl_clk)
|
||||||
|
input wire [511:0] rfnoc_core_config,
|
||||||
|
output wire [511:0] rfnoc_core_status
|
||||||
);
|
);
|
||||||
localparam RESET_LENGTH = 32;
|
localparam RESET_LENGTH = 32;
|
||||||
|
|
||||||
@@ -54,41 +54,64 @@ module backend_iface #(
|
|||||||
// CONFIG: Infrastructure => Block
|
// CONFIG: Infrastructure => Block
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
wire [BEC_TOTAL_WIDTH-1:0] rfnoc_core_config_trim = rfnoc_core_config[BEC_TOTAL_WIDTH-1:0];
|
wire [BEC_TOTAL_WIDTH-1:0] rfnoc_core_config_trim = rfnoc_core_config[BEC_TOTAL_WIDTH-1:0];
|
||||||
|
// Synchronize flush signals to the CHDR clock domain. Note this is only
|
||||||
|
// necessary if we have data ports.
|
||||||
|
generate
|
||||||
|
if (NUM_DATA_I > 0 || NUM_DATA_O > 0) begin
|
||||||
|
|
||||||
reg [31:0] flush_timeout_ctclk = 32'd0;
|
|
||||||
reg flush_en_ctclk = 1'b0;
|
|
||||||
reg soft_ctrl_rst_ctclk = 1'b0;
|
|
||||||
reg soft_chdr_rst_ctclk = 1'b0;
|
|
||||||
|
|
||||||
// Register logic before synchronizer
|
reg [31:0] flush_timeout_ctclk = 32'd0;
|
||||||
always @(posedge rfnoc_ctrl_clk) begin
|
reg flush_en_ctclk = 1'b0;
|
||||||
flush_timeout_ctclk <= rfnoc_core_config_trim[BEC_FLUSH_TIMEOUT_OFFSET +: BEC_FLUSH_TIMEOUT_WIDTH];
|
|
||||||
flush_en_ctclk <= rfnoc_core_config_trim[BEC_FLUSH_EN_OFFSET +: BEC_FLUSH_EN_WIDTH ];
|
|
||||||
soft_ctrl_rst_ctclk <= rfnoc_core_config_trim[BEC_SOFT_CTRL_RST_OFFSET +: BEC_SOFT_CTRL_RST_WIDTH];
|
|
||||||
soft_chdr_rst_ctclk <= rfnoc_core_config_trim[BEC_SOFT_CHDR_RST_OFFSET +: BEC_SOFT_CHDR_RST_WIDTH];
|
|
||||||
end
|
|
||||||
|
|
||||||
// Synchronizer
|
// Register logic before synchronizer
|
||||||
wire [31:0] flush_timeout_chclk;
|
always @(posedge rfnoc_ctrl_clk) begin
|
||||||
wire flush_en_chclk;
|
flush_timeout_ctclk <= rfnoc_core_config_trim[BEC_FLUSH_TIMEOUT_OFFSET +: BEC_FLUSH_TIMEOUT_WIDTH];
|
||||||
|
flush_en_ctclk <= rfnoc_core_config_trim[BEC_FLUSH_EN_OFFSET +: BEC_FLUSH_EN_WIDTH ];
|
||||||
|
end
|
||||||
|
|
||||||
// Note: We are using a synchronizer to cross the 32-bit timeout bus
|
// Synchronizer
|
||||||
// into a different clock domain. Typically we would use a 2clk FIFO
|
wire [31:0] flush_timeout_chclk;
|
||||||
// but it's OK to have the bits unsynchronized here because the value
|
wire flush_en_chclk;
|
||||||
// is static and is set from SW long before it is actually used.
|
|
||||||
|
|
||||||
synchronizer #(.WIDTH(33), .INITIAL_VAL(33'd0)) sync_ctrl_i (
|
// Note: We are using a synchronizer to cross the 32-bit timeout bus
|
||||||
.clk(rfnoc_chdr_clk), .rst(1'b0),
|
// into a different clock domain. Typically we would use a 2clk FIFO
|
||||||
.in({flush_en_ctclk, flush_timeout_ctclk}),
|
// but it's OK to have the bits unsynchronized here because the value
|
||||||
.out({flush_en_chclk, flush_timeout_chclk})
|
// is static and is set from SW long before it is actually used.
|
||||||
);
|
|
||||||
|
|
||||||
// Synchronize the reset to the CHDR and CTRL clock domains, and extend the
|
synchronizer #(.WIDTH(33), .INITIAL_VAL(33'd0)) sync_ctrl_i (
|
||||||
|
.clk(rfnoc_chdr_clk), .rst(1'b0),
|
||||||
|
.in({flush_en_ctclk, flush_timeout_ctclk}),
|
||||||
|
.out({flush_en_chclk, flush_timeout_chclk})
|
||||||
|
);
|
||||||
|
|
||||||
|
assign data_i_flush_timeout = flush_timeout_chclk;
|
||||||
|
assign data_o_flush_timeout = flush_timeout_chclk;
|
||||||
|
assign data_i_flush_en = flush_en_chclk;
|
||||||
|
assign data_o_flush_en = flush_en_chclk;
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
assign data_i_flush_timeout = 32'h0;
|
||||||
|
assign data_o_flush_timeout = 32'h0;
|
||||||
|
assign data_i_flush_en = 1'b0;
|
||||||
|
assign data_o_flush_en = 1'b0;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
// Synchronize the reset to the CHDR and CTRL clock domains, and extend the
|
||||||
// reset pulse to make it long enough for most IP to reset correctly.
|
// reset pulse to make it long enough for most IP to reset correctly.
|
||||||
|
|
||||||
|
reg soft_ctrl_rst_ctclk = 1'b0;
|
||||||
|
reg soft_chdr_rst_ctclk = 1'b0;
|
||||||
|
|
||||||
wire rfnoc_ctrl_rst_pulse;
|
wire rfnoc_ctrl_rst_pulse;
|
||||||
wire rfnoc_chdr_rst_pulse;
|
wire rfnoc_chdr_rst_pulse;
|
||||||
|
|
||||||
|
// Register logic before synchronizer
|
||||||
|
always @(posedge rfnoc_ctrl_clk) begin
|
||||||
|
soft_ctrl_rst_ctclk <= rfnoc_core_config_trim[BEC_SOFT_CTRL_RST_OFFSET +: BEC_SOFT_CTRL_RST_WIDTH];
|
||||||
|
soft_chdr_rst_ctclk <= rfnoc_core_config_trim[BEC_SOFT_CHDR_RST_OFFSET +: BEC_SOFT_CHDR_RST_WIDTH];
|
||||||
|
end
|
||||||
|
|
||||||
pulse_synchronizer #(.MODE("POSEDGE")) soft_ctrl_rst_sync_i (
|
pulse_synchronizer #(.MODE("POSEDGE")) soft_ctrl_rst_sync_i (
|
||||||
.clk_a(rfnoc_ctrl_clk), .rst_a(1'b0), .pulse_a(soft_ctrl_rst_ctclk), .busy_a(),
|
.clk_a(rfnoc_ctrl_clk), .rst_a(1'b0), .pulse_a(soft_ctrl_rst_ctclk), .busy_a(),
|
||||||
.clk_b(rfnoc_ctrl_clk), .pulse_b(rfnoc_ctrl_rst_pulse)
|
.clk_b(rfnoc_ctrl_clk), .pulse_b(rfnoc_ctrl_rst_pulse)
|
||||||
@@ -109,33 +132,54 @@ module backend_iface #(
|
|||||||
.pulse_in(rfnoc_chdr_rst_pulse), .pulse_out(rfnoc_chdr_rst)
|
.pulse_in(rfnoc_chdr_rst_pulse), .pulse_out(rfnoc_chdr_rst)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign data_i_flush_timeout = flush_timeout_chclk;
|
|
||||||
assign data_o_flush_timeout = flush_timeout_chclk;
|
|
||||||
assign data_i_flush_en = flush_en_chclk;
|
|
||||||
assign data_o_flush_en = flush_en_chclk;
|
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// STATUS: Block => Infrastructure
|
// STATUS: Block => Infrastructure
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
||||||
reg flush_active_chclk = 1'b0;
|
generate
|
||||||
reg flush_done_chclk = 1'b0;
|
if (NUM_DATA_I > 0 || NUM_DATA_O > 0) begin
|
||||||
|
|
||||||
// Register logic before synchronizer
|
reg flush_active_chclk = 1'b0;
|
||||||
wire flush_active_ctclk;
|
reg flush_done_chclk = 1'b0;
|
||||||
wire flush_done_ctclk;
|
|
||||||
|
|
||||||
always @(posedge rfnoc_chdr_clk) begin
|
// Register logic before synchronizer
|
||||||
flush_active_chclk <= (|data_i_flush_active[NUM_DATA_I-1:0]) | (|data_o_flush_active[NUM_DATA_O-1:0]);
|
wire flush_active_ctclk;
|
||||||
flush_done_chclk <= (&data_i_flush_done [NUM_DATA_I-1:0]) & (&data_o_flush_done [NUM_DATA_O-1:0]);
|
wire flush_done_ctclk;
|
||||||
end
|
|
||||||
|
|
||||||
// Synchronizer
|
if (NUM_DATA_I > 0 && NUM_DATA_O > 0) begin
|
||||||
synchronizer #(.WIDTH(2), .INITIAL_VAL(2'd0)) sync_status_i (
|
always @(posedge rfnoc_chdr_clk) begin
|
||||||
.clk(rfnoc_ctrl_clk), .rst(1'b0),
|
flush_active_chclk <= (|data_i_flush_active[NUM_DATA_I-1:0]) | (|data_o_flush_active[NUM_DATA_O-1:0]);
|
||||||
.in({flush_active_chclk, flush_done_chclk}),
|
flush_done_chclk <= (&data_i_flush_done [NUM_DATA_I-1:0]) & (&data_o_flush_done [NUM_DATA_O-1:0]);
|
||||||
.out({flush_active_ctclk, flush_done_ctclk})
|
end
|
||||||
);
|
end else if (NUM_DATA_I > 0 && NUM_DATA_O == 0) begin
|
||||||
|
always @(posedge rfnoc_chdr_clk) begin
|
||||||
|
flush_active_chclk <= (|data_i_flush_active[NUM_DATA_I-1:0]);
|
||||||
|
flush_done_chclk <= (&data_i_flush_done [NUM_DATA_I-1:0]);
|
||||||
|
end
|
||||||
|
end else if (NUM_DATA_I == 0 && NUM_DATA_O > 0) begin
|
||||||
|
always @(posedge rfnoc_chdr_clk) begin
|
||||||
|
flush_active_chclk <= (|data_o_flush_active[NUM_DATA_O-1:0]);
|
||||||
|
flush_done_chclk <= (&data_o_flush_done [NUM_DATA_O-1:0]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Synchronizer
|
||||||
|
synchronizer #(.WIDTH(2), .INITIAL_VAL(2'd0)) sync_status_i (
|
||||||
|
.clk(rfnoc_ctrl_clk), .rst(1'b0),
|
||||||
|
.in({flush_active_chclk, flush_done_chclk}),
|
||||||
|
.out({flush_active_ctclk, flush_done_ctclk})
|
||||||
|
);
|
||||||
|
|
||||||
|
assign rfnoc_core_status[BES_FLUSH_ACTIVE_OFFSET+:BES_FLUSH_ACTIVE_WIDTH] = flush_active_ctclk;
|
||||||
|
assign rfnoc_core_status[BES_FLUSH_DONE_OFFSET +:BES_FLUSH_DONE_WIDTH ] = flush_done_ctclk;
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
assign rfnoc_core_status[BES_FLUSH_ACTIVE_OFFSET+:BES_FLUSH_ACTIVE_WIDTH] = {BES_FLUSH_ACTIVE_WIDTH{1'b0}};
|
||||||
|
assign rfnoc_core_status[BES_FLUSH_DONE_OFFSET +:BES_FLUSH_DONE_WIDTH ] = {BES_FLUSH_DONE_WIDTH{1'b1}};
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
endgenerate
|
||||||
|
|
||||||
assign rfnoc_core_status[BES_PROTO_VER_OFFSET +:BES_PROTO_VER_WIDTH ] = BACKEND_PROTO_VER;
|
assign rfnoc_core_status[BES_PROTO_VER_OFFSET +:BES_PROTO_VER_WIDTH ] = BACKEND_PROTO_VER;
|
||||||
assign rfnoc_core_status[BES_NUM_DATA_I_OFFSET +:BES_NUM_DATA_I_WIDTH ] = NUM_DATA_I;
|
assign rfnoc_core_status[BES_NUM_DATA_I_OFFSET +:BES_NUM_DATA_I_WIDTH ] = NUM_DATA_I;
|
||||||
@@ -143,8 +187,6 @@ module backend_iface #(
|
|||||||
assign rfnoc_core_status[BES_CTRL_FIFOSIZE_OFFSET +:BES_CTRL_FIFOSIZE_WIDTH ] = CTRL_FIFOSIZE;
|
assign rfnoc_core_status[BES_CTRL_FIFOSIZE_OFFSET +:BES_CTRL_FIFOSIZE_WIDTH ] = CTRL_FIFOSIZE;
|
||||||
assign rfnoc_core_status[BES_CTRL_MAX_ASYNC_MSGS_OFFSET+:BES_CTRL_MAX_ASYNC_MSGS_WIDTH] = CTRL_MAX_ASYNC_MSGS;
|
assign rfnoc_core_status[BES_CTRL_MAX_ASYNC_MSGS_OFFSET+:BES_CTRL_MAX_ASYNC_MSGS_WIDTH] = CTRL_MAX_ASYNC_MSGS;
|
||||||
assign rfnoc_core_status[BES_NOC_ID_OFFSET +:BES_NOC_ID_WIDTH ] = NOC_ID;
|
assign rfnoc_core_status[BES_NOC_ID_OFFSET +:BES_NOC_ID_WIDTH ] = NOC_ID;
|
||||||
assign rfnoc_core_status[BES_FLUSH_ACTIVE_OFFSET +:BES_FLUSH_ACTIVE_WIDTH ] = flush_active_ctclk;
|
|
||||||
assign rfnoc_core_status[BES_FLUSH_DONE_OFFSET +:BES_FLUSH_DONE_WIDTH ] = flush_done_ctclk;
|
|
||||||
assign rfnoc_core_status[BES_DATA_MTU_OFFSET +:BES_DATA_MTU_WIDTH ] = MTU;
|
assign rfnoc_core_status[BES_DATA_MTU_OFFSET +:BES_DATA_MTU_WIDTH ] = MTU;
|
||||||
assign rfnoc_core_status[BES_CTRL_CLK_IDX_OFFSET +:BES_CTRL_CLK_IDX_WIDTH ] = CTRL_CLK_IDX;
|
assign rfnoc_core_status[BES_CTRL_CLK_IDX_OFFSET +:BES_CTRL_CLK_IDX_WIDTH ] = CTRL_CLK_IDX;
|
||||||
assign rfnoc_core_status[BES_TB_CLK_IDX_OFFSET +:BES_TB_CLK_IDX_WIDTH ] = TB_CLK_IDX;
|
assign rfnoc_core_status[BES_TB_CLK_IDX_OFFSET +:BES_TB_CLK_IDX_WIDTH ] = TB_CLK_IDX;
|
||||||
|
|||||||
@@ -97,19 +97,15 @@ package PkgRfnocBlockCtrlBfm;
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
class RfnocBlockCtrlBfm #(CHDR_W = 64, ITEM_W = 32);
|
// Control functionality only
|
||||||
|
class RfnocBlockCtrlBfmCtrlOnly;
|
||||||
|
|
||||||
local virtual RfnocBackendIf.master backend;
|
protected virtual RfnocBackendIf.master backend;
|
||||||
local CtrlIfaceBfm ctrl;
|
protected CtrlIfaceBfm ctrl;
|
||||||
local ChdrIfaceBfm #(CHDR_W, ITEM_W) m_data[$];
|
protected bit running;
|
||||||
local ChdrIfaceBfm #(CHDR_W, ITEM_W) s_data[$];
|
|
||||||
local bit running;
|
|
||||||
|
|
||||||
localparam CMD_PROP_CYC = 5;
|
localparam CMD_PROP_CYC = 5;
|
||||||
|
|
||||||
typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
|
|
||||||
typedef ChdrData #(CHDR_W, ITEM_W)::item_t item_t;
|
|
||||||
|
|
||||||
// Class constructor to create a new BFM instance.
|
// Class constructor to create a new BFM instance.
|
||||||
//
|
//
|
||||||
// backend: Interface for the backend signals of a block
|
// backend: Interface for the backend signals of a block
|
||||||
@@ -130,6 +126,123 @@ package PkgRfnocBlockCtrlBfm;
|
|||||||
this.running = 0;
|
this.running = 0;
|
||||||
endfunction : new
|
endfunction : new
|
||||||
|
|
||||||
|
// Start the data and control BFM's processes running.
|
||||||
|
task run();
|
||||||
|
assert (backend.sts.v1.proto_ver == 1) else begin
|
||||||
|
$fatal(1, "The connected block has an incompatible backend interface");
|
||||||
|
end
|
||||||
|
if (!running) begin
|
||||||
|
ctrl.run();
|
||||||
|
running = 1;
|
||||||
|
end
|
||||||
|
endtask : run
|
||||||
|
|
||||||
|
// Get static info about the block
|
||||||
|
function logic [7:0] get_proto_ver();
|
||||||
|
return backend.sts.v1.proto_ver;
|
||||||
|
endfunction : get_proto_ver
|
||||||
|
|
||||||
|
function logic [31:0] get_noc_id();
|
||||||
|
return backend.sts.v1.noc_id;
|
||||||
|
endfunction : get_noc_id
|
||||||
|
|
||||||
|
function logic [5:0] get_num_data_i();
|
||||||
|
return backend.sts.v1.num_data_i;
|
||||||
|
endfunction : get_num_data_i
|
||||||
|
|
||||||
|
function logic [5:0] get_num_data_o();
|
||||||
|
return backend.sts.v1.num_data_o;
|
||||||
|
endfunction : get_num_data_o
|
||||||
|
|
||||||
|
function logic [5:0] get_ctrl_fifosize();
|
||||||
|
return backend.sts.v1.ctrl_fifosize;
|
||||||
|
endfunction : get_ctrl_fifosize
|
||||||
|
|
||||||
|
function logic [5:0] get_mtu();
|
||||||
|
return backend.sts.v1.mtu;
|
||||||
|
endfunction : get_mtu
|
||||||
|
|
||||||
|
// Soft-Reset the Control path
|
||||||
|
//
|
||||||
|
// rst_cyc: Number of cycles to wait for reset completion
|
||||||
|
//
|
||||||
|
task reset_ctrl(input int rst_cyc = 100);
|
||||||
|
assert (running) else begin
|
||||||
|
$fatal(1, "Cannot call flush_and_reset until RfnocBlockCtrlBfm is running");
|
||||||
|
end
|
||||||
|
|
||||||
|
// Assert soft_ctrl_rst then wait
|
||||||
|
@(posedge backend.ctrl_clk);
|
||||||
|
backend.cfg.v1.soft_ctrl_rst = 1;
|
||||||
|
repeat (CMD_PROP_CYC) @(posedge backend.ctrl_clk);
|
||||||
|
backend.cfg.v1.soft_ctrl_rst = 0;
|
||||||
|
repeat (rst_cyc) @(posedge backend.ctrl_clk);
|
||||||
|
endtask : reset_ctrl
|
||||||
|
|
||||||
|
// Send a read request packet on the AXIS-Ctrl interface and get the
|
||||||
|
// response.
|
||||||
|
//
|
||||||
|
// addr: Address for the read request
|
||||||
|
// word: Data word that was returned in response to the read
|
||||||
|
//
|
||||||
|
task reg_read(
|
||||||
|
input ctrl_address_t addr,
|
||||||
|
output ctrl_word_t word
|
||||||
|
);
|
||||||
|
assert (running) else begin
|
||||||
|
$fatal(1, "Cannot call reg_read until RfnocBlockCtrlBfm is running");
|
||||||
|
end
|
||||||
|
|
||||||
|
ctrl.reg_read(addr, word);
|
||||||
|
endtask : reg_read
|
||||||
|
|
||||||
|
|
||||||
|
// Send a a write request packet on the AXIS-Ctrl interface and get the
|
||||||
|
// response.
|
||||||
|
//
|
||||||
|
// addr: Address for the write request
|
||||||
|
// word: Data word to write
|
||||||
|
//
|
||||||
|
task reg_write(
|
||||||
|
ctrl_address_t addr,
|
||||||
|
ctrl_word_t word
|
||||||
|
);
|
||||||
|
assert (running) else begin
|
||||||
|
$fatal(1, "Cannot call reg_write until RfnocBlockCtrlBfm is running");
|
||||||
|
end
|
||||||
|
|
||||||
|
ctrl.reg_write(addr, word);
|
||||||
|
endtask : reg_write
|
||||||
|
|
||||||
|
endclass : RfnocBlockCtrlBfmCtrlOnly
|
||||||
|
|
||||||
|
// Control functionality plus streaming (the normal/default case)
|
||||||
|
class RfnocBlockCtrlBfm #(CHDR_W = 64, ITEM_W = 32) extends RfnocBlockCtrlBfmCtrlOnly;
|
||||||
|
|
||||||
|
local ChdrIfaceBfm #(CHDR_W, ITEM_W) m_data[$];
|
||||||
|
local ChdrIfaceBfm #(CHDR_W, ITEM_W) s_data[$];
|
||||||
|
|
||||||
|
typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
|
||||||
|
typedef ChdrData #(CHDR_W, ITEM_W)::item_t item_t;
|
||||||
|
|
||||||
|
// Class constructor to create a new BFM instance.
|
||||||
|
//
|
||||||
|
// backend: Interface for the backend signals of a block
|
||||||
|
// m_ctrl: Interface for the CTRL master connection (EP's AXIS-Ctrl output)
|
||||||
|
// s_ctrl: Interface for the CTRL slave connection (EP's AXIS-Ctrl input)
|
||||||
|
// dst_port: Destination port to use in generated control packets
|
||||||
|
// src_port: Source port to use in generated control packets
|
||||||
|
//
|
||||||
|
function new(
|
||||||
|
virtual RfnocBackendIf.master backend,
|
||||||
|
virtual AxiStreamIf #(32).master m_ctrl,
|
||||||
|
virtual AxiStreamIf #(32).slave s_ctrl,
|
||||||
|
input ctrl_port_t dst_port = 10'd2,
|
||||||
|
input ctrl_port_t src_port = 10'd1
|
||||||
|
);
|
||||||
|
super.new(backend, m_ctrl, s_ctrl, dst_port, src_port);
|
||||||
|
endfunction : new
|
||||||
|
|
||||||
// Add a master data port. This should connect to a DUT slave input.
|
// Add a master data port. This should connect to a DUT slave input.
|
||||||
//
|
//
|
||||||
// m_chdr: Virtual master interface to connect new port to.
|
// m_chdr: Virtual master interface to connect new port to.
|
||||||
@@ -202,7 +315,7 @@ package PkgRfnocBlockCtrlBfm;
|
|||||||
|
|
||||||
// Start the data and control BFM's processes running.
|
// Start the data and control BFM's processes running.
|
||||||
task run();
|
task run();
|
||||||
assert (backend.sts.v1.proto_ver == 1) else begin
|
assert (super.backend.sts.v1.proto_ver == 1) else begin
|
||||||
$fatal(1, "The connected block has an incompatible backend interface");
|
$fatal(1, "The connected block has an incompatible backend interface");
|
||||||
end
|
end
|
||||||
if (!running) begin
|
if (!running) begin
|
||||||
@@ -284,31 +397,6 @@ package PkgRfnocBlockCtrlBfm;
|
|||||||
return m_data[port].get_ticks_per_word();
|
return m_data[port].get_ticks_per_word();
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
// Get static info about the block
|
|
||||||
function logic [7:0] get_proto_ver();
|
|
||||||
return backend.sts.v1.proto_ver;
|
|
||||||
endfunction : get_proto_ver
|
|
||||||
|
|
||||||
function logic [31:0] get_noc_id();
|
|
||||||
return backend.sts.v1.noc_id;
|
|
||||||
endfunction : get_noc_id
|
|
||||||
|
|
||||||
function logic [5:0] get_num_data_i();
|
|
||||||
return backend.sts.v1.num_data_i;
|
|
||||||
endfunction : get_num_data_i
|
|
||||||
|
|
||||||
function logic [5:0] get_num_data_o();
|
|
||||||
return backend.sts.v1.num_data_o;
|
|
||||||
endfunction : get_num_data_o
|
|
||||||
|
|
||||||
function logic [5:0] get_ctrl_fifosize();
|
|
||||||
return backend.sts.v1.ctrl_fifosize;
|
|
||||||
endfunction : get_ctrl_fifosize
|
|
||||||
|
|
||||||
function logic [5:0] get_mtu();
|
|
||||||
return backend.sts.v1.mtu;
|
|
||||||
endfunction : get_mtu
|
|
||||||
|
|
||||||
// Soft-Reset the CHDR path
|
// Soft-Reset the CHDR path
|
||||||
//
|
//
|
||||||
// rst_cyc: Number of cycles to wait for reset completion
|
// rst_cyc: Number of cycles to wait for reset completion
|
||||||
@@ -328,23 +416,6 @@ package PkgRfnocBlockCtrlBfm;
|
|||||||
repeat (rst_cyc) @(posedge backend.ctrl_clk);
|
repeat (rst_cyc) @(posedge backend.ctrl_clk);
|
||||||
endtask : reset_chdr
|
endtask : reset_chdr
|
||||||
|
|
||||||
// Soft-Reset the Control path
|
|
||||||
//
|
|
||||||
// rst_cyc: Number of cycles to wait for reset completion
|
|
||||||
//
|
|
||||||
task reset_ctrl(input int rst_cyc = 100);
|
|
||||||
assert (running) else begin
|
|
||||||
$fatal(1, "Cannot call flush_and_reset until RfnocBlockCtrlBfm is running");
|
|
||||||
end
|
|
||||||
|
|
||||||
// Assert soft_ctrl_rst then wait
|
|
||||||
@(posedge backend.ctrl_clk);
|
|
||||||
backend.cfg.v1.soft_ctrl_rst = 1;
|
|
||||||
repeat (CMD_PROP_CYC) @(posedge backend.ctrl_clk);
|
|
||||||
backend.cfg.v1.soft_ctrl_rst = 0;
|
|
||||||
repeat (rst_cyc) @(posedge backend.ctrl_clk);
|
|
||||||
endtask : reset_ctrl
|
|
||||||
|
|
||||||
// Flush the data ports of the block
|
// Flush the data ports of the block
|
||||||
//
|
//
|
||||||
// idle_cyc: Number of idle cycles before done is asserted
|
// idle_cyc: Number of idle cycles before done is asserted
|
||||||
@@ -822,42 +893,6 @@ package PkgRfnocBlockCtrlBfm;
|
|||||||
m_data[port].set_master_stall_prob(stall_prob);
|
m_data[port].set_master_stall_prob(stall_prob);
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
// Send a read request packet on the AXIS-Ctrl interface and get the
|
|
||||||
// response.
|
|
||||||
//
|
|
||||||
// addr: Address for the read request
|
|
||||||
// word: Data word that was returned in response to the read
|
|
||||||
//
|
|
||||||
task reg_read(
|
|
||||||
input ctrl_address_t addr,
|
|
||||||
output ctrl_word_t word
|
|
||||||
);
|
|
||||||
assert (running) else begin
|
|
||||||
$fatal(1, "Cannot call reg_read until RfnocBlockCtrlBfm is running");
|
|
||||||
end
|
|
||||||
|
|
||||||
ctrl.reg_read(addr, word);
|
|
||||||
endtask : reg_read
|
|
||||||
|
|
||||||
|
|
||||||
// Send a a write request packet on the AXIS-Ctrl interface and get the
|
|
||||||
// response.
|
|
||||||
//
|
|
||||||
// addr: Address for the write request
|
|
||||||
// word: Data word to write
|
|
||||||
//
|
|
||||||
task reg_write(
|
|
||||||
ctrl_address_t addr,
|
|
||||||
ctrl_word_t word
|
|
||||||
);
|
|
||||||
assert (running) else begin
|
|
||||||
$fatal(1, "Cannot call reg_write until RfnocBlockCtrlBfm is running");
|
|
||||||
end
|
|
||||||
|
|
||||||
ctrl.reg_write(addr, word);
|
|
||||||
endtask : reg_write
|
|
||||||
|
|
||||||
// Compare data vectors
|
// Compare data vectors
|
||||||
static function bit compare_data(
|
static function bit compare_data(
|
||||||
input chdr_word_t lhs[$],
|
input chdr_word_t lhs[$],
|
||||||
|
|||||||
Reference in New Issue
Block a user