Statistics
| Branch: | Tag: | Revision:

root / usrp2 / fifo / packet_dispatcher36_x4.v @ 78b9db58

History | View | Annotate | Download (11.7 KB)

1 78b9db58 Josh Blum
//
2
// Copyright 2011-2012 Ettus Research LLC
3
//
4
// Packet dispatcher with fifo36 interface and 4 outputs.
5
//
6
// The packet dispatcher expects 2-byte padded ethernet frames.
7
// The frames will be inspected at ethernet, IPv4, UDP, and VRT layers.
8
// Packets are dispatched into the following streams:
9
//   * tx dsp stream
10
//   * tx control stream
11
//   * to cpu stream
12
//   * to external stream
13
//   * to both cpu and external
14
//
15
// The following registers are used for dispatcher control:
16
//   * base + 0 = this ipv4 address (32 bits)
17
//   * base + 1 = udp control port (upper 16 bits), udp dsp port (lower 16 bits)
18
//
19
20
module packet_dispatcher36_x4
21
    #(
22
        parameter BASE = 0
23
    )
24
    (
25
        //clocking and reset interface:
26
        input clk, input rst, input clr,
27
28
        //setting register interface:
29
        input set_stb, input [7:0] set_addr, input [31:0] set_data,
30
31
        //input stream interfaces:
32
        input [35:0] com_inp_data, input com_inp_valid, output com_inp_ready,
33
34
        //output stream interfaces:
35
        output [35:0] ext_out_data, output ext_out_valid, input ext_out_ready,
36
        output [35:0] dsp_out_data, output dsp_out_valid, input dsp_out_ready,
37
        output [35:0] ctl_out_data, output ctl_out_valid, input ctl_out_ready,
38
        output [35:0] cpu_out_data, output cpu_out_valid, input cpu_out_ready
39
    );
40
41
    //setting register to program the IP address
42
    wire [31:0] my_ip_addr;
43
    setting_reg #(.my_addr(BASE+0)) sreg_ip_addr(
44
        .clk(clk),.rst(rst),
45
        .strobe(set_stb),.addr(set_addr),.in(set_data),
46
        .out(my_ip_addr),.changed()
47
    );
48
49
    //setting register to program the UDP DSP port
50
    wire [15:0] dsp_udp_port, ctl_udp_port;
51
    setting_reg #(.my_addr(BASE+1), .width(32)) sreg_data_port(
52
        .clk(clk),.rst(rst),
53
        .strobe(set_stb),.addr(set_addr),.in(set_data),
54
        .out({ctl_udp_port, dsp_udp_port}),.changed()
55
    );
56
57
    ////////////////////////////////////////////////////////////////////
58
    // Communication input inspector
59
    //   - inspect com input and send it to DSP, EXT, CPU, or BOTH
60
    ////////////////////////////////////////////////////////////////////
61
    localparam PD_STATE_READ_COM_PRE = 0;
62
    localparam PD_STATE_READ_COM = 1;
63
    localparam PD_STATE_WRITE_REGS = 2;
64
    localparam PD_STATE_WRITE_LIVE = 3;
65
66
    localparam PD_DEST_DSP = 0;
67
    localparam PD_DEST_EXT = 1;
68
    localparam PD_DEST_CPU = 2;
69
    localparam PD_DEST_BOF = 3;
70
    localparam PD_DEST_CTL = 4;
71
72
    localparam PD_MAX_NUM_DREGS = 13; //padded_eth + ip + udp + seq + vrt_hdr
73
    localparam PD_DREGS_DSP_OFFSET = 11; //offset to start dsp at
74
75
    //output inspector interfaces
76
    wire [35:0] pd_out_dsp_data;
77
    wire        pd_out_dsp_valid;
78
    wire        pd_out_dsp_ready;
79
80
    wire [35:0] pd_out_ext_data;
81
    wire        pd_out_ext_valid;
82
    wire        pd_out_ext_ready;
83
84
    wire [35:0] pd_out_cpu_data;
85
    wire        pd_out_cpu_valid;
86
    wire        pd_out_cpu_ready;
87
88
    wire [35:0] pd_out_bof_data;
89
    wire        pd_out_bof_valid;
90
    wire        pd_out_bof_ready;
91
92
    wire [35:0] pd_out_ctl_data;
93
    wire        pd_out_ctl_valid;
94
    wire        pd_out_ctl_ready;
95
96
    reg [1:0] pd_state;
97
    reg [2:0] pd_dest;
98
    reg [3:0] pd_dreg_count; //data registers to buffer headers
99
    wire [3:0] pd_dreg_count_next = pd_dreg_count + 1'b1;
100
    wire pd_dreg_counter_done = (pd_dreg_count_next == PD_MAX_NUM_DREGS)? 1'b1 : 1'b0;
101
    reg [35:0] pd_dregs [PD_MAX_NUM_DREGS-1:0];
102
103
    reg is_eth_dst_mac_bcast;
104
    reg is_eth_type_ipv4;
105
    reg is_eth_ipv4_proto_udp;
106
    reg is_eth_ipv4_dst_addr_here;
107
    reg is_eth_udp_dsp_port_here;
108
    reg is_eth_udp_ctl_port_here;
109
    wire is_vrt_size_zero = (com_inp_data[15:0] == 16'h0); //needed on the same cycle, so it cant be registered
110
111
    //Inspector output flags special case:
112
    //Inject SOF into flags at first DSP line.
113
    wire [3:0] pd_out_flags = (
114
        (pd_dreg_count == PD_DREGS_DSP_OFFSET) &&
115
        (pd_dest == PD_DEST_DSP)
116
    )? 4'b0001 : pd_dregs[pd_dreg_count][35:32];
117
118
    //The communication inspector ouput data and valid signals:
119
    //Mux between com input and data registers based on the state.
120
    wire [35:0] pd_out_data = (pd_state == PD_STATE_WRITE_REGS)?
121
        {pd_out_flags, pd_dregs[pd_dreg_count][31:0]} : com_inp_data
122
    ;
123
    wire pd_out_valid =
124
        (pd_state == PD_STATE_WRITE_REGS)? 1'b1          : (
125
        (pd_state == PD_STATE_WRITE_LIVE)? com_inp_valid : (
126
    1'b0));
127
128
    //The communication inspector ouput ready signal:
129
    //Mux between the various destination ready signals.
130
    wire pd_out_ready =
131
        (pd_dest == PD_DEST_DSP)? pd_out_dsp_ready : (
132
        (pd_dest == PD_DEST_EXT)? pd_out_ext_ready : (
133
        (pd_dest == PD_DEST_CPU)? pd_out_cpu_ready : (
134
        (pd_dest == PD_DEST_BOF)? pd_out_bof_ready : (
135
        (pd_dest == PD_DEST_CTL)? pd_out_ctl_ready : (
136
    1'b0)))));
137
138
    //Always connected output data lines.
139
    assign pd_out_dsp_data = pd_out_data;
140
    assign pd_out_ext_data = pd_out_data;
141
    assign pd_out_cpu_data = pd_out_data;
142
    assign pd_out_bof_data = pd_out_data;
143
    assign pd_out_ctl_data = pd_out_data;
144
145
    //Destination output valid signals:
146
    //Comes from inspector valid when destination is selected, and otherwise low.
147
    assign pd_out_dsp_valid = (pd_dest == PD_DEST_DSP)? pd_out_valid : 1'b0;
148
    assign pd_out_ext_valid = (pd_dest == PD_DEST_EXT)? pd_out_valid : 1'b0;
149
    assign pd_out_cpu_valid = (pd_dest == PD_DEST_CPU)? pd_out_valid : 1'b0;
150
    assign pd_out_bof_valid = (pd_dest == PD_DEST_BOF)? pd_out_valid : 1'b0;
151
    assign pd_out_ctl_valid = (pd_dest == PD_DEST_CTL)? pd_out_valid : 1'b0;
152
153
    //The communication inspector ouput ready signal:
154
    //Always ready when storing to data registers,
155
    //comes from inspector ready output when live,
156
    //and otherwise low.
157
    assign com_inp_ready =
158
        (pd_state == PD_STATE_READ_COM_PRE)  ? 1'b1         : (
159
        (pd_state == PD_STATE_READ_COM)      ? 1'b1         : (
160
        (pd_state == PD_STATE_WRITE_LIVE)    ? pd_out_ready : (
161
    1'b0)));
162
163
    //inspect the incoming data and mark register booleans
164
    always @(posedge clk)
165
    if (com_inp_ready & com_inp_valid) begin
166
        case(pd_dreg_count)
167
        0: begin
168
            is_eth_dst_mac_bcast <= (com_inp_data[15:0] == 16'hffff);
169
        end
170
        1: begin
171
            is_eth_dst_mac_bcast <= is_eth_dst_mac_bcast && (com_inp_data[31:0] == 32'hffffffff);
172
        end
173
        3: begin
174
            is_eth_type_ipv4 <= (com_inp_data[15:0] == 16'h800);
175
        end
176
        6: begin
177
            is_eth_ipv4_proto_udp <= (com_inp_data[23:16] == 8'h11);
178
        end
179
        8: begin
180
            is_eth_ipv4_dst_addr_here <= (com_inp_data[31:0] == my_ip_addr);
181
        end
182
        9: begin
183
            is_eth_udp_dsp_port_here <= (com_inp_data[15:0] == dsp_udp_port);
184
            is_eth_udp_ctl_port_here <= (com_inp_data[15:0] == ctl_udp_port);
185
        end
186
        endcase //pd_dreg_count
187
    end
188
189
    always @(posedge clk)
190
    if(rst | clr) begin
191
        pd_state <= PD_STATE_READ_COM_PRE;
192
        pd_dreg_count <= 0;
193
    end
194
    else begin
195
        case(pd_state)
196
        PD_STATE_READ_COM_PRE: begin
197
            if (com_inp_ready & com_inp_valid & com_inp_data[32]) begin
198
                pd_state <= PD_STATE_READ_COM;
199
                pd_dreg_count <= pd_dreg_count_next;
200
                pd_dregs[pd_dreg_count] <= com_inp_data;
201
            end
202
        end
203
204
        PD_STATE_READ_COM: begin
205
            if (com_inp_ready & com_inp_valid) begin
206
                pd_dregs[pd_dreg_count] <= com_inp_data;
207
                if (pd_dreg_counter_done | com_inp_data[33]) begin
208
                    pd_state <= PD_STATE_WRITE_REGS;
209
                    pd_dreg_count <= 0;
210
211
                    //---------- begin inspection decision -----------//
212
                    //EOF or bcast or not IPv4 or not UDP:
213
                    if (
214
                        com_inp_data[33] || is_eth_dst_mac_bcast ||
215
                        ~is_eth_type_ipv4 || ~is_eth_ipv4_proto_udp
216
                    ) begin
217
                        pd_dest <= PD_DEST_BOF;
218
                    end
219
220
                    //not my IP address:
221
                    else if (~is_eth_ipv4_dst_addr_here) begin
222
                        pd_dest <= PD_DEST_EXT;
223
                    end
224
225
                    //UDP control port and VRT:
226
                    else if (is_eth_udp_ctl_port_here && ~is_vrt_size_zero) begin
227
                        pd_dest <= PD_DEST_CTL;
228
                        pd_dreg_count <= PD_DREGS_DSP_OFFSET;
229
                    end
230
231
                    //UDP data port and VRT:
232
                    else if (is_eth_udp_dsp_port_here && ~is_vrt_size_zero) begin
233
                        pd_dest <= PD_DEST_DSP;
234
                        pd_dreg_count <= PD_DREGS_DSP_OFFSET;
235
                    end
236
237
                    //other:
238
                    else begin
239
                        pd_dest <= PD_DEST_CPU;
240
                    end
241
                    //---------- end inspection decision -------------//
242
243
                end
244
                else begin
245
                    pd_dreg_count <= pd_dreg_count_next;
246
                end
247
            end
248
        end
249
250
        PD_STATE_WRITE_REGS: begin
251
            if (pd_out_ready & pd_out_valid) begin
252
                if (pd_out_data[33]) begin
253
                    pd_state <= PD_STATE_READ_COM_PRE;
254
                    pd_dreg_count <= 0;
255
                end
256
                else if (pd_dreg_counter_done) begin
257
                    pd_state <= PD_STATE_WRITE_LIVE;
258
                    pd_dreg_count <= 0;
259
                end
260
                else begin
261
                    pd_dreg_count <= pd_dreg_count_next;
262
                end
263
            end
264
        end
265
266
        PD_STATE_WRITE_LIVE: begin
267
            if (pd_out_ready & pd_out_valid & pd_out_data[33]) begin
268
                pd_state <= PD_STATE_READ_COM_PRE;
269
            end
270
        end
271
272
        endcase //pd_state
273
    end
274
275
    //connect this fast-path signals directly to the DSP out
276
    assign dsp_out_data = pd_out_dsp_data;
277
    assign dsp_out_valid = pd_out_dsp_valid;
278
    assign pd_out_dsp_ready = dsp_out_ready;
279
280
    assign ctl_out_data = pd_out_ctl_data;
281
    assign ctl_out_valid = pd_out_ctl_valid;
282
    assign pd_out_ctl_ready = ctl_out_ready;
283
284
    ////////////////////////////////////////////////////////////////////
285
    // Splitter and output muxes for the bof packets
286
    //   - split the bof packets into two streams
287
    //   - mux split packets into cpu out and ext out
288
    ////////////////////////////////////////////////////////////////////
289
290
    //dummy signals to join the the splitter and muxes below
291
    wire [35:0] _split_to_ext_data,  _split_to_cpu_data;
292
    wire        _split_to_ext_valid, _split_to_cpu_valid;
293
    wire        _split_to_ext_ready, _split_to_cpu_ready;
294
295
    splitter36 bof_out_splitter(
296
        .clk(clk), .rst(rst), .clr(clr),
297
        .inp_data(pd_out_bof_data), .inp_valid(pd_out_bof_valid), .inp_ready(pd_out_bof_ready),
298
        .out0_data(_split_to_ext_data), .out0_valid(_split_to_ext_valid), .out0_ready(_split_to_ext_ready),
299
        .out1_data(_split_to_cpu_data), .out1_valid(_split_to_cpu_valid), .out1_ready(_split_to_cpu_ready)
300
    );
301
302
    fifo36_mux ext_out_mux(
303
        .clk(clk), .reset(rst), .clear(clr),
304
        .data0_i(pd_out_ext_data), .src0_rdy_i(pd_out_ext_valid), .dst0_rdy_o(pd_out_ext_ready),
305
        .data1_i(_split_to_ext_data), .src1_rdy_i(_split_to_ext_valid), .dst1_rdy_o(_split_to_ext_ready),
306
        .data_o(ext_out_data), .src_rdy_o(ext_out_valid), .dst_rdy_i(ext_out_ready)
307
    );
308
309
    fifo36_mux cpu_out_mux(
310
        .clk(clk), .reset(rst), .clear(clr),
311
        .data0_i(pd_out_cpu_data), .src0_rdy_i(pd_out_cpu_valid), .dst0_rdy_o(pd_out_cpu_ready),
312
        .data1_i(_split_to_cpu_data), .src1_rdy_i(_split_to_cpu_valid), .dst1_rdy_o(_split_to_cpu_ready),
313
        .data_o(cpu_out_data), .src_rdy_o(cpu_out_valid), .dst_rdy_i(cpu_out_ready)
314
    );
315
316
endmodule // packet_dispatcher36_x3