§ Описание
Процессор предназначен для встраивания в схемы Dendy.
- clock — тактовая частота, 1.7 Мгц
- locked — если 1, процессор активен
- reset_n — сброс, если 0
- address, in, out, we — интерфейс работы с памятью
- rd — строб 1, если только что было запрошено чтение с памяти, необходимо для PPU
§ Исходный код
Последнее обновление: 22 мар 2024
1
2
3
4
5
6module nes
7(
8 input clock,
9 input locked,
10 input reset_n,
11 input irq,
12 output [15:0] address,
13 input [ 7:0] in,
14 output reg [ 7:0] out,
15 output reg we,
16 output reg rd
17);
18
19
20assign address = mm ? cp : pc;
21
22
23localparam
24
25 MAIN = 8'h00,
26 ZP = 8'h01, ZPX = 8'h02, ZPY = 8'h03,
27 ABS = 8'h04, JSR = 8'h05, IND = 8'h06,
28 ABX = 8'h07, ABY = 8'h08, REL = 8'h09,
29 NDX = 8'h0A, NDY = 8'h0B, RUN = 8'h0C,
30 DLY = 8'h0D, ABS2 = 8'h0E, ABX2 = 8'h0F,
31 NDX2 = 8'h10, NDX3 = 8'h11, NDY2 = 8'h12,
32 NDY3 = 8'h13, REL2 = 8'h14, REL3 = 8'h15,
33 RTS = 8'h16, BRK = 8'h17, RTI = 8'h18;
34
35
36localparam
37 ORA = 0, AND = 1, EOR = 2, ADC = 3,
38 STA = 4, LDA = 5, CMP = 6, SBC = 7,
39 INC = 8, DEC = 9, ASL = 10, ROL = 11,
40 LSR = 12, ROR = 13, BIT = 14;
41
42localparam
43 DST_A = 0, DST_X = 1, DST_Y = 2, DST_D = 3,
44 SRC_D = 0, SRC_A = 1, SRC_X = 2, SRC_Y = 3;
45
46
47localparam
48 CF = 0, ZF = 1, IF = 2, DF = 3,
49 BF = 4, XF = 5, VF = 6, NF = 7;
50
51
52
53reg [ 7:0] a, x, y, p, s;
54reg mm, sta, utk, irq_prev;
55reg [15:0] pc, cp;
56reg [ 7:0] op, tm;
57reg [ 6:0] t;
58reg [ 2:0] m;
59reg [ 3:0] alu;
60reg [ 1:0] src, dst, vec;
61
62
63
64wire [15:0] pcn = pc + {{8{in[7]}},in} + 1;
65wire [15:0] pc2 = pc + 2;
66wire [ 7:0] zpx = x + in,
67 zpy = y + in;
68wire [ 8:0] ndy = tm + y;
69wire [ 7:0] sm = s - 1,
70 sp = s + 1;
71wire [ 3:0] brc = {p[NF], p[CF], p[VF], p[ZF]};
72
73
74wire nx1 = sta || cp[8] || utk;
75wire nx2 = sta || ndy[8] || utk;
76
77
78
79always @(posedge clock)
80
81if (reset_n == 1'b0) begin
82
83 t <= BRK;
84 vec <= 2'b10;
85 m <= 3;
86 pc <= 16'h0000;
87 mm <= 1;
88 we <= 0;
89 a <= 8'h84;
90 x <= 8'h4F;
91 y <= 8'h00;
92 s <= 8'h3F;
93
94 p <= 8'b01000001;
95
96end
97
98else if (locked) begin
99
100 rd <= 1'b0;
101 we <= 1'b0;
102
103 case (t)
104
105
106 MAIN: begin
107
108 t <= 1;
109 m <= 0;
110 op <= in;
111 pc <= pc + 1;
112 alu <= in[7:5];
113 dst <= DST_A;
114 src <= SRC_D;
115 sta <= 0;
116 utk <= 0;
117 out <= a;
118 vec <= 2'b11;
119 irq_prev <= irq;
120
121 casex (in)
122
123 8'b000_000_00: t <= BRK;
124 8'b001_000_00: t <= JSR;
125 8'b010_000_00: t <= RTI;
126 8'b011_000_00: t <= RTS;
127 8'b011_011_00: t <= IND;
128 8'b10x_101_10: t <= ZPY;
129
130 8'bxxx_001_xx: t <= ZP;
131 8'bxxx_101_xx: t <= ZPX;
132 8'bxxx_011_xx: t <= ABS;
133 8'bxxx_111_xx: t <= ABX;
134 8'bxxx_110_x1: t <= ABY;
135 8'bxxx_000_x1: t <= NDX;
136 8'bxxx_100_x1: t <= NDY;
137 8'bxxx_100_00: t <= REL;
138 default: t <= RUN;
139 endcase
140
141
142 casex (in)
143 8'b1010_00x0,
144 8'b101x_x110,
145 8'b101x_x100: begin alu <= LDA; end
146 8'b1110_0000,
147 8'b1110_x100: begin dst <= DST_X; alu <= CMP; end
148 8'b1100_0000,
149 8'b1100_x100: begin dst <= DST_Y; alu <= CMP; end
150
151 8'b1000_1000: begin dst <= DST_Y; alu <= DEC; end
152 8'b1100_1000: begin dst <= DST_Y; alu <= INC; end
153 8'b1100_1010: begin dst <= DST_X; alu <= DEC; end
154 8'b1110_1000: begin dst <= DST_X; alu <= INC; end
155
156 8'b110x_x110: begin dst <= DST_D; alu <= DEC; utk <= 1; end
157 8'b111x_x110: begin dst <= DST_D; alu <= INC; utk <= 1; end
158
159 8'b0xxx_x110: begin alu <= ASL + in[6:5]; dst <= DST_D; utk <= 1; end
160 8'b0xx0_1010: begin alu <= ASL + in[6:5]; end
161 8'b0010_x100: begin alu <= BIT; end
162
163 8'b1001_1000: begin alu <= LDA; src <= SRC_Y; end
164 8'b1010_10x0: begin alu <= LDA; src <= SRC_A; end
165 8'b1000_1010: begin alu <= LDA; src <= SRC_X; end
166 endcase
167
168
169 if ({irq_prev, irq} == 2'b01) begin pc <= pc - 2; vec <= 2'b01; t <= BRK; end
170 else begin
171
172
173 casex (in)
174 8'b100x_xx01: begin sta <= 1; end
175 8'b100x_x110: begin sta <= 1; out <= x; end
176 8'b100x_x100: begin sta <= 1; out <= y; end
177
178 8'b0x00_1000: begin cp <= {8'h01, s}; s <= sm; out <= in[6] ? a : p | 8'h30; end
179 8'b0x10_1000: begin cp <= {8'h01, sp}; s <= sp; mm <= 1; end
180 endcase
181
182 end
183
184 end
185
186
187
188
189
190 ZP: begin t <= RUN; pc <= pc + 1; mm <= 1; cp <= in; we <= sta; rd <= !sta; end
191 ZPX: begin t <= DLY; pc <= pc + 1; mm <= 1; cp <= zpx; we <= sta; end
192 ZPY: begin t <= DLY; pc <= pc + 1; mm <= 1; cp <= zpy; we <= sta; end
193
194
195 ABS: begin t <= ABS2; pc <= pc + 1; cp[7:0] <= in; end
196 ABS2: begin
197
198 if (op == 8'h4C)
199 begin t <= MAIN; pc <= {in, cp[7:0]}; end
200 else begin t <= RUN; pc <= pc + 1; cp[15:8] <= in; mm <= 1; {we, rd} <= {sta, !sta}; end
201
202 end
203
204
205 ABX: begin t <= ABX2; pc <= pc + 1; cp <= in + x; end
206 ABY: begin t <= ABX2; pc <= pc + 1; cp <= in + y; end
207 ABX2: begin t <= nx1 ? DLY : RUN; pc <= pc + 1; cp <= cp + {in, 8'h00}; mm <= 1; we <= sta; rd <= !nx1; end
208
209
210 NDX: begin t <= NDX2; pc <= pc + 1; cp <= zpx; mm <= 1; end
211 NDX2: begin t <= NDX3; cp[7:0] <= cp[7:0] + 1; tm <= in; end
212 NDX3: begin t <= DLY; cp <= {in, tm}; we <= sta; end
213
214
215 NDY: begin t <= NDY2; mm <= 1; cp <= in; pc <= pc + 1; end
216 NDY2: begin t <= NDY3; tm <= in; cp[7:0] <= cp[7:0] + 1; end
217 NDY3: begin t <= nx2 ? DLY : RUN; cp <= {in, 8'h00} + ndy; we <= sta; rd <= !nx2; end
218
219
220 REL: begin if (brc[op[7:6]] == op[5]) t <= REL2; else begin t <= MAIN; pc <= pc + 1; end end
221 REL2: begin pc <= pcn; t <= (pc[15:8] != pcn[15:8]) ? REL3 : MAIN; end
222 REL3: begin t <= MAIN; end
223
224
225 DLY: begin rd <= !sta; t <= RUN; end
226
227
228
229
230 RUN: begin
231
232 t <= MAIN;
233 mm <= 0;
234
235
236 casex (op) 8'b1xx_000_x0, 8'bxxx_010_x1: pc <= pc + 1; endcase
237
238 casex (op)
239
240 8'b00x1_1000: p[CF] <= op[5];
241 8'b01x1_1000: p[IF] <= op[5];
242 8'b11x1_1000: p[DF] <= op[5];
243 8'b1011_1000: p[VF] <= 1'b0;
244
245 8'b1001_1010: begin s <= x; end
246 8'b1011_1010: begin x <= s; {p[NF], p[ZF]} <= {s[7], s == 8'h00}; end
247
248 8'b101x_x110,
249 8'b1010_x010,
250 8'b1100_1010,
251 8'b1110_1000:
252 begin x <= alur; p <= aluf; end
253
254 8'b101x_x100,
255 8'b1010_x000,
256 8'b1x00_1000:
257 begin y <= alur; p <= aluf; end
258
259 8'b11x0_0000,
260 8'b0010_x100,
261 8'b11x0_x100:
262 begin p <= aluf; end
263
264 8'b11xx_x110,
265 8'b0xxx_x110:
266 case (m)
267 0: begin m <= 1; t <= RUN; mm <= 1; we <= 1; out <= alur; p <= aluf; end
268 1: begin m <= 2; t <= RUN; end
269 endcase
270
271 8'b0x00_1000:
272 case (m) 0: begin m <= 1; t <= RUN; mm <= 1; we <= 1; end endcase
273
274 8'b0x10_1000:
275 case (m)
276 0: begin
277
278 m <= 1;
279 t <= RUN;
280 if (op[6]) begin a <= in; {p[NF], p[ZF]} <= {in[7], in == 8'h00}; end
281 else begin p <= in; end
282
283 end
284 1: begin m <= 2; t <= RUN; end
285 endcase
286
287 8'b100x_xx01:
288 begin end
289
290 8'bxxxx_xx01,
291 8'b0xx0_1010,
292 8'b1001_1000,
293 8'b1000_1010:
294 begin a <= (alu == CMP) ? a : alur; p <= aluf; end
295 endcase
296
297 end
298
299
300
301
302 IND: case (m)
303 0: begin m <= 1; cp[ 7:0] <= in; pc <= pc + 1; end
304 1: begin m <= 2; cp[15:8] <= in; mm <= 1; end
305 2: begin m <= 3; pc[ 7:0] <= in; cp <= cp + 1; end
306 3: begin mm <= 0; pc[15:8] <= in; t <= MAIN; end
307 endcase
308
309
310 JSR: case (m)
311 0: begin m <= 1; pc <= pc + 1; tm <= in; end
312 1: begin m <= 2; out <= pc[15:8]; tm <= pc[7:0]; cp <= s; s <= sm; pc <= {in, tm}; we <= 1; mm <= 1; end
313 2: begin m <= 3; out <= tm; we <= 1; cp <= s; s <= sm; end
314 3: begin m <= 4; mm <= 0; end
315 4: begin t <= MAIN; end
316 endcase
317
318
319 BRK: case (m)
320 0: begin m <= 1; we <= 1; cp <= s; s <= sm; out <= pc2[15:8]; mm <= 1; end
321 1: begin m <= 2; we <= 1; cp <= s; s <= sm; out <= pc2[ 7:0]; end
322 2: begin m <= 3; we <= 1; cp <= s; s <= sm; out <= p | 8'h10; p <= p | 8'h14; end
323 3: begin m <= 4; cp <= {12'hFFF, 1'b1, vec, 1'b0}; end
324 4: begin m <= 5; cp[0] <= 1'b1; pc[7:0] <= in; end
325 5: begin t <= MAIN; pc[15:8] <= in; mm <= 0; end
326 endcase
327
328
329 RTS: case (m)
330 0: begin m <= 1; mm <= 1; cp <= sp; s <= sp; end
331 1: begin m <= 2; pc <= in; cp <= sp; s <= sp; end
332 2: begin m <= 3; pc <= pc + {in, 8'h01}; end
333 3: begin m <= 4; mm <= 0; end
334 4: begin t <= MAIN; end
335 endcase
336
337
338 RTI: case (m)
339 0: begin m <= 1; cp <= sp; s <= sp; mm <= 1; end
340 1: begin m <= 2; cp <= sp; s <= sp; p <= in; end
341 2: begin m <= 3; cp <= sp; s <= sp; pc <= in; end
342 3: begin m <= 4; mm <= 0; pc[15:8] <= in; end
343 4: begin t <= MAIN; end
344 endcase
345
346 endcase
347
348end
349
350
351
352
353
354
355wire [7:0] op1 = dst == DST_A ? a : (dst == DST_X ? x : (dst == DST_Y ? y : in));
356wire [7:0] op2 = src == SRC_D ? in : (src == SRC_A ? a : (src == SRC_X ? x : y));
357
358
359wire [8:0] alur =
360 alu == ORA ? op1 | op2 :
361 alu == AND ? op1 & op2 :
362 alu == EOR ? op1 ^ op2 :
363 alu == ADC ? op1 + op2 + p[CF] :
364 alu == STA ? op1 :
365 alu == LDA ? op2 :
366 alu == BIT ? op1 & op2 :
367 alu == CMP ? op1 - op2 :
368 alu == SBC ? op1 - op2 - !p[CF] :
369 alu == INC ? op1 + 1 :
370 alu == DEC ? op1 - 1 :
371 alu == ASL ? {op1[6:0], 1'b0} :
372 alu == ROL ? {op1[6:0], p[CF]} :
373 alu == LSR ? {1'b0, op1[7:1]} :
374 alu == ROR ? {p[CF], op1[7:1]} :
375 8'hFF;
376
377
378wire zf = alur[7:0] == 8'h00;
379wire nf = alur[7];
380wire cf = alur[8];
381wire va = (op1[7] == op2[7]) & (op1[7] ^ alur[7]);
382wire vs = (op1[7] != op2[7]) & (op1[7] ^ alur[7]);
383
384wire [7:0] aluf =
385 alu == ADC ? {nf, va, p[5:2], zf, cf} :
386 alu == SBC ? {nf, vs, p[5:2], zf, !cf} :
387 alu == CMP ? {nf, p[6:2], zf, !cf} :
388 alu == BIT ? {op2[7:6], p[5:2], zf, p[CF]} :
389 alu == ASL ||
390 alu == ROL ? {nf, p[6:2], zf, op1[7]} :
391 alu == LSR ||
392 alu == ROR ? {nf, p[6:2], zf, op1[0]} :
393 {nf, p[6:2], zf, p[CF]};
394
395endmodule