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