Commit aa1a8ab3 authored by Maciej Lipinski's avatar Maciej Lipinski

Importing swcore's testbench to the new repo: adding swcore testbench files from…

Importing swcore's testbench to the new repo: adding swcore testbench files from the old repo (hopefully with the history) to the new repo
parents dddedff7 f12efbef
// Fabric TAP emulator example.
// usage: (as root)
// tunctl -t tap0
// ifconfig tap0 192.168.100.100
// arping -I tap0 192.168.100.101
// you should see some ARP requests coming
`timescale 1ns / 1ps
`include "fabric_emu.sv"
`include "fabric_emu_tap.sv"
module main;
const int c_clock_period = 8;
reg clk = 0;
reg rst_n = 0;
`WRF_WIRES(from_tap); // Data coming from tap0 interface
`WRF_WIRES(to_tap); // Data going to tap0 interface
// generate clock and reset signals
always #(c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
// Two fabric emulators talking to each other
fabric_emu_tap U_tap
(
.clk_sys_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, from_tap), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, to_tap)
);
fabric_emu U_emu
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, to_tap),
`WRF_CONNECT_SINK(tx, from_tap)
);
// Check if there's anything received by the TAP emulator
always @(posedge clk) if (U_emu.poll())
begin
ether_frame_t frame;
$display("TAP Emulator received a frame!");
U_emu.receive(frame);
dump_frame_header("EmuB RX: ", frame);
frame.hdr.src = 'h010203040506; // modify the MAC address and send the frame back to tap interface
U_emu.send(frame.hdr, frame.payload, frame.size);
end
endmodule // main
/*
White Rabbit endpoint fabric interface BFM/emulator
*/
`include "fabric_emu_defs.sv"
`include "fabric_emu_funcs.sv"
module fabric_emu
(
// fabric clock & reset
input clk_i,
input rst_n_i,
//////////////////////////////////////////////////////////////////////////////
// Fabric output (source)
//////////////////////////////////////////////////////////////////////////////
`WRF_FULL_PORTS_SOURCE(rx),
//////////////////////////////////////////////////////////////////////////////
// Fabric input (sink)
//////////////////////////////////////////////////////////////////////////////
`WRF_FULL_PORTS_SINK(tx),
/////////////////////////////////////////////////////////////////////////
// Endpoint TXTSU emulation. See wrsw_endpoint.vhd for signal details ///
/////////////////////////////////////////////////////////////////////////
input [4:0] txtsu_port_id_i,
input [15:0] txtsu_fid_i,
input [31:0] txtsu_tsval_i,
input txtsu_valid_i,
output txtsu_ack_o
);
// max. number of packet in TX/RX queues
parameter g_QUEUE_SIZE = 128;
// packet queues holding TXed and RXed packets
CPacketQueue tx_queue, rx_queue;
typedef struct {
bit sim_tx_underrun;
bit sim_tx_abort;
bit sim_rx_abort;
bit sim_tx_error;
bit sim_rx_error;
bit sim_rx_throttle;
bit sim_tx_throttle;
int tx_underrun_delay;
int tx_abort_delay;
int rx_abort_delay;
int tx_error_delay;
int rx_error_delay;
int rx_throttle_prob; // throttle event probability (0 = never, 100 = always - stalled WRF)
int tx_throttle_prob;
} _settings_t ;
_settings_t SIM;
reg txtsu_ack_int;
int rx_gen_oob = 1;
int ready = 0;
// output regs
reg [15:0] irx_data_o;
reg [4:0] irx_ctrl_o;
reg irx_bytesel_o;
reg irx_sof_p1_o;
reg irx_eof_p1_o;
reg irx_valid_o;
reg irx_rerror_p1_o;
reg irx_idle_o;
reg irx_tabort_p1_o;
reg itx_dreq_o;
reg itx_terror_p1_o;
reg itx_rabort_p1_o;
assign rx_data_o = irx_data_o;
assign rx_ctrl_o = irx_ctrl_o;
assign rx_bytesel_o = irx_bytesel_o;
assign rx_sof_p1_o = irx_sof_p1_o;
assign rx_eof_p1_o = irx_eof_p1_o;
assign rx_valid_o = irx_valid_o;
assign rx_rerror_p1_o = irx_rerror_p1_o;
assign rx_idle_o = irx_idle_o;
assign rx_tabort_p1_o = irx_tabort_p1_o;
assign tx_dreq_o = itx_dreq_o;
assign tx_terror_p1_o = itx_terror_p1_o;
assign tx_rabort_p1_o = itx_rabort_p1_o;
// monitor the reset line and initialize the fabric I/F when reset is active
always@(posedge clk_i)
if(!rst_n_i) begin
ready = 0;
// reset WRF source signals
irx_data_o <= 16'hxxxx;
irx_ctrl_o <= 4'hx;
irx_bytesel_o <= 1'bx;
irx_sof_p1_o <= 0;
irx_eof_p1_o <= 0;
irx_valid_o <= 0;
irx_rerror_p1_o <= 0;
irx_tabort_p1_o <= 0;
// reset WRF sink signals
itx_dreq_o <= 1;
itx_terror_p1_o <= 0;
itx_rabort_p1_o <= 0;
tx_queue = new (g_QUEUE_SIZE);
rx_queue = new (g_QUEUE_SIZE);
txtsu_ack_int <= 0;
wait_clk();
wait_clk();
ready = 1;
end
// waits for 1 fabric clock cycle
task wait_clk;
@(posedge clk_i);
endtask // wait_clk
// returns 1 with probability (prob/max_prob)
function automatic int probability_hit(int prob, int max_prob);
int rand_val;
rand_val = $random % (max_prob+1);
if(rand_val < 0) rand_val = -rand_val;
if(rand_val < prob)
return 1;
else
return 0;
endfunction // probability_hit
// enables/disables RX fabric (data source) flow throttling. prob parameter defines the probability (0-100)
// of throttle events
task simulate_rx_throttling(input enable, int prob);
SIM.sim_rx_throttle = enable;
SIM.rx_throttle_prob = prob;
endtask // simulate_tx_throttling
// the same for TX fabric (data sink)
task simulate_tx_throttling(input enable, int prob);
SIM.sim_tx_throttle = enable;
SIM.tx_throttle_prob = prob;
endtask // simulate_tx_throttling
// enables TX fabric source underrun simulation. When enabled, the fabric emulator will stop
// transmitting the data after un_delay transmitted, causing an underrun error in the endopoint.
task simulate_tx_underrun(input enable, input [31:0] un_delay);
SIM.sim_tx_underrun = enable;
SIM.tx_underrun_delay = un_delay;
endtask // simulate_tx_underrun
// Simulates an abort on data source after delay outputted words
task simulate_rx_abort(input enable, input [31:0] delay);
SIM.sim_rx_abort = enable;
SIM.rx_abort_delay = delay;
endtask
task simulate_tx_abort(input enable, input[31:0] delay);
SIM.sim_tx_abort = enable;
SIM.tx_abort_delay = delay;
endtask
task simulate_rx_error(input enable, input [31:0] delay);
SIM.sim_rx_error = enable;
SIM.rx_error_delay = delay;
endtask
task simulate_tx_error(input enable, input[31:0] delay);
SIM.sim_tx_error = enable;
SIM.tx_error_delay = delay;
endtask
// low-level packet send function: spits out tot_len data_vec[] and ctrl_vec[] values onto the WRF, simulating various error/abort/throttling conditions. Do not call directly.
task send_fabric(input [15:0] data_vec[],
input [3:0] ctrl_vec[],
input int odd_len,
input int tot_len,
input int single_idx,
output int error);
int i;
int rand_val;
i = 0;
error = 0;
// wait untile the remote side wants some data from us
while(!rx_dreq_i) wait_clk();
// generate a single-cycle pulse on SOF_P1
irx_valid_o <= 0;
irx_sof_p1_o <= 1;
wait_clk();
irx_sof_p1_o <= 0;
while(i<tot_len) begin
// simulate TX abort condition
if(SIM.sim_tx_abort && i == SIM.tx_abort_delay) begin
irx_valid_o <= 0;
irx_tabort_p1_o <= 1;
wait_clk();
irx_tabort_p1_o <= 0;
wait_clk();
return;
end
// simulate TX (source-orginating) error
if(SIM.sim_tx_error && i == SIM.tx_error_delay) begin
irx_rerror_p1_o <= 1;
wait_clk();
irx_valid_o <= 0;
irx_rerror_p1_o <= 0;
wait_clk();
return;
end
// packet sink requested transfer abort
if(rx_rabort_p1_i) begin
irx_valid_o <= 0;
irx_sof_p1_o <= 0;
irx_eof_p1_o <= 0;
irx_tabort_p1_o <= 0;
error = 1;
return;
end
// simulate TX buffer underrun
if(!rx_dreq_i || (SIM.sim_tx_underrun && (i >= SIM.tx_underrun_delay))) begin
wait_clk();
continue;
// simulate TX flow throttling
end else if(SIM.sim_tx_throttle && probability_hit(SIM.tx_throttle_prob, 100)) begin
irx_valid_o <= 0;
wait_clk();
continue;
// no errors and nothing to mimick? just send the frame...
end else begin
irx_valid_o <= 1;
irx_data_o <= data_vec[i];
irx_ctrl_o <= ctrl_vec[i];
irx_bytesel_o <= (single_idx == i && odd_len);
if(i == tot_len -1) begin
irx_eof_p1_o <= 1;
wait_clk();
irx_valid_o <= 0;
irx_eof_p1_o <= 0;
end
i++;
end
wait_clk();
irx_valid_o <= 0;
end // while (i<tot_len)
/* -----\/----- EXCLUDED -----\/-----
while(rx_dreq_i) begin
if(irx_rerror_p1_i) begin
error = 1;
$display("fabric_emu::send(): RX error during gap");
irx_valid_o <= 0;
irx_sof_p1_o <= 0;
irx_eof_p1_o <= 0;
irx_tabort_p1_o <= 0;
return;
end
wait_clk();
end
-----/\----- EXCLUDED -----/\----- */
endtask // _send_fabric
// Main send function. inputs a frame with ethernet header hdr and a payload (without FCS)
// of length "length"
task send(input ether_header_t hdr, input int payload[], input int length);
reg [`c_wrsw_ctrl_size - 1 : 0] ctrl_vec[0:2000];
reg [15:0] data_vec[0:2000];
reg [31:0] fcs_val;
int i;
int tot_len;
int odd_len;
int single_idx;
int error;
CCRC32 crc_gen;
ether_frame_t frame;
if(!ready) begin
$error("Attempt to call fabric_emu::send() when the emulator is being reset");
return;
end
// $display("Endpoint::send %s [%d bytes]", format_ether_header(hdr), length);
ctrl_vec[0] = `c_wrsw_ctrl_dst_mac; data_vec [0] = hdr.dst[47:32];
ctrl_vec[1] = `c_wrsw_ctrl_dst_mac; data_vec [1] = hdr.dst[31:16];
ctrl_vec[2] = `c_wrsw_ctrl_dst_mac; data_vec [2] = hdr.dst[15:0];
if(!hdr.no_mac) begin
ctrl_vec[3] = `c_wrsw_ctrl_src_mac; data_vec [3] = hdr.src[47:32];
ctrl_vec[4] = `c_wrsw_ctrl_src_mac; data_vec [4] = hdr.src[31:16];
ctrl_vec[5] = `c_wrsw_ctrl_src_mac; data_vec [5] = hdr.src[15:0];
end else begin
ctrl_vec[3] = `c_wrsw_ctrl_none; data_vec [3] = 0;
ctrl_vec[4] = `c_wrsw_ctrl_none; data_vec [4] = 0;
ctrl_vec[5] = `c_wrsw_ctrl_none; data_vec [5] = 0;
end
if(hdr.is_802_1q) begin
ctrl_vec[6] = `c_wrsw_ctrl_none; data_vec[6] = 'h8100;
ctrl_vec[7] = `c_wrsw_ctrl_ethertype; data_vec[7] = hdr.ethertype;
ctrl_vec[8] = `c_wrsw_ctrl_vid_prio; data_vec[8] = hdr.vid | (hdr.prio << 13);
tot_len = 9;
end else begin
ctrl_vec[6] = `c_wrsw_ctrl_ethertype; data_vec[6] = hdr.ethertype;
tot_len = 7;
end
for(int i = 0; i<(length+1) / 2; i++)
begin
data_vec[tot_len + i] = (payload[i*2] << 8) | payload[i*2+1];
ctrl_vec[tot_len + i] = `c_wrsw_ctrl_payload;
end
tot_len = tot_len + (length + 1) / 2;
odd_len = (length & 1);
single_idx = tot_len-1;
crc_gen = new;
for(int i = 0; i< tot_len; i++)
crc_gen.update(data_vec[i], (i==single_idx && odd_len ? 1 : 0));
fcs_val = crc_gen.get();
// insert the OOB (if applicable)
if(hdr.oob_type == `OOB_TYPE_TXTS) begin
if(hdr.oob_fid == 0)
hdr.oob_fid = $random;
data_vec[tot_len] = hdr.oob_fid;
ctrl_vec[tot_len] = `c_wrsw_ctrl_tx_oob;
tot_len ++;
end else if (hdr.oob_type == `OOB_TYPE_RXTS) begin
bit[47:0] oob_data;
oob_data = 0;
oob_data[32+4:32] = hdr.port_id;
oob_data[31:28] = hdr.timestamp_f;
oob_data[27:0] = hdr.timestamp_r;
data_vec[tot_len] = oob_data[47:32]; ctrl_vec[tot_len] = `c_wrsw_ctrl_rx_oob; tot_len++;
data_vec[tot_len] = oob_data[31:16]; ctrl_vec[tot_len] = `c_wrsw_ctrl_rx_oob; tot_len++;
data_vec[tot_len] = oob_data[16:0]; ctrl_vec[tot_len] = `c_wrsw_ctrl_rx_oob; tot_len++;
end
frame.error = 0;
frame.hdr = hdr;
frame.hdr.has_timestamp = 0;
frame.fcs = fcs_val;
for(i=0;i<length;i++)
frame.payload[i] = payload[i];
frame.size = length;
// generate the frame on the TX fabric
send_fabric(data_vec, ctrl_vec, odd_len, tot_len, single_idx, error);
frame.error = error;
tx_queue.push(frame);
endtask // send
// Handles WRF packet sink input
task automatic rx_process();
reg [`c_wrsw_ctrl_size - 1 : 0] ctrl_vec[0:2000];
reg [15:0] data_vec[0:2000];
int bytesel_saved;
ether_frame_t frame;
int error;
int rand_val;
int i, data_start, tot_len, payload_len;
i = 0;
bytesel_saved = 0;
wait_clk();
while(1) begin //while(!tx_eof_p1_i && !tx_rerror_p1_i) begin
// simulate the flow throttling
if(SIM.sim_rx_throttle && probability_hit(SIM.rx_throttle_prob, 100))
itx_dreq_o <= 0;
else
itx_dreq_o <= 1;
// simulate the RX abort
if(SIM.sim_rx_abort && i >= SIM.rx_abort_delay)
begin
itx_rabort_p1_o <= 1;
wait_clk();
itx_rabort_p1_o <= 0;
return;
end
// got a valid data word? Put it in the buffer
if(tx_valid_i) begin
ctrl_vec[i] = tx_ctrl_i;
data_vec[i] = tx_data_i;
// $display("tx_data_i %x", tx_data_i);
if(tx_bytesel_i && tx_ctrl_i == `c_wrsw_ctrl_payload) bytesel_saved = 1;
i++;
end
if(tx_eof_p1_i || tx_rerror_p1_i) break;
wait_clk();
end
error = tx_rerror_p1_i;
tot_len = i;
frame.hdr.dst[47:32] = data_vec[0];
frame.hdr.dst[31:16] = data_vec[1];
frame.hdr.dst[15:0] = data_vec[2];
frame.hdr.src[47:32] = data_vec[3];
frame.hdr.src[31:16] = data_vec[4];
frame.hdr.src[15:0] = data_vec[5];
if(data_vec[6] == 16'h8100) begin // 802.1q header
frame.hdr.is_802_1q = 1;
frame.hdr.ethertype = data_vec[7];
frame.hdr.vid = data_vec[8] & 16'h0fff;
frame.hdr.prio = (data_vec[8] >> 13);
data_start = 9;
end else begin
frame.hdr.is_802_1q = 0;
frame.hdr.ethertype = data_vec[6];
data_start = 7;
end
payload_len = 0;
for(i=0; ctrl_vec[data_start + i] == `c_wrsw_ctrl_payload && i < tot_len; i++)
begin
frame.payload[2*i] = data_vec[data_start + i][15:8];
frame.payload[2*i+1] = data_vec[data_start + i][7:0];
payload_len = payload_len + 2;
end
if(bytesel_saved)
payload_len --;
if(tot_len > i && ctrl_vec[data_start + i] == `c_wrsw_ctrl_rx_oob) begin
frame.hdr.has_timestamp = 1;
frame.hdr.port_id = data_vec[data_start+i][15:11];
frame.hdr.timestamp_r = {data_vec[data_start+i+1][11:0],data_vec[data_start+i+2]} ;
frame.hdr.timestamp_f = data_vec[data_start+i+1][15:12];
end
frame.size = payload_len;
frame.error = error;
// dump_frame_header("RX: ", frame);
rx_queue.push(frame);
endtask // rx_process
task emulate_txtsu();
if(txtsu_valid_i && !txtsu_ack_int) begin
if(tx_queue.update_tx_timestamp( txtsu_fid_i, txtsu_port_id_i,txtsu_tsval_i))
// $display("emulate_txtsu(): got TX timestamp for FID: 0x%04x", txtsu_fid_i);
wait_clk();
txtsu_ack_int <= 1;
end else
txtsu_ack_int <= 0;
endtask // sim_txtsu
initial forever begin
itx_dreq_o <= 1;
wait_clk();
if(tx_sof_p1_i) rx_process();
end
initial forever begin
wait_clk();
if(txtsu_valid_i) emulate_txtsu();
end
assign txtsu_ack_o = txtsu_ack_int;
function int poll();
if(!ready) return 0;
return rx_queue.get_count();
endfunction // UNMATCHED !!
task automatic receive(output ether_frame_t fra);
rx_queue.pop(fra);
endtask
endmodule
\ No newline at end of file
`ifndef __FABRIC_EMU_DEFS_SV
`define __FABRIC_EMU_DEFS_SV
/* Ethernet frame header extended with WR-compliant OOB signalling */
typedef struct {
bit no_mac; // when 1, there's no valid source MAC present in the frame header and the SRC MAC field must be filled by the endpoint
bit [47:0] dst; // DST MAC
bit [47:0] src; // SRC MAC
bit [15:0] ethertype;
bit is_802_1q; // when 1, the frame has 802.1q header
bit [11:0] vid; // VLAN ID
bit [2:0] prio; // PCP priority tag
int oob_type; // OOB TYPE: OOB_TYPE_TXTS = TX frame ID (for TX timestamping), OOB_TYPE_RXTS = RX timestamp
bit[15:0] oob_fid; //
bit [27:0] timestamp_r;
bit [3:0] timestamp_f;
bit [4:0] port_id;
bit has_timestamp; // when 1, the TX/RX timestamp is valid
} ether_header_t;
/* Full ethernet frame */
typedef struct {
ether_header_t hdr;
int size;
int payload[2048];
bit[31:0] fcs;
bit error;
bit has_payload;
} ether_frame_t;
/* WR-compliant TX frame timestamp */
typedef struct {
bit[15:0] fid;
bit [4:0] pid;
bit [27:0] timestamp_r;
bit [3:0] timestamp_f;
} tx_timestamp_t;
`timescale 1ns/1ps
/* Bus widths definition, taken from global_defs.vhd */
`define c_wrsw_ctrl_size 4
`define c_wrsw_oob_frame_id_size 16
`define c_wrsw_timestamp_size_r 28
`define c_wrsw_timestamp_size_f 4
`define c_wrsw_mac_addr_width 48
`define c_wrsw_vid_width 12
`define c_wrsw_prio_width 3
`define c_wrsw_num_ports 11
/* ctrl bus codes */
`define c_wrsw_ctrl_none 4'h0
`define c_wrsw_ctrl_dst_mac 4'h1
`define c_wrsw_ctrl_src_mac 4'h2
`define c_wrsw_ctrl_ethertype 4'h3
`define c_wrsw_ctrl_vid_prio 4'h4
`define c_wrsw_ctrl_tx_oob 4'h5
`define c_wrsw_ctrl_rx_oob 4'h6
`define c_wrsw_ctrl_payload 4'h7
/* OOB types */
`define OOB_TYPE_TXTS 1
`define OOB_TYPE_RXTS 2
`define QUEUE_MAX_FRAMES 128
//
// WhiteRabbit Fabric Interface (WRF) Macros
//
// declares basic fabric interface (only the mandatory singals)
// sink port list in a verilog/SV module, prefixed with "prefix":
// for example `WRF_PORTS_SINK(test) will generate the following signals
// test_sof_p1_i, test_eof_p1_i, test_data_i, etc....
`define WRF_PORTS_SINK(prefix) \
input [15:0] prefix``_data_i,\
input [3:0] prefix``_ctrl_i,\
input prefix``_bytesel_i,\
input prefix``_sof_p1_i,\
input prefix``_eof_p1_i,\
output prefix``_dreq_o,\
input prefix``_valid_i,\
input prefix``_rerror_p1_i
// array version
/*
`define WRF_PORTS_SINK_ARRAY(prefix) \
input [11*15-1:0] prefix``_data_i,\
input [11* 3-1:0] prefix``_ctrl_i,\
input [10:0] prefix``_bytesel_i,\
input [10:0] prefix``_sof_p1_i,\
input [10:0] prefix``_eof_p1_i[size - 1 : 0],\
output[10:0] prefix``_dreq_o,\
input [10:0] prefix``_valid_i,\
input [10:0] prefix``_rerror_p1_i
*/
// same as above but with all WRF signals
`define WRF_FULL_PORTS_SINK(prefix) \
`WRF_PORTS_SINK(prefix),\
output prefix``_terror_p1_o,\
input prefix``_idle_i,\
input prefix``_tabort_p1_i,\
output prefix``_rabort_p1_o
// like the macro above, but for fabric source, mandatory signals only
`define WRF_PORTS_SOURCE(prefix) \
output [15:0] prefix``_data_o,\
output [3:0] prefix``_ctrl_o,\
output prefix``_bytesel_o,\
output prefix``_sof_p1_o,\
output prefix``_eof_p1_o,\
input prefix``_dreq_i,\
output prefix``_valid_o,\
output prefix``_rerror_p1_o
// same as above, but for full WRF
`define WRF_FULL_PORTS_SOURCE(prefix) \
`WRF_PORTS_SOURCE(prefix), \
input prefix``_terror_p1_i,\
output prefix``_idle_o,\
output prefix``_tabort_p1_o,\
input prefix``_rabort_p1_i
// declares a list of verilog/SV wires for a given fabric name
`define WRF_WIRES(prefix) \
wire [15:0] prefix``_data;\
wire [3 :0] prefix``_ctrl;\
wire prefix``_bytesel;\
wire prefix``_dreq;\
wire prefix``_valid;\
wire prefix``_sof_p1;\
wire prefix``_eof_p1;\
wire prefix``_rerror_p1;
// same as above, but for full WRF
`define WRF_FULL_WIRES(prefix) \
`WRF_SIGNALS(prefix)\
wire prefix``_terror_p1;\
wire prefix``_idle;\
wire prefix``_tabort_p1;\
wire prefix``_rabort_p1;
// Connects fabric sink ports prefixed with port_pfx to fabric wires prefixed with fab_pfx
`define _WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx) \
.port_pfx``_data_i(fab_pfx``_data),\
.port_pfx``_ctrl_i(fab_pfx``_ctrl),\
.port_pfx``_bytesel_i(fab_pfx``_bytesel),\
.port_pfx``_dreq_o(fab_pfx``_dreq),\
.port_pfx``_valid_i(fab_pfx``_valid),\
.port_pfx``_sof_p1_i(fab_pfx``_sof_p1),\
.port_pfx``_eof_p1_i(fab_pfx``_eof_p1),\
.port_pfx``_rerror_p1_i(fab_pfx``_rerror_p1)
`define _WRF_CONNECT_MANDATORY_SINK_ML(port_pfx, fab_pfx, port) \
.port_pfx``_data_i(fab_pfx``_data[(port + 1)*16 - 1 : port*16]),\
.port_pfx``_ctrl_i(fab_pfx``_ctrl[(port + 1)*4 - 1 : port*4 ]),\
.port_pfx``_bytesel_i(fab_pfx``_bytesel[port]),\
.port_pfx``_dreq_o(fab_pfx``_dreq[port]),\
.port_pfx``_valid_i(fab_pfx``_valid[port]),\
.port_pfx``_sof_p1_i(fab_pfx``_sof_p1[port]),\
.port_pfx``_eof_p1_i(fab_pfx``_eof_p1[port]),\
.port_pfx``_rerror_p1_i(fab_pfx``_rerror_p1[port])
// full fabric I/F version
`define WRF_FULL_CONNECT_SINK(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx), \
.port_pfx``_terror_p1_o(fab_pfx``_terror_p1),\
.port_pfx``_tabort_p1_i(fab_pfx``_tabort_p1),\
.port_pfx``_rabort_p1_o(fab_pfx``_rabort_p1),\
.port_pfx``_idle_i(fab_pfx``_idle)
`define WRF_FULL_CONNECT_SINK_ML(port_pfx, fab_pfx, port) \
`_WRF_CONNECT_MANDATORY_SINK_ML(port_pfx, fab_pfx, port), \
.port_pfx``_terror_p1_o(fab_pfx``_terror_p1[port]),\
// .port_pfx``_tabort_p1_i(fab_pfx``_tabort_p1[port]),\
.port_pfx``_rabort_p1_o(fab_pfx``_tabort_p1[port]),\
.port_pfx``_idle_i(fab_pfx``_idle[port])
// Connects fabric sink ports prefixed with port_pfx to fabric wires prefixed with fab_pfx
`define WRF_CONNECT_SINK(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx), \
.port_pfx``_terror_p1_o(),\
.port_pfx``_tabort_p1_i(1'b0),\
.port_pfx``_rabort_p1_o(),\
.port_pfx``_idle_i(1'b0)
`define WRF_CONNECT_SINK_ML(port_pfx, fab_pfx, port) \
`_WRF_CONNECT_MANDATORY_SINK_ML(port_pfx, fab_pfx, port), \
.port_pfx``_terror_p1_o(),\
.port_pfx``_tabort_p1_i(1'b0),\
.port_pfx``_rabort_p1_o(),\
.port_pfx``_idle_i(1'b0)
`define _WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx) \
.port_pfx``_data_o(fab_pfx``_data),\
.port_pfx``_ctrl_o(fab_pfx``_ctrl),\
.port_pfx``_bytesel_o(fab_pfx``_bytesel),\
.port_pfx``_dreq_i(fab_pfx``_dreq),\
.port_pfx``_valid_o(fab_pfx``_valid),\
.port_pfx``_sof_p1_o(fab_pfx``_sof_p1),\
.port_pfx``_eof_p1_o(fab_pfx``_eof_p1),\
.port_pfx``_rerror_p1_o(fab_pfx``_rerror_p1)
`define _WRF_CONNECT_MANDATORY_SOURCE_ML(port_pfx, fab_pfx, port) \
.port_pfx``_data_o(fab_pfx``_data[(port + 1)*16 - 1: port*16]),\
.port_pfx``_ctrl_o(fab_pfx``_ctrl[(port + 1)*4 - 1: port*4]),\
.port_pfx``_bytesel_o(fab_pfx``_bytesel[port]),\
.port_pfx``_dreq_i(fab_pfx``_dreq[port]),\
.port_pfx``_valid_o(fab_pfx``_valid[port]),\
.port_pfx``_sof_p1_o(fab_pfx``_sof_p1[port]),\
.port_pfx``_eof_p1_o(fab_pfx``_eof_p1[port]),\
.port_pfx``_rerror_p1_o(fab_pfx``_rerror_p1[port])
// same as above, but for source ports, full WRF version
`define WRF_FULL_CONNECT_SOURCE(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx),\
.port_pfx``_terror_p1_i(fab_pfx``_terror_p1),\
.port_pfx``_tabort_p1_o(fab_pfx``_tabort_p1),\
.port_pfx``_rabort_p1_i(fab_pfx``_rabort_p1),\
.port_pfx``_idle_o(fab_pfx``_idle)
`define WRF_FULL_CONNECT_SOURCE_ML(port_pfx, fab_pfx, port) \
`_WRF_CONNECT_MANDATORY_SOURCE_ML(port_pfx, fab_pfx, port),\
.port_pfx``_terror_p1_i(fab_pfx``_terror_p1[port]),\
.port_pfx``_tabort_p1_o(fab_pfx``_tabort_p1[port])
// .port_pfx``_rabort_p1_i(fab_pfx``_rabort_p1[port])
// .port_pfx``_idle_o(fab_pfx``_idle[port])
// same as above, but for source ports, basic WRF version
`define WRF_CONNECT_SOURCE(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx),\
.port_pfx``_terror_p1_i(1'b0),\
.port_pfx``_tabort_p1_o(),\
.port_pfx``_rabort_p1_i(1'b0),\
.port_pfx``_idle_o()
// same as above, but for source ports, basic WRF version
`define WRF_CONNECT_SOURCE_ML(port_pfx, fab_pfx, port) \
`_WRF_CONNECT_MANDATORY_SOURCE_ML(port_pfx, fab_pfx, port),\
.port_pfx``_terror_p1_i(1'b0),\
.port_pfx``_tabort_p1_o(),\
.port_pfx``_rabort_p1_i(1'b0),\
.port_pfx``_idle_o()
`endif
\ No newline at end of file
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`timescale 1ns / 1ps
`include "fabric_emu.sv"
module main;
const int c_clock_period = 8;
reg clk = 0;
reg rst_n = 0;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
// generate clock and reset signals
always #(c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
// Two fabric emulators talking to each other
fabric_emu U_emuA
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ba), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, ab)
);
fabric_emu U_emuB
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ab),
`WRF_CONNECT_SINK(tx, ba)
);
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(U_emuA.ready); // wait until both emulators are initialized
wait(U_emuB.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<100;i++)
buffer[i] = i;
// simulate some flow throttling
U_emuA.simulate_rx_throttling(1, 50);
U_emuA.send(hdr, buffer, 100);
hdr.src = 'h0f0e0a0b0d00;
U_emuB.send(hdr, buffer, 50);
end
// Check if there's anything received by EMU B
always @(posedge clk) if (U_emuB.poll())
begin
ether_frame_t frame;
$display("Emulator B received a frame!");
U_emuB.receive(frame);
dump_frame_header("EmuB RX: ", frame);
end
// Check if there's anything received by EMU A
always @(posedge clk) if (U_emuA.poll())
begin
ether_frame_t frame;
$display("Emulator A received a frame!");
U_emuA.receive(frame);
dump_frame_header("EmuA RX: ", frame);
end
endmodule // main
`timescale 1ns/1ps
/* Ethernet FCS calculator class */
class CCRC32;
protected bit [31:0] crc;
protected bit [31:0] crc_tab[256];
function new();
reg [31:0] c, poly;
int i, j;
poly = 32'hEDB88320;
for (i = 0; i < 256; i++) begin
c = i;
for (j = 8; j > 0; j--) begin
if (c & 1)
c = (c >> 1) ^ poly;
else
c >>= 1;
end
crc_tab[i] = c;
end
crc = 32'hffffffff;
endfunction // new
function bit[31:0] bitrev(bit[31:0] x, int n);
reg [31:0] y= 0;
int i;
for(i=0;i<n;i++) if(x & (1<<i)) y|= 1<< (n-1-i);
bitrev=y;
endfunction
task update_int(bit[7:0] x);
crc = ((crc >> 8) & 32'h00FFFFFF) ^ crc_tab[(crc ^ bitrev(x,8)) & 32'hFF];
endtask
task update(input [15:0] x, int bytesel);
update_int(x[15:8]);
if(!bytesel)
update_int(x[7:0]);
endtask // update
function bit[31:0] get();
get = bitrev(crc ^ 32'hffffffff, 32);
endfunction // get
endclass
/* Simple packet queue */
class CPacketQueue;
protected int head, tail, count;
protected int size;
protected ether_frame_t d[];
function new (int _size);
size = _size;
head = 0;
tail = 0;
count = 0;
d = new [_size];
endfunction // new
task push(input ether_frame_t frame);
if(count == size) begin
$display("CPacketQueue::push(): queue overflow");
$stop();
end
d[head] = frame;
head++; if(head == size) head = 0;
count++;
endtask // push
task pop (output ether_frame_t frame);
if(count <= 0) begin
$display("CPacketQueue::pop(): queue empty");
$stop();
end
frame = d[tail];
tail++; if(tail == size) tail = 0;
count--;
endtask // pop
function int get_count();
return count;
endfunction // get_count
/* Looks for a packet with matching OOB frame identifier and updates it with the new timestamp value */
function int update_tx_timestamp(input [15:0] oob_fid,
input [4:0] port_id,
input [31:0] ts_value);
int i;
i = tail;
while(i != head)
begin
if(d[i].hdr.oob_type == `OOB_TYPE_TXTS && d[i].hdr.oob_fid == oob_fid) begin
d[i].hdr.timestamp_r = ts_value[27:0];
d[i].hdr.timestamp_f = ts_value[31:28];
d[i].hdr.has_timestamp = 1;
return 1;
end
i++;
if(i == count) i = 0;
end
return 0;
endfunction // update_tx_timestamp
endclass // CPacketQueue
// converts a nbytes-long number (hex) to hexadecimal string
function automatic string hex_2_str(input [47:0] hex, int nbytes);
int i;
string s = "";
string hexchars = "0123456789abcdef";
reg [47:0] t;
t = hex;
for(i=0; i<2*nbytes; i++) begin
s= {hexchars[t&'hf], s};
t=t>>4;
end
return s;
endfunction // hex_2_str
// formats an Ethernet frame header as a nice looking string
function automatic string format_ether_header(input ether_header_t hdr);
string s = {"DST: ", hex_2_str(hdr.dst, 6),
" SRC: ", hex_2_str(hdr.src, 6),
" Type: 0x",hex_2_str(hdr.ethertype, 2) };
if(hdr.is_802_1q) s = {s, " VLAN: 0x", hex_2_str({4'b0,hdr.vid}, 2), " PRIO: ", hex_2_str({5'b0, hdr.prio},1) };
return s;
endfunction // automatic
task dump_frame_header(string s, ether_frame_t frame);
if(frame.hdr.ethertype == frame.size)
$display("%s %s (size: %d, port_id: %4d) length = %d %s %s", s, format_ether_header(frame.hdr),frame.hdr.ethertype, frame.hdr.src >> 44, frame.size, frame.error?"ERROR":"OK", frame.hdr.has_timestamp?"TS":"NoTS");
else
begin
$display("%s %s (size: %d, port_id: %4d) length = %d %s %s =>> ERROR here", s, format_ether_header(frame.hdr),frame.hdr.ethertype, frame.hdr.src >> 44, frame.size, frame.error?"ERROR":"OK", frame.hdr.has_timestamp?"TS":"NoTS");
$fatal("dupa");
end
endtask // dump_frame_header
\ No newline at end of file
-- Copyright (C) 1991-2009 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Quartus II generated Memory Initialization File (.mif)
WIDTH=32;
DEPTH=32;
ADDRESS_RADIX=UNS;
DATA_RADIX=UNS;
CONTENT BEGIN
[0..31] : 4294967295;
END;
vlib work
vlog -sv fabric_emu_demo.sv
vsim work.main -voptargs="+acc"
radix -hexadecimal
do wave.do
run 300us
wave zoomfull
\ No newline at end of file
vlib work
#vcom ../../../platform/altera/generic_sync_fifo.vhd
#vcom ../../../platform/altera/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem.vhd
vcom ../../../modules/wrsw_swcore/swc_page_alloc.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_page_allocator.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_linked_list.vhd
vcom ../../../modules/wrsw_swcore/swc_input_block.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_read_pump.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_write_pump.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_input.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_output.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_arbiter.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_pg_free_module.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_pck_pg_free_module.vhd
vcom ../../../modules/wrsw_swcore/swc_ob_prio_queue.vhd
vcom ../../../modules/wrsw_swcore/swc_output_block.vhd
vcom ../../../sim/vhdl_stdio/PCK_FIO_1993.vhd
vcom ../../../sim/vhdl_stdio/PCK_FIO_1993_BODY.vhd
vcom ../../../modules/wrsw_swcore/swc_core.vhd
vlog -sv swc_core.v4.sv
#vlog -sv swc_core.sv
vsim work.main -voptargs="+acc"
radix -hexadecimal
do wave.do
run 300us
#wave zoomfull
vlib work
#vcom ../../../platform/altera/generic_sync_fifo.vhd
vcom ../../../platform/altera/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem.vhd
vcom ../../../modules/wrsw_swcore/swc_page_alloc.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_page_allocator.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_linked_list.vhd
vcom ../../../modules/wrsw_swcore/swc_input_block.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_read_pump.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_write_pump.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_input.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_output.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_arbiter.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_pg_free_module.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_pck_pg_free_module.vhd
vcom ../../../modules/wrsw_swcore/swc_ob_prio_queue.vhd
vcom ../../../modules/wrsw_swcore/swc_output_block.vhd
vcom ../../../modules/wrsw_swcore/swc_core_single_port.vhd
vlog -sv swc_core_single_port.sv
vsim work.main -voptargs="+acc"
radix -hexadecimal
do wave.do
run 30us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_input_block.vhd
vlog -sv swc_input_block.sv
vsim work.main -voptargs="+acc"
radix -hexadecimal
do wave.do
run 3us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_prio_encoder.vhd
vcom ../../../modules/wrsw_swcore/swc_rr_arbiter.vhd
vcom ../../../modules/wrsw_swcore/swc_page_alloc.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_page_allocator.vhd
vlog swc_multiport_allocator_tb.v
vsim work.main
radix -hexadecimal
add wave \
{sim:/main/pgaddr_alloc } \
{sim:/main/done_alloc } \
{sim:/main/done_free } \
{sim:/main/done_force_free } \
{sim:/main/done_set_usecnt }
add wave \
{sim:/main/DUT/rst_n_i } \
{sim:/main/DUT/clk_i } \
{sim:/main/DUT/alloc_i } \
{sim:/main/DUT/free_i } \
{sim:/main/DUT/force_free_i } \
{sim:/main/DUT/set_usecnt_i } \
{sim:/main/DUT/alloc_done_o } \
{sim:/main/DUT/free_done_o } \
{sim:/main/DUT/force_free_done_o } \
{sim:/main/DUT/set_usecnt_done_o } \
{sim:/main/DUT/pgaddr_free_i } \
{sim:/main/DUT/usecnt_i } \
{sim:/main/DUT/pgaddr_alloc_o } \
{sim:/main/DUT/nomem_o } \
{sim:/main/DUT/pg_alloc } \
{sim:/main/DUT/pg_free } \
{sim:/main/DUT/pg_force_free } \
{sim:/main/DUT/pg_set_usecnt } \
{sim:/main/DUT/pg_usecnt } \
{sim:/main/DUT/pg_addr_alloc } \
{sim:/main/DUT/pg_addr_free } \
{sim:/main/DUT/pg_addr_valid } \
{sim:/main/DUT/pg_idle } \
{sim:/main/DUT/pg_done } \
{sim:/main/DUT/pg_nomem } \
{sim:/main/DUT/request_vec } \
{sim:/main/DUT/request_grant } \
{sim:/main/DUT/request_next } \
{sim:/main/DUT/request_grant_valid } \
{sim:/main/DUT/in_sel } \
{sim:/main/DUT/alloc_done_feedback } \
{sim:/main/DUT/alloc_done } \
{sim:/main/DUT/free_done_feedback } \
{sim:/main/DUT/free_done } \
{sim:/main/DUT/force_free_done_feedback } \
{sim:/main/DUT/force_free_done } \
{sim:/main/DUT/set_usecnt_done_feedback } \
{sim:/main/DUT/set_usecnt_done }
do wave.do
run 500us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_prio_encoder.vhd
vcom ../../../modules/wrsw_swcore/swc_rr_arbiter.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_linked_list.vhd
vlog swc_multiport_linked_list_tb.v
vsim work.main
radix -hexadecimal
do wave.do
add wave \
{sim:/main/done_write } \
{sim:/main/done_free } \
{sim:/main/done_free_pck } \
{sim:/main/done_read } \
{sim:/main/data_out }
add wave \
{sim:/main/DUT/rst_n_i } \
{sim:/main/DUT/clk_i } \
{sim:/main/DUT/write_i } \
{sim:/main/DUT/free_i } \
{sim:/main/DUT/read_pump_read_i } \
{sim:/main/DUT/free_pck_read_i } \
{sim:/main/DUT/write_done_o } \
{sim:/main/DUT/free_done_o } \
{sim:/main/DUT/read_pump_read_done_o } \
{sim:/main/DUT/free_pck_read_done_o } \
{sim:/main/DUT/read_pump_addr_i } \
{sim:/main/DUT/free_pck_addr_i } \
{sim:/main/DUT/write_addr_i } \
{sim:/main/DUT/free_addr_i } \
{sim:/main/DUT/write_data_i } \
{sim:/main/DUT/data_o } \
{sim:/main/DUT/ll_write_enable } \
{sim:/main/DUT/ll_write_addr } \
{sim:/main/DUT/ll_free_addr } \
{sim:/main/DUT/ll_wr_addr } \
{sim:/main/DUT/ll_rd_addr } \
{sim:/main/DUT/ll_write_data } \
{sim:/main/DUT/ll_wr_data } \
{sim:/main/DUT/ll_read_data } \
{sim:/main/DUT/write_request_vec } \
{sim:/main/DUT/read_request_vec } \
{sim:/main/DUT/write_request_grant } \
{sim:/main/DUT/read_request_grant } \
{sim:/main/DUT/write_request_grant_valid } \
{sim:/main/DUT/read_request_grant_valid } \
{sim:/main/DUT/in_sel_write } \
{sim:/main/DUT/in_sel_read } \
{sim:/main/DUT/write_done_feedback } \
{sim:/main/DUT/write_done } \
{sim:/main/DUT/free_done_feedback } \
{sim:/main/DUT/free_done } \
{sim:/main/DUT/read_pump_read_done_feedback } \
{sim:/main/DUT/read_pump_read_done } \
{sim:/main/DUT/free_pck_read_done_feedback } \
{sim:/main/DUT/free_pck_read_done }
run 500us
wave zoomfull
\ No newline at end of file
vlib work
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../platform/altera/generic_async_fifo_2stage.vhd
vcom ../../../modules/wrsw_swcore/swc_prio_encoder.vhd
vcom ../../../modules/wrsw_swcore/swc_rr_arbiter.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_lost_pck_dealloc.vhd
vlog swc_multiport_lost_pck_dealloc_tb.v
vsim work.main
radix -hexadecimal
do wave.do
add wave \
{sim:/main/DUT/rst_n_i } \
{sim:/main/DUT/clk_i } \
{sim:/main/DUT/ib_force_free_i } \
{sim:/main/DUT/ib_force_free_done_o } \
{sim:/main/DUT/ib_pgaddr_free_i } \
{sim:/main/DUT/ob_force_free_i } \
{sim:/main/DUT/ob_force_free_done_o } \
{sim:/main/DUT/ob_pgaddr_free_i } \
{sim:/main/DUT/request_grant } \
{sim:/main/DUT/request_grant_valid } \
{sim:/main/DUT/in_sel } \
{sim:/main/DUT/force_free_done_feedback } \
{sim:/main/DUT/force_free_done } \
{sim:/main/DUT/ib_force_free_done } \
{sim:/main/DUT/fifo_full } \
{sim:/main/DUT/pgaddr } \
{sim:/main/DUT/request } \
{sim:/main/DUT/pg_addr_free }
run 500us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_ob_prio_queue.vhd
vlog -sv swc_ob_prio_quque_tb.v
#vsim work.main
#radix -hexadecimal
#do wave.do
#add wave \
#{sim:/main/DUT/clk_i } \
#{sim:/main/DUT/rst_n_i } \
#{sim:/main/DUT/write_i } \
#{sim:/main/DUT/read_i } \
#{sim:/main/DUT/wr_en_o } \
#{sim:/main/DUT/wr_addr_o } \
#{sim:/main/DUT/rd_addr_o } \
#{sim:/main/DUT/head } \
#{sim:/main/DUT/tail } \
#{sim:/main/DUT/not_full } \
#{sim:/main/DUT/not_empty }
restart
run 15us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_prio_encoder.vhd
vcom ../../../modules/wrsw_swcore/swc_ob_prio_queue.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_output_block.vhd
vlog -sv swc_output_block_tb.v
vsim work.main
radix -hexadecimal
do wave.do
add wave \
{sim:/main/DUT/clk_i } \
{sim:/main/DUT/rst_n_i } \
{sim:/main/DUT/pta_transfer_data_valid_i } \
{sim:/main/DUT/pta_pageaddr_i } \
{sim:/main/DUT/pta_prio_i } \
{sim:/main/DUT/pta_pck_size_i } \
{sim:/main/DUT/pta_transfer_data_ack_o } \
{sim:/main/DUT/mpm_pgreq_o } \
{sim:/main/DUT/mpm_pgaddr_o } \
{sim:/main/DUT/mpm_pckend_i } \
{sim:/main/DUT/mpm_pgend_i } \
{sim:/main/DUT/mpm_drdy_i } \
{sim:/main/DUT/mpm_dreq_o } \
{sim:/main/DUT/mpm_data_i } \
{sim:/main/DUT/mpm_ctrl_i } \
{sim:/main/DUT/rx_sof_p1_o } \
{sim:/main/DUT/rx_eof_p1_o } \
{sim:/main/DUT/rx_dreq_i } \
{sim:/main/DUT/rx_ctrl_o } \
{sim:/main/DUT/rx_data_o } \
{sim:/main/DUT/rx_valid_o } \
{sim:/main/DUT/rx_bytesel_o } \
{sim:/main/DUT/rx_idle_o } \
{sim:/main/DUT/rx_rerror_p1_o } \
{sim:/main/DUT/wr_addr } \
{sim:/main/DUT/rd_addr } \
{sim:/main/DUT/wr_prio } \
{sim:/main/DUT/rd_prio } \
{sim:/main/DUT/not_full_array } \
{sim:/main/DUT/not_empty_array } \
{sim:/main/DUT/read_array } \
{sim:/main/DUT/read } \
{sim:/main/DUT/write_array } \
{sim:/main/DUT/write } \
{sim:/main/DUT/wr_en } \
{sim:/main/DUT/rd_data_valid } \
{sim:/main/DUT/zeros } \
{sim:/main/DUT/wr_array } \
{sim:/main/DUT/rd_array } \
{sim:/main/DUT/state } \
{sim:/main/DUT/pgreq } \
{sim:/main/DUT/wr_data } \
{sim:/main/DUT/rd_data } \
{sim:/main/DUT/rd_pck_size } \
{sim:/main/DUT/current_pck_size } \
{sim:/main/DUT/cnt_pck_size } \
{sim:/main/DUT/rx_sof_p1 } \
{sim:/main/DUT/rx_eof_p1 } \
{sim:/main/DUT/rx_valid }
run 1us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_multiport_linked_list.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_read_pump.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_write_pump.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem.vhd
vlog -sv swc_packet_mem_tb.v
vsim work.main
radix -hexadecimal
do wave.do
run 15us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_prio_encoder.vhd
vcom ../../../modules/wrsw_swcore/swc_page_alloc.vhd
vlog swc_page_alloc_tb.v
vsim work.main
radix -hexadecimal
do wave.do
add wave \
{sim:/main/idle } \
{sim:/main/nomem } \
{sim:/main/pgaddr_o } \
{sim:/main/pgaddr_valid }
add wave \
{sim:/main/dut/g_num_pages } \
{sim:/main/dut/g_page_addr_bits } \
{sim:/main/dut/g_use_count_bits } \
{sim:/main/dut/clk_i } \
{sim:/main/dut/rst_n_i } \
{sim:/main/dut/alloc_i } \
{sim:/main/dut/free_i } \
{sim:/main/dut/force_free_i } \
{sim:/main/dut/set_usecnt_i } \
{sim:/main/dut/usecnt_i } \
{sim:/main/dut/pgaddr_i } \
{sim:/main/dut/pgaddr_o } \
{sim:/main/dut/pgaddr_valid_o } \
{sim:/main/dut/idle_o } \
{sim:/main/dut/done_o } \
{sim:/main/dut/nomem_o } \
{sim:/main/dut/l1_bitmap } \
{sim:/main/dut/l1_first_free } \
{sim:/main/dut/l1_mask } \
{sim:/main/dut/l0_mask } \
{sim:/main/dut/l0_first_free } \
{sim:/main/dut/state } \
{sim:/main/dut/free_blocks } \
{sim:/main/dut/l0_wr_data } \
{sim:/main/dut/l0_rd_data } \
{sim:/main/dut/l0_wr_addr } \
{sim:/main/dut/l0_rd_addr } \
{sim:/main/dut/l0_wr } \
{sim:/main/dut/usecnt_mem_wraddr } \
{sim:/main/dut/usecnt_mem_rdaddr } \
{sim:/main/dut/usecnt_mem_wr } \
{sim:/main/dut/usecnt_mem_rddata } \
{sim:/main/dut/usecnt_mem_wrdata }
run 400us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_input.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_output.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_arbiter.vhd
vlog -sv swc_pck_transfer_arbiter_tb.v
vsim work.main
radix -hexadecimal
do wave.do
add wave \
{sim:/main/DUT/clk_i } \
{sim:/main/DUT/rst_n_i } \
{sim:/main/DUT/ob_data_valid_o } \
{sim:/main/DUT/ob_ack_i } \
{sim:/main/DUT/ob_pageaddr_o } \
{sim:/main/DUT/ob_prio_o } \
{sim:/main/DUT/ib_transfer_pck_i } \
{sim:/main/DUT/ib_transfer_ack_o } \
{sim:/main/ib_busy } \
{sim:/main/DUT/ib_busy_o } \
{sim:/main/DUT/ib_pageaddr_i } \
{sim:/main/DUT/ib_mask_i } \
{sim:/main/DUT/ib_prio_i } \
{sim:/main/DUT/pto_pageaddr } \
{sim:/main/DUT/pto_output_mask } \
{sim:/main/DUT/pto_read_mask } \
{sim:/main/DUT/pto_prio } \
{sim:/main/DUT/pti_transfer_data_ack } \
{sim:/main/DUT/pti_transfer_data_valid } \
{sim:/main/DUT/pti_pageaddr } \
{sim:/main/DUT/pti_prio } \
{sim:/main/DUT/sync_sreg } \
{sim:/main/DUT/sync_cntr } \
{sim:/main/DUT/sync_cntr_ack }
add wave \
{sim:/main/DUT/gen_output(0)/transfer_output/ob_pageaddr_o } \
{sim:/main/DUT/gen_output(0)/transfer_output/ob_prio_o } \
{sim:/main/DUT/gen_output(0)/transfer_output/pti_pageaddr_i } \
{sim:/main/DUT/gen_output(0)/transfer_output/pti_prio_i } \
{sim:/main/DUT/gen_output(0)/transfer_output/pti_transfer_data_ack } \
{sim:/main/DUT/gen_output(0)/transfer_output/ob_transfer_data_valid } \
{sim:/main/DUT/gen_output(0)/transfer_output/ob_pageaddr } \
{sim:/main/DUT/gen_output(0)/transfer_output/ob_prio }
add wave \
{sim:/main/DUT/gen_input(0)/transfer_input/pto_pageaddr_o } \
{sim:/main/DUT/gen_input(0)/transfer_input/pto_output_mask_o } \
{sim:/main/DUT/gen_input(0)/transfer_input/pto_prio_o } \
{sim:/main/DUT/gen_input(0)/transfer_input/ib_pageaddr_i } \
{sim:/main/DUT/gen_input(0)/transfer_input/ib_mask_i } \
{sim:/main/DUT/gen_input(0)/transfer_input/ib_prio_i } \
{sim:/main/DUT/gen_input(0)/transfer_input/ib_transfer_ack } \
{sim:/main/DUT/gen_input(0)/transfer_input/ib_pageaddr } \
{sim:/main/DUT/gen_input(0)/transfer_input/ib_prio } \
{sim:/main/DUT/gen_input(0)/transfer_input/ib_mask } \
{sim:/main/DUT/gen_input(0)/transfer_input/pto_output_mask } \
{sim:/main/DUT/gen_input(0)/transfer_input/zeros }
add wave \
{sim:/main/DUT/gen_input(1)/transfer_input/pto_transfer_pck_o } \
{sim:/main/DUT/gen_input(1)/transfer_input/pto_pageaddr_o } \
{sim:/main/DUT/gen_input(1)/transfer_input/pto_output_mask_o } \
{sim:/main/DUT/gen_input(1)/transfer_input/pto_prio_o } \
{sim:/main/DUT/gen_input(1)/transfer_input/ib_pageaddr_i } \
{sim:/main/DUT/gen_input(1)/transfer_input/ib_mask_i } \
{sim:/main/DUT/gen_input(1)/transfer_input/ib_prio_i } \
{sim:/main/DUT/gen_input(1)/transfer_input/ib_transfer_ack } \
{sim:/main/DUT/gen_input(1)/transfer_input/ib_pageaddr } \
{sim:/main/DUT/gen_input(1)/transfer_input/ib_prio } \
{sim:/main/DUT/gen_input(1)/transfer_input/ib_mask } \
{sim:/main/DUT/gen_input(1)/transfer_input/pto_output_mask } \
{sim:/main/DUT/gen_input(1)/transfer_input/zeros }
add wave \
{sim:/main/DUT/gen_output(1)/transfer_output/ob_pageaddr_o } \
{sim:/main/DUT/gen_output(1)/transfer_output/ob_prio_o } \
{sim:/main/DUT/gen_output(1)/transfer_output/pti_pageaddr_i } \
{sim:/main/DUT/gen_output(1)/transfer_output/pti_prio_i } \
{sim:/main/DUT/gen_output(1)/transfer_output/pti_transfer_data_ack } \
{sim:/main/DUT/gen_output(1)/transfer_output/ob_transfer_data_valid } \
{sim:/main/DUT/gen_output(1)/transfer_output/ob_pageaddr } \
{sim:/main/DUT/gen_output(1)/transfer_output/ob_prio }
add wave \
{sim:/main/DUT/gen_output(2)/transfer_output/ob_pageaddr_o } \
{sim:/main/DUT/gen_output(2)/transfer_output/ob_prio_o } \
{sim:/main/DUT/gen_output(2)/transfer_output/pti_pageaddr_i } \
{sim:/main/DUT/gen_output(2)/transfer_output/pti_prio_i } \
{sim:/main/DUT/gen_output(2)/transfer_output/pti_transfer_data_ack } \
{sim:/main/DUT/gen_output(2)/transfer_output/ob_transfer_data_valid } \
{sim:/main/DUT/gen_output(2)/transfer_output/ob_pageaddr } \
{sim:/main/DUT/gen_output(2)/transfer_output/ob_prio }
add wave \
{sim:/main/DUT/gen_output(3)/transfer_output/ob_pageaddr_o } \
{sim:/main/DUT/gen_output(3)/transfer_output/ob_prio_o } \
{sim:/main/DUT/gen_output(3)/transfer_output/pti_pageaddr_i } \
{sim:/main/DUT/gen_output(3)/transfer_output/pti_prio_i } \
{sim:/main/DUT/gen_output(3)/transfer_output/pti_transfer_data_ack } \
{sim:/main/DUT/gen_output(3)/transfer_output/ob_transfer_data_valid } \
{sim:/main/DUT/gen_output(3)/transfer_output/ob_pageaddr } \
{sim:/main/DUT/gen_output(3)/transfer_output/ob_prio }
run 1500ns
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_pck_transfer_input.vhd
vlog -sv swc_pck_transfer_input_tb.v
vsim work.main
radix -hexadecimal
do wave.do
add wave \
{sim:/main/DUT/clk_i } \
{sim:/main/DUT/rst_n_i } \
{sim:/main/DUT/pto_transfer_pck_o } \
{sim:/main/DUT/pto_pageaddr_o } \
{sim:/main/DUT/pto_output_mask_o } \
{sim:/main/DUT/pto_read_mask_i } \
{sim:/main/DUT/pto_prio_o } \
{sim:/main/DUT/ib_transfer_pck_i } \
{sim:/main/DUT/ib_pageaddr_i } \
{sim:/main/DUT/ib_mask_i } \
{sim:/main/DUT/ib_prio_i } \
{sim:/main/DUT/ib_transfer_ack_o } \
{sim:/main/DUT/ib_transfer_ack } \
{sim:/main/DUT/ib_pageaddr } \
{sim:/main/DUT/ib_prio } \
{sim:/main/DUT/ib_mask } \
{sim:/main/DUT/pto_read_mask } \
{sim:/main/DUT/pto_output_mask } \
{sim:/main/DUT/zeros }
run 15us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/swc_prio_encoder.vhd
vlog swc_prio_encoder_tb.v
vsim work.main
radix -hexadecimal
do wave.do
run 100us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_read_pump.vhd
vlog swc_read_pump_tb.sv
vsim work.main
radix -hexadecimal
add wave \
{sim:/main/clk } \
{sim:/main/rst } \
{sim:/main/page_addr } \
{sim:/main/page_req } \
{sim:/main/pgend } \
{sim:/main/drdy } \
{sim:/main/dreq } \
{sim:/main/sync } \
{sim:/main/addr } \
{sim:/main/d } \
{sim:/main/q } \
{sim:/main/pckend } \
{sim:/main/current_page_addr } \
{sim:/main/next_page_addr } \
{sim:/main/read_req } \
{sim:/main/read_data_valid }
add wave \
{sim:/main/DUT/clk_i } \
{sim:/main/DUT/rst_n_i } \
{sim:/main/DUT/pgreq_i } \
{sim:/main/DUT/pgaddr_i } \
{sim:/main/DUT/pckend_o } \
{sim:/main/DUT/pgend_o } \
{sim:/main/DUT/drdy_o } \
{sim:/main/DUT/dreq_i } \
{sim:/main/DUT/sync_read_i } \
{sim:/main/DUT/ll_read_addr_o } \
{sim:/main/DUT/ll_read_data_i } \
{sim:/main/DUT/ll_read_req_o } \
{sim:/main/DUT/ll_read_valid_data_i } \
{sim:/main/DUT/d_o } \
{sim:/main/DUT/sync_i } \
{sim:/main/DUT/addr_o } \
{sim:/main/DUT/q_i } \
{sim:/main/DUT/out_reg } \
{sim:/main/DUT/cntr } \
{sim:/main/DUT/sync_d0 } \
{sim:/main/DUT/sync_d1 } \
{sim:/main/DUT/reg_not_empty } \
{sim:/main/DUT/cntr_full } \
{sim:/main/DUT/mem_addr } \
{sim:/main/DUT/allones } \
{sim:/main/DUT/zeros } \
{sim:/main/DUT/advance_addr } \
{sim:/main/DUT/load_out_reg } \
{sim:/main/DUT/pgend } \
{sim:/main/DUT/pckend } \
{sim:/main/DUT/current_page_addr } \
{sim:/main/DUT/next_page_addr }
do wave.do
run 3us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_prio_encoder.vhd
vcom ../../../modules/wrsw_swcore/swc_rr_arbiter.vhd
vlog swc_rr_arbiter_tb.v
vsim work.main
radix -hexadecimal
add wave \
{sim:/main/next } \
{sim:/main/grant } \
{sim:/main/grant_valid }
add wave \
{sim:/main/dut/g_num_ports } \
{sim:/main/dut/g_num_ports_log2 } \
{sim:/main/dut/rst_n_i } \
{sim:/main/dut/clk_i } \
{sim:/main/dut/next_i } \
{sim:/main/dut/request_i } \
{sim:/main/dut/grant_o } \
{sim:/main/dut/grant_valid_o } \
{sim:/main/dut/request_mask } \
{sim:/main/dut/request_vec_masked } \
{sim:/main/dut/rq_decoded } \
{sim:/main/dut/rq_decoded_mask } \
{sim:/main/dut/rq_zero } \
{sim:/main/dut/rq_wait_next }
do wave.do
run 1us
wave zoomfull
vlib work
vcom ../../../modules/wrsw_swcore/platform_specific.vhd
vcom ../../../modules/wrsw_swcore/generic_ssram_dualport_singleclock.vhd
vcom ../../../modules/wrsw_swcore/swc_swcore_pkg.vhd
vcom ../../../modules/wrsw_swcore/swc_packet_mem_write_pump.vhd
vlog swc_write_pump_tb.v
vsim work.main
radix -hexadecimal
do wave.do
run 30us
wave zoomfull
#include <stdio.h>
#define NUM_PAGES 2048
#define BITMAP_SIZE 2048/32
int use_count[NUM_PAGES];
int l0_bitmap[BITMAP_SIZE];
int l1_bitmap[BITMAP_SIZE];
int free_pages = NUM_PAGES;
int prio_enc(int *p, int count) {
int i;
for(i=0;i<count;i++)
if(p[i]) return i;
return -1;
}
int prio_enc_bin(int val, int bit_count) {
int i;
for(i=0;i<bit_count;i++)
if(val & (1<<i)) return i;
return -1;
}
int alloc_page(int ucnt)
{
if(!free_pages) return -1;
int l1_lookup = prio_enc(l1_bitmap, BITMAP_SIZE);
int l0_lookup = prio_enc_bin(l0_bitmap[l1_lookup], 32);
int newval = l0_bitmap[l1_lookup];
int pageaddr = l1_lookup * 32 + l0_lookup;
newval ^= (1<< l0_lookup); // clear the free page
l0_bitmap[l1_lookup] = newval;
if(!newval)
l1_bitmap[l1_lookup] = 0;
use_count[pageaddr] = ucnt;
printf("pageaddr: %d\n", pageaddr);
}
int free_page(int pageaddr)
{
if(use_count[pageaddr] > 1) {
use_count[pageaddr]--;
} else {
l0_bitmap[pageaddr >> 5] ^= (1 << (pageaddr & 0x1f));
l1_bitmap[pageaddr >> 5] = 1;
free_pages ++;
}
}
int alloc_init()
{
int i, j;
free_pages = NUM_PAGES;
for(i = 0; i< BITMAP_SIZE;i++)
{
l1_bitmap[i] = 1;
l0_bitmap[i] = 0xffffffff;
}
}
main()
{
alloc_init();
int i;
for (i=0;i<100;i++) alloc_page(1);
free_page(50);
alloc_page(1);
}
\ No newline at end of file
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`define c_clock_period 8
`define c_swc_page_addr_width 10
`define c_swc_usecount_width 4
`define c_wrsw_prio_width 3
`define c_swc_ctrl_width 4
`define c_swc_data_width 16
`define c_wrsw_num_ports 11
`timescale 1ns / 1ps
`include "fabric_emu.sv"
`define array_copy(a, ah, al, b, bl) \
for (k=al; k<=ah; k=k+1) a[k] <= b[bl+k-al];
integer k; // for the macro array_copy()
module main;
reg clk = 0;
reg rst_n = 0;
//`WRF_WIRES(a_to_input_block); // Emu A to B fabric
wire [`c_wrsw_num_ports * 16- 1:0] a_to_input_block_data;
wire [`c_wrsw_num_ports * 4 - 1:0] a_to_input_block_ctrl;
// wire [`c_wrsw_num_ports - 1:0][15:0] a_to_input_block_data;
// wire [`c_wrsw_num_ports - 1:0][3 :0] a_to_input_block_ctrl;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_bytesel;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_dreq;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_valid;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_sof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_eof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_rerror_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_abort_p1;
wire [`c_wrsw_num_ports * 16- 1:0] input_block_to_a_data;
wire [`c_wrsw_num_ports * 4 - 1:0] input_block_to_a_ctrl;
// wire [`c_wrsw_num_ports - 1:0][15:0] input_block_to_a_data;
// wire [`c_wrsw_num_ports:0][3 :0] input_block_to_a_ctrl;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_bytesel;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_dreq;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_valid;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_sof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_eof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_rerror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_idle;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_terror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_tabort_p1;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
// `WRF_PORTS_SINK_ARRAY(dupa);
reg [`c_wrsw_num_ports-1:0] rtu_rsp_valid = 0;
wire [`c_wrsw_num_ports-1:0] rtu_rsp_ack;
reg [`c_wrsw_num_ports * `c_wrsw_num_ports - 1 : 0] rtu_dst_port_mask = 0;
reg [`c_wrsw_num_ports-1:0] rtu_drop = 0;
reg [`c_wrsw_num_ports * `c_wrsw_prio_width -1 : 0] rtu_prio = 0;
// generate clock and reset signals
always #(`c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
swc_core
DUT (
.clk_i (clk),
.rst_n_i (rst_n),
//-------------------------------------------------------------------------------
//-- Fabric I/F
//-------------------------------------------------------------------------------
.tx_sof_p1_i (a_to_input_block_sof_p1),
.tx_eof_p1_i (a_to_input_block_eof_p1),
.tx_data_i (a_to_input_block_data),
.tx_ctrl_i (a_to_input_block_ctrl),
.tx_valid_i (a_to_input_block_valid),
.tx_bytesel_i (a_to_input_block_bytesel),
.tx_dreq_o (a_to_input_block_dreq),
.tx_abort_p1_i (a_to_input_block_abort_p1),
.tx_rerror_p1_i (a_to_input_block_rerror_p1),
//-------------------------------------------------------------------------------
//-- Fabric I/F : output (goes to the Endpoint)
//-------------------------------------------------------------------------------
.rx_sof_p1_o (input_block_to_a_sof_p1),
.rx_eof_p1_o (input_block_to_a_eof_p1),
.rx_dreq_i (input_block_to_a_dreq),
.rx_ctrl_o (input_block_to_a_ctrl),
.rx_data_o (input_block_to_a_data),
.rx_valid_o (input_block_to_a_valid),
.rx_bytesel_o (input_block_to_a_bytesel),
.rx_idle_o (input_block_to_a_idle),
.rx_rerror_p1_o (input_block_to_a_rerror_p1),
.rx_terror_p1_i (input_block_to_a_terror_p1),
.rx_tabort_p1_i (input_block_to_a_tabort_p1),
//-------------------------------------------------------------------------------
//-- I/F with Routing Table Unit (RTU)
//-------------------------------------------------------------------------------
.rtu_rsp_valid_i (rtu_rsp_valid),
.rtu_rsp_ack_o (rtu_rsp_ack),
.rtu_dst_port_mask_i (rtu_dst_port_mask),
.rtu_drop_i (rtu_drop),
.rtu_prio_i (rtu_prio)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
fabric_emu test_input_block_0
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE_ML(rx, a_to_input_block,0),
/*
.rx_data_o (a_to_input_block_data[15:0]),
.rx_ctrl_o (a_to_input_block_ctrl[15:0]),
.rx_bytesel_o (a_to_input_block_bytesel[0]),
.rx_dreq_i (a_to_input_block_dreq[0]),
.rx_valid_o (a_to_input_block_valid[0]),
.rx_sof_p1_o (a_to_input_block_sof_p1[0]),
.rx_eof_p1_o (a_to_input_block_eof_p1[0]),
.rx_rerror_p1_o (a_to_input_block_rerror_p1[0]),
.rx_terror_p1_i (1'b0),
.rx_tabort_p1_o (),
.rx_rabort_p1_i (1'b0),
.rx_idle_o (),
*/
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,0)
/*
.tx_data_i (input_block_to_a_data[15:0]),
.tx_ctrl_i (input_block_to_a_ctrl[15:0]),
.tx_bytesel_i (input_block_to_a_bytesel[0]),
.tx_dreq_o (input_block_to_a_dreq[0]),
.tx_valid_i (input_block_to_a_valid[0]),
.tx_sof_p1_i (input_block_to_a_sof_p1[0]),
.tx_eof_p1_i (input_block_to_a_eof_p1[0]),
.tx_rerror_p1_i (input_block_to_a_rerror_p1[0]),
.tx_terror_p1_o (input_block_to_a_terror_p1[0]),
.tx_rabort_p1_o (input_block_to_a_rabort_p1[0]),
.tx_idle_i (input_block_to_a_idle[0])
*/
);
fabric_emu test_input_block_1
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,1),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,1)
);
fabric_emu test_input_block_2
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,2),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,2)
);
fabric_emu test_input_block_3
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,3),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,3)
);
fabric_emu test_input_block_4
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,4),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,4)
);
fabric_emu test_input_block_5
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,5),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,5)
);
fabric_emu test_input_block_6
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,6),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,6)
);
fabric_emu test_input_block_7
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,7),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,7)
);
fabric_emu test_input_block_8
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,8),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,8)
);
fabric_emu test_input_block_9
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,9),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,9)
);
fabric_emu test_input_block_10
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,10),
`WRF_CONNECT_SINK_ML(tx, input_block_to_a,10)
);
task set_rtu_rsp;
input [31:0] chan;
input valid;
input drop;
input [`c_wrsw_num_ports - 1:0] prio;
input [`c_wrsw_num_ports - 1:0] mask;
begin : wait_body
integer i;
`array_copy(rtu_dst_port_mask,(chan+1)*`c_wrsw_num_ports - 1, chan*`c_wrsw_num_ports, mask ,0);
`array_copy(rtu_prio ,(chan+1)*`c_wrsw_prio_width - 1, chan*`c_wrsw_prio_width, prio, 0);
// rtu_dst_port_mask[(chan+1)*`c_wrsw_num_ports : `c_wrsw_num_ports*chan] = mask;
// rtu_prio [(chan+1)*`c_wrsw_prio_width : `c_wrsw_prio_width*chan] = prio;
rtu_drop [ chan ] = drop;
rtu_rsp_valid [ chan ] = valid;
end
endtask // wait_cycles
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(test_input_block_0.ready);
wait(test_input_block_1.ready);
wait(test_input_block_2.ready);
wait(test_input_block_3.ready);
wait(test_input_block_4.ready);
wait(test_input_block_5.ready);
wait(test_input_block_6.ready);
wait(test_input_block_7.ready);
wait(test_input_block_8.ready);
wait(test_input_block_9.ready);
wait(test_input_block_10.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<1000;i++)
buffer[i] = i;
/*
task set_rtu_rsp;
input [31:0] chan;
input valid;
input drop;
input [`c_wrsw_num_ports - 1:0] prio;
input [`c_wrsw_num_ports - 1:0] mask;
begin : wait_body
*/
wait_cycles(50);
//////////////// input port = 0 ////////////////
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 901);
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 202);
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 203);
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 204);
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 205);
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 206);
//////////////// input port = 1 ////////////////
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 911);
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 212);
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 213);
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 214);
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 215);
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 216);
//////////////// input port = 2 ////////////////
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 921);
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 222);
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 223);
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 224);
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 225);
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 226);
//////////////// input port = 3 ////////////////
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 931);
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 232);
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 233);
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 234);
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 235);
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 236);
//////////////// input port = 4 ////////////////
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 941);
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 242);
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 243);
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 244);
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 245);
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 246);
//////////////// input port = 5 ////////////////
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 951);
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 252);
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 253);
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 254);
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 255);
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 256);
//////////////// input port = 6 ////////////////
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 761);
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 262);
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 263);
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 264);
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 265);
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 266);
//////////////// input port = 7 ////////////////
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 971);
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 272);
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 273);
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 274);
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 275);
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 276);
//////////////// input port = 8 ////////////////
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 981);
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 282);
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 283);
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 284);
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 285);
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 286);
//////////////// input port = 9 ////////////////
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 991);
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 292);
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 293);
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 294);
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 295);
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 296);
//////////////// input port = 10 ////////////////
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 901);
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 202);
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 203);
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 204);
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 205);
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 206);
end
always @(posedge clk) if (rtu_rsp_ack != 0)
begin
rtu_rsp_valid = rtu_rsp_valid & !rtu_rsp_ack;
rtu_drop = rtu_drop & !rtu_rsp_ack;
end
// Check if there's anything received by EMU B
always @(posedge clk) if (test_input_block_0.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 0!");
test_input_block_0.receive(frame);
dump_frame_header("test RX_0: ", frame);
end
always @(posedge clk) if (test_input_block_1.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 1!");
test_input_block_1.receive(frame);
dump_frame_header("test RX_1: ", frame);
end
always @(posedge clk) if (test_input_block_2.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 2!");
test_input_block_2.receive(frame);
dump_frame_header("test RX_2: ", frame);
end
always @(posedge clk) if (test_input_block_3.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 3!");
test_input_block_3.receive(frame);
dump_frame_header("test RX_3: ", frame);
end
always @(posedge clk) if (test_input_block_4.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 4!");
test_input_block_4.receive(frame);
dump_frame_header("test RX_4: ", frame);
end
always @(posedge clk) if (test_input_block_5.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 5!");
test_input_block_5.receive(frame);
dump_frame_header("test RX_5: ", frame);
end
always @(posedge clk) if (test_input_block_6.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 6!");
test_input_block_6.receive(frame);
dump_frame_header("test RX_6: ", frame);
end
always @(posedge clk) if (test_input_block_7.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 7!");
test_input_block_7.receive(frame);
dump_frame_header("test RX_7: ", frame);
end
always @(posedge clk) if (test_input_block_8.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 8!");
test_input_block_8.receive(frame);
dump_frame_header("test RX_8: ", frame);
end
always @(posedge clk) if (test_input_block_9.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 9!");
test_input_block_9.receive(frame);
dump_frame_header("test RX_9: ", frame);
end
always @(posedge clk) if (test_input_block_10.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 10!");
test_input_block_10.receive(frame);
dump_frame_header("test RX_10: ", frame);
end
endmodule // main
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`define c_clock_period 8
`define c_swc_page_addr_width 10
`define c_swc_usecount_width 4
`define c_wrsw_prio_width 3
`define c_swc_ctrl_width 4
`define c_swc_data_width 16
`define c_wrsw_num_ports 11
`timescale 1ns / 1ps
`include "fabric_emu.sv"
`define array_copy(a, ah, al, b, bl) \
for (k=al; k<=ah; k=k+1) a[k] <= b[bl+k-al];
module main;
reg clk = 0;
reg rst_n = 0;
//`WRF_WIRES(a_to_input_block); // Emu A to B fabric
wire [`c_wrsw_num_ports * 16- 1:0] a_to_input_block_data;
wire [`c_wrsw_num_ports * 4 - 1:0] a_to_input_block_ctrl;
// wire [`c_wrsw_num_ports - 1:0][15:0] a_to_input_block_data;
// wire [`c_wrsw_num_ports - 1:0][3 :0] a_to_input_block_ctrl;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_bytesel;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_dreq;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_valid;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_sof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_eof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_rerror_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_abort_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_terror_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_tabort_p1;
wire [`c_wrsw_num_ports * 16- 1:0] input_block_to_a_data;
wire [`c_wrsw_num_ports * 4 - 1:0] input_block_to_a_ctrl;
// wire [`c_wrsw_num_ports - 1:0][15:0] input_block_to_a_data;
// wire [`c_wrsw_num_ports:0][3 :0] input_block_to_a_ctrl;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_bytesel;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_dreq;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_valid;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_sof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_eof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_rerror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_idle;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_terror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_tabort_p1;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
// `WRF_PORTS_SINK_ARRAY(dupa);
reg [`c_wrsw_num_ports-1:0] rtu_rsp_valid = 0;
wire [`c_wrsw_num_ports-1:0] rtu_rsp_ack;
reg [`c_wrsw_num_ports * `c_wrsw_num_ports - 1 : 0] rtu_dst_port_mask = 0;
reg [`c_wrsw_num_ports-1:0] rtu_drop = 0;
reg [`c_wrsw_num_ports * `c_wrsw_prio_width -1 : 0] rtu_prio = 0;
// generate clock and reset signals
always #(`c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
swc_core
DUT (
.clk_i (clk),
.rst_n_i (rst_n),
//-------------------------------------------------------------------------------
//-- Fabric I/F
//-------------------------------------------------------------------------------
.tx_sof_p1_i (a_to_input_block_sof_p1),
.tx_eof_p1_i (a_to_input_block_eof_p1),
.tx_data_i (a_to_input_block_data),
.tx_ctrl_i (a_to_input_block_ctrl),
.tx_valid_i (a_to_input_block_valid),
.tx_bytesel_i (a_to_input_block_bytesel),
.tx_dreq_o (a_to_input_block_dreq),
.tx_abort_p1_i (a_to_input_block_abort_p1),
.tx_rerror_p1_i (a_to_input_block_rerror_p1),
//-------------------------------------------------------------------------------
//-- Fabric I/F : output (goes to the Endpoint)
//-------------------------------------------------------------------------------
.rx_sof_p1_o (input_block_to_a_sof_p1),
.rx_eof_p1_o (input_block_to_a_eof_p1),
.rx_dreq_i (input_block_to_a_dreq),
.rx_ctrl_o (input_block_to_a_ctrl),
.rx_data_o (input_block_to_a_data),
.rx_valid_o (input_block_to_a_valid),
.rx_bytesel_o (input_block_to_a_bytesel),
.rx_idle_o (input_block_to_a_idle),
.rx_rerror_p1_o (input_block_to_a_rerror_p1),
.rx_terror_p1_i (input_block_to_a_terror_p1),
.rx_tabort_p1_i (input_block_to_a_tabort_p1),// tx_rabort_p1_i ????????
//-------------------------------------------------------------------------------
//-- I/F with Routing Table Unit (RTU)
//-------------------------------------------------------------------------------
.rtu_rsp_valid_i (rtu_rsp_valid),
.rtu_rsp_ack_o (rtu_rsp_ack),
.rtu_dst_port_mask_i (rtu_dst_port_mask),
.rtu_drop_i (rtu_drop),
.rtu_prio_i (rtu_prio)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
fabric_emu test_input_block_0
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE_ML(rx, a_to_input_block,0),
/*
.rx_data_o (a_to_input_block_data[15:0]),
.rx_ctrl_o (a_to_input_block_ctrl[15:0]),
.rx_bytesel_o (a_to_input_block_bytesel[0]),
.rx_dreq_i (a_to_input_block_dreq[0]),
.rx_valid_o (a_to_input_block_valid[0]),
.rx_sof_p1_o (a_to_input_block_sof_p1[0]),
.rx_eof_p1_o (a_to_input_block_eof_p1[0]),
.rx_rerror_p1_o (a_to_input_block_rerror_p1[0]),
.rx_terror_p1_i (1'b0),
.rx_tabort_p1_o (),
.rx_rabort_p1_i (1'b0),
.rx_idle_o (),
*/
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,0)
/*
.tx_data_i (input_block_to_a_data[15:0]),
.tx_ctrl_i (input_block_to_a_ctrl[15:0]),
.tx_bytesel_i (input_block_to_a_bytesel[0]),
.tx_dreq_o (input_block_to_a_dreq[0]),
.tx_valid_i (input_block_to_a_valid[0]),
.tx_sof_p1_i (input_block_to_a_sof_p1[0]),
.tx_eof_p1_i (input_block_to_a_eof_p1[0]),
.tx_rerror_p1_i (input_block_to_a_rerror_p1[0]),
.tx_terror_p1_o (input_block_to_a_terror_p1[0]),
.tx_rabort_p1_o (input_block_to_a_rabort_p1[0]),
.tx_idle_i (input_block_to_a_idle[0])
*/
);
fabric_emu test_input_block_1
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,1),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,1)
);
fabric_emu test_input_block_2
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,2),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,2)
);
fabric_emu test_input_block_3
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,3),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,3)
);
fabric_emu test_input_block_4
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,4),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,4)
);
fabric_emu test_input_block_5
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,5),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,5)
);
fabric_emu test_input_block_6
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,6),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,6)
);
fabric_emu test_input_block_7
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,7),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,7)
);
fabric_emu test_input_block_8
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,8),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,8)
);
fabric_emu test_input_block_9
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,9),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,9)
);
fabric_emu test_input_block_10
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,10),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,10)
);
task set_rtu_rsp;
input [31:0] chan;
input valid;
input drop;
input [`c_wrsw_num_ports - 1:0] prio;
input [`c_wrsw_num_ports - 1:0] mask;
begin : wait_body
integer i;
integer k; // for the macro array_copy()
`array_copy(rtu_dst_port_mask,(chan+1)*`c_wrsw_num_ports - 1, chan*`c_wrsw_num_ports, mask ,0);
`array_copy(rtu_prio ,(chan+1)*`c_wrsw_prio_width - 1, chan*`c_wrsw_prio_width, prio, 0);
// rtu_dst_port_mask[(chan+1)*`c_wrsw_num_ports : `c_wrsw_num_ports*chan] = mask;
// rtu_prio [(chan+1)*`c_wrsw_prio_width : `c_wrsw_prio_width*chan] = prio;
rtu_drop [ chan ] = drop;
rtu_rsp_valid [ chan ] = valid;
end
endtask // wait_cycles
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(test_input_block_0.ready);
wait(test_input_block_3.ready);
wait(test_input_block_6.ready);
wait(test_input_block_9.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<1000;i++)
buffer[i] = i;
//
// task set_rtu_rsp;
// input [31:0] chan;
// input valid;
// input drop;
// input [`c_wrsw_num_ports - 1:0] prio;
// input [`c_wrsw_num_ports - 1:0] mask;
// begin : wait_body
wait_cycles(50);
//////////////// input port = 0 ////////////////
hdr.src = 'h123456789abcde0;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 901);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 202);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 203);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 204);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 205);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(0,1,0,2,'h7FF);
test_input_block_0.send(hdr, buffer, 206);
//////////////// input port = 3 ////////////////
hdr.src = 'h123456789abcde3;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 931);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 232);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 233);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 234);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 235);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(3,1,0,2,'h7FF);
test_input_block_3.send(hdr, buffer, 236);
//////////////// input port = 6 ////////////////
hdr.src = 'h123456789abcde6;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 761);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 262);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 263);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 264);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 265);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(6,1,0,2,'h7FF);
test_input_block_6.send(hdr, buffer, 266);
//////////////// input port = 9 ////////////////
hdr.src = 'h123456789abcde9;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 991);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 292);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 293);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 294);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 295);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(9,1,0,2,'h7FF);
test_input_block_9.send(hdr, buffer, 296);
end
//////////////////////////////////////////////////////////
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(test_input_block_1.ready);
wait(test_input_block_4.ready);
wait(test_input_block_7.ready);
wait(test_input_block_10.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<1000;i++)
buffer[i] = i;
//
// task set_rtu_rsp;
// input [31:0] chan;
// input valid;
// input drop;
// input [`c_wrsw_num_ports - 1:0] prio;
// input [`c_wrsw_num_ports - 1:0] mask;
// begin : wait_body
wait_cycles(260);
//////////////// input port = 1 ////////////////
hdr.src = 'h123456789abcde1;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(1,1,0,2,'h7FF);
// test_input_block_1.simulate_tx_throttling(1, 10);
// test_input_block_0.simulate_rx_abort(1,80);
// test_input_block_1.simulate_tx_error(1,100);
// test_input_block_1.send(hdr, buffer, 911);
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 212);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 213);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 214);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(1,1,0,2,'h7FF);
test_input_block_1.send(hdr, buffer, 215);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(1,1,0,2,'h002);
test_input_block_1.send(hdr, buffer, 216);
//////////////// input port = 4 ////////////////
hdr.src = 'h123456789abcde4;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 941);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 242);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 243);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 244);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(4,1,0,2,'h7FF);
test_input_block_4.send(hdr, buffer, 245);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(4,1,0,2,'h008);
test_input_block_4.send(hdr, buffer, 246);
//////////////// input port = 7 ////////////////
hdr.src = 'h123456789abcde7;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 971);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 272);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 273);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 274);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 275);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(7,1,0,2,'h7FF);
test_input_block_7.send(hdr, buffer, 276);
//////////////// input port = 10 ////////////////
hdr.src = 'h123456789abcdeA;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 901);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 202);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 203);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 204);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 205);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(10,1,0,2,'h7FF);
test_input_block_10.send(hdr, buffer, 206);
end
//////////////////////////////////////////////////////////////
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(test_input_block_2.ready);
wait(test_input_block_5.ready);
wait(test_input_block_8.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<1000;i++)
buffer[i] = i;
//
// task set_rtu_rsp;
// input [31:0] chan;
// input valid;
// input drop;
// input [`c_wrsw_num_ports - 1:0] prio;
// input [`c_wrsw_num_ports - 1:0] mask;
// begin : wait_body
wait_cycles(80);
//////////////// input port = 2 ////////////////
hdr.src = 'h123456789abcde2;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 921);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 222);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 223);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 224);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 225);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(2,1,0,2,'h7FF);
test_input_block_2.send(hdr, buffer, 226);
//////////////// input port = 5 ////////////////
hdr.src = 'h123456789abcde5;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 951);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 252);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 253);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 254);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 255);
hdr.dst = 'hcafeb1badeadbe5;
set_rtu_rsp(5,1,0,2,'h7FF);
test_input_block_5.send(hdr, buffer, 256);
//////////////// input port = 8 ////////////////
hdr.src = 'h123456789abcde8;
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 981);
hdr.dst = 'hcafeb1badeadbe0;
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 282);
hdr.dst = 'hcafeb1badeadbe1;
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 283);
hdr.dst = 'hcafeb1badeadbe2;
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 284);
hdr.dst = 'hcafeb1badeadbe3;
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 285);
hdr.dst = 'hcafeb1badeadbe4;
set_rtu_rsp(8,1,0,2,'h7FF);
test_input_block_8.send(hdr, buffer, 286);
end
//////////////////////////////////////////////////////////
always @(posedge clk) if (rtu_rsp_ack != 0)
begin
rtu_rsp_valid = rtu_rsp_valid & !rtu_rsp_ack;
rtu_drop = rtu_drop & !rtu_rsp_ack;
end
// Check if there's anything received by EMU B
always @(posedge clk) if (test_input_block_0.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 0!");
test_input_block_0.receive(frame);
dump_frame_header("test RX_0: ", frame);
end
always @(posedge clk) if (test_input_block_1.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 1!");
test_input_block_1.receive(frame);
dump_frame_header("test RX_1: ", frame);
end
always @(posedge clk) if (test_input_block_2.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 2!");
test_input_block_2.receive(frame);
dump_frame_header("test RX_2: ", frame);
end
always @(posedge clk) if (test_input_block_3.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 3!");
test_input_block_3.receive(frame);
dump_frame_header("test RX_3: ", frame);
end
always @(posedge clk) if (test_input_block_4.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 4!");
test_input_block_4.receive(frame);
dump_frame_header("test RX_4: ", frame);
end
always @(posedge clk) if (test_input_block_5.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 5!");
test_input_block_5.receive(frame);
dump_frame_header("test RX_5: ", frame);
end
always @(posedge clk) if (test_input_block_6.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 6!");
test_input_block_6.receive(frame);
dump_frame_header("test RX_6: ", frame);
end
always @(posedge clk) if (test_input_block_7.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 7!");
test_input_block_7.receive(frame);
dump_frame_header("test RX_7: ", frame);
end
always @(posedge clk) if (test_input_block_8.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 8!");
test_input_block_8.receive(frame);
dump_frame_header("test RX_8: ", frame);
end
always @(posedge clk) if (test_input_block_9.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 9!");
test_input_block_9.receive(frame);
dump_frame_header("test RX_9: ", frame);
end
always @(posedge clk) if (test_input_block_10.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 10!");
test_input_block_10.receive(frame);
dump_frame_header("test RX_10: ", frame);
end
endmodule // main
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`define c_clock_period 8
`define c_swc_page_addr_width 10
`define c_swc_usecount_width 4
`define c_wrsw_prio_width 3
`define c_swc_ctrl_width 4
`define c_swc_data_width 16
`define c_wrsw_num_ports 11
`timescale 1ns / 1ps
`include "fabric_emu.sv"
`define array_copy(a, ah, al, b, bl) \
for (k=al; k<=ah; k=k+1) a[k] <= b[bl+k-al];
module main;
reg clk = 0;
reg rst_n = 0;
//`WRF_WIRES(a_to_input_block); // Emu A to B fabric
wire [`c_wrsw_num_ports * 16- 1:0] a_to_input_block_data;
wire [`c_wrsw_num_ports * 4 - 1:0] a_to_input_block_ctrl;
// wire [`c_wrsw_num_ports - 1:0][15:0] a_to_input_block_data;
// wire [`c_wrsw_num_ports - 1:0][3 :0] a_to_input_block_ctrl;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_bytesel;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_dreq;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_valid;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_sof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_eof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_rerror_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_abort_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_terror_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_tabort_p1;
wire [`c_wrsw_num_ports * 16- 1:0] input_block_to_a_data;
wire [`c_wrsw_num_ports * 4 - 1:0] input_block_to_a_ctrl;
// wire [`c_wrsw_num_ports - 1:0][15:0] input_block_to_a_data;
// wire [`c_wrsw_num_ports:0][3 :0] input_block_to_a_ctrl;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_bytesel;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_dreq;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_valid;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_sof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_eof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_rerror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_idle;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_terror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_tabort_p1;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
// `WRF_PORTS_SINK_ARRAY(dupa);
reg [`c_wrsw_num_ports-1:0] rtu_rsp_valid = 0;
wire [`c_wrsw_num_ports-1:0] rtu_rsp_ack;
reg [`c_wrsw_num_ports * `c_wrsw_num_ports - 1 : 0] rtu_dst_port_mask = 0;
reg [`c_wrsw_num_ports-1:0] rtu_drop = 0;
reg [`c_wrsw_num_ports * `c_wrsw_prio_width -1 : 0] rtu_prio = 0;
// generate clock and reset signals
always #(`c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
integer ports_read = 0;
swc_core
DUT (
.clk_i (clk),
.rst_n_i (rst_n),
//-------------------------------------------------------------------------------
//-- Fabric I/F
//-------------------------------------------------------------------------------
.tx_sof_p1_i (a_to_input_block_sof_p1),
.tx_eof_p1_i (a_to_input_block_eof_p1),
.tx_data_i (a_to_input_block_data),
.tx_ctrl_i (a_to_input_block_ctrl),
.tx_valid_i (a_to_input_block_valid),
.tx_bytesel_i (a_to_input_block_bytesel),
.tx_dreq_o (a_to_input_block_dreq),
.tx_abort_p1_i (a_to_input_block_abort_p1),
.tx_rerror_p1_i (a_to_input_block_rerror_p1),
//-------------------------------------------------------------------------------
//-- Fabric I/F : output (goes to the Endpoint)
//-------------------------------------------------------------------------------
.rx_sof_p1_o (input_block_to_a_sof_p1),
.rx_eof_p1_o (input_block_to_a_eof_p1),
.rx_dreq_i (input_block_to_a_dreq),
.rx_ctrl_o (input_block_to_a_ctrl),
.rx_data_o (input_block_to_a_data),
.rx_valid_o (input_block_to_a_valid),
.rx_bytesel_o (input_block_to_a_bytesel),
.rx_idle_o (input_block_to_a_idle),
.rx_rerror_p1_o (input_block_to_a_rerror_p1),
.rx_terror_p1_i (input_block_to_a_terror_p1),
.rx_tabort_p1_i (input_block_to_a_tabort_p1),// tx_rabort_p1_i ????????
//-------------------------------------------------------------------------------
//-- I/F with Routing Table Unit (RTU)
//-------------------------------------------------------------------------------
.rtu_rsp_valid_i (rtu_rsp_valid),
.rtu_rsp_ack_o (rtu_rsp_ack),
.rtu_dst_port_mask_i (rtu_dst_port_mask),
.rtu_drop_i (rtu_drop),
.rtu_prio_i (rtu_prio)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
fabric_emu test_input_block_0
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE_ML(rx, a_to_input_block,0),
/*
.rx_data_o (a_to_input_block_data[15:0]),
.rx_ctrl_o (a_to_input_block_ctrl[15:0]),
.rx_bytesel_o (a_to_input_block_bytesel[0]),
.rx_dreq_i (a_to_input_block_dreq[0]),
.rx_valid_o (a_to_input_block_valid[0]),
.rx_sof_p1_o (a_to_input_block_sof_p1[0]),
.rx_eof_p1_o (a_to_input_block_eof_p1[0]),
.rx_rerror_p1_o (a_to_input_block_rerror_p1[0]),
.rx_terror_p1_i (1'b0),
.rx_tabort_p1_o (),
.rx_rabort_p1_i (1'b0),
.rx_idle_o (),
*/
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,0)
/*
.tx_data_i (input_block_to_a_data[15:0]),
.tx_ctrl_i (input_block_to_a_ctrl[15:0]),
.tx_bytesel_i (input_block_to_a_bytesel[0]),
.tx_dreq_o (input_block_to_a_dreq[0]),
.tx_valid_i (input_block_to_a_valid[0]),
.tx_sof_p1_i (input_block_to_a_sof_p1[0]),
.tx_eof_p1_i (input_block_to_a_eof_p1[0]),
.tx_rerror_p1_i (input_block_to_a_rerror_p1[0]),
.tx_terror_p1_o (input_block_to_a_terror_p1[0]),
.tx_rabort_p1_o (input_block_to_a_rabort_p1[0]),
.tx_idle_i (input_block_to_a_idle[0])
*/
);
fabric_emu test_input_block_1
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,1),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,1)
);
fabric_emu test_input_block_2
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,2),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,2)
);
fabric_emu test_input_block_3
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,3),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,3)
);
fabric_emu test_input_block_4
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,4),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,4)
);
fabric_emu test_input_block_5
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,5),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,5)
);
fabric_emu test_input_block_6
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,6),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,6)
);
fabric_emu test_input_block_7
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,7),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,7)
);
fabric_emu test_input_block_8
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,8),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,8)
);
fabric_emu test_input_block_9
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,9),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,9)
);
fabric_emu test_input_block_10
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,10),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,10)
);
task set_rtu_rsp;
input [31:0] chan;
input valid;
input drop;
input [`c_wrsw_num_ports - 1:0] prio;
input [`c_wrsw_num_ports - 1:0] mask;
begin : wait_body
integer i;
integer k; // for the macro array_copy()
`array_copy(rtu_dst_port_mask,(chan+1)*`c_wrsw_num_ports - 1, chan*`c_wrsw_num_ports, mask ,0);
`array_copy(rtu_prio ,(chan+1)*`c_wrsw_prio_width - 1, chan*`c_wrsw_prio_width, prio, 0);
rtu_drop [ chan ] = drop;
rtu_rsp_valid [ chan ] = valid;
end
endtask // wait_cycles
task send_pck;
input ether_header_t hdr;
input int payload[];
input int length;
input [31:0] port;
input drop;
input [`c_wrsw_num_ports - 1:0] prio;
input [`c_wrsw_num_ports - 1:0] mask;
begin : send_pck_body
set_rtu_rsp(port,1,drop,prio,mask);
$display("Sending: port = %d, len = %d, drop = %d, prio = %d, mask = %x",port,length, drop, prio, mask);
case(port)
0: test_input_block_0.send(hdr, payload, length);
1: test_input_block_1.send(hdr, payload, length);
2: test_input_block_2.send(hdr, payload, length);
3: test_input_block_3.send(hdr, payload, length);
4: test_input_block_4.send(hdr, payload, length);
5: test_input_block_5.send(hdr, payload, length);
6: test_input_block_6.send(hdr, payload, length);
7: test_input_block_7.send(hdr, payload, length);
8: test_input_block_8.send(hdr, payload, length);
9: test_input_block_9.send(hdr, payload, length);
10:test_input_block_10.send(hdr, payload, length);
default: $display("ERROR: Wrong port number !!!");
endcase
end
endtask
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
int port = 0;
wait(test_input_block_0.ready);
wait(test_input_block_1.ready);
wait(test_input_block_2.ready);
wait(test_input_block_3.ready);
wait(test_input_block_4.ready);
wait(test_input_block_5.ready);
wait(test_input_block_6.ready);
wait(test_input_block_7.ready);
wait(test_input_block_8.ready);
wait(test_input_block_9.ready);
wait(test_input_block_10.ready);
ports_read = 1;
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
for(i=0;i<2000;i++)
buffer[i] = i;
//input ether_header_t hdr,
//input int payload[],
//input int length
//input [31:0] port;
//input drop;
//input [`c_wrsw_num_ports - 1:0] prio;
//input [`c_wrsw_num_ports - 1:0] mask;
wait_cycles(50);
//////////////// input port = 0 ////////////////
hdr.src = 'h123456789abcde0;
hdr.dst = 'hcafeb1badeadbe0;
for(i=200;i<1250;i=i+50)
begin
hdr.src = port;
hdr.port_id = port;
hdr.ethertype = i;
send_pck(hdr,buffer, i, port, (i/50)%20, (i/50)%7,(i/50)%11);
if(port == 3)
port = 0;
else
port++;
end
end
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
int port = 4;
wait(ports_read);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<2000;i++)
buffer[i] = i;
//input ether_header_t hdr,
//input int payload[],
//input int length
//input [31:0] port;
//input drop;
//input [`c_wrsw_num_ports - 1:0] prio;
//input [`c_wrsw_num_ports - 1:0] mask;
wait_cycles(50);
//////////////// input port = 0 ////////////////
hdr.src = 'h123456789abcde0;
hdr.dst = 'hcafeb1badeadbe0;
for(i=200;i<1250;i=i+50)
begin
hdr.src = port;
hdr.port_id = port;
hdr.ethertype = i;
send_pck(hdr,buffer, i, port, (i/50)%20, (i/50)%7,(i/50)%11);
if(port == 7)
port = 4;
else
port++;
end
end
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
int port = 8;
wait(ports_read);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<2000;i++)
buffer[i] = i;
//input ether_header_t hdr,
//input int payload[],
//input int length
//input [31:0] port;
//input drop;
//input [`c_wrsw_num_ports - 1:0] prio;
//input [`c_wrsw_num_ports - 1:0] mask;
wait_cycles(50);
//////////////// input port = 0 ////////////////
hdr.src = 'h123456789abcde0;
hdr.dst = 'hcafeb1badeadbe0;
for(i=200;i<1250;i=i+50)
begin
hdr.src = port;
hdr.port_id = port;
hdr.ethertype = i;
send_pck(hdr,buffer, i, port, (i/50)%20, (i/50)%7,(i/50)%11);
if(port == 10)
port = 8;
else
port++;
end
end
//////////////////////////////////////////////////////////
always @(posedge clk) if (rtu_rsp_ack != 0)
begin
rtu_rsp_valid = rtu_rsp_valid & !rtu_rsp_ack;
rtu_drop = rtu_drop & !rtu_rsp_ack;
end
// Check if there's anything received by EMU B
always @(posedge clk) if (test_input_block_0.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 0!");
test_input_block_0.receive(frame);
dump_frame_header("Receiving RX_0: ", frame);
end
always @(posedge clk) if (test_input_block_1.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 1!");
test_input_block_1.receive(frame);
dump_frame_header("Receiving RX_1: ", frame);
end
always @(posedge clk) if (test_input_block_2.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 2!");
test_input_block_2.receive(frame);
dump_frame_header("Receiving RX_2: ", frame);
end
always @(posedge clk) if (test_input_block_3.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 3!");
test_input_block_3.receive(frame);
dump_frame_header("Receiving RX_3: ", frame);
end
always @(posedge clk) if (test_input_block_4.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 4!");
test_input_block_4.receive(frame);
dump_frame_header("Receiving RX_4: ", frame);
end
always @(posedge clk) if (test_input_block_5.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 5!");
test_input_block_5.receive(frame);
dump_frame_header("Receiving RX_5: ", frame);
end
always @(posedge clk) if (test_input_block_6.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 6!");
test_input_block_6.receive(frame);
dump_frame_header("Receiving RX_6: ", frame);
end
always @(posedge clk) if (test_input_block_7.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 7!");
test_input_block_7.receive(frame);
dump_frame_header("Receiving RX_7: ", frame);
end
always @(posedge clk) if (test_input_block_8.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 8!");
test_input_block_8.receive(frame);
dump_frame_header("Receiving RX_8: ", frame);
end
always @(posedge clk) if (test_input_block_9.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 9!");
test_input_block_9.receive(frame);
dump_frame_header("Receiving RX_9: ", frame);
end
always @(posedge clk) if (test_input_block_10.poll())
begin
ether_frame_t frame;
// $display("Emulator test received a frame on port 10!");
test_input_block_10.receive(frame);
dump_frame_header("Receiving RX_10: ", frame);
end
endmodule // main
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`define c_clock_period 8
`define c_swc_page_addr_width 10
`define c_swc_usecount_width 4
`define c_wrsw_prio_width 3
`define c_swc_ctrl_width 4
`define c_swc_data_width 16
`define c_wrsw_num_ports 11
`timescale 1ns / 1ps
`include "fabric_emu.sv"
`define array_copy(a, ah, al, b, bl) \
for (k=al; k<=ah; k=k+1) a[k] <= b[bl+k-al];
typedef struct {
int cnt;
int usecnt[10];
int port[10];
} alloc_info_t;
alloc_info_t alloc_table[1024];
alloc_info_t dealloc_table[1024];
int stack_bastard = 0;
int pg_alloc_cnt[1024][20];
int pg_dealloc_cnt[1024][20];
module main;
reg clk = 0;
reg rst_n = 0;
wire [`c_wrsw_num_ports * 16- 1:0] a_to_input_block_data;
wire [`c_wrsw_num_ports * 4 - 1:0] a_to_input_block_ctrl;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_bytesel;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_dreq;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_valid;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_sof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_eof_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_rerror_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_abort_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_terror_p1;
wire [`c_wrsw_num_ports-1:0] a_to_input_block_tabort_p1;
wire [`c_wrsw_num_ports * 16- 1:0] input_block_to_a_data;
wire [`c_wrsw_num_ports * 4 - 1:0] input_block_to_a_ctrl;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_bytesel;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_dreq;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_valid;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_sof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_eof_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_rerror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_idle;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_terror_p1;
wire [`c_wrsw_num_ports-1:0] input_block_to_a_tabort_p1;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
reg [`c_wrsw_num_ports-1:0] rtu_rsp_valid = 0;
wire [`c_wrsw_num_ports-1:0] rtu_rsp_ack;
reg [`c_wrsw_num_ports * `c_wrsw_num_ports - 1 : 0] rtu_dst_port_mask = 0;
reg [`c_wrsw_num_ports-1:0] rtu_drop = 0;
reg [`c_wrsw_num_ports * `c_wrsw_prio_width -1 : 0] rtu_prio = 0;
// generate clock and reset signals
always #(`c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
int tx_cnt_0[11];
int tx_cnt_1[11];
int tx_cnt_2[11];
int tx_cnt_3[11];
int tx_cnt_4[11];
int tx_cnt_5[11];
int tx_cnt_6[11];
int tx_cnt_7[11];
int tx_cnt_8[11];
int tx_cnt_9[11];
int tx_cnt_10[11];
int rx_cnt[11];
int tx_cnt_by_port[11][11];
int rx_cnt_by_port[11][11];
int rx_cnt_0[11];
int rx_cnt_1[11];
int rx_cnt_2[11];
int rx_cnt_3[11];
int rx_cnt_4[11];
int rx_cnt_5[11];
int rx_cnt_6[11];
int rx_cnt_7[11];
int rx_cnt_8[11];
int rx_cnt_9[11];
int rx_cnt_10[11];
bit [10:0] tx_port_finished = 0;//{0,0,0,0,0,0,0,0,0,0,0};
integer ports_read = 0;
swc_core
DUT (
.clk_i (clk),
.rst_n_i (rst_n),
//-------------------------------------------------------------------------------
//-- Fabric I/F
//-------------------------------------------------------------------------------
.tx_sof_p1_i (a_to_input_block_sof_p1),
.tx_eof_p1_i (a_to_input_block_eof_p1),
.tx_data_i (a_to_input_block_data),
.tx_ctrl_i (a_to_input_block_ctrl),
.tx_valid_i (a_to_input_block_valid),
.tx_bytesel_i (a_to_input_block_bytesel),
.tx_dreq_o (a_to_input_block_dreq),
.tx_abort_p1_i (a_to_input_block_abort_p1),
.tx_rerror_p1_i (a_to_input_block_rerror_p1),
//-------------------------------------------------------------------------------
//-- Fabric I/F : output (goes to the Endpoint)
//-------------------------------------------------------------------------------
.rx_sof_p1_o (input_block_to_a_sof_p1),
.rx_eof_p1_o (input_block_to_a_eof_p1),
.rx_dreq_i (input_block_to_a_dreq),
.rx_ctrl_o (input_block_to_a_ctrl),
.rx_data_o (input_block_to_a_data),
.rx_valid_o (input_block_to_a_valid),
.rx_bytesel_o (input_block_to_a_bytesel),
.rx_idle_o (input_block_to_a_idle),
.rx_rerror_p1_o (input_block_to_a_rerror_p1),
.rx_terror_p1_i (input_block_to_a_terror_p1),
.rx_tabort_p1_i (input_block_to_a_tabort_p1),// tx_rabort_p1_i ????????
//-------------------------------------------------------------------------------
//-- I/F with Routing Table Unit (RTU)
//-------------------------------------------------------------------------------
.rtu_rsp_valid_i (rtu_rsp_valid),
.rtu_rsp_ack_o (rtu_rsp_ack),
.rtu_dst_port_mask_i (rtu_dst_port_mask),
.rtu_drop_i (rtu_drop),
.rtu_prio_i (rtu_prio)
);
task automatic wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
fabric_emu test_input_block_0
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE_ML(rx, a_to_input_block,0),
/*
.rx_data_o (a_to_input_block_data[15:0]),
.rx_ctrl_o (a_to_input_block_ctrl[15:0]),
.rx_bytesel_o (a_to_input_block_bytesel[0]),
.rx_dreq_i (a_to_input_block_dreq[0]),
.rx_valid_o (a_to_input_block_valid[0]),
.rx_sof_p1_o (a_to_input_block_sof_p1[0]),
.rx_eof_p1_o (a_to_input_block_eof_p1[0]),
.rx_rerror_p1_o (a_to_input_block_rerror_p1[0]),
.rx_terror_p1_i (1'b0),
.rx_tabort_p1_o (),
.rx_rabort_p1_i (1'b0),
.rx_idle_o (),
*/
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,0)
/*
.tx_data_i (input_block_to_a_data[15:0]),
.tx_ctrl_i (input_block_to_a_ctrl[15:0]),
.tx_bytesel_i (input_block_to_a_bytesel[0]),
.tx_dreq_o (input_block_to_a_dreq[0]),
.tx_valid_i (input_block_to_a_valid[0]),
.tx_sof_p1_i (input_block_to_a_sof_p1[0]),
.tx_eof_p1_i (input_block_to_a_eof_p1[0]),
.tx_rerror_p1_i (input_block_to_a_rerror_p1[0]),
.tx_terror_p1_o (input_block_to_a_terror_p1[0]),
.tx_rabort_p1_o (input_block_to_a_rabort_p1[0]),
.tx_idle_i (input_block_to_a_idle[0])
*/
);
fabric_emu test_input_block_1
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,1),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,1)
);
fabric_emu test_input_block_2
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,2),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,2)
);
fabric_emu test_input_block_3
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,3),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,3)
);
fabric_emu test_input_block_4
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,4),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,4)
);
fabric_emu test_input_block_5
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,5),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,5)
);
fabric_emu test_input_block_6
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,6),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,6)
);
fabric_emu test_input_block_7
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,7),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,7)
);
fabric_emu test_input_block_8
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,8),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,8)
);
fabric_emu test_input_block_9
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,9),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,9)
);
fabric_emu test_input_block_10
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_FULL_CONNECT_SOURCE_ML(rx, a_to_input_block,10),
`WRF_FULL_CONNECT_SINK_ML(tx, input_block_to_a,10)
);
task automatic set_rtu_rsp;
input [31:0] chan;
input valid;
input drop;
input [`c_wrsw_num_ports - 1:0] prio;
input [`c_wrsw_num_ports - 1:0] mask;
begin : wait_body
integer i;
integer k; // for the macro array_copy()
`array_copy(rtu_dst_port_mask,(chan+1)*`c_wrsw_num_ports - 1, chan*`c_wrsw_num_ports, mask ,0);
`array_copy(rtu_prio ,(chan+1)*`c_wrsw_prio_width - 1, chan*`c_wrsw_prio_width, prio, 0);
rtu_drop [ chan ] = drop;
rtu_rsp_valid [ chan ] = valid;
end
endtask // wait_cycles
task automatic send_pck;
input ether_header_t hdr;
input int payload[];
input int length;
input [31:0] port;
input drop;
input [`c_wrsw_num_ports - 1:0] prio;
input [`c_wrsw_num_ports - 1:0] mask;
input int frame_number;
begin : send_pck_body
int j;
set_rtu_rsp(port,1,drop,prio,mask);
// $display("Sending [f_nr: %2d]: src = %x, port = %d, len = %d, drop = %d, prio = %d, mask = %x",frame_number,hdr.src, port,length, drop, prio, mask);
case(port)
0: test_input_block_0.send(hdr, payload, length);
1: test_input_block_1.send(hdr, payload, length);
2: test_input_block_2.send(hdr, payload, length);
3: test_input_block_3.send(hdr, payload, length);
4: test_input_block_4.send(hdr, payload, length);
5: test_input_block_5.send(hdr, payload, length);
6: test_input_block_6.send(hdr, payload, length);
7: test_input_block_7.send(hdr, payload, length);
8: test_input_block_8.send(hdr, payload, length);
9: test_input_block_9.send(hdr, payload, length);
10:test_input_block_10.send(hdr, payload, length);
default: $display("ERROR: Wrong port number !!!");
endcase
if(drop == 0 && mask != 0)
begin
for(j=0;j<11;j++)
begin
if(mask[j])
begin
tx_cnt_by_port[port][j]++;
case(port)
0: tx_cnt_0[j]++;
1: tx_cnt_1[j]++;
2: tx_cnt_2[j]++;
3: tx_cnt_3[j]++;
4: tx_cnt_4[j]++;
5: tx_cnt_5[j]++;
6: tx_cnt_6[j]++;
7: tx_cnt_7[j]++;
8: tx_cnt_8[j]++;
9: tx_cnt_9[j]++;
10:tx_cnt_10[j]++;
default: $display("ERROR: Wrong port number !!!");
endcase
end
end
end
end
endtask
task automatic load_port;
input [31:0] port;
begin : load_port_body
ether_header_t hdr;
int buffer[2024];
int i,j;
int cnt =0;
bit [10:0] mask ;
int drop;
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
for(i=0;i<2000;i++)
buffer[i] = i;
$display("Initial waiting: %d cycles",((port*50)%11)*50);
wait_cycles(((port*50)%11)*50);
for(i=400;i<1250;i=i+25)
begin
hdr.src = port << 44 | cnt ;
hdr.port_id = port;
hdr.ethertype = i;
// mask = 'h7FF;;
// mask = 'h00f;;
mask = (port*cnt + 3*cnt + 2*cnt + cnt)%2047;
if( (i/50)%20 > 10) drop = 1; else drop = 0;
// drop = 0;
send_pck(hdr,buffer, i, port, drop, ((port*i)/50)%7, mask, cnt);
// if(port == 7) $display("====>>> Port 7: send pck nr %d",cnt);
//if(port == 6) $display("====>>> Port 6: send pck nr %d",cnt);
if(i > 600)
begin
test_input_block_0.simulate_rx_abort(0,10);
test_input_block_1.simulate_rx_abort(0,20);
test_input_block_2.simulate_rx_abort(0,30);
test_input_block_3.simulate_rx_abort(0,40);
test_input_block_4.simulate_rx_abort(0,50);
test_input_block_5.simulate_rx_abort(0,60);
test_input_block_6.simulate_rx_abort(0,70);
test_input_block_7.simulate_rx_abort(0,80);
test_input_block_8.simulate_rx_abort(0,90);
test_input_block_9.simulate_rx_abort(0,100);
test_input_block_10.simulate_rx_abort(0,110);
end
cnt ++;
end
$display(" ");
$display("==>> FINISHED: %2d !!!!!",port);
$display(" ");
end
endtask
initial begin
ports_read = 0;
wait(test_input_block_0.ready);
wait(test_input_block_1.ready);
wait(test_input_block_2.ready);
wait(test_input_block_3.ready);
wait(test_input_block_4.ready);
wait(test_input_block_5.ready);
wait(test_input_block_6.ready);
wait(test_input_block_7.ready);
wait(test_input_block_8.ready);
wait(test_input_block_9.ready);
wait(test_input_block_10.ready);
//////////////// input thottling ///////////////
test_input_block_0.simulate_tx_throttling(1, 50);
test_input_block_1.simulate_tx_throttling(1, 20);
test_input_block_2.simulate_tx_throttling(1, 30);
test_input_block_3.simulate_tx_throttling(1, 40);
test_input_block_4.simulate_tx_throttling(1, 10);
test_input_block_5.simulate_tx_throttling(1, 20);
test_input_block_6.simulate_tx_throttling(1, 30);
test_input_block_7.simulate_tx_throttling(1, 40);
test_input_block_8.simulate_tx_throttling(1, 10);
test_input_block_9.simulate_tx_throttling(1, 20);
test_input_block_10.simulate_tx_throttling(1,40);
//////////////// output thottling ///////////////
test_input_block_0.simulate_rx_throttling(1, 10);
test_input_block_1.simulate_rx_throttling(1, 20);
test_input_block_2.simulate_rx_throttling(1, 10);
test_input_block_3.simulate_rx_throttling(1, 20);
test_input_block_4.simulate_rx_throttling(1, 10);
test_input_block_5.simulate_rx_throttling(1, 20);
test_input_block_6.simulate_rx_throttling(1, 10);
test_input_block_7.simulate_rx_throttling(1, 20);
test_input_block_8.simulate_rx_throttling(1, 10);
test_input_block_9.simulate_rx_throttling(1, 20);
test_input_block_10.simulate_rx_throttling(1, 10);
test_input_block_0.simulate_rx_abort(1,10);
test_input_block_1.simulate_rx_abort(1,20);
test_input_block_2.simulate_rx_abort(1,30);
test_input_block_3.simulate_rx_abort(1,40);
test_input_block_4.simulate_rx_abort(1,50);
test_input_block_5.simulate_rx_abort(1,60);
test_input_block_6.simulate_rx_abort(1,70);
test_input_block_7.simulate_rx_abort(1,80);
test_input_block_8.simulate_rx_abort(1,90);
test_input_block_9.simulate_rx_abort(1,100);
test_input_block_10.simulate_rx_abort(1,110);
//////////////// input error ///////////////
/*
test_input_block_0.simulate_tx_error(1,90);
test_input_block_1.simulate_tx_error(1,110);
test_input_block_2.simulate_tx_error(1,130);
test_input_block_3.simulate_tx_error(1,140);
test_input_block_4.simulate_tx_error(1,150);
test_input_block_5.simulate_tx_error(1,160);
test_input_block_6.simulate_tx_error(1,170);
test_input_block_7.simulate_tx_error(1,180);
test_input_block_8.simulate_tx_error(1,190);
test_input_block_9.simulate_tx_error(1,100);
test_input_block_10.simulate_tx_error(1,800);
*/
ports_read = 1;
$display("=======ALL PORTS READY======");
end
initial begin
int i;
wait(ports_read);
load_port(0);
tx_port_finished[0] = 1;
end
initial begin
wait(ports_read);
load_port(1);
tx_port_finished[1] = 1;
end
initial begin
wait(ports_read);
load_port(2);
tx_port_finished[2] = 1;
end
initial begin
wait(ports_read);
load_port(3);
tx_port_finished[3] = 1;
end
initial begin
wait(ports_read);
load_port(4);
tx_port_finished[4] = 1;
end
initial begin
wait(ports_read);
load_port(5);
tx_port_finished[5] = 1;
end
initial begin
wait(ports_read);
load_port(6);
tx_port_finished[6] = 1;
end
initial begin
wait(ports_read);
load_port(7);
tx_port_finished[7] = 1;
end
initial begin
wait(ports_read);
load_port(8);
tx_port_finished[8] = 1;
end
initial begin
wait(ports_read);
load_port(9);
tx_port_finished[9] = 1;
end
initial begin
wait(ports_read);
load_port(10);
tx_port_finished[10] = 1;
end
initial begin
int i,j, cnt;
int sum_rx, sum_tx, sum_tx_by_port[11],sum_rx_by_port[11];
wait(tx_port_finished[0] & tx_port_finished[1] & tx_port_finished[2] & tx_port_finished[3] & tx_port_finished[4] &
tx_port_finished[5] & tx_port_finished[6] & tx_port_finished[7] & tx_port_finished[8] & tx_port_finished[9] & tx_port_finished[10]);
wait_cycles(1000000);
$display("=============================================== DBG =================================================");
$display("Rx Ports : P 0 | P 1 | P 2 | P 3 | P 4 | P 5 | P 6 | P 7 | P 8 | P 9 | P10 | ");
$display("-----------------------------------------------------------------------------------------------------");
$display(" (number of pcks sent from port Rx to port Tx) > (number of pcks received on port Tx from port Rx) | ");
$display("-----------------------------------------------------------------------------------------------------");
for(i=0;i<11;i++)
$display("TX Port %2d : %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d | %2d>%2d |",i,
tx_cnt_by_port[i][0],rx_cnt_by_port[i][0],tx_cnt_by_port[i][1],rx_cnt_by_port[i][1],tx_cnt_by_port[i][2],rx_cnt_by_port[i][2],tx_cnt_by_port[i][3],rx_cnt_by_port[i][3],
tx_cnt_by_port[i][4],rx_cnt_by_port[i][4],tx_cnt_by_port[i][5],rx_cnt_by_port[i][5],tx_cnt_by_port[i][6],rx_cnt_by_port[i][6],tx_cnt_by_port[i][7],rx_cnt_by_port[i][7],
tx_cnt_by_port[i][8],rx_cnt_by_port[i][8],tx_cnt_by_port[i][9],rx_cnt_by_port[i][9],tx_cnt_by_port[i][10],rx_cnt_by_port[i][10]);
$display("=============================================== DBG =================================================");
for(i=0;i<11;i++)
begin
for(j=0;j<11;j++) sum_tx_by_port[i] += tx_cnt_by_port[j][i];
$display("Tx Port %2d : pcks sent to P%2d = %2d, pcks received on P%2d = %2d",i,i, sum_tx_by_port[i],i ,rx_cnt[i]);
end
for(i=0;i<11;i++) sum_tx += sum_tx_by_port[i];
for(i=0;i<11;i++) sum_rx += rx_cnt[i];
$display("=======================================================================");
$display("SUM : sent pcks = %2d, received pcks = %2d", sum_tx,sum_rx);
$display("=================================== DBG ===============================");
/*
cnt =0;
for(i=0;i<1024;i++)
if(pg_dealloc_cnt[i][0] != pg_alloc_cnt[i][0])
begin
$display("Page %3d: allocated = %2d [%1d|%1d|%1d|%1d|%1d|%1d] <=|=> deallocated = %2d [%1d|%1d|%1d|%1d|%1d|%1d] <- lost page !!!!",i,pg_alloc_cnt[i][0],
pg_alloc_cnt[i][1], pg_alloc_cnt[i][2],pg_alloc_cnt[i][3],pg_alloc_cnt[i][4],pg_alloc_cnt[i][5],pg_alloc_cnt[i][6], pg_dealloc_cnt[i][0],
pg_dealloc_cnt[i][1],pg_dealloc_cnt[i][2],pg_dealloc_cnt[i][3],pg_dealloc_cnt[i][4],pg_dealloc_cnt[i][5],pg_dealloc_cnt[i][6]);
cnt++;
end
$display("=======================================================================");
$display("MEM LEAKGE Report: number of lost pages = %2d", cnt);
$display("=================================== DBG ===============================");
*/
cnt =0;
for(i=0;i<1024;i++)
if(dealloc_table[i].cnt!= alloc_table[i].cnt)
begin
$display("Page %4d: alloc = %2d [%2d:%2d|%2d:%2d|%2d:%2d|%2d:%2d|%2d:%2d|%2d:%2d]<=|=>dealloc = %2d [%2d:%11b|%2d:%11b|%2d:%11b|%2d:%11b|%2d:%11b|%2d:%11b] ",
i,
alloc_table[i].cnt,
alloc_table[i].usecnt[0], alloc_table[i].port[0],
alloc_table[i].usecnt[1], alloc_table[i].port[1],
alloc_table[i].usecnt[2], alloc_table[i].port[2],
alloc_table[i].usecnt[3], alloc_table[i].port[3],
alloc_table[i].usecnt[4], alloc_table[i].port[4],
alloc_table[i].usecnt[5], alloc_table[i].port[5],
dealloc_table[i].cnt,
dealloc_table[i].usecnt[0], dealloc_table[i].port[0],
dealloc_table[i].usecnt[1], dealloc_table[i].port[1],
dealloc_table[i].usecnt[2], dealloc_table[i].port[2],
dealloc_table[i].usecnt[3], dealloc_table[i].port[3],
dealloc_table[i].usecnt[4], dealloc_table[i].port[4],
dealloc_table[i].usecnt[5], dealloc_table[i].port[5]);
cnt++;
end
$display("=======================================================================");
if(cnt == 22)
$display("%4d pages allocated in advance (port X start_of_pck + port X pck_internal pages)", cnt);
else
$display("MEM LEAKGE Report: number of lost pages = %2d", (cnt - 22));
$display("=================================== DBG ===============================");
$fatal("dupa");
end
//////////////////////////////////////////////////////////
always @(posedge clk)
begin
int i;
for(i = 0;i<11;i++)
begin
rtu_rsp_valid[i] = rtu_rsp_valid[i] & !rtu_rsp_ack[i];
rtu_drop[i] = rtu_drop[i] & !rtu_rsp_ack[i];
end
end
// Check if there's anything received by EMU B
always @(posedge clk) if (test_input_block_0.poll())
begin
ether_frame_t frame;
test_input_block_0.receive(frame);
rx_cnt[0]++;
rx_cnt_0[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][0]++;
// dump_frame_header("Receiving RX_0: ", frame);
end
always @(posedge clk) if (test_input_block_1.poll())
begin
ether_frame_t frame;
test_input_block_1.receive(frame);
rx_cnt[1]++;
rx_cnt_1[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][1]++;;
// dump_frame_header("Receiving RX_1: ", frame);
end
always @(posedge clk) if (test_input_block_2.poll())
begin
ether_frame_t frame;
test_input_block_2.receive(frame);
rx_cnt[2]++;
rx_cnt_2[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][2]++;
// dump_frame_header("Receiving RX_2: ", frame);
end
always @(posedge clk) if (test_input_block_3.poll())
begin
ether_frame_t frame;
test_input_block_3.receive(frame);
rx_cnt[3]++;
rx_cnt_3[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][3]++;
// dump_frame_header("Receiving RX_3: ", frame);
end
always @(posedge clk) if (test_input_block_4.poll())
begin
ether_frame_t frame;
test_input_block_4.receive(frame);
rx_cnt[4]++;
rx_cnt_4[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][4]++;
// dump_frame_header("Receiving RX_4: ", frame);
end
always @(posedge clk) if (test_input_block_5.poll())
begin
ether_frame_t frame;
test_input_block_5.receive(frame);
rx_cnt[5]++;
rx_cnt_5[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][5]++;
// dump_frame_header("Receiving RX_5: ", frame);
end
always @(posedge clk) if (test_input_block_6.poll())
begin
ether_frame_t frame;
test_input_block_6.receive(frame);
rx_cnt[6]++;
rx_cnt_6[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][6]++;
// dump_frame_header("Receiving RX_6: ", frame);
end
always @(posedge clk) if (test_input_block_7.poll())
begin
ether_frame_t frame;
test_input_block_7.receive(frame);
rx_cnt[7]++;
rx_cnt_7[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][7]++;
// dump_frame_header("Receiving RX_7: ", frame);
end
always @(posedge clk) if (test_input_block_8.poll())
begin
ether_frame_t frame;
test_input_block_8.receive(frame);
rx_cnt[8]++;
rx_cnt_8[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][8]++;
// dump_frame_header("Receiving RX_8: ", frame);
end
always @(posedge clk) if (test_input_block_9.poll() )
begin
ether_frame_t frame;
test_input_block_9.receive(frame);
rx_cnt[9]++;
rx_cnt_9[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][9]++;
// dump_frame_header("Receiving RX_9: ", frame);
end
always @(posedge clk) if (test_input_block_10.poll() )
begin
ether_frame_t frame;
test_input_block_10.receive(frame);
rx_cnt[10]++;
rx_cnt_10[frame.hdr.src >> 44]++;
rx_cnt_by_port[frame.hdr.src >> 44][10]++;
// dump_frame_header("Receiving RX_10: ", frame);
end
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////// Monitoring allocation of pages /////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
// always @(posedge clk) if(DUT.memory_management_unit.pg_addr_valid)
always @(posedge clk) if(DUT.memory_management_unit.pg_alloc & DUT.memory_management_unit.pg_done)
begin
int address;
int usecnt;
usecnt = DUT.memory_management_unit.pg_usecnt;
wait(DUT.memory_management_unit.pg_addr_valid);
address = DUT.memory_management_unit.pg_addr_alloc;
pg_alloc_cnt[address][pg_alloc_cnt[address][0]+1]= usecnt;
pg_alloc_cnt[address][0]++;
alloc_table[address].usecnt[alloc_table[address].cnt] = usecnt;
alloc_table[address].port[alloc_table[address].cnt] = DUT.memory_management_unit.in_sel;
alloc_table[address].cnt++;
end
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////// Monitoring deallocation of pages /////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
always @(posedge clk) if(DUT.memory_management_unit.alloc_core.tmp_dbg_dealloc)
begin
int address;
address = DUT.memory_management_unit.alloc_core.tmp_page;
pg_dealloc_cnt[address][0]++;
dealloc_table[address].cnt++;
end
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////// Monitoring freeing of pages /////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
always @(posedge clk) if(DUT.memory_management_unit.pg_free & DUT.memory_management_unit.pg_done)
begin
int address;
int port_mask;
int port;
port = DUT.memory_management_unit.in_sel;
address = DUT.memory_management_unit.pg_addr;
port_mask = dealloc_table[address].port[dealloc_table[address].cnt ] ;
pg_dealloc_cnt[address][pg_dealloc_cnt[address][0] + 1]++;
dealloc_table[address].port[dealloc_table[address].cnt ] = ((1 << port) | port_mask) & 'h7FF;
dealloc_table[address].usecnt[dealloc_table[address].cnt ]++;
end
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////// Monitoring setting of pages' usecnt /////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
always @(posedge clk) if(DUT.memory_management_unit.pg_set_usecnt & DUT.memory_management_unit.pg_done)
begin
int address;
address = DUT.memory_management_unit.pg_addr;
pg_alloc_cnt[address][pg_alloc_cnt[address][0] + 1] = DUT.memory_management_unit.pg_usecnt;
alloc_table[address].usecnt[alloc_table[address].cnt - 1] = DUT.memory_management_unit.pg_usecnt;;
end
endmodule // main
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`define c_clock_period 8
`define c_swc_page_addr_width 10
`define c_swc_usecount_width 4
`define c_wrsw_prio_width 3
`define c_swc_ctrl_width 16
`define c_swc_data_width 4
`define c_wrsw_num_ports 11
`timescale 1ns / 1ps
`include "fabric_emu.sv"
module main;
reg clk = 0;
reg rst_n = 0;
//`WRF_WIRES(a_to_input_block); // Emu A to B fabric
wire [15:0] a_to_input_block_data;
wire [3 :0] a_to_input_block_ctrl;
wire a_to_input_block_bytesel;
wire a_to_input_block_dreq;
wire a_to_input_block_valid;
wire a_to_input_block_sof_p1;
wire a_to_input_block_eof_p1;
wire a_to_input_block_rerror_p1;
wire [15:0] input_block_to_a_data;
wire [3 :0] input_block_to_a_ctrl;
wire input_block_to_a_bytesel;
wire input_block_to_a_dreq;
wire input_block_to_a_valid;
wire input_block_to_a_sof_p1;
wire input_block_to_a_eof_p1;
wire input_block_to_a_rerror_p1;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
reg rtu_rsp_valid = 0;
wire rtu_rsp_ack;
reg [`c_wrsw_num_ports - 1 : 0] rtu_dst_port_mask = 0;
reg rtu_drop = 0;
reg [`c_wrsw_prio_width - 1 : 0] rtu_prio = 0;
// generate clock and reset signals
always #(`c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
swc_core
DUT (
.clk_i (clk),
.rst_n_i (rst_n),
//-------------------------------------------------------------------------------
//-- Fabric I/F
//-------------------------------------------------------------------------------
`_WRF_CONNECT_MANDATORY_SINK (tx, a_to_input_block),
`_WRF_CONNECT_MANDATORY_SOURCE (rx, input_block_to_a),
//-------------------------------------------------------------------------------
//-- I/F with Routing Table Unit (RTU)
//-------------------------------------------------------------------------------
.rtu_rsp_valid_i (rtu_rsp_valid),
.rtu_rsp_ack_o (rtu_rsp_ack),
.rtu_dst_port_mask_i (rtu_dst_port_mask),
.rtu_drop_i (rtu_drop),
.rtu_prio_i (rtu_prio)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
fabric_emu test_input_block
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, a_to_input_block),
`WRF_CONNECT_SINK(tx, input_block_to_a)
);
// Two fabric emulators talking to each other
fabric_emu U_emuA
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ba), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, ab)
);
fabric_emu U_emuB
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ab),
`WRF_CONNECT_SINK(tx, ba)
);
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
// wait(U_emuA.ready); // wait until both emulators are initialized
/// wait(U_emuB.ready);
wait(test_input_block.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
rtu_dst_port_mask = 1;
rtu_drop = 0;
rtu_prio = 2;
for(i=0;i<1000;i++)
buffer[i] = i;
// simulate some flow throttling
//U_emuA.simulate_rx_throttling(1, 50);
// test_input_block.simulate_rx_throttling(1, 0);
// test_input_block.simulate_rx_error(1,10);
// test_input_block.simulate_tx_error(1,100);
//U_emuA.send(hdr, buffer, 100);
wait_cycles(20);
rtu_rsp_valid = 1;
rtu_prio = 1;
test_input_block.send(hdr, buffer, 200);
rtu_prio = 2;
test_input_block.send(hdr, buffer, 201);
rtu_prio = 2;
test_input_block.send(hdr, buffer, 202);
rtu_prio = 1;
test_input_block.send(hdr, buffer, 203);
rtu_prio = 4;
test_input_block.send(hdr, buffer, 204);
rtu_prio = 6;
test_input_block.send(hdr, buffer, 205);
rtu_prio = 7;
test_input_block.send(hdr, buffer, 206);
rtu_prio = 3;
test_input_block.send(hdr, buffer, 207);
rtu_prio = 1;
test_input_block.send(hdr, buffer, 208);
rtu_prio = 7;
test_input_block.send(hdr, buffer, 495);
rtu_drop = 1;
test_input_block.send(hdr, buffer, 595);
rtu_drop = 0;
rtu_prio = 4;
test_input_block.send(hdr, buffer, 95);
rtu_rsp_valid = 0;
test_input_block.send(hdr, buffer, 100);
//hdr.src = 'h0f0e0a0b0d00;
//U_emuB.send(hdr, buffer, 50);
end
// Check if there's anything received by EMU B
always @(posedge clk) if (test_input_block.poll())
begin
ether_frame_t frame;
$display("Emulator test received a frame!");
test_input_block.receive(frame);
dump_frame_header("test RX: ", frame);
end
// Check if there's anything received by EMU B
always @(posedge clk) if (U_emuB.poll())
begin
ether_frame_t frame;
$display("Emulator B received a frame!");
U_emuB.receive(frame);
dump_frame_header("EmuB RX: ", frame);
end
// Check if there's anything received by EMU A
always @(posedge clk) if (U_emuA.poll())
begin
ether_frame_t frame;
$display("Emulator A received a frame!");
U_emuA.receive(frame);
dump_frame_header("EmuA RX: ", frame);
end
endmodule // main
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`define c_clock_period 8
`define c_swc_page_addr_width 10
`define c_swc_usecount_width 4
`define c_wrsw_prio_width 3
`define c_swc_ctrl_width 4
`define c_swc_data_width 16
`define c_wrsw_num_ports 11
`timescale 1ns / 1ps
`include "fabric_emu.sv"
module main;
reg clk = 0;
reg rst_n = 0;
//`WRF_WIRES(a_to_input_block); // Emu A to B fabric
wire [15:0] a_to_input_block_data;
wire [3 :0] a_to_input_block_ctrl;
wire a_to_input_block_bytesel;
wire a_to_input_block_dreq;
wire a_to_input_block_valid;
wire a_to_input_block_sof_p1;
wire a_to_input_block_eof_p1;
wire a_to_input_block_rerror_p1;
wire [15:0] input_block_to_a_data;
wire [3 :0] input_block_to_a_ctrl;
wire input_block_to_a_bytesel;
wire input_block_to_a_dreq;
wire input_block_to_a_valid;
wire input_block_to_a_sof_p1;
wire input_block_to_a_eof_p1;
wire input_block_to_a_rerror_p1;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
wire mmu_page_alloc_req;
reg mmu_page_alloc_done = 0;
reg [`c_swc_page_addr_width - 1 : 0] mmu_pageaddr_in = 0;
wire [`c_swc_page_addr_width - 1 : 0] mmu_pageaddr_out;
wire mmu_force_free;
wire mmu_set_usecnt ;
reg mmu_set_usecnt_done = 0;
wire [`c_swc_usecount_width - 1 : 0] mmu_usecnt;
reg rtu_rsp_valid = 0;
wire rtu_rsp_ack;
reg [`c_wrsw_num_ports - 1 : 0] rtu_dst_port_mask = 0;
reg rtu_drop = 0;
reg [`c_wrsw_prio_width - 1 : 0] rtu_prio = 0;
wire mpm_pckstart;
wire [`c_swc_page_addr_width - 1 : 0] mpm_pageaddr;
reg mpm_pageend = 0;
wire [`c_swc_data_width - 1 : 0] mpm_data;
wire [`c_swc_ctrl_width - 1 : 0] mpm_ctrl;
wire mpm_drdy;
reg mpm_full = 0;
wire mpm_flush;
wire pta_transfer_pck;
wire [`c_swc_page_addr_width - 1 : 0] pta_pageaddr;
wire [`c_wrsw_num_ports - 1 : 0] pta_mask;
wire [`c_wrsw_prio_width - 1 : 0] pta_prio;
// generate clock and reset signals
always #(`c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
swc_input_block
DUT (
.clk_i (clk),
.rst_n_i (rst_n),
//-------------------------------------------------------------------------------
//-- Fabric I/F
//-------------------------------------------------------------------------------
`_WRF_CONNECT_MANDATORY_SINK (tx, a_to_input_block),
//-------------------------------------------------------------------------------
//-- I/F with Page allocator (MMU)
//-------------------------------------------------------------------------------
.mmu_page_alloc_req_o (mmu_page_alloc_req),
.mmu_page_alloc_done_i (mmu_page_alloc_done),
.mmu_pageaddr_i (mmu_pageaddr_in),
.mmu_pageaddr_o (mmu_pageaddr_out),
.mmu_force_free_o (mmu_force_free),
.mmu_set_usecnt_o (mmu_set_usecnt),
.mmu_set_usecnt_done_i (mmu_set_usecnt_done),
.mmu_usecnt_o (mmu_usecnt),
//-------------------------------------------------------------------------------
//-- I/F with Routing Table Unit (RTU)
//-------------------------------------------------------------------------------
.rtu_rsp_valid_i (rtu_rsp_valid),
.rtu_rsp_ack_o (rtu_rsp_ack),
.rtu_dst_port_mask_i (rtu_dst_port_mask),
.rtu_drop_i (rtu_drop),
.rtu_prio_i (rtu_prio),
//-------------------------------------------------------------------------------
//-- I/F with Multiport Memory (MPU)
//-------------------------------------------------------------------------------
.mpm_pckstart_o (mpm_pckstart),
.mpm_pageaddr_o (mpm_pageaddr),
.mpm_pageend_i (mpm_pageend),
.mpm_data_o (mpm_data),
.mpm_ctrl_o (mpm_ctrl),
.mpm_drdy_o (mpm_drdy),
.mpm_full_i (mpm_full),
.mpm_flush_o (mpm_flush),
//-------------------------------------------------------------------------------
//-- I/F with Page Transfer Arbiter (PTA)
//-------------------------------------------------------------------------------
.pta_transfer_pck_o (pta_transfer_pck),
.pta_pageaddr_o (pta_pageaddr),
.pta_mask_o (pta_mask),
.pta_prio_o (pta_prio)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
fabric_emu test_input_block
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, a_to_input_block),
`WRF_CONNECT_SINK(tx, input_block_to_a)
);
// Two fabric emulators talking to each other
fabric_emu U_emuA
(
.clk_i(clk),
.rst_n_i(rst_n),
//`WRF_CONNECT_SOURCE(rx, a_to_input_block),
`WRF_CONNECT_SOURCE(rx, ba), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, ab)
//`WRF_CONNECT_SINK(tx,a_to_input_block)
);
fabric_emu U_emuB
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ab),
`WRF_CONNECT_SINK(tx, ba)
);
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(U_emuA.ready); // wait until both emulators are initialized
wait(U_emuB.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
rtu_dst_port_mask = 6;
rtu_drop = 0;
rtu_prio = 2;
for(i=0;i<100;i++)
buffer[i] = i;
// simulate some flow throttling
U_emuA.simulate_rx_throttling(1, 50);
U_emuA.send(hdr, buffer, 100);
rtu_rsp_valid = 1;
test_input_block.send(hdr, buffer, 100);
rtu_rsp_valid = 0;
//hdr.src = 'h0f0e0a0b0d00;
//U_emuB.send(hdr, buffer, 50);
end
// Check if there's anything received by EMU B
always @(posedge clk) if (U_emuB.poll())
begin
ether_frame_t frame;
$display("Emulator B received a frame!");
U_emuB.receive(frame);
dump_frame_header("EmuB RX: ", frame);
end
// Check if there's anything received by EMU A
always @(posedge clk) if (U_emuA.poll())
begin
ether_frame_t frame;
$display("Emulator A received a frame!");
U_emuA.receive(frame);
dump_frame_header("EmuA RX: ", frame);
end
endmodule // main
`timescale 1ns / 1ps
`define NUM_PORTS 11
`define NUM_PAGES 1024
`define PAGE_ADDR_BITS 10
`define USECNT_BITS 4
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
integer i, j;
integer fail = 0;
reg [`NUM_PORTS * 10 - 1:0] pgaddr_free = 0;
reg [`NUM_PORTS * 4 - 1:0] usecnt_alloc = 0;
wire [`PAGE_ADDR_BITS-1:0] pgaddr_alloc;
reg [`NUM_PORTS-1:0] rq_alloc=0, rq_free=0, rq_force_free = 0, rq_set_usecnt = 0;
wire [`NUM_PORTS-1:0] done_alloc, done_free,done_force_free, done_set_usecnt;
reg [`PAGE_ADDR_BITS-1:0] pgaddr_alloc_tab [`NUM_PORTS-1:0];
reg [`PAGE_ADDR_BITS-1:0] usecnt_alloc_tab [`NUM_PORTS-1:0];
integer alloced_pages_map [0:`NUM_PAGES-1];
integer alloced_pages_count = 0;
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
task alloc_page_multi;
input [4:0] channel;
begin : alloc_body
integer lo, hi;
if(rq_alloc[channel]) begin
$display("Wait...");
while(!done_alloc[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Alloc! (ch %d)", channel);
rq_alloc[channel] <= 1'b1;
lo = channel * `USECNT_BITS;
usecnt_alloc[lo] <= 1'b0;
usecnt_alloc[lo+1] <= 1'b1;
usecnt_alloc[lo+2] <= 1'b0;
usecnt_alloc[lo+3] <= 1'b0;
@(posedge clk);
end
endtask // alloc_page_multi
task alloc_all_pages;
input [4:0] channel;
begin : alloc_body
integer lo, hi, i;
for(i=0;i<`NUM_PORTS;i=i+1) begin
if(rq_alloc[i]) begin
$display("Wait...");
while(!done_alloc[i]) begin @(posedge clk); end
@(posedge clk);
end
end
for(i=0;i<`NUM_PORTS;i=i+1) begin
$display("Alloc! (ch %d)", i);
rq_alloc[i] <= 1'b1;
lo = i * `USECNT_BITS;
usecnt_alloc[lo] <= 1'b0;
usecnt_alloc[lo+1] <= 1'b1;
usecnt_alloc[lo+2] <= 1'b0;
usecnt_alloc[lo+3] <= 1'b0;
end
@(posedge clk);
end
endtask // alloc_page_multi
task set_usecnt;
input [4:0] channel;
input [`PAGE_ADDR_BITS-1: 0] pageaddr;
input [3:0] usecnt;
begin : free_body
integer lo, k,n;
if(rq_set_usecnt[channel])
begin
$display("Wait...");
while(!done_set_usecnt[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Set user count %d! (ch %d, page %d)", usecnt, channel, pageaddr);
lo = channel * `USECNT_BITS;
for (k=0; k < `USECNT_BITS; k=k+1)
usecnt_alloc[channel * `USECNT_BITS + k] <= usecnt[k];
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
pgaddr_free[channel * `PAGE_ADDR_BITS + k] <= pageaddr[k];
rq_set_usecnt[channel] <= 1'b1;
@(posedge clk);
//rq_set_usecnt[channel] <= 1'b0;
end
endtask
task free_page_multi;
input [4:0] channel;
input [`PAGE_ADDR_BITS-1: 0] pageaddr;
begin : free_body
integer k,n;
if(rq_free[channel]) begin
$display("Wait...");
while(!done_free[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Free! (ch %d, page %d)", channel, pageaddr);
rq_free[channel] <= 1'b1;
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
pgaddr_free[channel * `PAGE_ADDR_BITS + k] <= pageaddr[k];
@(posedge clk);
end
endtask
task force_free_page_multi;
input [4:0] channel;
input [`PAGE_ADDR_BITS-1: 0] pageaddr;
begin : free_body
integer k,n;
if(rq_force_free[channel]) begin
$display("Wait...");
while(!done_force_free[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Force Free! (ch %d, page %d)", channel, pageaddr);
rq_force_free[channel] <= 1'b1;
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
pgaddr_free[channel * `PAGE_ADDR_BITS + k] <= pageaddr[k];
@(posedge clk);
end
endtask
swc_multiport_page_allocator #(
.g_num_ports (`NUM_PORTS),
.g_num_pages (`NUM_PAGES),
.g_page_addr_bits (`PAGE_ADDR_BITS),
.g_use_count_bits (`USECNT_BITS)
) DUT (
.rst_n_i (rst),
.clk_i (clk),
.alloc_i (rq_alloc),
.free_i (rq_free),
.force_free_i (rq_force_free),
.set_usecnt_i (rq_set_usecnt),
.alloc_done_o (done_alloc),
.free_done_o (done_free),
.force_free_done_o (done_force_free),
.set_usecnt_done_o (done_set_usecnt),
.pgaddr_free_i (pgaddr_free),
.usecnt_i (usecnt_alloc),
.pgaddr_alloc_o (pgaddr_alloc)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
initial begin
@(posedge rst);
#(100);
@(posedge clk);
#1;
//alloc_all_pages(0);
//#(1)
for (i=0;i<`NUM_PAGES;i=i+1) alloced_pages_map[i] = 0;
for (i=0;i<`NUM_PAGES/2;i=i+1) alloc_page_multi((i*7123) % `NUM_PORTS);
#(1000);
@(posedge clk);
#1;
// wait_cycles(1000);
for(i=0;i<`NUM_PAGES/2;i=i+1) set_usecnt((i*7123) % `NUM_PORTS, i,4);
@(posedge clk);
#1
for(i=0;i<`NUM_PAGES/2;i=i+1) free_page_multi((i*23) % `NUM_PORTS, i);
for(i=0;i<`NUM_PAGES/2;i=i+1) free_page_multi((i*23) % `NUM_PORTS, i);
wait_cycles(1000);
for (i=0;i<`NUM_PAGES/2;i=i+1) alloc_page_multi((i*7123) % `NUM_PORTS);
#(1000);
@(posedge clk);
#1;
for(i=0;i<`NUM_PAGES/2;i=i+1) free_page_multi((i*23) % `NUM_PORTS, i);
for(i=0;i<`NUM_PAGES/2;i=i+1) force_free_page_multi((i*23) % `NUM_PORTS, i);
#(1000);
@(posedge clk);
#1;
alloc_page_multi(5);
end
always@(posedge clk)
begin
rq_alloc <= rq_alloc & (~done_alloc);
rq_free <= rq_free & (~done_free);
rq_force_free <= rq_force_free & (~done_force_free);
rq_set_usecnt <= rq_set_usecnt & (~done_set_usecnt);
for (j=0;j<`NUM_PORTS;j=j+1) begin
if(done_alloc[j])
begin
$display("Allocated: ch %d page %d", j, pgaddr_alloc);
end
if(done_free[j]) begin
$display("freed page ch %d", j);
end
end
end // UNMATCHED !!
endmodule // main
`timescale 1ns / 1ps
`define NUM_PORTS 11
`define NUM_PAGES 1024
`define PAGE_ADDR_BITS 10
`define USECNT_BITS 4
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
integer i, j;
integer fail = 0;
reg [`NUM_PORTS * 10 - 1:0] read_pump_addr = 0;
reg [`NUM_PORTS * 10 - 1:0] free_pck_addr = 0;
reg [`NUM_PORTS * 10 - 1:0] write_addr = 0;
reg [`NUM_PORTS * 10 - 1:0] free_page_addr = 0;
reg [`NUM_PORTS * 10 - 1:0] write_data = 0;
reg [`NUM_PORTS-1:0] rq_write=0, rq_free_page_write=0, rq_free_pck_read = 0, rq_read = 0;
wire [`NUM_PORTS-1:0] done_write, done_free,done_free_pck, done_read;
wire [`PAGE_ADDR_BITS-1:0] data_out;
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
task write_page_addr;
input [4:0] channel;
input [`PAGE_ADDR_BITS-1: 0] page_addr;
input [`PAGE_ADDR_BITS-1: 0] page_data;
begin : write_page_body
integer lo, h,k;
if(rq_write[channel]) begin
$display("Wait...");
while(rq_write[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Write! (ch=%d, p=%d,d=%d)", channel,page_addr,page_data);
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
write_addr[channel * `PAGE_ADDR_BITS + k] <= page_addr[k];
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
write_data[channel * `PAGE_ADDR_BITS + k] <= page_data[k];
rq_write[channel] <= 1'b1;
@(posedge clk);
end
endtask // write_page_body
task write_free_page_addr;
input [4:0] channel;
input [`PAGE_ADDR_BITS-1: 0] page_addr;
begin : write_free_page_body
integer lo, h,k;
if(rq_free_page_write[channel]) begin
$display("Wait...");
while(rq_free_page_write[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Free! (ch=%d, p=%d)", channel,page_addr);
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
free_page_addr[channel * `PAGE_ADDR_BITS + k] <= page_addr[k];
rq_free_page_write[channel] <= 1'b1;
@(posedge clk);
end
endtask // write_page_body
task pump_read_page_addr;
input [4:0] channel;
input [`PAGE_ADDR_BITS-1: 0] page_addr;
begin : pump_read_page_body
integer lo, h,k;
if(rq_read[channel]) begin
$display("Wait...");
while(rq_read[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Reading page data [by pump]! (ch=%d, p=%d)", channel,page_addr);
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
read_pump_addr[channel * `PAGE_ADDR_BITS + k] <= page_addr[k];
rq_read[channel] <= 1'b1;
@(posedge clk);
end
endtask // write_page_body
task free_pck_read_page_addr;
input [4:0] channel;
input [`PAGE_ADDR_BITS-1: 0] page_addr;
begin : free_pck_read_page_body
integer lo, h,k;
if(rq_free_pck_read[channel]) begin
$display("Wait...");
while(rq_free_pck_read[channel]) begin @(posedge clk); end
@(posedge clk);
end
$display("Reading page data [by pck free modul]! (ch=%d, p=%d)", channel,page_addr);
for (k=0; k < `PAGE_ADDR_BITS; k=k+1)
free_pck_addr[channel * `PAGE_ADDR_BITS + k] <= page_addr[k];
rq_free_pck_read[channel] <= 1'b1;
@(posedge clk);
end
endtask // write_page_body
swc_multiport_linked_list
DUT (
.rst_n_i (rst),
.clk_i (clk),
//requests
.write_i (rq_write),
.free_i (rq_free_page_write),
.read_pump_read_i (rq_read),
.free_pck_read_i (rq_free_pck_read),
// done strobes
.write_done_o (done_write),
.free_done_o (done_free),
.read_pump_read_done_o (done_read),
.free_pck_read_done_o (done_free_pck),
//addresses
.read_pump_addr_i (read_pump_addr),
.free_pck_addr_i (free_pck_addr),
.write_addr_i (write_addr),
.free_addr_i (free_page_addr),
//data
.write_data_i (write_data),
.data_o (data_out)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
initial begin
@(posedge rst);
#(100);
@(posedge clk);
#1;
//for (i=1;i<`NUM_PAGES/2;i=i+1) write_page_addr((i*7123) % `NUM_PORTS,(i*7123) % `NUM_PAGES, (i*7123) % `NUM_PAGES );
for (i=1;i<`NUM_PAGES/2;i=i+1) write_page_addr((i*7123) % `NUM_PORTS, i , i);
#(1000);
@(posedge clk);
#1;
//for (i=1;i<`NUM_PAGES/2;i=i+1) pump_read_page_addr((i*7123) % `NUM_PORTS,(i*7123) % `NUM_PAGES );
for (i=1;i<`NUM_PAGES/2;i=i+1) pump_read_page_addr((i*7123) % `NUM_PORTS,i);
#(1000);
@(posedge clk);
#1;
//for (i=1;i<`NUM_PAGES/2;i=i+1) free_pck_read_page_addr((i*7123) % `NUM_PORTS,(i*7123) % `NUM_PAGES );
for (i=1;i<`NUM_PAGES/2;i=i+1) free_pck_read_page_addr((i*7123) % `NUM_PORTS,i );
#(1000);
@(posedge clk);
#1;
for (i=1;i<`NUM_PAGES/2;i=i+1)
begin
//free_pck_read_page_addr((i*7123) % `NUM_PORTS,(i*7123) % `NUM_PAGES );
//pump_read_page_addr ((i*7123) % `NUM_PORTS,(i*7123) % `NUM_PAGES );
free_pck_read_page_addr((i*7123) % `NUM_PORTS,i);
pump_read_page_addr ((i*7123) % `NUM_PORTS,i);
end
#(1000);
@(posedge clk);
#1;
for (i=1;i<`NUM_PAGES/2;i=i+1)
begin
//free_pck_read_page_addr((i*7123) % `NUM_PORTS,(i*7123) % `NUM_PAGES );
//pump_read_page_addr ((i*3456) % `NUM_PORTS,(i*3456) % `NUM_PAGES );
//write_free_page_addr ((i*9876) % `NUM_PORTS,(i*9876) % `NUM_PAGES );
free_pck_read_page_addr((i*7123) % `NUM_PORTS, i);
pump_read_page_addr ((i*3456) % `NUM_PORTS, i);
write_free_page_addr ((i*9876) % `NUM_PORTS, i);
end
#(1000);
@(posedge clk);
#1;
wait_cycles(1000);
end
always@(posedge clk)
begin
rq_write <= rq_write & (~done_write);
rq_free_page_write <= rq_free_page_write & (~done_free);
rq_read <= rq_read & (~done_read);
rq_free_pck_read <= rq_free_pck_read & (~done_free_pck);
end // UNMATCHED !!
endmodule // main
\ No newline at end of file
`timescale 1ns / 1ps
`define NUM_PORTS 11
`define NUM_PAGES 1024
`define PAGE_ADDR_BITS 10
`define USECNT_BITS 4
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
integer i, j;
integer fail = 0;
reg [`NUM_PORTS * `PAGE_ADDR_BITS - 1:0] ib_pgaddr_free = 0;
reg [`NUM_PORTS * `PAGE_ADDR_BITS - 1:0] ob_pgaddr_free = 0;
reg [`NUM_PORTS-1:0] ib_force_free = 0;
reg [`NUM_PORTS-1:0] ob_force_free = 0;
wire [`NUM_PORTS-1:0] ib_done_force_free;
wire [`NUM_PORTS-1:0] ob_done_force_free;
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
swc_multiport_lost_pck_dealloc
DUT (
.rst_n_i (rst),
.clk_i (clk),
.ib_force_free_i (ib_force_free),
.ib_force_free_done_o(ib_done_force_free),
.ib_pgaddr_free_i (ib_pgaddr_free),
.ob_force_free_i (ob_force_free),
.ob_force_free_done_o(ob_done_force_free),
.ob_pgaddr_free_i (ob_pgaddr_free)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
initial begin
@(posedge rst);
#(100);
@(posedge clk);
#1;
ib_pgaddr_free = 14234;
ob_pgaddr_free = 9764;
ib_force_free = 7777;
ob_force_free = 7777;
wait_cycles(1);
ib_force_free = 0;
ob_force_free = 0;
wait_cycles(100);
end
endmodule // main
`timescale 1ns / 1ps
`define NUM_PORTS 11
`define NUM_PAGES 1024
`define PAGE_ADDR_BITS 10
`define USECNT_BITS 4
`define CLK_PERIOD 10
`define wait_cycles(x) for(int iii=0;iii<x;iii++) @(posedge clk);
module main;
reg clk = 0;
reg rst = 0;
integer i, j;
integer fail = 0;
reg pq_write = 0;
reg pq_read = 0;
wire wr_en;
wire not_full;
wire not_empty;
wire [3:0] wr_addr;
wire [3:0] rd_addr;
swc_ob_prio_queue
DUT (
.rst_n_i (rst),
.clk_i (clk),
.write_i (pq_write),
.read_i (pq_read),
.not_full_o (not_full),
.not_empty_o (not_empty),
.wr_en_o (wr_en),
.wr_addr_o (wr_addr),
.rd_addr_o (rd_addr)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
initial begin
`wait_cycles(10);
pq_write = 1;
`wait_cycles(1);
pq_write = 0;
`wait_cycles(10);
pq_write = 1;
`wait_cycles(3);
pq_write = 0;
`wait_cycles(10);
pq_read = 1;
`wait_cycles(3);
pq_read = 0;
`wait_cycles(10);
pq_read = 1;
`wait_cycles(3);
pq_read = 0;
`wait_cycles(10);
pq_write = 1;
`wait_cycles(18);
pq_write = 0;
`wait_cycles(10);
end
endmodule // main
`timescale 1ns / 1ps
`define NUM_PORTS 11
`define NUM_PAGES 1024
`define PAGE_ADDR_BITS 10
`define USECNT_BITS 4
`define CLK_PERIOD 10
`define wait_cycles(x) for(int iii=0;iii<x;iii++) @(posedge clk);
module main;
parameter c_swc_num_ports = 11;
parameter c_swc_packet_mem_size = 65536;
parameter c_swc_packet_mem_multiply = 16;
parameter c_swc_data_width = 16;
parameter c_swc_ctrl_width = 4; //16;
parameter c_swc_page_size = 64;
parameter c_swc_packet_mem_num_pages = (c_swc_packet_mem_size / c_swc_page_size);
parameter c_swc_page_addr_width = 10; //$clog2(c_swc_packet_mem_num_pages-1);
parameter c_swc_usecount_width = 4; //$clog2(c_swc_num_ports-1);
parameter c_swc_page_offset_width = 2; //$clog2(c_swc_page_size / c_swc_packet_mem_multiply);
parameter c_swc_packet_mem_addr_width= c_swc_page_addr_width + c_swc_page_offset_width;
parameter c_swc_pump_width = c_swc_data_width + c_swc_ctrl_width;
parameter c_wrsw_prio_width = 3;
parameter c_swc_max_pck_size_width = 14;
reg clk = 0;
reg rst = 0;
integer i, j;
integer fail = 0;
reg pta_transfer_data_valid = 0;
reg [c_swc_page_addr_width - 1 : 0] pta_pageaddr = 0;
reg [c_wrsw_prio_width - 1 : 0] pta_prio = 0;
reg [c_swc_max_pck_size_width - 1 : 0] pta_pck_size = 0;
wire pta_transfer_data_ack;
wire mpm_pgreq;
wire [c_swc_page_addr_width - 1 : 0] mpm_pgaddr;
reg mpm_pckend = 0;
reg mpm_pgend = 0;
reg mpm_drdy = 0;
wire mpm_dreq;
reg [c_swc_data_width - 1 : 0] mpm_data = 0;
reg [c_swc_ctrl_width - 1 : 0] mpm_ctrl = 0;
wire rx_sof_p1;
wire rx_eof_p1;
reg rx_dreq = 0;
wire [c_swc_ctrl_width - 1 : 0] rx_ctrl;
wire [c_swc_data_width - 1 : 0] rx_data;
wire rx_valid;
wire rx_bytesel;
wire rx_idle;
wire rx_rerror_p1;
swc_output_block
DUT (
.rst_n_i (rst),
.clk_i (clk),
.pta_transfer_data_valid_i (pta_transfer_data_valid),
.pta_pageaddr_i (pta_pageaddr),
.pta_prio_i (pta_prio),
.pta_pck_size_i (pta_pck_size),
.pta_transfer_data_ack_o (pta_transfer_data_ack),
.mpm_pgreq_o (mpm_pgreq),
.mpm_pgaddr_o (mpm_pgaddr),
.mpm_pckend_i (mpm_pckend),
.mpm_pgend_i (mpm_pgend),
.mpm_drdy_i (mpm_drdy),
.mpm_dreq_o (mpm_dreq),
.mpm_data_i (mpm_data),
.mpm_ctrl_i (mpm_ctrl),
.rx_sof_p1_o (rx_sof_p1),
.rx_eof_p1_o (rx_eof_p1),
.rx_dreq_i (rx_dreq),
.rx_ctrl_o (rx_ctrl),
.rx_data_o (rx_data),
.rx_valid_o (rx_valid),
.rx_bytesel_o (rx_bytesel),
.rx_idle_o (rx_idle),
.rx_rerror_p1_o (rx_rerror_p1)
);
task write;
input [c_swc_page_addr_width - 1 : 0] pageaddr;
input [c_wrsw_prio_width - 1 : 0] prio ;
input [c_swc_max_pck_size_width - 1 : 0] pck_size;
begin : wait_body
integer i;
pta_pageaddr = pageaddr;
pta_prio = prio;
pta_pck_size = pck_size;
pta_transfer_data_valid = 1;
`wait_cycles(1);
pta_transfer_data_valid = 0;
end
endtask // wait_cycles
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
initial begin
integer i;
`wait_cycles(10);
for(i=0;i<10; i=i+1)
write(i,7,10);
for(i=0;i<10; i=i+1)
write(i,0,20);
for(i=0;i<10; i=i+1)
write(i,1,20);
for(i=0;i<10; i=i+1)
write(i,2,30);
`wait_cycles(10)
rx_dreq = 1;
mpm_drdy = 1;
`wait_cycles(10)
mpm_drdy = 0;
`wait_cycles(2);
mpm_drdy = 1;
`wait_cycles(50)
mpm_drdy = 0;
`wait_cycles(10)
end
endmodule // main
`timescale 1ns / 1ps
`define CLK_PERIOD 10
module main;
parameter c_swc_num_ports = 11;
parameter c_swc_packet_mem_size = 65536;
parameter c_swc_packet_mem_multiply = 16;
parameter c_swc_data_width = 16;
parameter c_swc_ctrl_width = 4; //16;
parameter c_swc_page_size = 64;
parameter c_swc_packet_mem_num_pages = (c_swc_packet_mem_size / c_swc_page_size);
parameter c_swc_page_addr_width = 10; //$clog2(c_swc_packet_mem_num_pages-1);
parameter c_swc_usecount_width = 4; //$clog2(c_swc_num_ports-1);
parameter c_swc_page_offset_width = 2; //$clog2(c_swc_page_size / c_swc_packet_mem_multiply);
parameter c_swc_packet_mem_addr_width= c_swc_page_addr_width + c_swc_page_offset_width;
parameter c_swc_pump_width = c_swc_data_width + c_swc_ctrl_width;
reg clk = 1;
reg rst = 0;
reg [c_swc_packet_mem_multiply - 1 : 0] sync = 1;
reg [c_swc_num_ports-1 : 0] wr_pagereq =0;
reg [c_swc_num_ports-1 : 0] wr_pckstart =0;
wire [c_swc_num_ports-1 : 0] wr_pageend;
reg [c_swc_num_ports * c_swc_page_addr_width - 1 : 0] wr_pageaddr =0;
reg [c_swc_num_ports-1 : 0] rd_pagereq =0;
wire [c_swc_num_ports-1 : 0] rd_pageend;
reg [c_swc_num_ports * c_swc_page_addr_width - 1 : 0] rd_pageaddr =0;
reg [c_swc_num_ports * c_swc_ctrl_width - 1 : 0] wr_ctrl = 0;
reg [c_swc_num_ports * c_swc_data_width - 1 : 0] wr_data = 0;
reg [c_swc_num_ports-1 : 0] wr_drdy =0;
wire [c_swc_num_ports-1 : 0] wr_full ;
reg [c_swc_num_ports-1 : 0] wr_flush =0;
reg [c_swc_num_ports-1 : 0] rd_dreq =0;
wire [c_swc_num_ports-1 : 0] rd_drdy;
reg [c_swc_num_ports-1 : 0] rd_sync_read =0;
wire [c_swc_num_ports * c_swc_ctrl_width - 1 : 0] rd_ctrl;
wire [c_swc_num_ports * c_swc_data_width - 1 : 0] rd_data;
wire [c_swc_num_ports-1 : 0] rd_pckend;
wire [c_swc_num_ports-1 : 0] rd_page_end;
swc_packet_mem DUT(
.clk_i (clk),
.rst_n_i (rst),
.wr_pagereq_i (wr_pagereq),
.wr_pageaddr_i (wr_pageaddr),
.wr_pckstart_i (wr_pckstart),
.wr_pageend_o (wr_pageend),
.wr_ctrl_i (wr_ctrl),
.wr_data_i (wr_data),
.wr_drdy_i (wr_drdy),
.wr_full_o (wr_full),
.wr_flush_i (wr_flush),
.rd_pagereq_i (rd_pagereq),
.rd_pageaddr_i (rd_pageaddr),
.rd_pageend_o (rd_page_end),
.rd_pckend_o (rd_pckend),
.rd_dreq_i (rd_dreq),
.rd_sync_read_i(rd_sync_read),
.rd_drdy_o (rd_drdy),
.rd_data_o (rd_data),
.rd_ctrl_o (rd_ctrl)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
`define array_copy(a, ah, al, b, bl) \
for (k=al; k<=ah; k=k+1) a[k] <= b[bl+k-al];
`define wait_cycles(x) for(int iii=0;iii<x;iii++) @(posedge clk);
task pktmem_write;
input [4:0] channel;
input [c_swc_data_width-1:0] data;
input [c_swc_ctrl_width-1:0] ctrl;
begin : wr_body
integer k;
while(wr_full[channel]) `wait_cycles(1)
$display("PKT_write: t %d chan %d data %x ctrl %x", $time, channel, data,ctrl);
`array_copy(wr_data, (c_swc_data_width * channel + c_swc_data_width -1), c_swc_data_width * channel, data, 0);
`array_copy(wr_ctrl, (c_swc_ctrl_width * channel + c_swc_ctrl_width -1), c_swc_ctrl_width * channel, ctrl, 0);
wr_drdy[channel] <= 1'b1;
`wait_cycles(1);
wr_drdy[channel] <= 1'b0;
end
endtask // pktmem_write
task pktmem_write_flush;
input [4:0] channel;
begin
if(wr_full[channel]) return;
wr_flush[channel] <= 1'b1;
`wait_cycles(1);
wr_flush[channel] <= 1'b0;
end
endtask // pktmem_write_flush
task pktmem_read;
input [4:0] channel;
input [10:0] count;
input [c_swc_data_width-1:0] data[0:c_swc_page_size -1];
input [c_swc_ctrl_width-1:0] ctrl[0:c_swc_page_size -1];
input [c_swc_page_addr_width-1:0] next_page=0;
begin : rd_body
integer k,n;
for (n=0;n<count;n=n+1) begin
// $display("read n=%d", n);
while(!rd_drdy[channel]) `wait_cycles(1);
rd_dreq[channel] <= rd_drdy[channel];
$display("rddata: %x", rd_data);
`array_copy(data[k], c_swc_data_width-1, 0, rd_data, c_swc_data_width * channel);
`array_copy(ctrl[k], c_swc_ctrl_width-1, 0, rd_ctrl, c_swc_ctrl_width * channel);
$display("read data %x", data[k]);
if(n==0) rd_sync_read<=1;
`wait_cycles(1);
rd_sync_read<=0;
end
end
endtask
integer i;
integer request_stuff = 0;
reg [c_swc_ctrl_width-1:0] cbuf[0:c_swc_page_size-1];
reg [c_swc_data_width-1:0] dbuf[0:c_swc_page_size-1];
reg dupa=0, cipa=0;
initial fork begin `wait_cycles(10); dupa = 1; end
begin `wait_cycles(50); cipa = 1; end join
initial begin
integer i;
`wait_cycles(10);
$display("ML: writing ......");
wr_pageaddr <= 4;
wr_pckstart[0] <=1;
wr_pagereq[0] <= 1;
for (i=3;i<200;i=i+1) begin
if(wr_pageend[0] & !wr_pagereq[0]) begin
wr_pagereq[0] <= 1;
wr_pageaddr <= wr_pageaddr + 1;
end
pktmem_write(0, i, 'hffff);
wr_pckstart[0] <= 0;
wr_pagereq[0] <= 0;
end
//for (i=3;i<62;i=i+1) pktmem_write(1, i, 'hffff);
//for (i=3;i<62;i=i+1) pktmem_write(i%16, i, 'hffff);
$display("ML: flusing writing ......");
pktmem_write_flush(0);
end
initial begin
integer i;
`wait_cycles(100);
$display("ML: reading ......");
rd_pageaddr <= 4;
rd_pagereq <= 11'b11111111111;
`wait_cycles(1);
rd_pagereq <=0;
pktmem_read(0, 60, dbuf,cbuf, 0);
end
endmodule // main
`timescale 1ns / 1ps
`define NUM_PAGES 2048
`define PAGE_ADDR_BITS 11
`define USE_COUNT_BITS 4
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
reg alloc = 0;
reg free = 0;
wire idle;
wire nomem;
reg [`USE_COUNT_BITS-1:0] use_cnt;
wire [`PAGE_ADDR_BITS-1:0] pgaddr_o;
reg [`PAGE_ADDR_BITS-1:0] pgaddr_i=0;
wire pgaddr_valid;
reg force_free = 0;
reg set_usecnt = 0;
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
swc_page_allocator #(
.g_num_pages (`NUM_PAGES),
.g_page_addr_bits (`PAGE_ADDR_BITS),
.g_use_count_bits (`USE_COUNT_BITS))
dut (
.clk_i (clk),
.rst_n_i (rst),
.alloc_i (alloc),
.free_i (free),
.force_free_i (force_free),
.set_usecnt_i (set_usecnt),
.pgaddr_i (pgaddr_i),
.usecnt_i (use_cnt),
.pgaddr_o (pgaddr_o),
.nomem_o (nomem),
.pgaddr_valid_o(pgaddr_valid),
.idle_o (idle)
);
task alloc_page;
input [`USE_COUNT_BITS:0] cnt;
output[`PAGE_ADDR_BITS:0] pageaddr;
begin
if(nomem) begin
$display("alloc_page: no more free pages left");
$finish;
end else begin
use_cnt = cnt;
alloc <= 1;
@(posedge clk); #1;
alloc <= 0;
while(idle == 0) begin
if(pgaddr_valid) pageaddr <= pgaddr_o;
@(posedge clk); #1;
end
end
end
endtask // allocate_page
task free_page;
input[`PAGE_ADDR_BITS:0] pageaddr;
begin
pgaddr_i = pageaddr;
free <= 1;
@(posedge clk); #1;
free <= 0;
while(idle == 0)
begin
@(posedge clk); #1;
end
end
endtask
task set_usecount;
input [`USE_COUNT_BITS:0] cnt;
input [`PAGE_ADDR_BITS:0] pageaddr;
begin
pgaddr_i = pageaddr;
use_cnt = cnt;
set_usecnt <= 1;
@(posedge clk); #1;
set_usecnt <= 0;
while(idle == 0)
begin
@(posedge clk); #1;
end
end
endtask
task force_free_page;
input[`PAGE_ADDR_BITS:0] pageaddr;
begin
pgaddr_i = pageaddr;
force_free <= 1;
@(posedge clk); #1;
force_free <= 0;
while(idle == 0)
begin
@(posedge clk); #1;
end
end
endtask
integer i;
integer n;
initial begin
@(posedge rst); @(posedge clk);#1;
for (i=0;i<200;i=i+1) begin
alloc_page(1,n);
$display(n);
end
for(i=0;i<200;i=i+1) free_page(i);
for (i=0;i<200;i=i+1) begin
alloc_page(1,n);
$display(n);
end
//set_usecount(5,5);
//set_usecount(30,1);
//set_usecount(55,10);
//set_usecount(100,2);
@(posedge clk);#1;
free_page(10);
free_page(50);
free_page(80);
@(posedge clk);#1;
alloc_page(1,n);
set_usecount(3,n);
free_page(n);
free_page(n);
free_page(n);
alloc_page(1,n);
set_usecount(3,n);
force_free_page(n);
alloc_page(1,n);
free_page(n);
force_free_page(100);
force_free_page(90);
force_free_page(20);
alloc_page(1, n); $display(n);
alloc_page(1, n); $display(n);
alloc_page(1, n); $display(n);
end
endmodule // main
`timescale 1ns / 1ps
`define CLK_PERIOD 10
`define wait_cycles(x) for(int iii=0;iii<x;iii++) @(posedge clk);
`define array_copy(a, ah, al, b, bl) \
for (k=al; k<=ah; k=k+1) a[k] <= b[bl+k-al];
module main;
integer start = 0;
parameter c_swc_num_ports = 11;
parameter c_swc_packet_mem_size = 65536;
parameter c_swc_packet_mem_multiply = 16;
parameter c_swc_data_width = 16;
parameter c_swc_ctrl_width = 16;
parameter c_swc_page_size = 64;
parameter c_swc_prio_width = 3;
parameter c_swc_packet_mem_num_pages = (c_swc_packet_mem_size / c_swc_page_size);
parameter c_swc_page_addr_width = 10; //$clog2(c_swc_packet_mem_num_pages-1);
parameter c_swc_usecount_width = 4; //$clog2(c_swc_num_ports-1);
parameter c_swc_page_offset_width = 2; //$clog2(c_swc_page_size / c_swc_packet_mem_multiply);
parameter c_swc_packet_mem_addr_width= c_swc_page_addr_width + c_swc_page_offset_width;
parameter c_swc_pump_width = c_swc_data_width + c_swc_ctrl_width;
reg clk = 1;
reg rst = 0;
reg [c_swc_num_ports -1 : 0] ob_data_valid_d1=0;
wire [c_swc_num_ports -1 : 0] ob_data_valid;
reg [c_swc_num_ports -1 : 0] ob_ack = 0;
wire [c_swc_num_ports*c_swc_page_addr_width -1 : 0] ob_pageaddr;
wire [c_swc_num_ports * c_swc_prio_width - 1 : 0] ob_prio;
reg [c_swc_num_ports -1 : 0] ib_transfer_pck = 0;
wire [c_swc_num_ports -1 : 0] ib_transfer_ack;
wire [c_swc_num_ports -1 : 0] ib_busy;
reg [c_swc_num_ports*c_swc_page_addr_width - 1 : 0]ib_pageaddr = 0;
reg [c_swc_num_ports*c_swc_num_ports - 1 : 0]ib_mask = 0;
reg [c_swc_num_ports * c_swc_prio_width - 1 : 0]ib_prio = 0;
swc_pck_transfer_arbiter DUT(
.clk_i (clk),
.rst_n_i (rst),
.ob_data_valid_o (ob_data_valid),
.ob_ack_i (ob_ack),
.ob_pageaddr_o (ob_pageaddr),
.ob_prio_o (ob_prio),
.ib_transfer_pck_i (ib_transfer_pck),
.ib_transfer_ack_o (ib_transfer_ack),
.ib_busy_o (ib_busy),
.ib_pageaddr_i (ib_pageaddr),
.ib_mask_i (ib_mask),
.ib_prio_i (ib_prio)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
task pck_transfer_write;
input [4:0] channel;
input [c_swc_page_addr_width - 1 : 0] pageaddr;
input [c_swc_num_ports - 1 : 0] mask;
input [c_swc_prio_width - 1 : 0] prio;
begin : wr_body
integer k,i;
while (ib_busy[channel] == 1) `wait_cycles(1);
if(ib_transfer_ack[channel] == 1 ) ib_transfer_pck[channel] <= 0; else `wait_cycles(1);
$display("Transfering page : input block = %d; addr = %d (0x%x) mask = %x prio = %x \n",channel, pageaddr,pageaddr,mask,prio);
`array_copy(ib_pageaddr, (c_swc_page_addr_width * channel + c_swc_page_addr_width -1), c_swc_page_addr_width * channel, pageaddr, 0);
`array_copy(ib_mask, (c_swc_num_ports * channel + c_swc_num_ports -1), c_swc_num_ports * channel, mask , 0);
`array_copy(ib_prio, (c_swc_prio_width * channel + c_swc_prio_width -1), c_swc_prio_width * channel, prio , 0);
`wait_cycles(1);
ib_transfer_pck[channel] <= 1;
`wait_cycles(1);
// while(ib_transfer_ack[channel] == 0 ) `wait_cycles(1);
ib_transfer_pck[channel] <= 0;
end
endtask // pck_transfer_write
task pck_transfer_write_set;
input [4:0] channel;
input [c_swc_page_addr_width - 1 : 0] pageaddr;
input [c_swc_num_ports - 1 : 0] mask;
input [c_swc_prio_width - 1 : 0] prio;
begin : wr_body
integer k,i;
$display("Transfering page : input block = %d; addr = %d (0x%x) mask = %x prio = %x \n",channel, pageaddr,pageaddr,mask,prio);
`array_copy(ib_pageaddr, (c_swc_page_addr_width * channel + c_swc_page_addr_width -1), c_swc_page_addr_width * channel, pageaddr, 0);
`array_copy(ib_mask, (c_swc_num_ports * channel + c_swc_num_ports -1), c_swc_num_ports * channel, mask , 0);
`array_copy(ib_prio, (c_swc_prio_width * channel + c_swc_prio_width -1), c_swc_prio_width * channel, prio , 0);
end
endtask // pck_transfer_write
task pck_transfer_read;
input [4:0] channel;
output [c_swc_page_addr_width - 1 : 0] pageaddr;
output [c_swc_prio_width - 1 : 0] prio;
begin : wr_body
integer k,i;
if(ob_data_valid[channel] == 1 && ob_ack[channel] == 0 && start == 1)
begin
`array_copy(pageaddr, c_swc_page_addr_width - 1 , 0, ob_pageaddr, (c_swc_page_addr_width * channel ));
`array_copy(prio , c_swc_prio_width - 1 , 0, ob_prio , (c_swc_prio_width * channel ));
// `wait_cycles(3);
ob_ack[channel] <= 1;
`wait_cycles(1);
ob_ack[channel] <= 0;
$display("Transfering page: output block = %d addr = %x prio = %x [prio= %x, addr = %x] (%x) \n",channel, pageaddr,prio, ob_prio, ob_pageaddr,ob_data_valid_d1);
end
else
begin
ob_ack[channel] <= 0;
`wait_cycles(1) ;
end
end
endtask // pck_transfer_write
task pck_transfer_read_all_ch;
output [c_swc_page_addr_width - 1 : 0] pageaddr;
output [c_swc_prio_width - 1 : 0] prio;
begin : wr_body
integer k,i;
$display("------------------------------------------------------------------------------------ \n",);
for (i=0;i<11;i=i+1)
ob_ack[i] <= 1;
for (i=0;i<11;i=i+1)
begin
`array_copy(pageaddr, c_swc_page_addr_width - 1 , 0, ob_pageaddr, (c_swc_page_addr_width * i ));
`array_copy(prio , c_swc_prio_width - 1 , 0, ob_prio , (c_swc_prio_width * i ));
$display("Transfering page: output block = %d addr = %d prio = %x [prio= %x, addr = %x] \n",i, pageaddr,prio, ob_prio, ob_pageaddr);
end
`wait_cycles(1);
for (i=0;i<11;i=i+1)
ob_ack[i] <= 0;
$display("------------------------------------------------------------------------------------ \n",);
end
endtask // pck_transfer_write
integer i;
integer x,y;
initial begin
integer i;
`wait_cycles(4);
rst = 1;
`wait_cycles(10);
/*
task pck_transfer_write;
input [4:0] channel;
input [c_swc_page_addr_width - 1 : 0] pageaddr;
input [c_swc_num_ports - 1 : 0] mask;
input [c_swc_prio_width - 1 : 0] prio;
*/
start = 1;
/*
ib_transfer_pck[0] <= 1;
ib_transfer_pck[1] <= 1;
ib_transfer_pck[2] <= 1;
ib_transfer_pck[4] <= 1;
ib_transfer_pck[5] <= 1;
ib_transfer_pck[6] <= 1;
pck_transfer_write(0,11, 1, 1);
pck_transfer_write(1,11, 1, 2);
pck_transfer_write(2,11, 1, 3);
pck_transfer_write(4,11, 1, 3);
pck_transfer_write(5,11, 1, 3);
pck_transfer_write(6,11, 1, 3);
`wait_cycles(1);
ib_transfer_pck[0] <= 0;
ib_transfer_pck[1] <= 0;
ib_transfer_pck[2] <= 0;
ib_transfer_pck[4] <= 0;
ib_transfer_pck[5] <= 0;
ib_transfer_pck[6] <= 0;
*/
// pck_transfer_write(0,11, 2047, 7);
pck_transfer_write(0, 10, 2047, 3);
pck_transfer_write(1, 11, 2047, 1);
pck_transfer_write(2, 12, 2047, 2);
pck_transfer_write(3, 13, 2047, 3);
pck_transfer_write(4, 14, 2047, 4);
pck_transfer_write(5, 15, 2047, 5);
pck_transfer_write(6, 16, 2047, 6);
pck_transfer_write(7, 17, 2047, 7);
pck_transfer_write(8, 18, 2047, 1);
pck_transfer_write(9, 19, 2047, 2);
pck_transfer_write(10,20, 2047, 3);
`wait_cycles(20);
// start = 1;
`wait_cycles(100);
/*
pck_transfer_read(0,x ,y );
pck_transfer_read(1,x ,y );
pck_transfer_read(2,x ,y );
pck_transfer_read(3,x ,y );
pck_transfer_read(4,x ,y );
pck_transfer_read(5,x ,y );
pck_transfer_read(6,x ,y );
pck_transfer_read(7,x ,y );
pck_transfer_read(8,x ,y );
pck_transfer_read(9,x ,y );
pck_transfer_read(10,x ,y );
*/
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
// `wait_cycles(1);
pck_transfer_read_all_ch(x,y);
`wait_cycles(100);
end
/*
always begin
integer x,y;
pck_transfer_read(0,x ,y );
end
always begin
integer x,y;
pck_transfer_read(1,x ,y );
end
always begin
integer x,y;
pck_transfer_read(2,x ,y );
end
always begin
integer x,y;
pck_transfer_read(3,x ,y );
end
always begin
integer x,y;
pck_transfer_read(4,x ,y );
end
always begin
integer x,y;
pck_transfer_read(5,x ,y );
end
always begin
integer x,y;
pck_transfer_read(6,x ,y );
end
always begin
integer x,y;
pck_transfer_read(7,x ,y );
end
always begin
integer x,y;
pck_transfer_read(8,x ,y );
end
always begin
integer x,y;
pck_transfer_read(9,x ,y );
end
always begin
integer x,y;
pck_transfer_read(10,x ,y );
end
*/
endmodule // main
`timescale 1ns / 1ps
`define CLK_PERIOD 10
`define wait_cycles(x) for(int iii=0;iii<x;iii++) @(posedge clk);
module main;
parameter c_swc_num_ports = 11;
parameter c_swc_packet_mem_size = 65536;
parameter c_swc_packet_mem_multiply = 16;
parameter c_swc_data_width = 16;
parameter c_swc_ctrl_width = 16;
parameter c_swc_page_size = 64;
parameter c_swc_prio_width = 3;
parameter c_swc_packet_mem_num_pages = (c_swc_packet_mem_size / c_swc_page_size);
parameter c_swc_page_addr_width = 10; //$clog2(c_swc_packet_mem_num_pages-1);
parameter c_swc_usecount_width = 4; //$clog2(c_swc_num_ports-1);
parameter c_swc_page_offset_width = 2; //$clog2(c_swc_page_size / c_swc_packet_mem_multiply);
parameter c_swc_packet_mem_addr_width= c_swc_page_addr_width + c_swc_page_offset_width;
parameter c_swc_pump_width = c_swc_data_width + c_swc_ctrl_width;
reg clk = 1;
reg rst = 0;
wire ob_transfer_pck ;
wire [c_swc_page_addr_width - 1 : 0] ob_pageaddr ;
wire [c_swc_num_ports - 1 : 0] ob_output_mask ;
reg [c_swc_num_ports - 1 : 0] ob_read_mask = 0;
wire [c_swc_prio_width - 1 : 0] ob_prio ;
reg pta_transfer_pck = 0;
reg [c_swc_page_addr_width - 1 : 0] pta_pageaddr = 0;
reg [c_swc_num_ports - 1 : 0] pta_mask = 0;
reg [c_swc_prio_width - 1 : 0] pta_prio = 0;
wire pta_transfer_ack;
swc_pck_transfer_input DUT(
.clk_i (clk),
.rst_n_i (rst),
.pto_transfer_pck_o (ob_transfer_pck),
.pto_pageaddr_o (ob_pageaddr),
.pto_output_mask_o (ob_output_mask),
.pto_read_mask_i (ob_read_mask),
.pto_prio_o (ob_prio),
.ib_transfer_pck_i(pta_transfer_pck),
.ib_pageaddr_i (pta_pageaddr),
.ib_mask_i (pta_mask),
.ib_prio_i (pta_prio),
.ib_transfer_ack_o(pta_transfer_ack)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
task pck_transfer_write;
input [c_swc_page_addr_width - 1 : 0] pageaddr;
input [c_swc_num_ports - 1 : 0] mask;
input [c_swc_prio_width - 1 : 0] prio;
begin : wr_body
integer k;
$display("Transfering page: addr = %x mask = %x prio = %x ", pta_pageaddr,pta_mask,pta_prio);
pta_transfer_pck = 1;
pta_pageaddr = pageaddr;
pta_mask = mask;
pta_prio = prio;
`wait_cycles(1);
pta_transfer_pck = 0;
end
endtask // pck_transfer_write
task pck_transfer_read;
input [4:0] channel;
begin : wr_body
integer k,i;
ob_read_mask <= channel;
// for (i = 0; i < c_swc_num_ports ; i = i + 1)
// begin
// if(i==3) ob_read_mask(i) <= 1 ;
// if(i != 3) ob_read_mask(i) <= 0 ;
// end
`wait_cycles(1);
ob_read_mask <= 0;
// for (i = 0; i < c_swc_num_ports; i = i + 1) begin
// ob_read_mask(i) <= 0;
// end
$display("Transfering page: addr = %x prio = %x ", ob_pageaddr,ob_prio);
end
endtask // pck_transfer_write
integer i;
initial begin
integer i;
`wait_cycles(4);
rst = 1;
`wait_cycles(10);
pck_transfer_write(123, 5, 2);
`wait_cycles(10);
pck_transfer_read(2);
`wait_cycles(10);
pck_transfer_read(4);
`wait_cycles(10);
pck_transfer_read(1);
end
endmodule // main
`timescale 1ns / 1ps
`define INPUT_SIZE 36
`define OUTPUT_BITS 6
module main;
reg [`INPUT_SIZE-1:0] a = 0;
wire [`OUTPUT_BITS-1:0] q ;
integer i, j;
integer fail = 0;
swc_prio_encoder #(
.g_num_inputs(`INPUT_SIZE),
.g_output_bits(`OUTPUT_BITS))
dut (
.in_i(a),
.out_o(q)
);
initial begin
for(i=0;i<`INPUT_SIZE;i=i+1) begin
a[i] = 1'b1;
if(i>0) for (j=0;j<=i-1;j=j+1) a[j] = 1'b0;
if(i<`INPUT_SIZE-1) for(j=i+1; j<`INPUT_SIZE; j=j+1) a[j] = $random;
#200;
if(i!=q) begin
$display(i,"!=",q);
fail = 1;
end
end
if(!fail)
$display("test passed");
else
$display("test failed");
end
endmodule // main
`timescale 1ns / 1ps
`define PAGE_ADDR_BITS 10
`define PAGE_SIZE 128
`define OUTPUT_WIDTH (16 + 4)//32
`define MULTIPLY 16
`define FBRAM_SIZE 256
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
reg [`PAGE_ADDR_BITS-1:0] page_addr=0;
reg page_req = 0;
wire pgend;
wire drdy;
reg dreq = 0;
reg [15:0] sync = 11'b00010000000;
wire [11:0]addr;
reg [11:0]fb_sram_addr;
wire [`OUTPUT_WIDTH-1:0] d;
reg [`OUTPUT_WIDTH * `MULTIPLY - 1:0] q;
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
wire page_done;
wire pckend;
wire [`PAGE_ADDR_BITS-1 : 0] current_page_addr ;
reg [`PAGE_ADDR_BITS-1 : 0] next_page_addr = 0;
reg [`FBRAM_SIZE - 1 : 0][`OUTPUT_WIDTH * `MULTIPLY - 1:0] fbsram ;
reg [`FBRAM_SIZE - 1 : 0][`PAGE_ADDR_BITS - 1 : 0] llsram ;
wire read_req;
reg read_data_valid = 0;
swc_packet_mem_read_pump
DUT (
.clk_i (clk),
.rst_n_i (rst),
.pgaddr_i (page_addr),
.pgreq_i (page_req),
.pgend_o (pgend),
.pckend_o (pckend),
.drdy_o (drdy),
.dreq_i (dreq),
.sync_i (sync[0]),
.ll_read_addr_o(current_page_addr),
.ll_read_data_i(next_page_addr),
.ll_read_req_o(read_req),
.ll_read_valid_data_i(read_data_valid),
.addr_o(addr),
.d_o(d),
.q_i(q)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
task set_page_addr;
input [11 : 0] in;
begin : wr_body
page_req <= 1;
page_addr <= in;
wait_cycles(1);
page_req <= 0;
end
endtask // write_data
task read_data;
output [`OUTPUT_WIDTH - 1 : 0] out;
begin : wr_body
dreq <= 1;
while(!drdy) wait_cycles(1);
out <= out;
wait_cycles(1);
dreq <= 0;
end
endtask // write_data
integer i, n, m,z, cnt = 0;
integer readout[48];
integer page = 8;
initial begin
llsram[0] = `PAGE_ADDR_BITS'h3;
for (n = 0; n < `FBRAM_SIZE; n = n + 1) begin
fbsram[n] = 512'h0;
for (m = 0; m < `MULTIPLY; m = m + 1) begin
fbsram[n] = cnt << (m*`OUTPUT_WIDTH) | fbsram[n];
cnt = cnt + 1;
end;
if(n != 0) llsram[n] = (llsram[n-1] + 3) % (`FBRAM_SIZE / 4);
$display("cnt = %p; fbsram[%p] = %x, llsram[%p] = %x",cnt, n, fbsram[n],n,llsram[n]);
end;
for(z = 0; z < `PAGE_ADDR_BITS; z++) llsram[30][z] = 1;
for(z = 0; z < `PAGE_ADDR_BITS; z++) llsram[4][z] = 1;
for (n = 0; n < `FBRAM_SIZE; n = n + 1) begin
$display("WTF: llsram[%p] = %x",n,llsram[n]);
end;
wait_cycles(10);
set_page_addr(2);
wait_cycles(3);
for (n =0; n<20;n=n+1) begin
wait_cycles(n);
for (i=0;i<88;i=i+1) begin
if(pckend == 1 && (page < 9 || page > 20)) set_page_addr(page++);
else if(pckend == 1 ) page++;
read_data(readout[i]);
end;
wait_cycles(1);
end
end
reg [4:0] r;
always@(posedge clk) begin
if(drdy) begin
end
end
always@(posedge clk) begin
if(sync[0])
fb_sram_addr <= addr;
else
fb_sram_addr <= 15;
end
always@(posedge clk) begin
if(sync[1])
q <= fbsram[addr];
else
q <= fbsram[15];
end
// always@(posedge clk) begin
// next_page_addr <= llsram[current_page_addr];
// end
always@(posedge clk) sync <= {sync[0], sync[15:1]};
always@(posedge clk) begin
if(read_req) begin
$display("page read request");
wait_cycles(4);
read_data_valid <=1;
next_page_addr <= llsram[current_page_addr];
wait_cycles(1);
read_data_valid <=0;
end
end
endmodule // main
`timescale 1ns / 1ps
`define PAGE_ADDR_BITS 10
`define PAGE_SIZE 128
`define OUTPUT_WIDTH 32
`define MULTIPLY 16
`define FBRAM_SIZE 16
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
reg [`PAGE_ADDR_BITS-1:0] page_addr=0;
reg page_req = 0;
wire pgend;
wire drdy;
reg [15:0] sync = 11'b00010000000;
wire [`OUTPUT_WIDTH-1:0] d;
reg [`OUTPUT_WIDTH * `MULTIPLY - 1:0] q;
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
wire page_done;
swc_packet_mem_read_pump
DUT (
.clk_i (clk),
.rst_n_i (rst),
.pgaddr_i (page_addr),
.pgreq_i (page_req),
.pgend_o (pgend),
.drdy_o (drdy),
.dreq_i (dreq),
.sync_i (sync[0]),
.d_o(d),
.q_i(q)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
task read_data;
output [`OUTPUT_WIDTH - 1 : 0] out;
begin : wr_body
dreq <= 1;
while(!drdy) wait_cycles(1);
out <= out;
wait_cycles(1);
dreq <= 0;
end
endtask // write_data
integer i, n, m, cnt = 0;
integer readout[48];
initial begin
wait_cycles(10);
q <= 512'h000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e;
// for (n = 0; n < FBRAM_SIZE; n = n + 1) begin
// for (m = 0; m < FBRAM_SIZE * MULTIPLY; m = m + 1) begin
// q[n] = (cnt << m) || q[n];
// cnt = cnt + 1;
// end;
// end;
for (n =0; n<17;n=n+1) begin
wait_cycles(n);
for (i=0;i<48;i=i+1)
read_data(readout[i]);
flush <= 1;
wait_cycles(1);
flush <= 0;
end
end
reg [4:0] r;
always@(posedge clk) begin
if(we) begin
$display("write %x",q);
end
end
always@(posedge clk) sync <= {sync[0], sync[15:1]};
endmodule // main
`timescale 1ns / 1ps
`define INPUT_SIZE 22
`define INPUT_SIZE_LOG2 5
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
reg [`INPUT_SIZE-1:0] rq = 0;
wire next;
wire [`INPUT_SIZE_LOG2-1 : 0] grant;
wire grant_valid;
integer i, j;
integer fail = 0;
swc_rr_arbiter
#(
.g_num_ports(`INPUT_SIZE),
.g_num_ports_log2(`INPUT_SIZE_LOG2))
dut (
.rst_n_i (rst),
.clk_i (clk),
.next_i (next),
.request_i (rq),
.grant_o (grant),
.grant_valid_o (grant_valid)
);
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
initial begin
@(posedge rst);
#(100);
@(posedge clk);
#1;
rq = 'b00101010011110001001;
$display("RQ?");
end
integer idx;
always@(posedge clk)
begin
if(grant_valid) begin
$display("Grant: %d", grant);
rq[grant] <= 0;
idx = $random % grant;
rq[idx] <= 1'b1;
end
end
assign next = grant_valid;
endmodule // main
`timescale 1ns / 1ps
`define PAGE_ADDR_BITS 10
`define PAGE_SIZE 128
`define INPUT_WIDTH 20
`define MULTIPLY 16
`define CLK_PERIOD 10
module main;
reg clk = 0;
reg rst = 0;
reg [`INPUT_WIDTH-1:0] d;
wire reg_full ;
reg flush = 0;
reg [15:0] sync = 11'b00010000000;
wire [`INPUT_WIDTH * `MULTIPLY - 1:0] q;
wire we;
reg drdy =0;
wire pgend;
reg pckstart = 0;
always #(`CLK_PERIOD/2) clk = ~clk;
initial #(`CLK_PERIOD*2) rst = 1;
reg [`PAGE_ADDR_BITS-1:0] page_addr=0;
reg page_req = 0;
wire page_done;
wire [`PAGE_ADDR_BITS-1:0] current_page_addr;
wire [`PAGE_ADDR_BITS-1:0] next_page_addr;
wire next_page_addr_wr_req;
reg next_page_addr_wr_done = 0;
swc_packet_mem_write_pump
DUT (
.clk_i (clk),
.rst_n_i (rst),
.pgaddr_i (page_addr),
.pgreq_i (page_req),
.pgend_o (pgend),
.pckstart_i (pckstart),
.drdy_i (drdy),
.full_o (reg_full),
.flush_i (flush),
.sync_i (sync[0]),
.ll_addr_o (current_page_addr),
.ll_data_o (next_page_addr),
.ll_wr_req_o (next_page_addr_wr_req),
.ll_wr_done_i(next_page_addr_wr_done),
.d_i (d),
.q_o (q),
.we_o (we)
);
task wait_cycles;
input [31:0] ncycles;
begin : wait_body
integer i;
for(i=0;i<ncycles;i=i+1) @(posedge clk);
end
endtask // wait_cycles
task write_data;
input [`INPUT_WIDTH - 1 : 0] in;
begin : wr_body
while(reg_full) wait_cycles(1);
d <= in;
drdy <= 1;
wait_cycles(1);
drdy <= 0;
end
endtask // write_data
integer i, n;
initial begin
// page_addr <= 3;
wait_cycles(10);
// write first page number
// page_req <= 1;
// pckstart <=1;
// wait_cycles(1);
// page_req <= 0;
// pckstart <=0;
for (n =0; n<17;n=n+1) begin
wait_cycles(1);
while(reg_full) wait_cycles(1);
wait_cycles(n);
if(n%5 == 0) begin
page_addr <= page_addr + 4;
page_req <= 1;
end
pckstart <=1;
for (i=1;i<100;i=i+1) begin
if(n%5 != 0 && i == 5) begin
page_addr <= page_addr + 4;
page_req <= 1;
end
if(pgend & !page_req) begin
page_req <= 1;
page_addr <= page_addr + 1;
end
write_data(i);
page_req <= 0;
pckstart <=0;
end
flush <= 1;
drdy <= 1;
wait_cycles(1);
flush <= 0;
drdy <= 0;
end
end
reg [4:0] r;
always@(posedge clk) begin
if(we) begin
$display("write %x",q);
end
end
always@(posedge clk) sync <= {sync[0], sync[15:1]};
//initial begin
always@(posedge clk) begin
if(next_page_addr_wr_req) begin
$display("page write request");
wait_cycles(4);
next_page_addr_wr_done <=1;
wait_cycles(1);
next_page_addr_wr_done <=0;
end
end
endmodule // main
# Current time Mon Oct 18 18:05:56 2010
# ModelSim Stack Trace
# Program = vish
# Id = "6.6a"
# Version = "2010.03"
# Date = "Mar 19 2010"
# Platform = linux
# 0 0x08184ff0: 'treew_TriggerEventQ + 0x160' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 1 0x0812ded3: 'name_ValueCancelPendingEvents + 0x1043' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 2 0x083b138c: 'TclServiceIdle + 0x48' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 3 0x083a3a99: 'Tcl_DoOneEvent + 0x1ad' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 4 0x082cd87d: 'Tk_MainLoop + 0x19' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 5 0x082d4a50: 'Tk_MainEx + 0x298' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 6 0x0816b0e8: 'vish_inner_loop + 0x238' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 7 0x0816bde2: 'main + 0x862' in '/opt/modeltech/modeltech/bin/../linux/vish'
# 8 0xb74ddbd1: '_libc_start_main + 0xe1' in '/lib/tls/i686/cmov/libc.so.6'
# 9 0x080bc3fc: 'start + 0x1c' in '/opt/modeltech/modeltech/bin/../linux/vish'
# End of Stack Trace
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -format Logic /main/clk
add wave -noupdate -format Logic /main/rst
add wave -noupdate -format Logic /main/stb
add wave -noupdate -format Logic /main/cyc
add wave -noupdate -format Logic /main/we
add wave -noupdate -format Literal /main/addr
add wave -noupdate -format Literal /main/data_o
add wave -noupdate -format Literal /main/data_i
add wave -noupdate -format Logic /main/stall
add wave -noupdate -format Logic /main/ack
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {505000 ps} 0}
configure wave -namecolwidth 362
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
update
WaveRestoreZoom {0 ps} {3681818 ps}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment