File: chdr_data_swapper.v

package info (click to toggle)
uhd 4.9.0.0%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 184,180 kB
  • sloc: cpp: 262,887; python: 112,011; ansic: 102,670; vhdl: 57,031; tcl: 19,924; xml: 8,581; makefile: 3,028; sh: 2,812; pascal: 230; javascript: 120; csh: 94; asm: 20; perl: 11
file content (227 lines) | stat: -rw-r--r-- 7,252 bytes parent folder | download | duplicates (3)
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//
// Copyright 2019 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: chdr_data_swapper
// Description:
//  A module to adapt a CHDR stream to correctly sequence in
//  a software buffer of a user-specified type. Here are the 
//  the swapping assumptions:
//  - The CHDR header, timestamp and metadata for all packet
//    types must be interpreted as a uint64_t.
//  - All Control, Stream Status/Cmd, Management packet payloads
//    must reside in a uint64_t* buffer.
//  - The buffer type for the data packet payload and metadata
//    is user configurable
//
// Parameters:
//   - CHDR_W: Width of the tdata bus in bits
//
// Signals:
//   - payload_sw_buff: SW buffer mode for payload (0=u64, 1=u32, 2=u16, 3=u8)
//   - mdata_sw_buff  : SW buffer mode for metadata (0=u64, 1=u32, 2=u16, 3=u8)
//   - s_axis_*       : The input AXI stream
//   - m_axis_*       : The output AXI stream
//

module chdr_data_swapper #(
  parameter CHDR_W = 256
)(
  // Clock and Reset
  input  wire              clk,
  input  wire              rst,
  // Software Buffer Mode
  input  wire [1:0]        payload_sw_buff,
  input  wire [1:0]        mdata_sw_buff,
  input  wire              swap_endianness,
  // Input AXIS
  input  wire [CHDR_W-1:0] s_axis_tdata,
  input  wire              s_axis_tlast,
  input  wire              s_axis_tvalid,
  output wire              s_axis_tready,
  // Output AXIS           
  output wire [CHDR_W-1:0] m_axis_tdata,
  output wire              m_axis_tlast,
  output wire              m_axis_tvalid,
  input  wire              m_axis_tready
);

  `include "../core/rfnoc_chdr_utils.vh"

  // *_sw_buff values
  localparam [1:0] SW_BUFF_UINT64 = 2'd0;
  localparam [1:0] SW_BUFF_UINT32 = 2'd1;
  localparam [1:0] SW_BUFF_UINT16 = 2'd2;
  localparam [1:0] SW_BUFF_UINT8  = 2'd3;

  localparam SWAP_W = $clog2(CHDR_W);

  // Packet states
  localparam [2:0] ST_HDR       = 3'd0;
  localparam [2:0] ST_TS        = 3'd1;
  localparam [2:0] ST_MDATA     = 3'd2;
  localparam [2:0] ST_DATA_BODY = 3'd3;
  localparam [2:0] ST_OTHER     = 3'd4;

  reg [2:0]         state = ST_HDR;
  reg [4:0]         mdata_pending = CHDR_NO_MDATA;
  reg [SWAP_W-2:0]  pyld_tswap = 'h0, mdata_tswap = 'h0;

  // Shortcuts: CHDR header
  wire [2:0] pkt_type = chdr_get_pkt_type(s_axis_tdata[63:0]);
  wire [4:0] num_mdata = chdr_get_num_mdata(s_axis_tdata[63:0]);

  // State machine to determine packet state
  always @(posedge clk) begin
    if (rst) begin
      state <= ST_HDR;
    end else if (s_axis_tvalid & s_axis_tready) begin
      case (state)
        ST_HDR: begin
          mdata_pending <= num_mdata;
          if (!s_axis_tlast) begin
            if (CHDR_W > 64) begin
              if (pkt_type == CHDR_PKT_TYPE_DATA || pkt_type == CHDR_PKT_TYPE_DATA_TS) begin
                if (num_mdata != CHDR_NO_MDATA) begin
                  state <= ST_MDATA;
                end else begin
                  state <= ST_DATA_BODY;
                end
              end else begin
                state <= ST_OTHER;
              end
            end else begin
              if (pkt_type == CHDR_PKT_TYPE_DATA_TS) begin
                state <= ST_TS;
              end else if (pkt_type == CHDR_PKT_TYPE_DATA) begin
                if (num_mdata != CHDR_NO_MDATA) begin
                  state <= ST_MDATA;
                end else begin
                  state <= ST_DATA_BODY;
                end
              end else begin
                state <= ST_OTHER;
              end
            end
          end else begin
            state <= ST_HDR;
          end
        end
        ST_TS: begin
          if (!s_axis_tlast) begin
            if (mdata_pending != CHDR_NO_MDATA) begin
              state <= ST_MDATA;
            end else begin
              state <= ST_DATA_BODY;
            end
          end else begin
            state <= ST_HDR;
          end
        end
        ST_MDATA: begin
          if (!s_axis_tlast) begin
            if (mdata_pending == 5'd1) begin
              state <= ST_DATA_BODY;
            end else begin
              mdata_pending <= mdata_pending - 5'd1;
            end
          end else begin
            state <= ST_HDR;
          end
        end
        ST_DATA_BODY: begin
          if (s_axis_tlast) begin
            state <= ST_HDR;
          end
        end
        ST_OTHER: begin
          if (s_axis_tlast) begin
            state <= ST_HDR;
          end
        end
        default: begin
          state <= ST_HDR;
        end
      endcase
    end
  end

  // Convert SW buff size to swap-lane map
  always @(posedge clk) begin
    pyld_tswap <= 'h0;
    mdata_tswap <= 'h0;
    case (payload_sw_buff)
      SW_BUFF_UINT8:
        pyld_tswap[4:2] <= 3'b111;
      SW_BUFF_UINT16:
        pyld_tswap[4:2] <= 3'b110;
      SW_BUFF_UINT32:
        pyld_tswap[4:2] <= 3'b100;
      default:
        pyld_tswap[4:2] <= 3'b000;
    endcase
    case (mdata_sw_buff)
      SW_BUFF_UINT8:
        mdata_tswap[4:2] <= 3'b111;
      SW_BUFF_UINT16:
        mdata_tswap[4:2] <= 3'b110;
      SW_BUFF_UINT32:
        mdata_tswap[4:2] <= 3'b100;
      default:
        mdata_tswap[4:2] <= 3'b000;
    endcase
  end

  wire [SWAP_W-2:0] s_axis_tswap_dyn = 
    (state == ST_DATA_BODY) ? pyld_tswap : (
    (state == ST_MDATA) ? mdata_tswap : {(SWAP_W-1){1'b0}}
  );
  wire s_axis_tswap_end = swap_endianness && 
    (state == ST_DATA_BODY || state == ST_MDATA);

  // Swapper that re-aligns items in a buffer for software
 wire [CHDR_W-1:0] out_swap_tdata, out_swap_tdata_pre;
 wire              out_swap_tswap_end, out_swap_tlast, out_swap_tvalid, out_swap_tready;

  axis_data_swap #(
    .DATA_W(CHDR_W), .USER_W(1'b1),
    .STAGES_EN({{(SWAP_W-6){1'b0}}, 6'b111100}), .DYNAMIC(1)
  ) chdr_dyn_swap_i (
    .clk          (clk               ),
    .rst          (rst               ),
    .s_axis_tdata (s_axis_tdata      ),
    .s_axis_tswap (s_axis_tswap_dyn  ),
    .s_axis_tuser (s_axis_tswap_end  ),
    .s_axis_tlast (s_axis_tlast      ),
    .s_axis_tvalid(s_axis_tvalid     ),
    .s_axis_tready(s_axis_tready     ),
    .m_axis_tdata (out_swap_tdata_pre),
    .m_axis_tuser (out_swap_tswap_end),
    .m_axis_tlast (out_swap_tlast    ),
    .m_axis_tvalid(out_swap_tvalid   ),
    .m_axis_tready(out_swap_tready   )
  );

  // Swapper that pre-corrects for transport endianness
  genvar i;
  generate for (i = 0; i < CHDR_W/8; i=i+1) begin
    assign out_swap_tdata[i*8 +: 8] = out_swap_tswap_end ? 
      out_swap_tdata_pre[((CHDR_W/8)-i-1)*8 +: 8] : out_swap_tdata_pre[i*8 +: 8];
  end endgenerate

  axi_fifo_flop2 #(.WIDTH(CHDR_W+1)) out_reg_i (
    .clk     (clk                             ),
    .reset   (rst                             ),
    .clear   (1'b0                            ),
    .i_tdata ({out_swap_tlast, out_swap_tdata}),
    .i_tvalid(out_swap_tvalid                 ),
    .i_tready(out_swap_tready                 ),
    .o_tdata ({m_axis_tlast, m_axis_tdata}    ),
    .o_tvalid(m_axis_tvalid                   ),
    .o_tready(m_axis_tready                   ),
    .occupied(                                ),
    .space   (                                )
  );

endmodule // chdr_data_swapper