vstream.v 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * vstream.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 vstream #(
  35. parameter integer N_ROWS = 64, // # of rows (must be power of 2!!!)
  36. parameter integer N_COLS = 64, // # of columns
  37. parameter integer BITDEPTH = 24,
  38. // Auto-set
  39. parameter integer LOG_N_ROWS = $clog2(N_ROWS),
  40. parameter integer LOG_N_COLS = $clog2(N_COLS)
  41. )(
  42. // SPI to the host
  43. input wire spi_mosi,
  44. output wire spi_miso,
  45. input wire spi_cs_n,
  46. input wire spi_clk,
  47. // Frame Buffer write interface
  48. output wire [LOG_N_ROWS-1:0] fbw_row_addr,
  49. output wire fbw_row_store,
  50. input wire fbw_row_rdy,
  51. output wire fbw_row_swap,
  52. output wire [BITDEPTH-1:0] fbw_data,
  53. output wire [LOG_N_COLS-1:0] fbw_col_addr,
  54. output wire fbw_wren,
  55. output wire frame_swap,
  56. input wire frame_rdy,
  57. // Clock / Reset
  58. input wire clk,
  59. input wire rst
  60. );
  61. localparam integer TW = BITDEPTH / 8;
  62. // Signals
  63. // -------
  64. // SPI bus
  65. wire [7:0] sb_addr;
  66. wire [7:0] sb_data;
  67. wire sb_first;
  68. wire sb_last;
  69. wire sb_stb;
  70. wire [7:0] sb_out;
  71. // Front Buffer write
  72. reg [TW-1:0] trig;
  73. reg [LOG_N_COLS-1:0] cnt_col;
  74. reg [7:0] sb_data_r[0:1];
  75. reg store_swap_pending;
  76. reg [5:0] err_cnt;
  77. wire err;
  78. // SPI interface
  79. // -------------
  80. `ifdef SPI_FAST
  81. spi_fast spi_I (
  82. `else
  83. spi_simple spi_I (
  84. `endif
  85. .spi_mosi(spi_mosi),
  86. .spi_miso(spi_miso),
  87. .spi_cs_n(spi_cs_n),
  88. .spi_clk(spi_clk),
  89. .addr(sb_addr),
  90. .data(sb_data),
  91. .first(sb_first),
  92. .last(sb_last),
  93. .strobe(sb_stb),
  94. .out(sb_out),
  95. .clk(clk),
  96. .rst(rst)
  97. );
  98. assign sb_out = { err_cnt, frame_rdy, fbw_row_rdy };
  99. // Front-Buffer write
  100. // ------------------
  101. // "Trigger"
  102. always @(posedge clk or posedge rst)
  103. if (TW > 1) begin
  104. if (rst)
  105. trig <= { 1'b1, {(TW-1){1'b0}} };
  106. else if (sb_stb)
  107. trig <= sb_last ? { 1'b1, {(TW-1){1'b0}} } : { trig[0], trig[TW-1:1] };
  108. end else
  109. trig <= 1'b1;
  110. // Column counter
  111. always @(posedge clk or posedge rst)
  112. if (rst)
  113. cnt_col <= 0;
  114. else if (sb_stb)
  115. cnt_col <= sb_last ? 0 : (cnt_col + trig[0]);
  116. // Register data for wide writes
  117. always @(posedge clk)
  118. if (sb_stb) begin
  119. sb_data_r[0] <= sb_data;
  120. sb_data_r[1] <= sb_data_r[0];
  121. end
  122. // Write commands
  123. assign fbw_wren = sb_stb & sb_addr[7] & trig[0];
  124. assign fbw_col_addr = cnt_col;
  125. // Map to color
  126. generate
  127. if (BITDEPTH == 8)
  128. assign fbw_data = sb_data;
  129. else if (BITDEPTH == 16)
  130. assign fbw_data = { sb_data, sb_data_r[0] };
  131. else if (BITDEPTH == 24)
  132. assign fbw_data = { sb_data, sb_data_r[0], sb_data_r[1] };
  133. endgenerate
  134. // Back-Buffer store
  135. // -----------------
  136. // Direct commands
  137. assign fbw_row_addr = sb_data[LOG_N_ROWS-1:0];
  138. assign fbw_row_store = (sb_stb & sb_first & ~sb_addr[7] & sb_addr[0]) | (fbw_row_rdy & store_swap_pending);
  139. assign fbw_row_swap = (sb_stb & sb_first & ~sb_addr[7] & sb_addr[1]) | (fbw_row_rdy & store_swap_pending);
  140. // Delayed command
  141. always @(posedge clk or posedge rst)
  142. if (rst)
  143. store_swap_pending <= 1'b0;
  144. else
  145. store_swap_pending <= (store_swap_pending & ~fbw_row_rdy) | (sb_stb & sb_first & ~sb_addr[7] & sb_addr[3]);
  146. // Error tracking
  147. assign err =
  148. (~fbw_row_rdy & (fbw_row_store | fbw_row_swap)) |
  149. (store_swap_pending & fbw_wren);
  150. always @(posedge clk or posedge rst)
  151. if (rst)
  152. err_cnt <= 0;
  153. else
  154. err_cnt <= err_cnt + err;
  155. // Next frame
  156. // ----------
  157. assign frame_swap = sb_stb & sb_first & ~sb_addr[7] & sb_addr[2];
  158. endmodule // vstream