File: sim_cvita_lib.svh

package info (click to toggle)
uhd 3.9.5-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 107,272 kB
  • ctags: 57,231
  • sloc: cpp: 66,160; ansic: 59,349; python: 13,245; vhdl: 7,651; tcl: 2,668; sh: 1,634; makefile: 1,031; xml: 557; pascal: 230; csh: 94; asm: 20; perl: 11
file content (211 lines) | stat: -rw-r--r-- 6,013 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//
// Copyright 2015 Ettus Research LLC
//

`include "sim_axis_lib.svh"

typedef enum logic [1:0] {
  DATA=2'b00, FC=2'b01, CMD=2'b10, RESP=2'b11
} cvita_pkt_t;
  
typedef struct packed {
  logic [31:0]  sid;
  logic [15:0]  length;
  logic [11:0]  seqno;
  logic         eob;
  logic         has_time;
  cvita_pkt_t   pkt_type;
  logic [63:0]  timestamp;
} cvita_hdr_t;

function logic[63:0] flatten_chdr_no_ts(input cvita_hdr_t hdr);
  return {hdr.pkt_type, hdr.has_time, hdr.eob, hdr.seqno, hdr.length, hdr.sid};
endfunction

//TODO: This should be a function but it segfaults XSIM.
task automatic unflatten_chdr_no_ts;
  input logic[63:0] hdr_bits;
  output cvita_hdr_t hdr;
  begin
    hdr = '{
      pkt_type:cvita_pkt_t'(hdr_bits[63:62]), has_time:hdr_bits[61], eob:hdr_bits[60],
      seqno:hdr_bits[59:48], length:hdr_bits[47:32], sid:hdr_bits[31:0], timestamp:0  //Default timestamp
    };
  end
endtask

task automatic unflatten_chdr;
  input logic[63:0] hdr_bits;
  input logic[63:0] timestamp;
  output cvita_hdr_t hdr;
  begin
    hdr = '{
      pkt_type:cvita_pkt_t'(hdr_bits[63:62]), has_time:hdr_bits[61], eob:hdr_bits[60],
      seqno:hdr_bits[59:48], length:hdr_bits[47:32], sid:hdr_bits[31:0], timestamp:timestamp
    };
  end
endtask

function logic chdr_compare(input cvita_hdr_t a, input cvita_hdr_t b);
  return ((a.pkt_type == b.pkt_type) && (a.has_time == b.has_time) && (a.eob == b.eob) &&
          (a.seqno == b.seqno) && (a.length == b.length) && (a.sid == b.sid));
endfunction

typedef struct packed {
  logic [31:0]  count;
  logic [63:0]  sum;
  logic [63:0]  min;
  logic [63:0]  max;
  logic [63:0]  crc;
} cvita_stats_t;


interface cvita_stream_t (input clk);
  axis_t #(.DWIDTH(64)) axis (.clk(clk));

  // Push a CVITA header into the stream
  // Args:
  // - hdr: The header to push
  task automatic push_hdr;
    input cvita_hdr_t hdr;
    axis.push_word(flatten_chdr_no_ts(hdr), 0);
  endtask

  // Push a word onto the AXI-Stream bus and wait for it to transfer
  // Args:
  // - word: The data to push onto the bus
  // - eop: End of packet (asserts tlast)
  task automatic push_data;
    input logic [63:0] word;
    input logic eop;
    axis.push_word(word, eop);
  endtask
  
  // Push a bubble cycle on the AXI-Stream bus
  task automatic push_bubble;
    axis.push_bubble();
  endtask

  // Wait for a sample to be transferred on the AXI Stream
  // bus and return the data and last
  // Args:
  // - word: The data pulled from the bus
  // - eop: End of packet (tlast)
  task automatic pull_word;
    output logic [63:0] word;
    output logic eop;
    axis.pull_word(word, eop);
  endtask

  // Wait for a bubble cycle on the AXI Stream bus
  task automatic wait_for_bubble;
    axis.wait_for_bubble();
  endtask

  // Wait for a packet to finish on the bus
  task automatic wait_for_pkt;
    axis.wait_for_pkt();
  endtask

  `define WAIT_FOR_PKT_GET_INFO__UPDATE \
    stats.count = stats.count + 1; \
    stats.sum   = stats.sum + axis.tdata; \
    stats.crc   = stats.crc ^ axis.tdata; \
    if (axis.tdata < stats.min) stats.min = axis.tdata; \
    if (axis.tdata > stats.max) stats.max = axis.tdata;

  // Wait for a packet to finish on the bus
  task automatic wait_for_pkt_get_info;
    output cvita_hdr_t    hdr;
    output cvita_stats_t  stats;
    begin
      automatic logic is_hdr  = 1;
      automatic logic is_time = 0;
      stats.count = 32'h0;
      stats.sum   = 64'h0;
      stats.min   = 64'h7FFFFFFFFFFFFFFF;
      stats.max   = 64'h0;
      stats.crc   = 64'h0;

      @(posedge clk);
      //Corner case. We are already looking at the end
      //of a packet i.e. its just a header
      if (axis.tready&axis.tvalid&axis.tlast) begin
        unflatten_chdr_no_ts(axis.tdata, hdr);
        @(negedge clk);
      end else begin
        while(~(axis.tready&axis.tvalid&axis.tlast)) begin
          if (axis.tready&axis.tvalid) begin
            if (is_hdr) begin
              unflatten_chdr_no_ts(axis.tdata, hdr);
              is_time = hdr.has_time;
              is_hdr = 0;
            end else if (is_time) begin
              hdr.timestamp = axis.tdata;
              is_time = 0;
            end else begin
              `WAIT_FOR_PKT_GET_INFO__UPDATE
            end
          end
          @(posedge clk);
        end
        `WAIT_FOR_PKT_GET_INFO__UPDATE
        @(negedge clk);
      end
    end
  endtask

  `undef WAIT_FOR_PKT_GET_INFO__UPDATE

  // Push a packet with random data onto to the AXI Stream bus
  // Args:
  // - num_samps: Packet size.
  // - hdr: Header to attach to packet (length will be ignored)
  // - timestamp: Optional timestamp
  task automatic push_rand_pkt;
    input integer       num_samps;
    input cvita_hdr_t   hdr;
    begin
      cvita_hdr_t tmp_hdr = hdr;
      tmp_hdr.length = num_samps + (hdr.has_time ? 16 : 8);
      @(negedge clk);
      push_hdr(tmp_hdr);
      if (hdr.has_time) axis.push_word(hdr.timestamp, 0);

      repeat(num_samps-1) begin
        axis.push_word({$random,$random}, 0);
      end
      axis.push_word({$random,$random}, 1);
    end
  endtask

  // Push a packet with a ramp on to the AXI Stream bus
  // Args:
  // - num_samps: Packet size.
  // - ramp_start: Start value for the ramp
  // - ramp_inc: Increment per clock cycle
  // - hdr: Header to attach to packet (length will be ignored)
  // - timestamp: Optional timestamp
  task automatic push_ramp_pkt;
    input integer       num_samps;
    input logic [63:0]  ramp_start;
    input logic [63:0]  ramp_inc;
    input cvita_hdr_t   hdr;
    begin
      automatic integer counter = 0;

      cvita_hdr_t tmp_hdr = hdr;
      tmp_hdr.length = num_samps + (hdr.has_time ? 16 : 8);
      @(negedge clk);
      push_hdr(tmp_hdr);
      if (hdr.has_time) axis.push_word(hdr.timestamp, 0);

      repeat(num_samps-1) begin
        axis.push_word(ramp_start+(counter*ramp_inc), 0);
        counter = counter + 1;
      end
      axis.push_word(ramp_start+(counter*ramp_inc), 1);
    end
  endtask

endinterface