dcpktfifo.sv 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. //
  2. // dcpktfifo.sv
  3. //
  4. // Dual-clock RAM-based FIFO with transaction support (commit/abort)
  5. //
  6. // Parametric synchronous RAM module, dual clock,
  7. // one read and one write port; output data not
  8. // registered
  9. module dcqram
  10. #(
  11. parameter wbits, // log2(size in words)
  12. parameter width = 8
  13. )
  14. (
  15. input wclk,
  16. input wstb,
  17. input [wbits-1:0] waddr,
  18. input [width-1:0] wdata,
  19. input rclk,
  20. input [wbits-1:0] raddr,
  21. output [width-1:0] rdata
  22. );
  23. `ifdef ALTERA_RESERVED_QIS
  24. (* ramstyle = "no_rw_check" *)
  25. `endif
  26. reg [width-1:0] mem[0:(1 << wbits)-1];
  27. always @(posedge wclk)
  28. if (wstb)
  29. mem[waddr] <= wdata;
  30. reg [wbits-1:0] raddr_q;
  31. assign rdata = mem[raddr_q];
  32. always @(posedge rclk)
  33. raddr_q <= raddr;
  34. endmodule // dcqram
  35. module dcpktfifo
  36. #(
  37. parameter wbits = 10,
  38. parameter width = 8,
  39. parameter [0:0] wtrans = 1'b1, // Support transactions on write side
  40. parameter [0:0] rtrans = 1'b1 // Support transactions on read side
  41. )
  42. (
  43. input rst_n,
  44. input wclk,
  45. input wstb,
  46. input wcommit,
  47. input wabort,
  48. input [width-1:0] wdata,
  49. output reg [wbits-1:0] wnfree,
  50. output reg wempty,
  51. output reg wfull,
  52. input rclk,
  53. input rstb,
  54. input rcommit,
  55. input rabort,
  56. output [width-1:0] rdata,
  57. output reg [wbits-1:0] rnavail,
  58. output reg rempty,
  59. output reg rlast,
  60. output reg remptyh, // Cleared only on abort/commit
  61. output reg rlasth, // Cleared only on abort/commit
  62. output reg rfull
  63. );
  64. reg [wbits-1:0] wtaddr; // Transient write address
  65. reg [wbits-1:0] wcaddr; // Committed write address
  66. wire [wbits-1:0] w_rcaddr; // rcaddr latched in the wclk domain
  67. wire wcommit_w = wtrans ? wcommit : 1'b1;
  68. wire wabort_w = wtrans ? wabort : 1'b0;
  69. wire [wbits-1:0] wcaddr_w = wtrans ? wcaddr : wtaddr;
  70. wire wstb_w = wstb & ~wfull;
  71. wire [wbits-1:0] wnused = wtaddr + wstb_w - w_rcaddr;
  72. always @(negedge rst_n or posedge wclk)
  73. if (~rst_n)
  74. begin
  75. wtaddr <= 'b0;
  76. wcaddr <= 'b0;
  77. wempty <= 1'b1;
  78. wfull <= 1'b0;
  79. end
  80. else
  81. begin
  82. if (wabort_w)
  83. wtaddr <= wcaddr_w;
  84. else
  85. begin
  86. wtaddr <= wtaddr + wstb_w;
  87. if (wcommit_w)
  88. wcaddr <= wtaddr + wstb_w;
  89. end
  90. wnfree <= ~wnused;
  91. wempty <= ~|wnused;
  92. wfull <= &wnused;
  93. end // else: !if(~rst_n)
  94. reg [wbits-1:0] rtaddr; // Transient read address
  95. reg [wbits-1:0] rcaddr; // Committed read address
  96. wire [wbits-1:0] r_wcaddr; // wcaddr latched in the rclk domain
  97. wire rcommit_w = rtrans ? rcommit : 1'b1;
  98. wire rabort_w = rtrans ? rabort : 1'b0;
  99. wire [wbits-1:0] rcaddr_w = rtrans ? rcaddr : rtaddr;
  100. wire rstb_w = rstb & ~rempty;
  101. wire [wbits-1:0] rtaddr_next = (rabort_w & ~rcommit_w)
  102. ? rcaddr : rtaddr + rstb_w;
  103. wire [wbits-1:0] rnused_w = r_wcaddr - rtaddr_next;
  104. always @(negedge rst_n or posedge rclk)
  105. if (~rst_n)
  106. begin
  107. rtaddr <= 'b0;
  108. rcaddr <= 'b0;
  109. rnavail <= 'b0;
  110. rempty <= 1'b1;
  111. rlast <= 1'b1;
  112. rfull <= 1'b0;
  113. end
  114. else
  115. begin
  116. rtaddr <= rtaddr_next;
  117. if (rcommit_w)
  118. rcaddr <= rtaddr_next;
  119. rnavail <= rnused_w;
  120. rempty <= ~|rnused_w;
  121. remptyh <= ~|rnused_w | (remptyh & ~(rcommit_w|rabort_w));
  122. rlast <= ~|rnused_w[wbits-1:1];
  123. rlasth <= ~|rnused_w[wbits-1:1] | (rlasth & ~(rcommit_w|rabort_w));
  124. rfull <= &rnused_w;
  125. end // else: !if(~rst_n)
  126. // Address pointer synchronizers.
  127. synchronizer #(.width(wbits))
  128. syncrcaddr (
  129. .rst_n (rst_n),
  130. .clk (wclk),
  131. .d (rcaddr_w),
  132. .q (w_rcaddr)
  133. );
  134. synchronizer #(.width(wbits))
  135. syncwcaddr (
  136. .rst_n (rst_n),
  137. .clk (rclk),
  138. .d (wcaddr_w),
  139. .q (r_wcaddr)
  140. );
  141. //
  142. // Memory array
  143. //
  144. dcqram #(.wbits(wbits), .width(width))
  145. ram (
  146. .wclk (wclk),
  147. .wstb (wstb),
  148. .waddr (wtaddr),
  149. .wdata (wdata),
  150. .rclk (rclk),
  151. .raddr (rtaddr_next),
  152. .rdata (rdata)
  153. );
  154. // For debugging
  155. (* preserve, noprune *) reg wflag;
  156. always @(posedge wclk)
  157. wflag <= (wflag | wstb_w) & ~(wcommit|wabort);
  158. (* preserve, noprune *) reg rflag;
  159. always @(posedge rclk)
  160. rflag <= (rflag | rstb) & ~(rcommit|rabort);
  161. endmodule // dcpktfifo