URL
https://opencores.org/ocsvn/loadbalancer/loadbalancer/trunk
Subversion Repositories loadbalancer
[/] [loadbalancer/] [trunk/] [output_port_lookup.v.bak] - Rev 2
Compare with Previous | Blame | View Log
///////////////////////////////////////////////////////////////////////////////
// vim:set shiftwidth=3 softtabstop=3 expandtab:
// $Id: output_port_lookup.v 2201 2007-08-21 06:52:51Z jnaous $
//
// Module: switch_output_port.v
// Project: NF2.1
// Description: reads incoming packets parses them and decides on the output port
// and adds it as a header. The design of this module assumes that only one eop
// will be in the pipeline of this module at any given time.
// i.e. we assume pkt length incl pkt and module headers >= 8*DATA_WIDTH bits
// for a 64 bit datapath, this is 64 bytes.
//
///////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps
module output_port_lookup
#(parameter DATA_WIDTH = 64,
parameter CTRL_WIDTH=DATA_WIDTH/8,
parameter UDP_REG_SRC_WIDTH = 2,
parameter INPUT_ARBITER_STAGE_NUM = 2,
parameter NUM_OUTPUT_QUEUES = 8,
parameter STAGE_NUM = 4,
parameter NUM_IQ_BITS = 3)
(// --- data path interface
output reg [DATA_WIDTH-1:0] out_data,
output reg [CTRL_WIDTH-1:0] out_ctrl,
output reg out_wr,
input out_rdy,
input [DATA_WIDTH-1:0] in_data,
input [CTRL_WIDTH-1:0] in_ctrl,
input in_wr,
output in_rdy,
input en,
// --- Misc
input clk,
input reset);
function integer log2;
input integer number;
begin
log2=0;
while(2**log2<number) begin
log2=log2+1;
end
end
endfunction // log2
//--------------------- Internal Parameter-------------------------
parameter LUT_DEPTH_BITS = 4;
parameter DEFAULT_MISS_OUTPUT_PORTS = 8'b01010101; // exclude the CPU queues
parameter NUM_STATES = 4;
parameter WAIT_TILL_DONE_DECODE = 1;
parameter WRITE_HDR = 2;
parameter SKIP_HDRS = 4;
parameter WAIT_EOP = 8;
//---------------------- Wires and regs----------------------------
wire lookup_ack;
wire [47:0] dst_mac;
wire [47:0] src_mac;
wire [15:0] ethertype;
wire [NUM_IQ_BITS-1:0] src_port;
wire eth_done;
wire [NUM_OUTPUT_QUEUES-1:0] dst_ports;
wire [NUM_OUTPUT_QUEUES-1:0] dst_ports_latched;
wire [LUT_DEPTH_BITS-1:0] rd_addr; // address in table to read
wire rd_req; // request a read
wire [NUM_OUTPUT_QUEUES-1:0] rd_oq; // data read from the LUT at rd_addr
wire rd_wr_protect; // wr_protect bit read
wire [47:0] rd_mac; // data to match in the CAM
wire rd_ack; // pulses high when data is rdy
wire [LUT_DEPTH_BITS-1:0] wr_addr;
wire wr_req;
wire [NUM_OUTPUT_QUEUES-1:0] wr_oq;
wire wr_protect; // wr_protect bit to write
wire [47:0] wr_mac; // data to match in the CAM
wire wr_ack; // pulses high when wr is done
wire lut_hit; // pulses high on a hit
wire lut_miss; // pulses high on a miss
reg in_fifo_rd_en;
wire [CTRL_WIDTH-1:0] in_fifo_ctrl_dout;
wire [DATA_WIDTH-1:0] in_fifo_data_dout;
wire in_fifo_nearly_full;
wire in_fifo_empty;
reg dst_port_rd;
wire dst_port_fifo_nearly_full;
wire dst_port_fifo_empty;
reg [NUM_STATES-1:0] state, state_next;
//------------------------- Modules-------------------------------
ethernet_parser
#(.DATA_WIDTH (DATA_WIDTH),
.CTRL_WIDTH (CTRL_WIDTH),
.NUM_IQ_BITS(NUM_IQ_BITS),
.INPUT_ARBITER_STAGE_NUM(INPUT_ARBITER_STAGE_NUM))
eth_parser
(.in_data(in_data),
.in_ctrl(in_ctrl),
.in_wr(in_wr),
.dst_mac (dst_mac),
.src_mac(src_mac),
.ethertype (ethertype),
.eth_done (eth_done),
.src_port(src_port),
.reset(reset),
.clk(clk));
/* The size of this fifo has to be large enough to fit the previous modules' headers
* and the ethernet header */
small_fifo #(.WIDTH(DATA_WIDTH+CTRL_WIDTH), .MAX_DEPTH_BITS(4), .NEARLY_FULL(15))
input_fifo
(.din ({in_ctrl,in_data}), // Data in
.wr_en (in_wr), // Write enable
.rd_en (in_fifo_rd_en), // Read the next word
.dout ({in_fifo_ctrl_dout, in_fifo_data_dout}),
.full (),
.nearly_full (in_fifo_nearly_full),
.empty (in_fifo_empty),
.reset (reset),
.clk (clk)
);
small_fifo #(.WIDTH(NUM_OUTPUT_QUEUES), .MAX_DEPTH_BITS(2), .NEARLY_FULL(3))
dst_port_fifo
(.din (dst_ports), // Data in
.wr_en (lut_hit|lut_miss), // Write enable
.rd_en (dst_port_rd), // Read the next word
.dout (dst_ports_latched),
.full (),
.nearly_full (dst_port_fifo_nearly_full),
.empty (dst_port_fifo_empty),
.reset (reset),
.clk (clk)
);
//----------------------- Logic -----------------------------
assign in_rdy = !in_fifo_nearly_full && !dst_port_fifo_nearly_full;
/*********************************************************************
* Wait until the ethernet header has been decoded and the output
* port is found, then write the module header and move the packet
* to the output
**********************************************************************/
always @(*) begin
out_ctrl = in_fifo_ctrl_dout;
out_data = in_fifo_data_dout;
state_next = state;
out_wr = 0;
in_fifo_rd_en = 0;
dst_port_rd = 0;
case(state)
WAIT_TILL_DONE_DECODE: begin
if(!dst_port_fifo_empty) begin
dst_port_rd = 1;
state_next = WRITE_HDR;
in_fifo_rd_en = 1;
end
end
/* write Destionation output ports */
WRITE_HDR: begin
if(out_rdy) begin
if(in_fifo_ctrl_dout==2'hFF) begin
out_data[31:16] = dst_ports_latched;
end
out_wr = 1;
in_fifo_rd_en = 1;
state_next = SKIP_HDRS;
end
end
/* Skip the rest of the headers */
SKIP_HDRS: begin
if(in_fifo_ctrl_dout==0) begin
state_next = WAIT_EOP;
end
if(!in_fifo_empty & out_rdy) begin
in_fifo_rd_en = 1;
out_wr = 1;
end
end
/* write all data */
WAIT_EOP: begin
if(in_fifo_ctrl_dout!=0)begin
if(out_rdy) begin
state_next = WAIT_TILL_DONE_DECODE;
out_wr = 1;
end
end
else if(!in_fifo_empty & out_rdy) begin
in_fifo_rd_en = 1;
out_wr = 1;
end
end // case: WAIT_EOP
endcase // case(state)
end // always @ (*)
always @(posedge clk) begin
if(reset) begin
state <= WAIT_TILL_DONE_DECODE;
end
else begin
state <= state_next;
end
end
endmodule // switch_output_port