OpenCores
URL https://opencores.org/ocsvn/loadbalancer/loadbalancer/trunk

Subversion Repositories loadbalancer

[/] [loadbalancer/] [trunk/] [output_port_lookup.v] - 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),
          .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
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.