sync_fifo.v 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. module sync_fifo #(parameter WIDTH = 8, DEPTH = 4, SHOWAEAD = 1) (
  2. input clk,
  3. input rstn,
  4. input wren,
  5. input rden,
  6. input [WIDTH-1:0] din,
  7. output [WIDTH-1:0] dout,
  8. output full,
  9. output empty
  10. );
  11. parameter FIFO_MIN = DEPTH > 1 ? 0 : 1;
  12. parameter FIFO_MAX = DEPTH > 1 ? DEPTH - 1 : 1;
  13. reg [WIDTH-1:0] fifo[FIFO_MAX:FIFO_MIN];
  14. reg [WIDTH-1:0] fifo_out;
  15. parameter ADDR = $clog2(DEPTH);
  16. reg [ADDR:0] counter;
  17. wire [WIDTH-1:0] fifo_head;
  18. wire wrreq = wren && !full;
  19. wire rdreq = rden && !empty;
  20. generate
  21. if (DEPTH > 1)
  22. assign fifo_head = fifo[counter[ADDR-1:0]];
  23. else
  24. assign fifo_head = fifo[1];
  25. endgenerate
  26. always @(posedge clk or negedge rstn) begin
  27. if (!rstn) begin
  28. counter <= 0;
  29. end else if (wrreq && !rdreq) begin
  30. counter <= counter + 1;
  31. end else if (rdreq && !wrreq) begin
  32. counter <= counter - 1;
  33. end
  34. end
  35. integer i;
  36. always @(posedge clk) begin
  37. if (wrreq) begin
  38. for (i = FIFO_MIN; i <= FIFO_MAX; i = i + 1) begin
  39. if (i == 0) begin
  40. fifo[i] <= fifo[FIFO_MAX];
  41. end else if (i == 1) begin
  42. fifo[i] <= din;
  43. end else begin
  44. fifo[i] <= fifo[i - 1];
  45. end
  46. end
  47. end
  48. end
  49. always @(posedge clk or negedge rstn) begin
  50. if (!rstn) begin
  51. fifo_out <= 0;
  52. end else if (rdreq) begin
  53. fifo_out <= fifo_head;
  54. end
  55. end
  56. assign dout = SHOWAEAD ? fifo_head : fifo_out;
  57. assign full = counter[ADDR];
  58. assign empty = counter == 0;
  59. endmodule