vgen.v 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * vgen.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2019 Sylvain Munaut <tnt@246tNt.com>
  7. * All rights reserved.
  8. *
  9. * BSD 3-clause, see LICENSE.bsd
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are met:
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * * Neither the name of the <organization> nor the
  19. * names of its contributors may be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  26. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. `default_nettype none
  34. module vgen #(
  35. parameter ADDR_BASE = 24'h040000,
  36. parameter integer N_FRAMES = 30,
  37. parameter integer N_ROWS = 64, // # of rows (must be power of 2!!!)
  38. parameter integer N_COLS = 64, // # of columns
  39. parameter integer BITDEPTH = 24,
  40. // Auto-set
  41. parameter integer LOG_N_ROWS = $clog2(N_ROWS),
  42. parameter integer LOG_N_COLS = $clog2(N_COLS)
  43. )(
  44. // SPI reader interface
  45. output wire [23:0] sr_addr,
  46. output wire [15:0] sr_len,
  47. output wire sr_go,
  48. input wire sr_rdy,
  49. input wire [7:0] sr_data,
  50. input wire sr_valid,
  51. // Frame Buffer write interface
  52. output wire [LOG_N_ROWS-1:0] fbw_row_addr,
  53. output wire fbw_row_store,
  54. input wire fbw_row_rdy,
  55. output wire fbw_row_swap,
  56. output wire [BITDEPTH-1:0] fbw_data,
  57. output wire [LOG_N_COLS-1:0] fbw_col_addr,
  58. output wire fbw_wren,
  59. output wire frame_swap,
  60. input wire frame_rdy,
  61. // UI
  62. input wire ui_up,
  63. input wire ui_mode,
  64. input wire ui_down,
  65. // Clock / Reset
  66. input wire clk,
  67. input wire rst
  68. );
  69. localparam integer FW = 23 - LOG_N_ROWS - LOG_N_COLS;
  70. // Signals
  71. // -------
  72. // FSM
  73. localparam
  74. ST_FRAME_WAIT = 0,
  75. ST_ROW_SPI_CMD = 1,
  76. ST_ROW_SPI_READ = 2,
  77. ST_ROW_WRITE = 3,
  78. ST_ROW_WAIT = 4;
  79. reg [2:0] fsm_state;
  80. reg [2:0] fsm_state_next;
  81. // UI
  82. reg mode;
  83. reg [3:0] cfg_rep;
  84. reg [1:0] frame_sel;
  85. // Counters
  86. reg [FW-1:0] cnt_frame;
  87. reg cnt_frame_first;
  88. reg cnt_frame_last;
  89. reg [3:0] cnt_rep;
  90. reg cnt_rep_last;
  91. reg [LOG_N_ROWS-1:0] cnt_row;
  92. reg cnt_row_last;
  93. reg [LOG_N_COLS:0] cnt_col;
  94. // SPI
  95. reg [7:0] sr_data_r;
  96. wire [15:0] sr_data16;
  97. // Output
  98. wire [7:0] color [0:2];
  99. // FSM
  100. // ---
  101. // State register
  102. always @(posedge clk or posedge rst)
  103. if (rst)
  104. fsm_state <= ST_FRAME_WAIT;
  105. else
  106. fsm_state <= fsm_state_next;
  107. // Next-State logic
  108. always @(*)
  109. begin
  110. // Default is not to move
  111. fsm_state_next = fsm_state;
  112. // Transitions ?
  113. case (fsm_state)
  114. ST_FRAME_WAIT:
  115. if (frame_rdy & sr_rdy)
  116. fsm_state_next = ST_ROW_SPI_CMD;
  117. ST_ROW_SPI_CMD:
  118. fsm_state_next = ST_ROW_SPI_READ;
  119. ST_ROW_SPI_READ:
  120. if (sr_rdy)
  121. fsm_state_next = ST_ROW_WRITE;
  122. ST_ROW_WRITE:
  123. if (fbw_row_rdy)
  124. fsm_state_next = cnt_row_last ? ST_ROW_WAIT : ST_ROW_SPI_CMD;
  125. ST_ROW_WAIT:
  126. if (fbw_row_rdy)
  127. fsm_state_next = ST_FRAME_WAIT;
  128. endcase
  129. end
  130. // UI handling
  131. // -----------
  132. // Mode toggle
  133. always @(posedge clk or posedge rst)
  134. if (rst)
  135. mode <= 1'b0;
  136. else
  137. mode <= mode ^ ui_mode;
  138. // Repetition counter
  139. always @(posedge clk or posedge rst)
  140. if (rst)
  141. cfg_rep <= 4'h6;
  142. else if (~mode) begin
  143. if (ui_down & ~&cfg_rep)
  144. cfg_rep <= cfg_rep + 1;
  145. else if (ui_up & |cfg_rep)
  146. cfg_rep <= cfg_rep - 1;
  147. end
  148. // Latch request for prev / next frame
  149. always @(posedge clk)
  150. if (~mode)
  151. frame_sel <= cnt_rep_last ? 2'b11 : 2'b00;
  152. else if ((fsm_state == ST_ROW_WAIT) && fbw_row_rdy)
  153. frame_sel <= 2'b00;
  154. else if (ui_up)
  155. frame_sel <= 2'b10;
  156. else if (ui_down)
  157. frame_sel <= 2'b11;
  158. // Counters
  159. // --------
  160. // Frame counter
  161. always @(posedge clk or posedge rst)
  162. if (rst)
  163. cnt_frame <= 0;
  164. else if ((fsm_state == ST_ROW_WAIT) && fbw_row_rdy && frame_sel[1])
  165. if (frame_sel[0])
  166. cnt_frame <= cnt_frame_last ? { (FW){1'b0} } : (cnt_frame + 1);
  167. else
  168. cnt_frame <= cnt_frame_first ? (N_FRAMES - 1) : (cnt_frame - 1);
  169. always @(posedge clk)
  170. begin
  171. // Those end up one cycle late vs 'cnt_frame' but that's fine, they
  172. // won't be used until a while later
  173. cnt_frame_last <= (cnt_frame == (N_FRAMES - 1));
  174. cnt_frame_first <= (cnt_frame == 0);
  175. end
  176. // Repeat counter
  177. always @(posedge clk)
  178. if ((fsm_state == ST_ROW_WAIT) && fbw_row_rdy) begin
  179. cnt_rep <= cnt_rep_last ? 4'h0 : (cnt_rep + 1);
  180. cnt_rep_last <= (cnt_rep == cfg_rep);
  181. end
  182. // Row counter
  183. always @(posedge clk)
  184. if (fsm_state == ST_FRAME_WAIT) begin
  185. cnt_row <= 0;
  186. cnt_row_last <= 1'b0;
  187. end else if ((fsm_state == ST_ROW_WRITE) && fbw_row_rdy) begin
  188. cnt_row <= cnt_row + 1;
  189. cnt_row_last <= (cnt_row == (1 << LOG_N_ROWS) - 2);
  190. end
  191. // Column counter
  192. always @(posedge clk)
  193. if (fsm_state != ST_ROW_SPI_READ)
  194. cnt_col <= 0;
  195. else if (sr_valid)
  196. cnt_col <= cnt_col + 1;
  197. // SPI reader
  198. // ----------
  199. // Requests
  200. assign sr_addr = { cnt_frame, cnt_row, {(LOG_N_COLS+1){1'b0}} } + ADDR_BASE;
  201. assign sr_len = (N_COLS << 1) - 1;
  202. assign sr_go = (fsm_state == ST_ROW_SPI_CMD);
  203. // Data
  204. always @(posedge clk)
  205. if (sr_valid)
  206. sr_data_r <= sr_data;
  207. assign sr_data16 = { sr_data, sr_data_r };
  208. // Front-Buffer write
  209. // ------------------
  210. assign fbw_wren = sr_valid & cnt_col[0];
  211. assign fbw_col_addr = cnt_col[6:1];
  212. // Map to color
  213. assign color[2] = { sr_data16[15:11], sr_data16[15:13] };
  214. assign color[1] = { sr_data16[10: 5], sr_data16[10: 9] };
  215. assign color[0] = { sr_data16[ 4: 0], sr_data16[ 4: 2] };
  216. generate
  217. if (BITDEPTH == 8)
  218. assign fbw_data = { color[2][7:5], color[1][7:5], color[0][7:6] };
  219. else if (BITDEPTH == 16)
  220. assign fbw_data = { color[2][7:3], color[1][7:2], color[0][7:3] };
  221. else if (BITDEPTH == 24)
  222. assign fbw_data = { color[2], color[1], color[0] };
  223. endgenerate
  224. // Back-Buffer store
  225. // -----------------
  226. assign fbw_row_addr = cnt_row;
  227. assign fbw_row_store = (fsm_state == ST_ROW_WRITE) && fbw_row_rdy;
  228. assign fbw_row_swap = (fsm_state == ST_ROW_WRITE) && fbw_row_rdy;
  229. // Next frame
  230. // ----------
  231. assign frame_swap = (fsm_state == ST_ROW_WAIT) && fbw_row_rdy;
  232. endmodule // vgen