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

Subversion Repositories srdydrdy_lib

[/] [srdydrdy_lib/] [trunk/] [rtl/] [verilog/] [utility/] [llmanager.v] - Rev 30

Compare with Previous | Blame | View Log

//----------------------------------------------------------------------
//  Linked List Manager
//
//----------------------------------------------------------------------
//  Author: Guy Hutchison
//
// This block is uncopyrighted and released into the public domain.
//----------------------------------------------------------------------
 
module llmanager
  (/*AUTOARG*/
  // Outputs
  par_drdy, parr_srdy, parr_page, lnp_drdy, rlp_drdy, rlpr_srdy,
  rlpr_data, drf_drdy, refup_drdy, pgmem_wr_en, pgmem_wr_addr,
  pgmem_wr_data, pgmem_rd_addr, pgmem_rd_en, ref_wr_en, ref_wr_addr,
  ref_wr_data, ref_rd_addr, ref_rd_en, free_count,
  // Inputs
  clk, reset, par_srdy, parr_drdy, lnp_srdy, lnp_pnp, rlp_srdy,
  rlp_rd_page, rlpr_drdy, drf_srdy, drf_page_list, refup_srdy,
  refup_page, refup_count, pgmem_rd_data, ref_rd_data
  );
 
  parameter lpsz = 8;    // link list page size, in bits
  parameter lpdsz = lpsz+1;  // link page data size, must be at least size of address
  parameter pages = 256; // number of pages
  //parameter sidsz = 2; // source ID size, in bits
  parameter sources = 4; // number of sources
  parameter sinks = 4;    // number of sinks
  parameter sksz = 2;     // number of sink address bits
  parameter maxref = 7;   // maximum reference count, disable with maxref = 0
  parameter refsz  = 3;   // size of reference count bits
 
  input clk;
  input reset;
 
  // page allocation request i/f
  input [sources-1:0] par_srdy;
  output [sources-1:0] par_drdy;
 
  // page allocation request reply i/f
  output [sources-1:0] parr_srdy;
  input [sources-1:0] parr_drdy;
  output [lpsz-1:0]   parr_page;
 
  // link to next page i/f
  input [sources-1:0]  lnp_srdy;
  output [sources-1:0] lnp_drdy;
  input [sources*(lpsz+lpdsz)-1:0] lnp_pnp;
 
  // read link page i/f
  input [sinks-1:0]      rlp_srdy;
  output [sinks-1:0]     rlp_drdy;
  input [sinks*lpsz-1:0] rlp_rd_page;
 
  // read link page reply i/f
  output [sinks-1:0]     rlpr_srdy;
  input [sinks-1:0]      rlpr_drdy;
  output [lpdsz-1:0]     rlpr_data;
 
  // page dereference interface
  input [sinks-1:0]   drf_srdy;
  output [sinks-1:0]  drf_drdy;
  input [sinks*lpsz*2-1:0] drf_page_list;
 
  // reference count update interface
  input                  refup_srdy;
  output                 refup_drdy;
  input [lpsz-1:0]       refup_page;
  input [refsz-1:0]      refup_count;
 
  // link memory interface
  output                 pgmem_wr_en;
  output [lpsz-1:0]      pgmem_wr_addr;
  output [lpdsz-1:0]     pgmem_wr_data;
  output [lpsz-1:0]      pgmem_rd_addr;
  output                 pgmem_rd_en;
  input [lpdsz-1:0]      pgmem_rd_data;
 
  // reference count memory interface
  output                 ref_wr_en;
  output [lpsz-1:0]      ref_wr_addr;
  output [refsz-1:0]     ref_wr_data;
  output [lpsz-1:0]      ref_rd_addr;
  output                 ref_rd_en;
  input [refsz-1:0]      ref_rd_data;
 
 
  output [lpsz:0]        free_count;
 
  reg [lpsz-1:0]       r_free_head_ptr, free_tail_ptr;
  wire [lpsz-1:0]      free_head_ptr;
 
  reg                  pmstate;
  integer              i;
  wire [sources-1:0]   req_src_id;
  reg [sources-1:0]    iparr_src_id;
  wire                 req_srdy;
 
  wire reclaim_srdy;
  reg  reclaim_drdy;
  wire [lpsz-1:0] reclaim_start_page, reclaim_end_page;
 
  reg [lpdsz-1:0]  pgmem_wr_data;
  reg             pgmem_wr_en;
  reg [lpsz-1:0]  pgmem_wr_addr;
  reg [lpsz-1:0]  pgmem_rd_addr;
  reg             pgmem_rd_en;
 
  reg             init;
  reg [lpsz:0]    init_count;
  reg [lpsz:0]    free_count;
  wire            free_empty;
  reg             req_drdy;
 
  wire            irlp_srdy;
  reg             irlp_drdy;
  wire [lpsz-1:0] irlp_rd_page;
  wire [sinks-1:0] irlp_grant;
 
  reg             irlpr_srdy;
  wire            irlpr_drdy;
  reg [sinks-1:0] irlpr_grant, nxt_irlpr_grant;
  reg              load_head_ptr, nxt_load_head_ptr;
  reg              load_lp_data, nxt_load_lp_data;
 
  wire            ilnp_srdy;
  reg             ilnp_drdy;
  wire [lpsz-1:0] ilnp_page;
  wire [lpdsz-1:0] ilnp_nxt_page;
 
  wire dsbuf_srdy, dsbuf_drdy;
  wire [sources-1:0] dsbuf_source;
  wire [lpsz-1:0]    dsbuf_data;
  wire               iparr_drdy;
 
  assign free_empty = (free_head_ptr == free_tail_ptr);
  assign free_head_ptr = (load_head_ptr) ? pgmem_rd_data : r_free_head_ptr;
 
  sd_rrmux #(.mode(0), .fast_arb(1), 
             .width(1), .inputs(sources)) req_mux
    (
     .clk         (clk),
     .reset       (reset),
 
     .c_srdy      (par_srdy),
     .c_drdy      (par_drdy),
     .c_data      ({sources{1'b0}}),
     .c_rearb     (1'b1),
 
     .p_srdy      (req_srdy),
     .p_drdy      (req_drdy),
     .p_data      (),
     .p_grant     (req_src_id)
     );
 
  sd_rrmux #(.mode(0), .fast_arb(1), 
             .width(lpsz+lpdsz), .inputs(sources)) lnp_mux
    (
     .clk         (clk),
     .reset       (reset),
 
     .c_srdy      (lnp_srdy),
     .c_drdy      (lnp_drdy),
     .c_data      (lnp_pnp),
     .c_rearb     (1'b1),
 
     .p_srdy      (ilnp_srdy),
     .p_drdy      (ilnp_drdy),
     .p_data      ({ilnp_page,ilnp_nxt_page}),
     .p_grant     ()
     );
 
  sd_rrmux #(.mode(0), .fast_arb(1), 
             .width(lpsz), .inputs(sources)) rlp_mux
    (
     .clk         (clk),
     .reset       (reset),
 
     .c_srdy      (rlp_srdy),
     .c_drdy      (rlp_drdy),
     .c_data      (rlp_rd_page),
     .c_rearb     (1'b1),
 
     .p_srdy      (irlp_srdy),
     .p_drdy      (irlp_drdy),
     .p_data      (irlp_rd_page),
     .p_grant     (irlp_grant)
     );
 
  always @(posedge clk)
    begin
      if (reset)
        begin
          init <= 1;
          init_count <= 0;
          r_free_head_ptr <= 0;
          free_tail_ptr <= pages - 1;
          free_count <= pages;
          load_head_ptr <= 0;
          load_lp_data <= 0;
          irlpr_grant <= 0;
          iparr_src_id <= 0;
        end
      else
        begin
          load_head_ptr <= nxt_load_head_ptr;
          load_lp_data  <= nxt_load_lp_data;
          irlpr_grant <= nxt_irlpr_grant;
 
          if (init)
            begin
              init_count <= init_count + 1;
              if (init_count == (pages-1))
                init <= 0;
            end
          else
            begin
              if (load_head_ptr)
                r_free_head_ptr <= pgmem_rd_data;
 
              if (req_drdy)
                iparr_src_id    <= req_src_id;
 
              if (reclaim_srdy & reclaim_drdy)
                free_tail_ptr <= reclaim_end_page;
 
              if (pgmem_rd_en & !pgmem_wr_en)
                free_count <= free_count - 1;
              else if (pgmem_wr_en & !pgmem_rd_en)
                free_count <= free_count + 1;
            end
        end // else: !if(reset)
    end // always @ (posedge clk)
 
  always @*
    begin
      pgmem_wr_data = 0;
      pgmem_wr_en = 0;
      pgmem_wr_addr = 0;
      pgmem_rd_addr = 0;
      pgmem_rd_en = 0;
      ilnp_drdy = 0;
      nxt_load_head_ptr = 0;
      nxt_load_lp_data = 0;
      nxt_irlpr_grant = irlpr_grant;
      irlp_drdy = 0;
      req_drdy = 0;
 
      if (init)
        begin
          pgmem_wr_en = 1;
          pgmem_wr_addr = init_count;
          pgmem_wr_data[lpsz-1:0] = init_count + 1;
          pgmem_wr_data[lpdsz-1:lpsz] = 0;
          reclaim_drdy = 0;
        end
      else
        begin
          reclaim_drdy = 1;
          // load_lp check is to predict flow control on next cycle,
          // prevents back-to-pack Read Link Page requests
          if (irlp_srdy & irlpr_drdy & !load_lp_data)
            begin
              pgmem_rd_en = 1;
              pgmem_rd_addr = irlp_rd_page;
              nxt_load_lp_data = 1;
              nxt_irlpr_grant = irlp_grant;
              irlp_drdy = 1;
            end
          else if (req_srdy & (iparr_drdy & dsbuf_drdy) & !free_empty)
            begin
              pgmem_rd_en = 1;
              pgmem_rd_addr = free_head_ptr;
              nxt_load_head_ptr = 1;
              req_drdy = 1;
            end
 
          if (reclaim_srdy)
            begin
              pgmem_wr_en = 1;
              pgmem_wr_addr = free_tail_ptr;
              pgmem_wr_data = reclaim_start_page;
            end
          else if (ilnp_srdy)
            begin
              ilnp_drdy = 1;
              pgmem_wr_en = 1;
              pgmem_wr_addr = ilnp_page;
              pgmem_wr_data = ilnp_nxt_page;
           end
       end
    end
 
  sd_input #(.width(lpsz+sources)) lp_disp_buf
    (.clk (clk), .reset (reset),
     .c_srdy (load_head_ptr),
     .c_drdy (iparr_drdy),
     .c_data ({iparr_src_id,r_free_head_ptr}),
     .ip_srdy (dsbuf_srdy),
     .ip_drdy (dsbuf_drdy),
     .ip_data ({dsbuf_source,dsbuf_data}));
 
  sd_mirror #(.mirror(sources), .width(lpsz)) lp_dispatch
    (.clk   (clk),
     .reset (reset),
 
     .c_srdy (dsbuf_srdy),
     .c_drdy (dsbuf_drdy),
     .c_data (dsbuf_data),
     .c_dst_vld (dsbuf_source),
 
     .p_srdy (parr_srdy),
     .p_drdy (parr_drdy),
     .p_data (parr_page)
     );
 
  // output reflector for read link page interface
  sd_mirror #(.mirror(sinks), .width(lpdsz)) read_link_return
    (.clk   (clk),
     .reset (reset),
 
     .c_srdy (load_lp_data),
     .c_drdy (irlpr_drdy),
     .c_data (pgmem_rd_data),
     .c_dst_vld (irlpr_grant),
 
     .p_srdy (rlpr_srdy),
     .p_drdy (rlpr_drdy),
     .p_data (rlpr_data)
     );
 
  generate if (maxref == 0)
    begin : no_ref_count
  sd_rrmux #(.mode(0), .fast_arb(1), 
             .width(lpsz*2), .inputs(sinks)) reclaim_mux
    (
     .clk         (clk),
     .reset       (reset),
 
     .c_srdy      (drf_srdy),
     .c_drdy      (drf_drdy),
     .c_data      (drf_page_list),
     .c_rearb     (1'b1),
 
     .p_srdy      (reclaim_srdy),
     .p_drdy      (reclaim_drdy),
     .p_data      ({reclaim_start_page,reclaim_end_page}),
     .p_grant     ()
     );
    end // block: no_ref_count
  else
    begin : enable_ref_count
      wire drq_srdy, drq_drdy;
      wire [lpsz-1:0] drq_start_page, drq_end_page;
 
      sd_rrmux #(.mode(0), .fast_arb(1), 
                 .width(lpsz*2), .inputs(sinks)) reclaim_mux
        (
         .clk         (clk),
         .reset       (reset),
 
         .c_srdy      (drf_srdy),
         .c_drdy      (drf_drdy),
         .c_data      (drf_page_list),
         .c_rearb     (1'b1),
 
         .p_srdy      (drq_srdy),
         .p_drdy      (drq_drdy),
         .p_data      ({drq_start_page,drq_end_page}),
         .p_grant     ()
         );
 
      llmanager_refcount #(/*AUTOINSTPARAM*/
                           // Parameters
                           .lpsz                (lpsz),
                           .refsz               (refsz)) llref
        (/*AUTOINST*/
         // Outputs
         .drq_drdy                      (drq_drdy),
         .reclaim_srdy                  (reclaim_srdy),
         .reclaim_start_page            (reclaim_start_page[(lpsz)-1:0]),
         .reclaim_end_page              (reclaim_end_page[(lpsz)-1:0]),
         .refup_drdy                    (refup_drdy),
         .ref_wr_en                     (ref_wr_en),
         .ref_wr_addr                   (ref_wr_addr[(lpsz)-1:0]),
         .ref_wr_data                   (ref_wr_data[(refsz)-1:0]),
         .ref_rd_addr                   (ref_rd_addr[(lpsz)-1:0]),
         .ref_rd_en                     (ref_rd_en),
         // Inputs
         .clk                           (clk),
         .reset                         (reset),
         .drq_srdy                      (drq_srdy),
         .drq_start_page                (drq_start_page[(lpsz)-1:0]),
         .drq_end_page                  (drq_end_page[(lpsz)-1:0]),
         .reclaim_drdy                  (reclaim_drdy),
         .refup_srdy                    (refup_srdy),
         .refup_page                    (refup_page[(lpsz)-1:0]),
         .refup_count                   (refup_count[(refsz)-1:0]),
         .ref_rd_data                   (ref_rd_data[(refsz)-1:0]));
    end
  endgenerate
 
endmodule // llmanager
 

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.