dcpktfifo.sv 3.9 KB

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