1//
2// Copyright 2019 Ettus Research, A National Instruments Company
3//
4// SPDX-License-Identifier: LGPL-3.0-or-later
5//
6// Module: lossy_xport_model
7//
8
9module lossy_xport_model #(
10  parameter CHDR_W = 256
11)(
12  input  wire              clk,
13  input  wire              rst,
14  input  wire [CHDR_W-1:0] s_axis_tdata,
15  input  wire              s_axis_tlast,
16  input  wire              s_axis_tvalid,
17  output wire              s_axis_tready,
18  output wire [CHDR_W-1:0] m_axis_tdata,
19  output wire              m_axis_tlast,
20  output wire              m_axis_tvalid,
21  input  wire              m_axis_tready,
22  input  wire [7:0]        seqerr_prob,
23  input  wire [7:0]        rterr_prob,
24  input  wire              lossy
25);
26  wire [CHDR_W-1:0] tmp_tdata;
27  wire              tmp_tlast;
28  wire              tmp_tvalid;
29  wire              tmp_tready;
30
31  reg pkt_header = 1'b1;
32  always @(posedge clk) begin
33    if (rst) begin
34      pkt_header <= 1'b1;
35    end else if (s_axis_tvalid && s_axis_tready) begin
36      pkt_header <= s_axis_tlast;
37    end
38  end
39  wire pkt_stb = (s_axis_tvalid && s_axis_tready && s_axis_tlast);
40
41  reg force_seq_err, force_route_err;
42  always @(pkt_stb or seqerr_prob) begin
43    force_seq_err = ($urandom_range(99) < seqerr_prob);
44  end
45  always @(pkt_stb or rterr_prob) begin
46    force_route_err = ($urandom_range(99) < rterr_prob);
47  end
48
49  wire [15:0] new_seq_num  = s_axis_tdata[47:32] + 16'd1;   //Increment SeqNum
50  wire [15:0] new_dst_epid = ~s_axis_tdata[15:0];           //Invert DstEPID
51
52  assign tmp_tdata = !pkt_header ? s_axis_tdata : (
53    force_seq_err ? {s_axis_tdata[CHDR_W-1:48], new_seq_num, s_axis_tdata[31:0]} : (
54      force_route_err ? {s_axis_tdata[CHDR_W-1:16], new_dst_epid} : s_axis_tdata));
55  assign tmp_tlast  = s_axis_tlast;
56  assign tmp_tvalid = s_axis_tvalid;
57  assign s_axis_tready = lossy || tmp_tready;
58
59  axi_fifo #(.WIDTH(CHDR_W+1), .SIZE(1)) out_fifo (
60    .clk(clk), .reset(rst), .clear(1'b0),
61    .i_tdata({tmp_tlast, tmp_tdata}), .i_tvalid(tmp_tvalid), .i_tready(tmp_tready),
62    .o_tdata({m_axis_tlast, m_axis_tdata}), .o_tvalid(m_axis_tvalid), .o_tready(m_axis_tready),
63    .space(), .occupied()
64  );
65
66endmodule