top.v 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. `default_nettype none
  2. module top(
  3. input clka,
  4. output [2:0] vga_red,
  5. output [2:0] vga_green,
  6. output [2:0] vga_blue,
  7. output vga_hsync_n,
  8. output vga_vsync_n,
  9. input SCK, // arduino 13
  10. input MOSI, // arduino 11
  11. output MISO, // arduino 12
  12. input SSEL, // arduino 9
  13. input AUX, // arduino 2
  14. output AUDIOL,
  15. output AUDIOR,
  16. output flashMOSI,
  17. input flashMISO,
  18. output flashSCK,
  19. output flashSSEL
  20. );
  21. // Convert 25MHz input clock to 65MHz by multiplying by 13/5.
  22. wire ck_fb, clk;
  23. DCM #(
  24. .CLKFX_MULTIPLY(13),
  25. .CLKFX_DIVIDE(5),
  26. .DFS_FREQUENCY_MODE("LOW"),
  27. .DUTY_CYCLE_CORRECTION("TRUE"),
  28. .STARTUP_WAIT("TRUE")
  29. ) DCM_inst (
  30. .CLKIN(clka), // Clock input (from IBUFG, BUFG or DCM)
  31. .CLK0(ck_fb),
  32. .CLKFX(clk),
  33. .CLKFB(ck_fb), // DCM clock feedback
  34. .RST(0)
  35. );
  36. wire we;
  37. wire [7:0] wd;
  38. wire textMISO;
  39. spi _s (.clk(clk),
  40. .SCK(SCK),
  41. .MOSI(MOSI),
  42. .MISO(textMISO),
  43. .SSEL(SSEL),
  44. .we(we),
  45. .byte_recv(wd),
  46. .byte_xmit(8'ha0));
  47. reg [1:0] state; // 0: scroll, 1: hibyte, 2: lobyte, 3: data
  48. reg [6:0] scroll; // Y scroll register, 0-127
  49. reg[14:0] a;
  50. wire wclk = SCK;
  51. textmode tm(.wclk(wclk),
  52. .write(we & (state == 3)),
  53. .addr(a),
  54. .d(wd),
  55. .scroll(scroll),
  56. .clk(clk),
  57. .vga_red(vga_red),
  58. .vga_green(vga_green),
  59. .vga_blue(vga_blue),
  60. .vga_hsync_n(vga_hsync_n),
  61. .vga_vsync_n(vga_vsync_n));
  62. always @(posedge SSEL or posedge SCK)
  63. if (SSEL == 1)
  64. state <= 0;
  65. else if (we)
  66. case (state)
  67. 0: begin scroll <= wd[6:0]; state <= 1; end
  68. 1: begin a[14:8] <= wd[6:0]; state <= 2; end
  69. 2: begin a[7:0] <= wd; state <= 3; end
  70. 3: begin a <= a + 1; end
  71. endcase
  72. assign {AUDIOL, AUDIOR} = 2'b00;
  73. assign flashMOSI = MOSI;
  74. assign flashSCK = SCK;
  75. assign flashSSEL = AUX;
  76. assign MISO = (SSEL == 0) ? textMISO : flashMISO;
  77. endmodule
  78. // SPI controller
  79. module spi(
  80. input clk,
  81. input SCK, input MOSI, output MISO, input SSEL,
  82. output we,
  83. output [7:0] byte_recv,
  84. input [7:0] byte_xmit);
  85. reg [2:0] bit;
  86. reg [7:0] recv;
  87. wire [7:0] recvN = {recv[6:0], MOSI};
  88. always @(posedge SSEL or posedge SCK)
  89. if (SSEL == 1)
  90. bit <= 7;
  91. else begin
  92. recv <= recvN;
  93. bit <= bit - 1;
  94. end
  95. assign MISO = byte_xmit[bit[2:0]];
  96. assign byte_recv = recvN;
  97. assign we = !SSEL & (bit == 0);
  98. endmodule
  99. // A 16384x8 RAM with one write port and one read port
  100. module ram16k(
  101. input wclk,
  102. input write,
  103. input [13:0] waddr,
  104. input [7:0] din,
  105. input rclk,
  106. input [13:0] raddr,
  107. output [7:0] dout);
  108. //synthesis attribute ram_style of mem is block
  109. reg [7:0] mem[0:16383]; //pragma attribute mem ram_block TRUE
  110. reg [13:0] raddr_reg;
  111. always @ (posedge wclk)
  112. if (write)
  113. mem[waddr] <= din;
  114. always @ (posedge rclk)
  115. raddr_reg <= raddr;
  116. assign dout = mem[raddr_reg];
  117. endmodule
  118. module textmode(
  119. input wclk, // write clock
  120. input write, // write enable
  121. input [14:0] addr, // write address 0-32767
  122. input [7:0] d, // write data
  123. input clk, // pixel clock
  124. input [6:0] scroll, // Y scroll value, 0-127
  125. output reg [2:0] vga_red, // VGA output signals
  126. output reg [2:0] vga_green,
  127. output reg [2:0] vga_blue,
  128. output reg vga_hsync_n,
  129. output reg vga_vsync_n);
  130. // These timing values come from
  131. // http://tinyvga.com/vga-timing/1024x768@60Hz
  132. // hcounter:
  133. // 0 -1023 visible area
  134. // 1024-1047 front porch
  135. // 1048-1183 sync pulse
  136. // 1184-1343 back porch
  137. reg [10:0] hcounter;
  138. wire [10:0] hcounterN = (hcounter == 11'd1343) ? 11'd0 : (hcounter + 11'd1);
  139. // vcounter:
  140. // 0 -767 visible area
  141. // 768-770 front porch
  142. // 771-776 sync pulse
  143. // 777-805 back porch
  144. reg [9:0] vcounter;
  145. reg [9:0] vcounterN;
  146. always @*
  147. if (hcounterN != 11'd0)
  148. vcounterN = vcounter;
  149. else if (vcounter != 10'd805)
  150. vcounterN = vcounter + 1;
  151. else
  152. vcounterN = 10'd0;
  153. wire visible = (hcounter < 1024) & (vcounter < 768);
  154. wire [7:0] ram_char, ram_attr;
  155. wire [6:0] row = scroll + vcounterN[9:4];
  156. wire [13:0] raddr = {row, hcounterN[9:3]};
  157. ram16k attr(.wclk(wclk), .rclk(clk), .write(write & (addr[0] == 0)), .waddr(addr[14:1]), .raddr(raddr), .din(d), .dout(ram_char));
  158. ram16k char(.wclk(wclk), .rclk(clk), .write(write & (addr[0] == 1)), .waddr(addr[14:1]), .raddr(raddr), .din(d), .dout(ram_attr));
  159. wire pix;
  160. fontrom fr(.clk(clk), .ch(ram_char), .row(vcounterN[3:0]), .col(hcounterN[2:0] - 1), .pix(pix));
  161. reg pix_;
  162. reg [7:0] attr1, attr2;
  163. reg [1:0] visible_;
  164. reg [1:0] hsync_;
  165. always @(posedge clk) begin
  166. pix_ <= pix;
  167. {attr2, attr1} <= {attr1, ram_attr};
  168. visible_ <= {visible_[0], visible};
  169. hsync_ <= {hsync_[0], !((1048 <= hcounter) & (hcounter < 1184))};
  170. end
  171. wire [3:0] index = pix_ ? attr2[3:0] : attr2[7:4];
  172. reg [2:0] r, g, b;
  173. always @*
  174. case (index)
  175. 0: {r, g, b} = { 3'b000, 3'b000, 3'b000 };
  176. 1: {r, g, b} = { 3'b000, 3'b000, 3'b100 };
  177. 2: {r, g, b} = { 3'b000, 3'b100, 3'b000 };
  178. 3: {r, g, b} = { 3'b000, 3'b100, 3'b100 };
  179. 4: {r, g, b} = { 3'b100, 3'b000, 3'b000 };
  180. 5: {r, g, b} = { 3'b100, 3'b000, 3'b100 };
  181. 6: {r, g, b} = { 3'b100, 3'b001, 3'b000 };
  182. 7: {r, g, b} = { 3'b100, 3'b100, 3'b100 };
  183. 8: {r, g, b} = { 3'b011, 3'b011, 3'b011 };
  184. 9: {r, g, b} = { 3'b010, 3'b010, 3'b111 };
  185. 10: {r, g, b} = { 3'b010, 3'b111, 3'b010 };
  186. 11: {r, g, b} = { 3'b010, 3'b111, 3'b111 };
  187. 12: {r, g, b} = { 3'b111, 3'b010, 3'b010 };
  188. 13: {r, g, b} = { 3'b111, 3'b010, 3'b111 };
  189. 14: {r, g, b} = { 3'b111, 3'b111, 3'b010 };
  190. 15: {r, g, b} = { 3'b111, 3'b111, 3'b111 };
  191. endcase
  192. always @(posedge clk) begin
  193. hcounter <= hcounterN;
  194. vcounter <= vcounterN;
  195. vga_hsync_n <= hsync_[1];
  196. vga_vsync_n <= !((771 <= vcounter) & (vcounter < 777));
  197. vga_red <= visible_[1] ? r : 3'b000;
  198. vga_green <= visible_[1] ? g : 3'b000;
  199. vga_blue <= visible_[1] ? b : 3'b000;
  200. end
  201. endmodule