hub75_fb_readout.v 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * hub75_fb_readout.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2019 Sylvain Munaut <tnt@246tNt.com>
  7. * All rights reserved.
  8. *
  9. * LGPL v3+, see LICENSE.lgpl3
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation; either
  14. * version 3 of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public License
  22. * along with this program; if not, write to the Free Software Foundation,
  23. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24. */
  25. `default_nettype none
  26. module hub75_fb_readout #(
  27. parameter integer N_BANKS = 2,
  28. parameter integer N_ROWS = 32,
  29. parameter integer N_COLS = 64,
  30. parameter integer N_CHANS = 3,
  31. parameter integer N_PLANES = 8,
  32. parameter integer BITDEPTH = 24,
  33. parameter integer FB_AW = 13,
  34. parameter integer FB_DW = 16,
  35. parameter integer FB_DC = 2,
  36. // Auto-set
  37. parameter integer LOG_N_BANKS = $clog2(N_BANKS),
  38. parameter integer LOG_N_ROWS = $clog2(N_ROWS),
  39. parameter integer LOG_N_COLS = $clog2(N_COLS)
  40. )(
  41. // Read interface - Preload
  42. input wire [LOG_N_ROWS-1:0] rd_row_addr,
  43. input wire rd_row_load,
  44. output wire rd_row_rdy,
  45. input wire rd_row_swap,
  46. // Read interface - Access
  47. output wire [(N_BANKS * N_CHANS * N_PLANES)-1:0] rd_data,
  48. input wire [LOG_N_COLS-1:0] rd_col_addr,
  49. input wire rd_en,
  50. // Read Out - Control
  51. output wire ctrl_req,
  52. input wire ctrl_gnt,
  53. output reg ctrl_rel,
  54. // Read Out - Frame Buffer Access
  55. output wire [FB_AW-1:0] fb_addr,
  56. input wire [FB_DW-1:0] fb_data,
  57. // Clock / Reset
  58. input wire clk,
  59. input wire rst
  60. );
  61. // Counter = [ col_addr : bank_addr : dc_idx ]
  62. localparam integer CS1 = $clog2(FB_DC);
  63. localparam integer CS2 = CS1 + LOG_N_BANKS;
  64. localparam integer CW = CS2 + LOG_N_COLS;
  65. // Signals
  66. // -------
  67. // Read-out process
  68. reg rop_buf;
  69. reg rop_pending;
  70. reg rop_running;
  71. reg rop_ready;
  72. reg [LOG_N_ROWS-1:0] rop_row_addr;
  73. reg [CW-1:0] rop_cnt;
  74. reg rop_last;
  75. wire rop_move;
  76. wire rop_done;
  77. // Frame buffer access
  78. wire fb_rden;
  79. reg fb_rden_r;
  80. reg [FB_DW-1:0] fb_data_save;
  81. wire [FB_DW-1:0] fb_data_mux;
  82. reg [(FB_DC*FB_DW)-1:0] fb_data_ext;
  83. // Color Mapper
  84. reg [CW-CS1-1:0] cm_in_user_addr_pre;
  85. reg cm_in_user_last_pre;
  86. reg cm_in_valid_pre;
  87. wire [BITDEPTH-1:0] cm_in_data;
  88. reg [CW-CS1-1:0] cm_in_user_addr;
  89. reg cm_in_user_last;
  90. reg cm_in_valid;
  91. wire cm_in_ready;
  92. wire [(N_CHANS*N_PLANES)-1:0] cm_out_data;
  93. wire [CW-CS1-1:0] cm_out_user_addr;
  94. wire cm_out_user_last;
  95. wire cm_out_valid;
  96. // Line buffer access
  97. wire [(N_BANKS * N_CHANS * N_PLANES)-1:0] rolb_wr_data;
  98. wire [N_BANKS-1:0] rolb_wr_mask;
  99. wire [LOG_N_COLS-1:0] rolb_wr_addr;
  100. wire rolb_wr_ena;
  101. // Control
  102. // -------
  103. // Buffer swap
  104. always @(posedge clk or posedge rst)
  105. if (rst)
  106. rop_buf <= 1'b0;
  107. else
  108. rop_buf <= rop_buf ^ rd_row_swap;
  109. // Track status and requests
  110. always @(posedge clk or posedge rst)
  111. if (rst) begin
  112. rop_pending <= 1'b0;
  113. rop_running <= 1'b0;
  114. rop_ready <= 1'b0;
  115. end else begin
  116. rop_pending <= (rop_pending & ~ctrl_gnt) | rd_row_load;
  117. rop_running <= (rop_running & ~rop_done) | ctrl_gnt;
  118. rop_ready <= (rop_ready | rop_done) & ~rd_row_load;
  119. end
  120. // Arbiter interface
  121. assign ctrl_req = rop_pending;
  122. always @(posedge clk)
  123. ctrl_rel <= cm_out_valid & cm_out_user_last;
  124. // Read interface
  125. assign rd_row_rdy = rop_ready;
  126. // Latch row address
  127. always @(posedge clk)
  128. if (rd_row_load)
  129. rop_row_addr <= rd_row_addr;
  130. // Counter
  131. always @(posedge clk or negedge rop_running)
  132. if (~rop_running) begin
  133. rop_cnt <= 0;
  134. rop_last <= 1'b0;
  135. end else if (rop_move) begin
  136. rop_cnt <= rop_cnt + 1;
  137. rop_last <= rop_cnt == ((N_COLS << CS2) - 2);
  138. end
  139. assign rop_done = rop_last & rop_move;
  140. // Move pipeline ahead
  141. assign rop_move = ~cm_in_valid | cm_in_ready;
  142. // Line buffer
  143. // -----------
  144. hub75_linebuffer #(
  145. .N_WORDS(N_BANKS),
  146. .WORD_WIDTH(N_CHANS * N_PLANES),
  147. .ADDR_WIDTH(1 + LOG_N_COLS)
  148. ) readout_buf_I (
  149. .wr_addr({~rop_buf, rolb_wr_addr}),
  150. .wr_data(rolb_wr_data),
  151. .wr_mask(rolb_wr_mask),
  152. .wr_ena(rolb_wr_ena),
  153. .rd_addr({rop_buf, rd_col_addr}),
  154. .rd_data(rd_data),
  155. .rd_ena(rd_en),
  156. .clk(clk)
  157. );
  158. // Frame buffer -> Color mapper
  159. // ----------------------------
  160. // Frame buffer read
  161. assign fb_addr = { rop_row_addr, rop_cnt };
  162. assign fb_rden = rop_move;
  163. // Simulate a 'READ ENABLE' on the frame buffer by saving the previous
  164. // data and muxing
  165. always @(posedge clk)
  166. fb_rden_r <= fb_rden;
  167. always @(posedge clk)
  168. if (fb_rden_r)
  169. fb_data_save <= fb_data;
  170. assign fb_data_mux = fb_rden_r ? fb_data : fb_data_save;
  171. // Shift register of frame buffer words to reconstruct and entire
  172. // 'BITDEPTH' worth of bits.
  173. always @(posedge clk)
  174. if (rop_move)
  175. if (FB_DC > 1)
  176. fb_data_ext <= { fb_data_mux, fb_data_ext[(FB_DC*FB_DW)-1:FB_DW] };
  177. else
  178. fb_data_ext <= { fb_data_mux };
  179. // Map to the color mapper input
  180. assign cm_in_data = fb_data_ext[BITDEPTH-1:0];
  181. always @(posedge clk or posedge rst)
  182. if (rst) begin
  183. cm_in_valid_pre <= 1'b0;
  184. cm_in_valid <= 1'b0;
  185. end else if (rop_move) begin
  186. if (CS1 > 0)
  187. cm_in_valid_pre <= rop_running & &rop_cnt[CS1-1:0];
  188. else
  189. cm_in_valid_pre <= rop_running;
  190. cm_in_valid <= cm_in_valid_pre;
  191. end
  192. always @(posedge clk)
  193. if (rop_move) begin
  194. // This is synced with the RAM output
  195. cm_in_user_addr_pre <= rop_cnt[CW-1:CS1];
  196. cm_in_user_last_pre <= rop_last;
  197. // This is synced with the fb_data_ext signal
  198. cm_in_user_addr <= cm_in_user_addr_pre;
  199. cm_in_user_last <= cm_in_user_last_pre;
  200. end
  201. // Color mapping core
  202. // ------------------
  203. hub75_colormap #(
  204. .N_CHANS(N_CHANS),
  205. .N_PLANES(N_PLANES),
  206. .BITDEPTH(BITDEPTH),
  207. .USER_WIDTH(CW-CS1+1)
  208. ) cm_I (
  209. .in_data(cm_in_data),
  210. .in_user({cm_in_user_addr, cm_in_user_last}),
  211. .in_valid(cm_in_valid),
  212. .in_ready(cm_in_ready),
  213. .out_data(cm_out_data),
  214. .out_user({cm_out_user_addr, cm_out_user_last}),
  215. .out_valid(cm_out_valid),
  216. .clk(clk),
  217. .rst(rst)
  218. );
  219. // Color mapper -> Line buffer
  220. // ---------------------------
  221. genvar i;
  222. assign rolb_wr_data = { (N_BANKS){cm_out_data} };
  223. assign rolb_wr_addr = cm_out_user_addr[CW-CS1-1:CS2-CS1];
  224. assign rolb_wr_ena = cm_out_valid;
  225. generate
  226. if (N_BANKS > 1)
  227. for (i=0; i<N_BANKS; i=i+1)
  228. assign rolb_wr_mask[i] = (cm_out_user_addr[CS2-CS1-1:0] == i);
  229. else
  230. assign rolb_wr_mask = 1'b1;
  231. endgenerate
  232. endmodule // hub75_fb_readout