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 |