On Tuesday 27 December 2005 02:02, Pieter Hulshoff wrote:
> ... but if you don't mind I'd like to have a look at an alternative
> implementation, just for comparison, tomorrow, and send it to this thread.
> It'll also be a good opportunity for me to check how bad my Verilog
> understanding truly is. :)

OK, here's a first attempt. Let me know what you think, and be sure to point 
out mistakes (which I'm sure I've made). :)

Regards,

Pieter Hulshoff

-- 
The last good thing written in C was Franz Schubert's Symphony number 9.
When your hammer is C++, everything begins to look like a thumb.
module async_fifo
  (
    clk_wr,       // Write clock
    reset_clk_wr, // Reset synced on write clock
    data_in,      // Data input
    enq,          // Enqueue data
    full,         // FIFO full, couldn't write data
    clk_rd,       // Read clock
    reset_clk_rd, // Reset synced on read clock
    data_out,     // Data output
    valid_out,    // Output data is valid
    deq           // Dequeue data
  );


  parameter fifo_width = 32; // fifo depth is hard-wired to 16

  // Write side ports
  input  clk_wr;
  input  reset_clk_wr;
  input  [fifo_width-1:0] data_in;
  input  enq;
  output full;
  reg    full;

  // Read side ports
  input  clk_rd;
  input  reset_clk_rd;
  output [fifo_width-1:0] data_out;
  reg    [fifo_width-1:0] data_out;
  output valid_out;
  reg    valid_out;
  input  deq;

  // Write side registers
  reg [3:0] wr_ptr;
  reg [3:0] wr_ptr_nxt;
  reg [3:0] rd_ptr_c2c;
  reg [3:0] rd_ptr_meta;

  // FIFO
  reg [fifo_width-1:0] fifo_data [15:0];

  // Read side registers
  reg [3:0] rd_ptr;
  reg [3:0] wr_ptr_c2c;
  reg [3:0] wr_ptr_meta;


  // Write side
  always @(posedge clk_wr)
  begin

    if (enq && wr_ptr_next != rd_ptr_meta) begin // FIFO not full
      fifo_data[wr_ptr] <= data_in;
      wr_ptr            <= wr_ptr_nxt;
      wr_ptr_nxt        <= next_gray_code( wr_ptr_nxt );
      full              <= (next_gray_code( wr_ptr_nxt ) == rd_ptr_meta);
    end else begin
      full              <= (wr_ptr_nxt == rd_ptr_meta);
    end

    rd_ptr_meta <= rd_ptr_c2c;
    rd_ptr_c2c  <= rd_ptr;

    if (reset_clk_wr) begin
      wr_ptr     <= 0;
      wr_ptr_nxt <= 1;
      full       <= 0;
    end

  end


  // Read side
  always @(posedge clk_rd)
  begin

    if (deq && rd_ptr != wr_ptr_meta) begin // FIFO not empty
      data_out  <= fifo_data[rd_ptr];
      valid_out <= 1;
      rd_ptr    <= next_gray_code( rd_ptr );
    end else begin
      valid_out <= 0;
    end

    wr_ptr_meta <= wr_ptr_c2c;
    wr_ptr_c2c  <= wr_ptr;

    if (reset_clk_rd) begin
      rd_ptr    <= 0;
      valid_out <= 0;
    end

  end


  // This should turn into four LUT RAMs, which is the best you can get
  // from an FPGA for this function.
  function [3:0] next_gray_code;
    input [3:0] I;
    begin
      case (I)
         0: next_gray_code =  1;
         1: next_gray_code =  3;
         3: next_gray_code =  2;
         2: next_gray_code =  6;
         6: next_gray_code =  7;
         7: next_gray_code =  5;
         5: next_gray_code =  4;
         4: next_gray_code = 12;
        12: next_gray_code = 13;
        13: next_gray_code = 15;
        15: next_gray_code = 14;
        14: next_gray_code = 10;
        10: next_gray_code = 11;
        11: next_gray_code =  9;
         9: next_gray_code =  8;
         8: next_gray_code =  0;
      endcase
    end
  endfunction


endmodule
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to