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)