PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/verilog/BrainfuckCore.v

http://github.com/whitequark/bfcpu2
V | 307 lines | 304 code | 3 blank | 0 comment | 0 complexity | 933fa62800476f1652dbe6100340f23a MD5 | raw file
Possible License(s): JSON
  1. `timescale 1ns / 1ps
  2. `include "Common.tf"
  3. `include "Constants.v"
  4. module BrainfuckCore(
  5. clk,
  6. reset,
  7. /* IROM interface */
  8. ice,
  9. ia,
  10. id,
  11. /* DRAM read port */
  12. drce,
  13. dra,
  14. drd,
  15. /* DRAM write port */
  16. dwce,
  17. dwa,
  18. dwq,
  19. /* EXT read port */
  20. cd,
  21. crda,
  22. cack,
  23. /* EXT write port */
  24. cq,
  25. cwre,
  26. cbsy
  27. );
  28. parameter IA_WIDTH = 12;
  29. parameter ID_WIDTH = 8;
  30. parameter DA_WIDTH = 12;
  31. parameter DD_WIDTH = 8;
  32. input clk;
  33. input reset;
  34. wire [IA_WIDTH - 1:0] pc;
  35. wire pc_ce;
  36. Counter #(
  37. .WIDTH(IA_WIDTH)
  38. ) reg_pc (
  39. .clk(clk),
  40. .reset(reset),
  41. .ce(pc_ce),
  42. .q(pc),
  43. .d(12'b0),
  44. .load(1'b0),
  45. .down(1'b0)
  46. );
  47. wire [DA_WIDTH - 1:0] dp;
  48. wire dp_ce, dp_down;
  49. Counter #(
  50. .WIDTH(DA_WIDTH)
  51. ) reg_dp (
  52. .clk(clk),
  53. .reset(reset),
  54. .ce(dp_ce),
  55. .q(dp),
  56. .d(12'b0),
  57. .load(1'b0),
  58. .down(dp_down)
  59. );
  60. output ice;
  61. output [IA_WIDTH - 1:0] ia;
  62. input [ID_WIDTH - 1:0] id;
  63. output drce, dwce;
  64. output [DA_WIDTH - 1:0] dra;
  65. output [DA_WIDTH - 1:0] dwa;
  66. input [DD_WIDTH - 1:0] drd;
  67. output [DD_WIDTH - 1:0] dwq;
  68. input [7:0] cd;
  69. input crda;
  70. output cack;
  71. output [7:0] cq;
  72. output cwre;
  73. input cbsy;
  74. wire [ID_WIDTH - 1:0] idecode_opcode;
  75. wire idecode_ack;
  76. wire [`OPCODE_MSB:0] execute_operation;
  77. wire execute_ack;
  78. wire [DD_WIDTH - 1:0] execute_a;
  79. wire [`OPCODE_MSB:0] writeback_operation;
  80. wire writeback_ack;
  81. wire [DA_WIDTH - 1:0] writeback_dp;
  82. /*
  83. * Fetch instruction, taking memory delays into
  84. * account.
  85. * This stage prefetches one instruction.
  86. */
  87. StageIFetch #(
  88. .A_WIDTH(IA_WIDTH),
  89. .D_WIDTH(ID_WIDTH)
  90. ) ifetch (
  91. .clk(clk),
  92. .reset(reset),
  93. /* PC register value, to get instruction address */
  94. .pc(pc),
  95. /* Has ifetch got an instruction last cycle? */
  96. .step_pc(pc_ce),
  97. /* IROM interface */
  98. .ice(ice),
  99. .ia(ia),
  100. .id(id),
  101. .opcode(idecode_opcode),
  102. .ack_in(idecode_ack)
  103. );
  104. /*
  105. * Decode instruction. IDecode has fixed 8 bit width.
  106. */
  107. StageIDecode idecode (
  108. .clk(clk),
  109. .reset(reset),
  110. .opcode_in(idecode_opcode),
  111. .ack(idecode_ack),
  112. .operation(execute_operation),
  113. .ack_in(execute_ack)
  114. );
  115. /*
  116. * Execute the instruction.
  117. * This stage prefetches one datum and maintains cache consistency
  118. * on data pointer updates.
  119. */
  120. StageExecute #(
  121. .A_WIDTH(DA_WIDTH),
  122. .D_WIDTH(DD_WIDTH)
  123. ) execute (
  124. .clk(clk),
  125. .reset(reset),
  126. /* DP register value, to get a datum */
  127. .dp(dp),
  128. /* DP register increment and decrement control lines */
  129. .dp_ce(dp_ce),
  130. .dp_down(dp_down),
  131. /* DP register cache, to avoid WAW(mem,dp) hazard */
  132. .dp_cache(writeback_dp),
  133. /* DRAM read port interface */
  134. .dce(drce),
  135. .da(dra),
  136. .dd(drd),
  137. /* EXT read port interface */
  138. .cd(cd),
  139. .crda(crda),
  140. .cack(cack),
  141. /* Accumulator output */
  142. .a(execute_a),
  143. .operation_in(execute_operation),
  144. .ack(execute_ack),
  145. .operation(writeback_operation),
  146. .ack_in(writeback_ack)
  147. );
  148. /*
  149. * Write accumulator back to DRAM or to I/O module.
  150. */
  151. StageWriteback #(
  152. .A_WIDTH(DA_WIDTH),
  153. .D_WIDTH(DD_WIDTH)
  154. ) writeback (
  155. .clk(clk),
  156. .reset(reset),
  157. /* DP register value, to write a datum */
  158. .dp(writeback_dp),
  159. /* DRAM write port interface */
  160. .dce(dwce),
  161. .da(dwa),
  162. .dq(dwq),
  163. /* EXT write port interface */
  164. .cq(cq),
  165. .cwre(cwre),
  166. .cbsy(cbsy),
  167. /* Accumulator input */
  168. .a_in(execute_a),
  169. .operation_in(writeback_operation),
  170. .ack(writeback_ack),
  171. /* The last stage has ACK always asserted. */
  172. .ack_in(1'b1)
  173. );
  174. endmodule
  175. module BrainfuckCoreTest;
  176. reg clk;
  177. reg reset;
  178. wire ce, drce, dwce;
  179. wire [11:0] ia;
  180. wire [11:0] dra;
  181. wire [11:0] dwa;
  182. wire [7:0] id;
  183. wire [7:0] drd;
  184. wire [7:0] dwq;
  185. wire cack, cwre;
  186. reg crda, cbsy;
  187. reg [7:0] cd;
  188. wire [7:0] cq;
  189. BrainfuckCore uut (
  190. .clk(clk),
  191. .reset(reset),
  192. .ice(ice),
  193. .ia(ia),
  194. .id(id),
  195. .drce(drce),
  196. .dra(dra),
  197. .drd(drd),
  198. .dwce(dwce),
  199. .dwa(dwa),
  200. .dwq(dwq),
  201. .cd(cd),
  202. .crda(crda),
  203. .cack(cack),
  204. .cq(cq),
  205. .cwre(cwre),
  206. .cbsy(cbsy)
  207. );
  208. IROM irom (
  209. .clk(clk),
  210. .ce(ice),
  211. .a(ia),
  212. .q(id)
  213. );
  214. DRAM dram (
  215. .clk(clk),
  216. .rce(drce),
  217. .ra(dra),
  218. .rq(drd),
  219. .wce(dwce),
  220. .wa(dwa),
  221. .wd(dwq)
  222. );
  223. initial begin
  224. clk = 0;
  225. reset = 0;
  226. crda = 0;
  227. `reset
  228. #161; crda = 1; cd = 8'h42;
  229. #20; cd = 8'h43;
  230. #20; crda = 0; cd = 0;
  231. end
  232. always begin
  233. `step
  234. end
  235. reg [1:0] uart_wait = 2'b00;
  236. always @(posedge clk) begin
  237. if (cwre) begin
  238. $write("%c", cq);
  239. cbsy <= 1'b1;
  240. uart_wait <= 2'b11;
  241. end else begin
  242. if (uart_wait)
  243. uart_wait <= uart_wait - 1;
  244. else
  245. cbsy <= 1'b0;
  246. end
  247. end
  248. endmodule