cx4.v 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 23:14:37 10/13/2011
  7. // Design Name:
  8. // Module Name: cx4
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21. module cx4(
  22. input [7:0] DI,
  23. output [7:0] DO,
  24. input [12:0] ADDR,
  25. input CS,
  26. input SNES_VECT_EN,
  27. input nRD,
  28. input nWR,
  29. input CLK,
  30. input [23:0] DATROM_DI,
  31. input DATROM_WE,
  32. input [9:0] DATROM_ADDR,
  33. input [7:0] BUS_DI,
  34. output [23:0] BUS_ADDR,
  35. output BUS_RRQ,
  36. input BUS_RDY,
  37. output cx4_active
  38. );
  39. reg [2:0] cx4_busy;
  40. parameter BUSY_CACHE = 2'b00;
  41. parameter BUSY_DMA = 2'b01;
  42. parameter BUSY_CPU = 2'b10;
  43. wire datram_enable = CS & (ADDR[11:0] < 12'hc00);
  44. wire mmio_enable = CS & (ADDR[12:5] == 8'b11111010) & (ADDR[4:0] < 5'b10011);
  45. wire status_enable = CS & (ADDR[12:5] == 8'b11111010) & (ADDR[4:0] >= 5'b10011);
  46. wire vector_enable = (CS & (ADDR[12:5] == 8'b11111011)) | (cx4_active & SNES_VECT_EN);
  47. wire gpr_enable = CS & (&(ADDR[12:7]) && ADDR[5:4] != 2'b11);
  48. wire pgmrom_enable = CS & (ADDR[12:5] == 8'b11110000);
  49. wire [7:0] DATRAM_DO;
  50. reg [7:0] MMIO_DOr;
  51. wire [7:0] MMIO_DO;
  52. wire [7:0] STATUS_DO;
  53. wire [7:0] VECTOR_DO;
  54. wire [7:0] GPR_DO;
  55. assign DO = datram_enable ? DATRAM_DO
  56. : mmio_enable ? MMIO_DO
  57. : status_enable ? STATUS_DO
  58. : vector_enable ? VECTOR_DO
  59. : gpr_enable ? GPR_DO
  60. : 8'h00;
  61. /* 0x1f40 - 0x1f52: MMIO
  62. SNES: 8 bits / CX4: various */
  63. reg [23:0] cx4_mmio_dmasrc;
  64. reg [15:0] cx4_mmio_dmalen;
  65. reg [23:0] cx4_mmio_dmatgt;
  66. reg cx4_mmio_cachepage;
  67. reg [23:0] cx4_mmio_pgmoff;
  68. reg [1:0] cx4_mmio_savepage;
  69. reg [14:0] cx4_mmio_pgmpage;
  70. reg [7:0] cx4_mmio_pc;
  71. reg [7:0] cx4_mmio_r1f50;
  72. reg cx4_mmio_r1f51;
  73. reg cx4_mmio_r1f52;
  74. /* 0x1f53 - 0x1f5f: status register */
  75. assign cx4_active = |cx4_busy;
  76. /* 0x1f60 - 0x1f7f: reset vectors */
  77. reg [7:0] vector [31:0];
  78. /* 0x1f80 - 0x1faf (0x1fc0 - 0x1fef): general purpose register file
  79. SNES: 8 bits / CX4: 24 bits */
  80. reg [7:0] gpr [47:0];
  81. wire [47:0] cpu_mul_result;
  82. reg [14:0] cx4_mmio_pagemem[1:0];
  83. reg [23:0] const [15:0];
  84. reg [14:0] cachetag [1:0];
  85. reg [1:0] cachevalid;
  86. reg [14:0] cache_pgmpage;
  87. reg [14:0] cpu_cache_pgmpage;
  88. reg cache_cachepage;
  89. reg cpu_cache_cachepage;
  90. reg cpu_cache_done;
  91. reg [7:0] cpu_pc_stack [7:0];
  92. reg [7:0] cpu_page_stack;
  93. initial begin
  94. cache_pgmpage = 15'b0;
  95. cpu_cache_pgmpage = 15'b0;
  96. cache_cachepage = 1'b0;
  97. cpu_cache_cachepage = 1'b0;
  98. cpu_cache_done = 1'b0;
  99. cachetag[0] = 14'h0000;
  100. cachetag[1] = 14'h0000;
  101. cachevalid = 2'b00;
  102. cx4_busy = 3'b000;
  103. cx4_mmio_pgmoff = 24'h000000;
  104. cx4_mmio_pgmpage = 15'h0000;
  105. cx4_mmio_dmasrc = 24'h000000;
  106. cx4_mmio_dmalen = 16'h0000;
  107. cx4_mmio_dmatgt = 24'h000000;
  108. cx4_mmio_savepage = 2'b00;
  109. const[0] = 24'h000000;
  110. const[1] = 24'hffffff;
  111. const[2] = 24'h00ff00;
  112. const[3] = 24'hff0000;
  113. const[4] = 24'h00ffff;
  114. const[5] = 24'hffff00;
  115. const[6] = 24'h800000;
  116. const[7] = 24'h7fffff;
  117. const[8] = 24'h008000;
  118. const[9] = 24'h007fff;
  119. const[10] = 24'hff7fff;
  120. const[11] = 24'hffff7f;
  121. const[12] = 24'h010000;
  122. const[13] = 24'hfeffff;
  123. const[14] = 24'h000100;
  124. const[15] = 24'h00feff;
  125. cpu_pc_stack[0] = 8'b0;
  126. cpu_pc_stack[1] = 8'b0;
  127. cpu_pc_stack[2] = 8'b0;
  128. cpu_pc_stack[3] = 8'b0;
  129. cpu_pc_stack[4] = 8'b0;
  130. cpu_pc_stack[5] = 8'b0;
  131. cpu_pc_stack[6] = 8'b0;
  132. cpu_pc_stack[7] = 8'b0;
  133. cpu_page_stack = 8'b0;
  134. end
  135. assign MMIO_DO = MMIO_DOr;
  136. assign VECTOR_DO = vector [ADDR[4:0]];
  137. assign GPR_DO = gpr [ADDR[5:0]];
  138. assign STATUS_DO = {1'b0, cx4_active, 4'b0000, ~cx4_active, 1'b0};
  139. reg [7:0] DIr;
  140. always @(posedge CLK) DIr <= DI;
  141. reg [4:0] datram_enable_sreg;
  142. initial datram_enable_sreg = 5'b11111;
  143. always @(posedge CLK) datram_enable_sreg <= {datram_enable_sreg[3:0], datram_enable};
  144. reg [5:0] nWR_sreg;
  145. always @(posedge CLK) nWR_sreg <= {nWR_sreg[4:0], nWR};
  146. wire WR_EN = (nWR_sreg[5:0] == 6'b000001);
  147. wire DATRAM_WR_EN = datram_enable & WR_EN;
  148. wire MMIO_WR_EN = mmio_enable & WR_EN;
  149. wire VECTOR_WR_EN = vector_enable & WR_EN;
  150. wire GPR_WR_EN = gpr_enable & WR_EN;
  151. reg [23:0] cpu_idb; // tmp register for reg file read
  152. /* Need to cache when:
  153. 1f48 is written
  154. AND (selected cache page is invalid
  155. OR selected cache page does not contain requested page already)
  156. */
  157. reg CACHE_TRIG_ENr;
  158. reg CACHE_TRIG_EN2r;
  159. reg cpu_cache_en;
  160. initial begin
  161. CACHE_TRIG_ENr = 1'b0;
  162. CACHE_TRIG_EN2r = 1'b0;
  163. cpu_cache_en = 1'b0;
  164. end
  165. always @(posedge CLK) CACHE_TRIG_EN2r <= CACHE_TRIG_ENr;
  166. wire CACHE_TRIG_EN = CACHE_TRIG_EN2r;
  167. reg DMA_TRIG_ENr;
  168. initial DMA_TRIG_ENr = 1'b0;
  169. wire DMA_TRIG_EN = DMA_TRIG_ENr;
  170. reg CACHE_BUS_RRQr;
  171. reg DMA_BUS_RRQr;
  172. reg cpu_bus_rq;
  173. initial begin
  174. CACHE_BUS_RRQr = 1'b0;
  175. DMA_BUS_RRQr = 1'b0;
  176. cpu_bus_rq = 1'b0;
  177. end
  178. assign BUS_RRQ = CACHE_BUS_RRQr | DMA_BUS_RRQr | cpu_bus_rq;
  179. reg cpu_page;
  180. reg [14:0] cpu_p;
  181. reg [7:0] cpu_pc;
  182. reg [23:0] cpu_a;
  183. reg fl_n;
  184. reg fl_z;
  185. reg fl_c;
  186. reg cpu_go_en_r;
  187. initial cpu_go_en_r = 1'b0;
  188. initial begin
  189. cx4_mmio_r1f50 = 8'h33;
  190. cx4_mmio_r1f51 = 1'b0;
  191. cx4_mmio_r1f52 = 1'b1;
  192. end
  193. always @(posedge CLK) begin
  194. case (ADDR[4:0])
  195. 5'h00: MMIO_DOr <= cx4_mmio_dmasrc[7:0]; // 1f40
  196. 5'h01: MMIO_DOr <= cx4_mmio_dmasrc[15:8]; // 1f41
  197. 5'h02: MMIO_DOr <= cx4_mmio_dmasrc[23:16]; // 1f42
  198. 5'h03: MMIO_DOr <= cx4_mmio_dmalen[7:0]; // 1f43
  199. 5'h04: MMIO_DOr <= cx4_mmio_dmalen[15:8]; // 1f44
  200. 5'h05: MMIO_DOr <= cx4_mmio_dmatgt[7:0]; // 1f45
  201. 5'h06: MMIO_DOr <= cx4_mmio_dmatgt[15:8]; // 1f46
  202. 5'h07: MMIO_DOr <= cx4_mmio_dmatgt[23:16]; // 1f47
  203. 5'h08: MMIO_DOr <= {7'b0, cx4_mmio_cachepage};
  204. 5'h09: MMIO_DOr <= cx4_mmio_pgmoff[7:0]; // 1f49
  205. 5'h0a: MMIO_DOr <= cx4_mmio_pgmoff[15:8]; // 1f4a
  206. 5'h0b: MMIO_DOr <= cx4_mmio_pgmoff[23:16]; // 1f4b
  207. 5'h0c: MMIO_DOr <= {6'b0, cx4_mmio_savepage}; // 1f4c
  208. 5'h0d: MMIO_DOr <= cx4_mmio_pgmpage[7:0]; // 1f4d
  209. 5'h0e: MMIO_DOr <= {1'b0, cx4_mmio_pgmpage[14:8]}; // 1f4e
  210. 5'h0f: MMIO_DOr <= cx4_mmio_pc; // 1f4f
  211. 5'h10: MMIO_DOr <= cx4_mmio_r1f50; // 1f50
  212. 5'h11: MMIO_DOr <= {7'b0, cx4_mmio_r1f51}; // 1f51
  213. 5'h12: MMIO_DOr <= {7'b0, cx4_mmio_r1f52}; // 1f52
  214. default: MMIO_DOr <= 8'hff;
  215. endcase
  216. end
  217. always @(posedge CLK) begin
  218. if(MMIO_WR_EN) begin
  219. case(ADDR[4:0])
  220. 5'h00: cx4_mmio_dmasrc[7:0] <= DIr; // 1f40
  221. 5'h01: cx4_mmio_dmasrc[15:8] <= DIr; // 1f41
  222. 5'h02: cx4_mmio_dmasrc[23:16] <= DIr; // 1f42
  223. 5'h03: cx4_mmio_dmalen[7:0] <= DIr; // 1f43
  224. 5'h04: cx4_mmio_dmalen[15:8] <= DIr; // 1f44
  225. 5'h05: cx4_mmio_dmatgt[7:0] <= DIr; // 1f45
  226. 5'h06: cx4_mmio_dmatgt[15:8] <= DIr; // 1f46
  227. 5'h07: begin
  228. cx4_mmio_dmatgt[23:16] <= DIr; // 1f47
  229. DMA_TRIG_ENr <= 1'b1;
  230. end
  231. 5'h08: begin
  232. cx4_mmio_cachepage <= DIr[0]; // 1f48
  233. CACHE_TRIG_ENr <= 1'b1;
  234. end
  235. 5'h09: cx4_mmio_pgmoff[7:0] <= DIr; // 1f49
  236. 5'h0a: cx4_mmio_pgmoff[15:8] <= DIr; // 1f4a
  237. 5'h0b: cx4_mmio_pgmoff[23:16] <= DIr; // 1f4b
  238. 5'h0c: begin
  239. cx4_mmio_savepage <= DIr[1:0];
  240. if(DIr[0]) cx4_mmio_pagemem[0] <= cx4_mmio_pgmpage;
  241. if(DIr[1]) cx4_mmio_pagemem[1] <= cx4_mmio_pgmpage;
  242. end
  243. 5'h0d: cx4_mmio_pgmpage[7:0] <= DIr; // 1f4d
  244. 5'h0e: cx4_mmio_pgmpage[14:8] <= DIr[6:0]; // 1f4e
  245. 5'h0f: begin
  246. cx4_mmio_pc <= DIr; // 1f4f
  247. if(cx4_mmio_savepage[0]
  248. && cx4_mmio_pagemem[0] == cx4_mmio_pgmpage)
  249. cx4_mmio_cachepage <= 1'b0;
  250. else if(cx4_mmio_savepage[1]
  251. && cx4_mmio_pagemem[1] == cx4_mmio_pgmpage)
  252. cx4_mmio_cachepage <= 1'b1;
  253. cpu_go_en_r <= 1'b1;
  254. end
  255. 5'h10: cx4_mmio_r1f50 <= DIr & 8'h77; // 1f50
  256. 5'h11: cx4_mmio_r1f51 <= DIr[0]; // 1f51
  257. 5'h12: cx4_mmio_r1f52 <= DIr[0]; // 1f52
  258. endcase
  259. end else begin
  260. CACHE_TRIG_ENr <= 1'b0;
  261. DMA_TRIG_ENr <= 1'b0;
  262. cpu_go_en_r <= 1'b0;
  263. end
  264. end
  265. always @(posedge CLK) begin
  266. if(VECTOR_WR_EN) vector[ADDR[4:0]] <= DIr;
  267. end
  268. reg [4:0] CACHE_ST;
  269. parameter ST_CACHE_IDLE = 5'b00001;
  270. parameter ST_CACHE_START = 5'b00010;
  271. parameter ST_CACHE_WAIT = 5'b00100;
  272. parameter ST_CACHE_ADDR = 5'b01000;
  273. parameter ST_CACHE_END = 5'b10000;
  274. initial CACHE_ST = ST_CACHE_IDLE;
  275. reg [4:0] DMA_ST;
  276. parameter ST_DMA_IDLE = 5'b00001;
  277. parameter ST_DMA_START = 5'b00010;
  278. parameter ST_DMA_WAIT = 5'b00100;
  279. parameter ST_DMA_ADDR = 5'b01000;
  280. parameter ST_DMA_END = 5'b10000;
  281. initial DMA_ST = ST_DMA_IDLE;
  282. reg [23:0] CACHE_SRC_ADDRr;
  283. wire [22:0] MAPPED_CACHE_SRC_ADDR = {CACHE_SRC_ADDRr[23:16],CACHE_SRC_ADDRr[14:0]};
  284. reg [23:0] DMA_SRC_ADDRr;
  285. wire [22:0] MAPPED_DMA_SRC_ADDR = {DMA_SRC_ADDRr[23:16],DMA_SRC_ADDRr[14:0]};
  286. wire [22:0] MAPPED_CPU_BUS_ADDR;
  287. assign BUS_ADDR = cx4_busy[BUSY_CACHE] ? MAPPED_CACHE_SRC_ADDR
  288. : cx4_busy[BUSY_DMA] ? MAPPED_DMA_SRC_ADDR
  289. : MAPPED_CPU_BUS_ADDR;
  290. reg cx4_pgmrom_we;
  291. initial cx4_pgmrom_we = 1'b0;
  292. reg [9:0] cx4_pgmrom_addr;
  293. reg [19:0] cache_count;
  294. initial cache_count = 20'b0;
  295. always @(posedge CLK) begin
  296. case(CACHE_ST)
  297. ST_CACHE_IDLE: begin
  298. if(CACHE_TRIG_EN
  299. & (~cachevalid[cx4_mmio_cachepage]
  300. | |(cachetag[cx4_mmio_cachepage] ^ cx4_mmio_pgmpage))) begin
  301. CACHE_ST <= ST_CACHE_START;
  302. cache_pgmpage <= cx4_mmio_pgmpage;
  303. cache_cachepage <= cx4_mmio_cachepage;
  304. cx4_busy[BUSY_CACHE] <= 1'b1;
  305. end else if(cpu_cache_en
  306. & (~cachevalid[~cpu_page]
  307. | |(cachetag[~cpu_page] ^ cpu_p))) begin
  308. CACHE_ST <= ST_CACHE_START;
  309. cache_pgmpage <= cpu_p;
  310. cache_cachepage <= ~cpu_page;
  311. cx4_busy[BUSY_CACHE] <= 1'b1;
  312. end
  313. else CACHE_ST <= ST_CACHE_IDLE;
  314. end
  315. ST_CACHE_START: begin
  316. cx4_busy[BUSY_CACHE] <= 1'b1;
  317. CACHE_SRC_ADDRr <= cx4_mmio_pgmoff + {cache_pgmpage, 9'b0};
  318. cx4_pgmrom_addr <= {cache_cachepage, 9'b0};
  319. CACHE_ST <= ST_CACHE_WAIT;
  320. cache_count <= 10'b0;
  321. CACHE_BUS_RRQr <= 1'b1;
  322. end
  323. ST_CACHE_WAIT: begin
  324. CACHE_BUS_RRQr <= 1'b0;
  325. if(~CACHE_BUS_RRQr & BUS_RDY) begin
  326. CACHE_ST <= ST_CACHE_ADDR;
  327. cx4_pgmrom_we <= 1'b1;
  328. cache_count <= cache_count + 1;
  329. end else CACHE_ST <= ST_CACHE_WAIT;
  330. end
  331. ST_CACHE_ADDR: begin
  332. cx4_pgmrom_we <= 1'b0;
  333. CACHE_SRC_ADDRr <= CACHE_SRC_ADDRr + 1;
  334. cx4_pgmrom_addr <= cx4_pgmrom_addr + 1;
  335. if(cache_count == 9'h1ff) begin
  336. cx4_busy[BUSY_CACHE] <= 1'b0;
  337. cachetag[cache_cachepage] <= cache_pgmpage;
  338. cachevalid[cache_cachepage] <= 1'b1;
  339. CACHE_ST <= ST_CACHE_IDLE;
  340. end else begin
  341. CACHE_BUS_RRQr <= 1'b1;
  342. CACHE_ST <= ST_CACHE_WAIT;
  343. end
  344. end
  345. endcase
  346. end
  347. reg cx4_dma_datram_we;
  348. reg cx4_cpu_datram_we;
  349. initial cx4_dma_datram_we = 1'b0;
  350. initial cx4_cpu_datram_we = 1'b0;
  351. wire cx4_datram_we = cx4_dma_datram_we | cx4_cpu_datram_we;
  352. reg [11:0] cx4_dma_datram_addr;
  353. reg [11:0] cx4_cpu_datram_addr;
  354. wire [11:0] cx4_datram_addr = cx4_busy[BUSY_DMA] ? cx4_dma_datram_addr : cx4_cpu_datram_addr;
  355. reg [23:0] cx4_cpu_datram_di;
  356. wire [7:0] cx4_datram_di = cx4_busy[BUSY_DMA] ? BUS_DI : cx4_cpu_datram_di;
  357. reg [15:0] dma_count;
  358. initial dma_count = 16'b0;
  359. always @(posedge CLK) begin
  360. case(DMA_ST)
  361. ST_DMA_IDLE: begin
  362. if(DMA_TRIG_EN) begin
  363. DMA_ST <= ST_DMA_START;
  364. end else DMA_ST <= ST_DMA_IDLE;
  365. end
  366. ST_DMA_START: begin
  367. cx4_busy[BUSY_DMA] <= 1'b1;
  368. DMA_SRC_ADDRr <= cx4_mmio_dmasrc;
  369. cx4_dma_datram_addr <= (cx4_mmio_dmatgt & 24'h000fff);
  370. DMA_ST <= ST_DMA_WAIT;
  371. dma_count <= cx4_mmio_dmalen;
  372. DMA_BUS_RRQr <= 1'b1;
  373. end
  374. ST_DMA_WAIT: begin
  375. DMA_BUS_RRQr <= 1'b0;
  376. if(~DMA_BUS_RRQr & BUS_RDY) begin
  377. DMA_ST <= ST_DMA_ADDR;
  378. cx4_dma_datram_we <= 1'b1;
  379. dma_count <= dma_count - 1;
  380. end else DMA_ST <= ST_DMA_WAIT;
  381. end
  382. ST_DMA_ADDR: begin
  383. cx4_dma_datram_we <= 1'b0;
  384. DMA_SRC_ADDRr <= DMA_SRC_ADDRr + 1;
  385. cx4_dma_datram_addr <= cx4_dma_datram_addr + 1;
  386. if(dma_count == 16'h0000) begin
  387. cx4_busy[BUSY_DMA] <= 1'b0;
  388. DMA_ST <= ST_DMA_IDLE;
  389. end else begin
  390. DMA_BUS_RRQr <= 1'b1;
  391. DMA_ST <= ST_DMA_WAIT;
  392. end
  393. end
  394. endcase
  395. end
  396. /***************************
  397. =========== CPU ===========
  398. ***************************/
  399. reg [5:0] CPU_STATE;
  400. reg [2:0] cpu_sp;
  401. initial cpu_sp = 3'b000;
  402. wire [15:0] cpu_op_w;
  403. reg [15:0] cpu_op;
  404. reg [23:0] cpu_busdata;
  405. reg [23:0] cpu_romdata;
  406. reg [23:0] cpu_ramdata;
  407. reg [23:0] cpu_busaddr;
  408. assign MAPPED_CPU_BUS_ADDR = {cpu_busaddr[23:16], cpu_busaddr[14:0]};
  409. reg [23:0] cpu_romaddr;
  410. reg [23:0] cpu_ramaddr;
  411. reg [23:0] cpu_acch;
  412. reg [23:0] cpu_accl;
  413. reg [23:0] cpu_mul_src;
  414. reg [24:0] cpu_alu_res;
  415. reg [23:0] cpu_dummy;
  416. reg [23:0] cpu_tmp;
  417. reg [23:0] cpu_sa; // tmp register for shifted accumulator
  418. reg [7:0] cpu_wait;
  419. initial cpu_wait = 8'h00;
  420. wire [9:0] cx4_datrom_addr = cpu_a[9:0];
  421. wire [23:0] cx4_datrom_do;
  422. wire [7:0] cx4_datram_do;
  423. parameter ST_CPU_IDLE = 6'b000001;
  424. parameter ST_CPU_0 = 6'b000010;
  425. parameter ST_CPU_1 = 6'b000100;
  426. parameter ST_CPU_2 = 6'b001000;
  427. parameter ST_CPU_3 = 6'b010000;
  428. parameter ST_CPU_4 = 6'b100000;
  429. initial CPU_STATE = ST_CPU_IDLE;
  430. parameter OP_NOP = 5'b00000;
  431. parameter OP_JP = 5'b00001;
  432. parameter OP_SKIP = 5'b00010;
  433. parameter OP_RT = 5'b00011;
  434. parameter OP_LD = 5'b00100;
  435. parameter OP_ST = 5'b00101;
  436. parameter OP_SWP = 5'b00110;
  437. parameter OP_RDROM = 5'b00111;
  438. parameter OP_RDRAM = 5'b01000;
  439. parameter OP_WRRAM = 5'b01001;
  440. parameter OP_ALU = 5'b01010;
  441. parameter OP_MUL = 5'b01011;
  442. parameter OP_WAI = 5'b01100;
  443. parameter OP_BUS = 5'b01101;
  444. parameter OP_CMP = 5'b01110;
  445. parameter OP_SEX = 5'b01111;
  446. parameter OP_HLT = 5'b10000;
  447. wire [6:0] op_id = cpu_op_w[15:10];
  448. reg [7:0] op_param;
  449. reg [4:0] op;
  450. reg [1:0] op_sa;
  451. reg op_imm;
  452. reg op_p;
  453. reg op_call;
  454. reg op_jump;
  455. reg condtrue;
  456. always @(posedge CLK) begin
  457. if(cpu_go_en_r) cx4_busy[BUSY_CPU] <= 1'b1;
  458. else if(op == OP_HLT) cx4_busy[BUSY_CPU] <= 1'b0;
  459. end
  460. always @(posedge CLK) begin
  461. case(op_sa)
  462. 2'b00: cpu_sa <= cpu_a;
  463. 2'b01: cpu_sa <= cpu_a << 1;
  464. 2'b10: cpu_sa <= cpu_a << 8;
  465. 2'b11: cpu_sa <= cpu_a << 16;
  466. endcase
  467. end
  468. reg jp_docache;
  469. initial jp_docache = 1'b0;
  470. always @(posedge CLK) begin
  471. case(CPU_STATE)
  472. ST_CPU_IDLE: begin
  473. if(cpu_go_en_r) begin
  474. cpu_pc <= cx4_mmio_pc;
  475. cpu_page <= cx4_mmio_cachepage;
  476. cpu_p <= cx4_mmio_pgmpage;
  477. op <= OP_NOP;
  478. CPU_STATE <= ST_CPU_2;
  479. end
  480. else CPU_STATE <= ST_CPU_IDLE;
  481. end
  482. ST_CPU_0: begin // Phase 0:
  483. cpu_cache_en <= 1'b0;
  484. if(op == OP_HLT) begin
  485. CPU_STATE <= ST_CPU_IDLE;
  486. end
  487. else CPU_STATE <= ST_CPU_1;
  488. case(op)
  489. OP_JP: begin
  490. case(cpu_op[11:10])
  491. 2'b10: condtrue <= 1'b1;
  492. 2'b11: condtrue <= fl_z;
  493. 2'b00: condtrue <= fl_c;
  494. 2'b01: condtrue <= fl_n;
  495. endcase
  496. if(op_p && !jp_docache) begin
  497. jp_docache <= 1'b1;
  498. cpu_cache_en <= 1'b1;
  499. end
  500. end
  501. OP_SKIP: begin
  502. case(cpu_op[9:8])
  503. 2'b01: condtrue <= (fl_c == cpu_op[0]);
  504. 2'b10: condtrue <= (fl_z == cpu_op[0]);
  505. 2'b11: condtrue <= (fl_n == cpu_op[0]);
  506. endcase
  507. end
  508. OP_LD, OP_ALU, OP_MUL, OP_CMP, OP_SEX: begin
  509. if(op_imm) cpu_idb <= {16'b0, op_param};
  510. else casex(op_param)
  511. 8'h00: cpu_idb <= cpu_a;
  512. 8'h01: cpu_idb <= cpu_acch;
  513. 8'h02: cpu_idb <= cpu_accl;
  514. 8'h03: cpu_idb <= cpu_busdata;
  515. 8'h08: cpu_idb <= cpu_romdata;
  516. 8'h0c: cpu_idb <= cpu_ramdata;
  517. 8'h13: cpu_idb <= cpu_busaddr;
  518. 8'h1c: cpu_idb <= cpu_ramaddr;
  519. 8'h5x: cpu_idb <= const[op_param[3:0]];
  520. 8'h6x: cpu_idb <= {gpr[op_param[3:0]*3+2],
  521. gpr[op_param[3:0]*3+1],
  522. gpr[op_param[3:0]*3]};
  523. default: cpu_idb <= 24'b0;
  524. endcase
  525. end
  526. OP_ST: begin
  527. cpu_idb <= cpu_a;
  528. end
  529. OP_SWP: begin
  530. cpu_idb <= cpu_a;
  531. casex(op_param)
  532. 8'h00: cpu_tmp <= cpu_a;
  533. 8'h01: cpu_tmp <= cpu_acch;
  534. 8'h02: cpu_tmp <= cpu_accl;
  535. 8'h03: cpu_tmp <= cpu_busdata;
  536. 8'h08: cpu_tmp <= cpu_romdata;
  537. 8'h0c: cpu_tmp <= cpu_ramdata;
  538. 8'h13: cpu_tmp <= cpu_busaddr;
  539. 8'h1c: cpu_tmp <= cpu_ramaddr;
  540. 8'h5x: cpu_tmp <= const[op_param[3:0]];
  541. 8'h6x: cpu_tmp <= {gpr[op_param[3:0]*3+2],
  542. gpr[op_param[3:0]*3+1],
  543. gpr[op_param[3:0]*3]};
  544. default: cpu_tmp <= 24'b0;
  545. endcase
  546. end
  547. OP_RDRAM, OP_WRRAM: begin
  548. if(op_imm) cx4_cpu_datram_addr <= {16'b0, op_param} + cpu_ramaddr;
  549. else casex(op_param)
  550. 8'h00: cx4_cpu_datram_addr <= cpu_a;
  551. 8'h01: cx4_cpu_datram_addr <= cpu_acch;
  552. 8'h02: cx4_cpu_datram_addr <= cpu_accl;
  553. 8'h03: cx4_cpu_datram_addr <= cpu_busdata;
  554. 8'h08: cx4_cpu_datram_addr <= cpu_romdata;
  555. 8'h0c: cx4_cpu_datram_addr <= cpu_ramdata;
  556. 8'h13: cx4_cpu_datram_addr <= cpu_busaddr;
  557. 8'h1c: cx4_cpu_datram_addr <= cpu_ramaddr;
  558. 8'h5x: cx4_cpu_datram_addr <= const[op_param[3:0]];
  559. 8'h6x: cx4_cpu_datram_addr <= {gpr[op_param[3:0]*3+2],
  560. gpr[op_param[3:0]*3+1],
  561. gpr[op_param[3:0]*3]};
  562. default: cx4_cpu_datram_addr <= 24'b0;
  563. endcase
  564. end
  565. OP_BUS: cpu_bus_rq <= 1'b1;
  566. endcase
  567. end
  568. ST_CPU_1: begin
  569. CPU_STATE <= ST_CPU_2;
  570. condtrue <= 1'b0;
  571. case(op)
  572. OP_JP: begin
  573. cpu_cache_en <= 1'b0;
  574. if(!cpu_cache_en && !cx4_busy[BUSY_CACHE]) begin
  575. jp_docache <= 1'b0;
  576. if(condtrue) begin
  577. if(op_call) begin
  578. cpu_page_stack[cpu_sp] <= cpu_page;
  579. cpu_pc_stack[cpu_sp] <= cpu_pc + 1;
  580. cpu_sp <= cpu_sp + 1;
  581. end
  582. cpu_pc <= op_param;
  583. cpu_page <= cpu_page ^ op_p;
  584. end else cpu_pc <= cpu_pc + 1;
  585. end
  586. end
  587. OP_SKIP: begin
  588. if(condtrue) cpu_pc <= cpu_pc + 2;
  589. else cpu_pc <= cpu_pc + 1;
  590. end
  591. OP_RT: begin
  592. cpu_page <= cpu_page_stack[cpu_sp - 1];
  593. cpu_pc <= cpu_pc_stack[cpu_sp - 1];
  594. cpu_sp <= cpu_sp - 1;
  595. end
  596. OP_WAI: if(BUS_RDY) cpu_pc <= cpu_pc + 1;
  597. OP_BUS: begin
  598. cpu_bus_rq <= 1'b0;
  599. cpu_pc <= cpu_pc + 1;
  600. end
  601. default: cpu_pc <= cpu_pc + 1;
  602. endcase
  603. end
  604. ST_CPU_2: begin
  605. CPU_STATE <= ST_CPU_3;
  606. case(op)
  607. OP_LD: begin
  608. casex(cpu_op[11:8])
  609. 4'b0x00: cpu_a <= cpu_idb;
  610. 4'b0x11: cpu_p <= cpu_idb;
  611. 4'b1100: cpu_p[7:0] <= op_param;
  612. 4'b1101: cpu_p[14:8] <= op_param;
  613. endcase
  614. end
  615. OP_ST, OP_SWP: begin
  616. casex(op_param)
  617. 8'h01: cpu_acch <= cpu_idb;
  618. 8'h02: cpu_accl <= cpu_idb;
  619. 8'h08: cpu_romdata <= cpu_idb;
  620. 8'h0c: cpu_ramdata <= cpu_idb;
  621. 8'h13: cpu_busaddr <= cpu_idb;
  622. 8'h1c: cpu_ramaddr <= cpu_idb;
  623. endcase
  624. if(op==OP_SWP) cpu_a <= cpu_tmp;
  625. end
  626. OP_RDROM: cpu_romdata <= cx4_datrom_do;
  627. OP_RDRAM: begin
  628. case(cpu_op[9:8])
  629. 2'b00: cpu_ramdata[7:0] <= cx4_datram_do;
  630. 2'b01: cpu_ramdata[15:8] <= cx4_datram_do;
  631. 2'b10: cpu_ramdata[23:16] <= cx4_datram_do;
  632. endcase
  633. end
  634. OP_WRRAM: begin
  635. case(cpu_op[9:8])
  636. 2'b00: cx4_cpu_datram_di <= cpu_ramdata[7:0];
  637. 2'b01: cx4_cpu_datram_di <= cpu_ramdata[15:8];
  638. 2'b10: cx4_cpu_datram_di <= cpu_ramdata[23:16];
  639. endcase
  640. cx4_cpu_datram_we <= 1'b1;
  641. end
  642. OP_CMP: begin
  643. case(cpu_op[15:11])
  644. 5'b01001: cpu_alu_res <= cpu_idb - cpu_sa;
  645. 5'b01010: cpu_alu_res <= cpu_sa - cpu_idb;
  646. endcase
  647. end
  648. OP_SEX: begin
  649. case(cpu_op[9:8])
  650. 2'b01: cpu_alu_res <= {{16{cpu_idb[7]}}, cpu_idb[7:0]};
  651. 2'b10: cpu_alu_res <= {{8{cpu_idb[15]}}, cpu_idb[15:0]};
  652. endcase
  653. end
  654. OP_ALU: begin
  655. case(cpu_op[15:11])
  656. 5'b10000: cpu_alu_res <= cpu_sa + cpu_idb;
  657. 5'b10001: cpu_alu_res <= cpu_idb - cpu_sa;
  658. 5'b10010: cpu_alu_res <= cpu_sa - cpu_idb;
  659. 5'b10101: cpu_alu_res <= cpu_sa ^ cpu_idb;
  660. 5'b10110: cpu_alu_res <= cpu_sa & cpu_idb;
  661. 5'b10111: cpu_alu_res <= cpu_sa | cpu_idb;
  662. 5'b11000: cpu_alu_res <= cpu_a >> cpu_idb;
  663. 5'b11001: cpu_alu_res <= ($signed(cpu_a)) >>> cpu_idb;
  664. 5'b11010: {cpu_dummy, cpu_alu_res[23:0]} <= {cpu_a, cpu_a} >> cpu_idb;
  665. 5'b11011: cpu_alu_res <= cpu_a << cpu_idb;
  666. endcase
  667. end
  668. endcase
  669. end
  670. ST_CPU_3: begin
  671. case(op)
  672. OP_BUS: cpu_busaddr <= cpu_busaddr + 1;
  673. OP_WRRAM: cx4_cpu_datram_we <= 1'b0;
  674. OP_CMP: begin
  675. fl_n <= cpu_alu_res[23];
  676. fl_z <= cpu_alu_res[23:0] == 24'b0;
  677. fl_c <= ~cpu_alu_res[24];
  678. end
  679. OP_SEX: cpu_a <= cpu_alu_res[23:0];
  680. OP_ALU: begin
  681. cpu_a <= cpu_alu_res[23:0];
  682. case(cpu_op[15:11])
  683. 5'b10000: begin
  684. fl_n <= cpu_alu_res[23];
  685. fl_z <= cpu_alu_res[23:0] == 24'b0;
  686. fl_c <= cpu_alu_res[24];
  687. end
  688. 5'b10001, 5'b10010: begin
  689. fl_n <= cpu_alu_res[23];
  690. fl_z <= cpu_alu_res[23:0] == 24'b0;
  691. fl_c <= ~cpu_alu_res[24];
  692. end
  693. default: begin
  694. fl_n <= cpu_alu_res[23];
  695. fl_z <= cpu_alu_res[23:0] == 24'b0;
  696. end
  697. endcase
  698. end
  699. OP_MUL: begin
  700. cpu_acch <= cpu_mul_result[47:24];
  701. cpu_accl <= cpu_mul_result[23:0];
  702. fl_z <= (cpu_mul_result == 48'b0);
  703. fl_n <= cpu_mul_result[47];
  704. end
  705. endcase
  706. cpu_op <= cpu_op_w;
  707. casex(cpu_op_w[15:11])
  708. 5'b00x01, 5'b00x10, 5'b00100, 5'b00111: begin
  709. cpu_wait <= 8'h07;
  710. CPU_STATE <= ST_CPU_4;
  711. end
  712. 5'b01110, 5'b01101, 5'b11101: begin
  713. cpu_wait <= 8'h03;
  714. CPU_STATE <= ST_CPU_4;
  715. end
  716. /*5'b10011: begin
  717. cpu_wait <= 8'h02;
  718. CPU_STATE <= ST_CPU_4;
  719. end
  720. 5'b01000: begin
  721. cpu_wait <= 8'h0e;
  722. CPU_STATE <= ST_CPU_4;
  723. end*/
  724. default: begin
  725. cpu_wait <= 8'h00;
  726. CPU_STATE <= ST_CPU_0;
  727. end
  728. endcase
  729. casex(cpu_op_w[15:11])
  730. 5'b00000: op <= OP_NOP;
  731. 5'b00x01: op <= OP_JP;
  732. 5'b00x10: op <= OP_JP;
  733. 5'b00100: op <= OP_SKIP;
  734. 5'b00111: op <= OP_RT;
  735. 5'b01100: op <= OP_LD;
  736. 5'b01111: op <= OP_LD;
  737. 5'b11100: op <= OP_ST;
  738. 5'b11110: op <= OP_SWP;
  739. 5'b01110: op <= OP_RDROM;
  740. 5'b01101: op <= OP_RDRAM;
  741. 5'b11101: op <= OP_WRRAM;
  742. 5'b01001: op <= OP_CMP;
  743. 5'b01010: op <= OP_CMP;
  744. 5'b01011: op <= OP_SEX;
  745. 5'b10000: op <= OP_ALU;
  746. 5'b10001: op <= OP_ALU;
  747. 5'b10010: op <= OP_ALU;
  748. 5'b10101: op <= OP_ALU;
  749. 5'b10110: op <= OP_ALU;
  750. 5'b10111: op <= OP_ALU;
  751. 5'b11000: op <= OP_ALU;
  752. 5'b11001: op <= OP_ALU;
  753. 5'b11010: op <= OP_ALU;
  754. 5'b11011: op <= OP_ALU;
  755. 5'b10011: op <= OP_MUL;
  756. 5'b00011: op <= OP_WAI;
  757. 5'b01000: op <= OP_BUS;
  758. 5'b11111: op <= OP_HLT;
  759. endcase
  760. op_imm <= cpu_op_w[10];
  761. op_p <= cpu_op_w[9];
  762. op_call <= cpu_op_w[13];
  763. op_param <= cpu_op_w[7:0];
  764. op_sa <= cpu_op_w[9:8];
  765. end
  766. ST_CPU_4: begin
  767. cpu_wait <= cpu_wait - 1;
  768. if(cpu_wait) CPU_STATE <= ST_CPU_4;
  769. else CPU_STATE <= ST_CPU_0;
  770. end
  771. endcase
  772. end
  773. reg[2:0] BUSRD_STATE;
  774. parameter ST_BUSRD_IDLE = 3'b001;
  775. parameter ST_BUSRD_WAIT = 3'b010;
  776. parameter ST_BUSRD_END = 3'b100;
  777. initial BUSRD_STATE = ST_BUSRD_IDLE;
  778. reg cpu_bus_rq2;
  779. always @(posedge CLK) cpu_bus_rq2 <= cpu_bus_rq;
  780. always @(posedge CLK) begin
  781. if(CPU_STATE == ST_CPU_2
  782. && (op == OP_ST || op == OP_SWP)
  783. && op_param == 8'h03)
  784. cpu_busdata <= cpu_idb;
  785. else begin
  786. case(BUSRD_STATE)
  787. ST_BUSRD_IDLE: begin
  788. if(cpu_bus_rq2) begin
  789. BUSRD_STATE <= ST_BUSRD_WAIT;
  790. end
  791. end
  792. ST_BUSRD_WAIT: begin
  793. if(BUS_RDY) BUSRD_STATE <= ST_BUSRD_END;
  794. else BUSRD_STATE <= ST_BUSRD_WAIT;
  795. end
  796. ST_BUSRD_END: begin
  797. if(~cpu_busaddr[22]) cpu_busdata <= BUS_DI;
  798. else cpu_busdata <= 8'h00;
  799. end
  800. endcase
  801. end
  802. end
  803. // gpr write, either by CPU or by MMIO
  804. always @(posedge CLK) begin
  805. if(CPU_STATE == ST_CPU_2
  806. && (op == OP_ST || op == OP_SWP)
  807. && (op_param[7:4] == 4'h6)) begin
  808. gpr[op_param[3:0]*3+2] <= cpu_idb[23:16];
  809. gpr[op_param[3:0]*3+1] <= cpu_idb[15:8];
  810. gpr[op_param[3:0]*3] <= cpu_idb[7:0];
  811. end
  812. else if(GPR_WR_EN) gpr[ADDR[5:0]] <= DIr;
  813. end
  814. /***************************
  815. =========== MEM ===========
  816. ***************************/
  817. cx4_datrom cx4_datrom (
  818. .clka(CLK), // input clka
  819. .wea(DATROM_WE), // input [0 : 0] wea
  820. .addra(DATROM_ADDR), // input [9 : 0] addra
  821. .dina(DATROM_DI), // input [23 : 0] dina
  822. .clkb(CLK), // input clkb
  823. .addrb(cx4_datrom_addr), // input [9 : 0] addrb
  824. .doutb(cx4_datrom_do) // output [23 : 0] doutb
  825. );
  826. cx4_datram cx4_datram (
  827. .clka(CLK), // input clka
  828. .wea(DATRAM_WR_EN), // input [0 : 0] wea
  829. .addra(ADDR[11:0]), // input [11 : 0] addra
  830. .dina(DIr), // input [7 : 0] dina
  831. .douta(DATRAM_DO), // output [7 : 0] douta
  832. .clkb(CLK), // input clkb
  833. .web(cx4_datram_we), // input [0 : 0] web
  834. .addrb(cx4_datram_addr), // input [11 : 0] addrb
  835. .dinb(cx4_datram_di), // input [7 : 0] dinb
  836. .doutb(cx4_datram_do) // output [7 : 0] doutb
  837. );
  838. cx4_pgmrom cx4_pgmrom (
  839. .clka(CLK), // input clka
  840. .wea(cx4_pgmrom_we), // input [0 : 0] wea
  841. .addra(cx4_pgmrom_addr), // input [9 : 0] addra
  842. .dina(BUS_DI), // input [7 : 0] dina
  843. .clkb(CLK), // input clkb
  844. .addrb({cpu_page,cpu_pc}), // input [8 : 0] addrb
  845. .doutb(cpu_op_w) // output [15 : 0] doutb
  846. );
  847. cx4_mul cx4_mul (
  848. .clk(CLK), // input clk
  849. .a(cpu_a), // input [23 : 0] a
  850. .b(cpu_idb), // input [23 : 0] b
  851. .p(cpu_mul_result) // output [47 : 0] p
  852. );
  853. endmodule