§ Код процессора

Процессор проходит все тесты ZXALL.
1/* verilator lint_off WIDTH */
2/* verilator lint_off CASEX */
3/* verilator lint_off CASEINCOMPLETE */
4/* verilator lint_off CASEOVERLAP */
5module z80
6(
7    input               clock,          // 3.5 или 25 Мгц
8    input               reset_n,        // =0 Сброс процессора
9    input               compat,         // =1 Включена совместимость с Z80 Cycles
10    input               hold,           // Если 0: не выполнять инструкции
11    input               irq,            // Вызов IRQ на позитивном фронте
12    output       [15:0] address,        // Адресная шина
13    input        [ 7:0] i_data,         // Входящие данные с шины
14    output  reg  [ 7:0] o_data,         // Данные на запись
15    output  reg         we,             // =1 Запись в память
16    output              m0,             // =1 Сигнал начала инструкции
17    input        [ 7:0] portin,         // portin=port[address]
18    output  reg         portwe          // Сигнал записи в порт address
19);
20// LOCALPARAM
21// -----------------------------------------------------------------------------
22localparam
23    CF = 8, NF = 9, PF = 10, F3F = 11, HF = 12, F5F = 13, ZF = 14, SF = 15;
24localparam
25    alu_add = 0, alu_rlc =  8, alu_inc = 16, alu_rlca = 24,
26    alu_adc = 1, alu_rrc =  9, alu_dec = 17, alu_rrca = 25,
27    alu_sub = 2, alu_rl  = 10,               alu_rla  = 26,
28    alu_sbc = 3, alu_rr  = 11,               alu_rra  = 27,
29    alu_and = 4, alu_sla = 12, alu_daa = 20, alu_bit  = 28,
30    alu_xor = 5, alu_sra = 13, alu_cpl = 21, alu_set  = 29,
31    alu_or  = 6, alu_sll = 14, alu_scf = 22, alu_res  = 30,
32    alu_cp  = 7, alu_srl = 15, alu_ccf = 23;
33localparam
34    spec_exaf   = 1,
35    spec_exx    = 2,
36    spec_exdehl = 3;
37localparam
38    ldcmd_ldi   = 1,
39    ldcmd_ldd   = 2,
40    ldcmd_cpi   = 3,
41    ldcmd_cpd   = 4;
42assign address = bus ? cp : pc;
43assign m0 = (t_state == 0 && prefix == 0 && delay == 0);
44// Основная логика работы процессора
45// -----------------------------------------------------------------------------
46always @(posedge clock) if (hold) begin
47// Сброс регистров управления
48exxw     <= 0;
49ldcmd    <= 0;
50reg_w8   <= 0;
51reg_w16  <= 0;
52reg_wf   <= 0;
53reg_wfex <= 0;
54we       <= 0;
55portwe   <= 0;
56// Ожидание задержки после исполнения инструкции
57if (compat && delay) delay <= delay - 1;
58// Сброс процессора
59else if (reset_n == 1'b0) begin
60    pc          <= 0;
61    bus         <= 0;
62    t_state     <= 0;
63    set_prefix  <= 0;
64    i_mode      <= 0;
65    hptr        <= 0;
66    iff1 <= 1'b0; iff1_ <= 1'b0;
67    iff2 <= 1'b0; iff2_ <= 1'b0;
68end
69// Обработка прерывания
70else if (irq_process) case (t_state)
71    // Запись PC[7:0]
72    0: begin
73        t_state <= 1;
74        // Писать в память
75        bus <= 1; we <= 1; cp <= sp - 2; o_data <= pc[7:0];
76        // SP=SP-2
77        reg_w16 <= 1; reg_dt <= sp - 2; reg_id <= 3;
78    end
79    // Запись PC[15:8]
80    1: begin t_state <= 2; we <= 1; o_data <= pc[15:8]; cp <= cp + 1; end
81    // Считывание адреса
82    2: begin
83        if (i_mode == 2) begin
84            t_state <= 3;
85            hptr    <= ir[15:8];
86            cp      <= {ir[15:8], 8'hFF};
87        end
88        // imode=0 [8080], imode=1 [standart]
89        else begin
90            t_state <= 0;
91            bus     <= 0;
92            pc      <= 8'h38;
93            delay   <= 13-3-1;
94            irq_process <= 0;
95        end
96    end
97    3: begin t_state <= 4; cp <= cp + 1; pc[7:0] <= i_data; end
98    4: begin
99        t_state  <= 0;
100        bus      <= 0;
101        pc[15:8] <= i_data;
102        delay    <= 19-5-1;
103        irq_process <= 0;
104    end
105endcase
106// На первом такте инструкции обнаружен вызов IRQ (и прерывания разрешены)
107else if (iff1 && prefix == 0 && t_state == 0 && irq ^ irq_latch) begin
108    // Проверить, что прерывания разрешены и что IRQ=0->1
109    if (irq) begin
110        irq_process <= 1;
111        iff1 <= 1'b0; iff1_ <= 1'b0;
112        iff2 <= 1'b0; iff2_ <= 1'b0;
113        // Если текущая инструкция HALT
114        if (i_data == 8'h76) pc <= pc + 1;
115    end
116    irq_latch <= irq;
117end
118// Исполнение инструкции
119else begin
120    // Защелкнуть опкод и увеличить R+1
121    if (t_state == 0) begin
122        // Если запрошено прерывание imode=0, то выбирает FF
123        opcode_latch <= i_data;
124        pc      <= pc + 1;
125        ir[6:0] <= ir[6:0] + 1;
126        // Защелкивание DI/EI через одну инструкцию
127        if (prefix == 0) begin
128            iff1 <= iff1_;
129            iff2 <= iff2_;
130        end
131    end
132    t_state <= t_state + 1;
133    casex (opcode)
134        // 1T|4T: EX AF,AF'
135        8'b00_001_000: begin exxw <= spec_exaf; {set_prefix, t_state} <= 0; delay <= 4-1; end
136        // 1/2T|8/13T: DJNZ *
137        8'b00_010_000: case (t_state)
138            0: begin
139                // Запись в регистр B
140                reg_w8 <= 1;
141                reg_id <= 0;
142                reg_dt <= bc[15:8] - 1;
143                set_prefix <= 0;
144                // Выход из цикла
145                if (bc[15:8] == 1) begin pc <= pc + 2; t_state <= 0; delay <= 8-1; end
146            end
147            // Прочитать следующий байт и перейти
148            1: begin
149                pc <= pc + 1 + signex;
150                t_state <= 0;
151                delay   <= 13-2;
152            end
153        endcase
154        // 2T|12T: JR *
155        8'b00_011_000: case (t_state)
156            1: begin pc <= pc + signex + 1; {set_prefix, t_state} <= 0; delay <= 12-2; end
157        endcase
158        // 1/2T|12/7T: JR cc, *
159        8'b00_1xx_000: case (t_state)
160            0: begin
161                set_prefix <= 0;
162                // Если условие не совпало, пропуск +2 байта вперед
163                // Пример, opcode[4:3]=0, то если ZF=1, то произойдет выход из JR
164                if (condition[ opcode[4:3] ]) begin
165                    t_state <= 0;
166                    pc      <= pc + 2;
167                    delay   <= 7-1;
168                end
169            end
170            // Иначе дочитать байт и перейти по метке
171            1: begin
172                pc <= pc + 1 + signex;
173                t_state <= 0;
174                delay   <= 12-2;
175            end
176        endcase
177        // 3T|10T: LD r16, nn
178        8'b00_xx_0001: case (t_state)
179            1: begin pc <= pc + 1; reg_dt[ 7:0] <= i_data; end
180            2: begin pc <= pc + 1; reg_dt[15:8] <= i_data;
181                     reg_w16    <= 1;
182                     reg_id     <= opcode[5:4];
183                     {set_prefix, t_state} <= 0;
184                     delay <= 10-3;
185            end
186        endcase
187        // 1T/11T: ADD HL, r16
188        8'b00_xx_1001: case (t_state)
189            0: begin
190                reg_w16  <= 1;
191                reg_wfex <= 1;
192                reg_id   <= 2;
193                reg_dt   <= do_hl_add[15:0];
194                flag_ex  <= do_hl_flag;
195                {set_prefix, t_state} <= 0; delay <= 11-1;
196            end
197        endcase
198        // 2T|7T: LD (BC|DE), A
199        8'b00_0x_0010: case (t_state)
200            0: begin
201                cp      <= opcode[4] ? de : bc;
202                bus     <= 1;
203                we      <= 1;
204                o_data  <= af[7:0];
205                hptr    <= af[7:0];
206            end
207            1: begin {set_prefix, t_state, bus} <= 0; delay <= 7-2; end
208        endcase
209        // 2T|7T: LD A, (BC|DE)
210        8'b00_0x_1010: case (t_state)
211            0: begin cp <= opcode[4] ? de : bc; bus <= 1; end
212            1: begin
213                reg_w8 <= 1;
214                reg_id <= 7;
215                reg_dt <= i_data;
216                {set_prefix, t_state, bus} <= 0; delay <= 7-2;
217            end
218        endcase
219        // 5T|16T: LD (**), HL
220        8'b00_10_0010: case (t_state)
221            1: begin cp[ 7:0] <= i_data; pc <= pc + 1; end
222            2: begin
223                bus      <= 1;
224                cp[15:8] <= i_data;
225                hptr     <= i_data;
226                pc       <= pc + 1;
227                o_data   <= hlx[7:0];
228                we       <= 1;
229            end
230            3: begin cp <= cp + 1; o_data <= hlx[15:8]; we <= 1; end
231            4: begin {set_prefix, t_state, bus} <= 0; delay <= 16-5; end
232        endcase
233        // 4T|13T: LD (**), A
234        8'b00_11_0010: case (t_state)
235            1: begin cp[ 7:0] <= i_data; pc <= pc + 1; end
236            2: begin
237                we       <= 1;
238                bus      <= 1;
239                cp[15:8] <= i_data;
240                pc       <= pc + 1;
241                o_data   <= af[7:0];
242                hptr     <= af[7:0];
243            end
244            3: begin {set_prefix, t_state, bus} <= 0; delay <= 16-4; end
245        endcase
246        // 5T|16T: LD HL, (**)
247        8'b00_10_1010: case (t_state)
248            1: begin cp[ 7:0] <= i_data; pc <= pc + 1; end
249            2: begin cp[15:8] <= i_data; pc <= pc + 1; bus <= 1; hptr <= i_data; end
250            3: begin reg_id <= /*L*/ 5; reg_dt <= i_data; reg_w8 <= 1; cp <= cp + 1; end
251            4: begin
252                reg_id <= /*H*/ 4; reg_dt <= i_data; reg_w8 <= 1;
253                {set_prefix, t_state, bus} <= 0; delay <= 16-5;
254            end
255        endcase
256        // 4T|13T: LD A, (**)
257        8'b00_11_1010: case (t_state)
258            1: begin cp[ 7:0] <= i_data; pc <= pc + 1; end
259            2: begin cp[15:8] <= i_data; pc <= pc + 1; bus <= 1; hptr <= i_data; end
260            3: begin
261                reg_id <= /*A*/ 7; reg_dt <= i_data; reg_w8 <= 1;
262                {set_prefix, t_state, bus} <= 0; delay <= 13-4;
263            end
264        endcase
265        // 1T|6T: INC|DEC r16
266        8'b00_xx_x011: case (t_state)
267            0: begin
268                reg_w16 <= 1;
269                reg_id  <= opcode[5:4];
270                case (opcode[5:4])
271                    2'b00: reg_dt <= opcode[3] ? bc  - 1 : bc + 1;
272                    2'b01: reg_dt <= opcode[3] ? de  - 1 : de + 1;
273                    2'b10: reg_dt <= opcode[3] ? hlx - 1 : hlx + 1;
274                    2'b11: reg_dt <= opcode[3] ? sp  - 1 : sp + 1;
275                endcase
276                {set_prefix, t_state} <= 0; delay <= 6-1;
277            end
278        endcase
279        // 4T|11T: INC|DEC (HL)
280        // 6T|23T: INC|DEC (IX|IY+d)
281        8'b00_110_10x: case (t_state)
282            // Запрос в память или чтение смещения
283            0: begin
284                bus     <= prefix ? 0 : 1;
285                t_state <= prefix ? 1 : 2;
286                alu_m   <= opcode[0] ? alu_dec : alu_inc;
287                cp      <= hl;
288            end
289            // Дочитать смещение к IX|IY
290            1: begin
291                bus     <= 1;
292                cp      <= hlx + signex;
293                pc      <= pc + 1;
294            end
295            // Вычисление
296            2: begin op1 <= i_data; op2 <= 1; end
297            // Запись в память
298            3: begin we <= 1; o_data <= alu_r[7:0]; reg_wf <= 1; end
299            // Завершение инструкции
300            4: begin {set_prefix, t_state, bus} <= 0; delay <= prefix ? 23-4-5: 11-4; end
301        endcase
302        // 2T|4T: INC|DEC r8
303        8'b00_xxx_10x: case (t_state)
304            0: begin op1 <= reg8_53; op2 <= 1; alu_m <= opcode[0] ? alu_dec : alu_inc; end
305            1: begin
306                reg_wf <= 1;
307                reg_w8 <= 1;
308                reg_id <= opcode[5:3];
309                reg_dt <= alu_r[7:0];
310                {set_prefix, t_state} <= 0; delay <= 4-2;
311            end
312        endcase
313        // 3T|10T: LD (HL), *
314        // 5T|19T: LD (IX|IY+d), *
315        8'b00_110_110: case (t_state)
316            // Писать в зависимости от префикса
317            1: begin
318                we      <= prefix ? 0 : 1;
319                bus     <= prefix ? 0 : 1;
320                t_state <= prefix ? 2 : 3;
321                cp      <= prefix ? (hlx + signex) : hl;
322                pc      <= pc + 1;
323                o_data  <= i_data;
324            end
325            // Префиксированный
326            2: begin
327                we      <= 1;
328                bus     <= 1;
329                pc      <= pc + 1;
330                o_data  <= i_data;
331            end
332            3: begin {bus, set_prefix, t_state} <= 0; delay <= prefix ? 19-4-4 : 10-3; end
333        endcase
334        // 2T|7T: LD r8, *
335        8'b00_xxx_110: case (t_state)
336            1: begin
337                pc      <= pc + 1;
338                reg_w8  <= 1;
339                reg_id  <= opcode[5:3];
340                reg_dt  <= i_data;
341                {set_prefix, t_state} <= 0; delay <= 7-2;
342            end
343        endcase
344        // 4T: <RLCA,RRCA,RLA,RRA,DAA,CPL,SCF,CCF>
345        8'b00_xxx_111: case (t_state)
346            0: begin op1 <= af[7:0]; alu_m <= (opcode[5] ? alu_daa : alu_rlca) + opcode[4:3]; end
347            1: begin
348                reg_w8 <= 1;
349                reg_wf <= 1;
350                reg_id <= 7;
351                reg_dt <= alu_r;
352                {set_prefix, t_state} <= 0; delay <= 4-2;
353            end
354        endcase
355        // 1T: HALT
356        8'b01_110_110: begin pc <= pc; {set_prefix, t_state} <= 0; delay <= 4-1; end
357        // 2T|7T: LD (HL), r8
358        // 4T|19T: LD (IX|IY+d), r8
359        8'b01_110_xxx: case (t_state)
360            0: begin
361                bus     <= prefix ? 0 : 1;
362                we      <= prefix ? 0 : 1;
363                t_state <= prefix ? 1 : 2;
364                cp      <= hl;
365                o_data  <= reg8_20;
366            end
367            // Считывание смещения для префикса
368            1: begin
369                we      <= 1;
370                bus     <= 1;
371                cp      <= hlx + signex;
372                pc      <= pc + 1;
373                o_data  <= hl20_org;
374            end
375            2: begin {set_prefix, t_state, bus} <= 0; delay <= prefix ? 19-4-3 : 7-2; end
376        endcase
377        // 2T|7T: LD r8, (HL)
378        // 4T|19T: LD r8, (IX|IY+d)
379        8'b01_xxx_110: case (t_state)
380            0: begin
381                bus     <= prefix ? 0 : 1;
382                t_state <= prefix ? 1 : 2;
383                t_pref  <= prefix ? 1 : 0;
384                cp      <= hl;
385            end
386            // Считывание смещения для префикса
387            1: begin
388                bus     <= 1;
389                cp      <= hlx + signex;
390                pc      <= pc + 1;
391                set_prefix <= 0;
392            end
393            // Запись в регистр
394            2: begin
395                reg_w8 <= 1;
396                reg_id <= opcode[5:3];
397                reg_dt <= i_data;
398                {t_state, bus} <= 0; delay <= t_pref ? 19-4-3 : 7-2;
399            end
400        endcase
401        // 1T|4T: LD r8, r8
402        8'b01_xxx_xxx: case (t_state)
403            0: begin
404                reg_w8 <= 1;
405                reg_id <= opcode[5:3];
406                reg_dt <= reg8_20;
407                {set_prefix, t_state} <= 0; delay <= 4-1;
408            end
409        endcase
410        // 3T|7T: <ALU> a, (HL)
411        // 5T|19T: <ALU> a, (IX|IY+d)
412        8'b10_xxx_110: case (t_state)
413            // Установить адрес на шину (если это HL)
414            0: begin
415                bus     <= prefix ? 0 : 1;
416                t_state <= prefix ? 1 : 2;
417                alu_m   <= opcode[5:3];
418                op1     <= af[7:0];
419                cp      <= hl;
420            end
421            // Дочитывание смещения к префиксу и адрес IX|IY+d
422            1: begin
423                bus     <= 1;
424                cp      <= hlx + signex;
425                pc      <= pc + 1;
426            end
427            // Лишний такт тратится впустую
428            2: begin op2 <= i_data; bus <= 0; end
429            3: begin
430                reg_wf <= 1;
431                reg_id <= 7;
432                reg_w8 <= opcode[5:3] != alu_cp;
433                reg_dt <= alu_r[7:0];
434                {set_prefix, t_state} <= 0; delay <= prefix ? 19-4-4: 7-3;
435            end
436        endcase
437        // 2T|4T: <ALU> a, r8
438        8'b10_xxx_xxx: case (t_state)
439            0: begin op1 <= af[7:0]; op2 <= reg8_20; alu_m <= opcode[5:3]; end
440            1: begin
441                reg_wf <= 1;
442                reg_id <= 7;
443                reg_w8 <= opcode[5:3] != alu_cp;
444                reg_dt <= alu_r[7:0];
445                {set_prefix, t_state} <= 0; delay <= 4-2;
446            end
447        endcase
448        // 1/3T|10/11/5T: RET ccc|RET
449        8'b11_001_001,
450        8'b11_xxx_000: case (t_state)
451            0: begin
452                set_prefix <= 0;
453                // Условие не сработало, к следующей инструкции
454                // Если opcode[0]=1, то RET безусловный
455                if (condition[ opcode[5:3] ] && (opcode[0] == 1'b0)) begin
456                    t_state <= 0;
457                    delay   <= 5-1;
458                end
459                else begin
460                    bus     <= 1;
461                    cp      <= sp;
462                    reg_w16 <= 1;
463                    reg_dt  <= sp + 2;
464                    reg_id  <= 3;
465                end
466            end
467            1: begin pc[7:0] <= i_data; cp <= cp + 1; end
468            2: begin
469                pc[15:8] <= i_data;
470                {t_state, bus} <= 0; delay <= opcode[0] ? 10-3 : 11-3;
471            end
472        endcase
473        // 3T|10T: POP r16
474        8'b11_xx0_001: case (t_state)
475            0: begin
476                bus     <= 1;
477                cp      <= sp;
478                reg_w16 <= 1;
479                reg_dt  <= sp + 2;
480                reg_id  <= 3;
481            end
482            1: begin
483                // POP AF
484                if (opcode[5:4] == 2'b11) begin
485                    reg_wfex <= 1;
486                    flag_ex  <= i_data;
487                end else begin
488                    reg_w8 <= 1;
489                    reg_id <= {opcode[5:4], 1'b1};
490                    reg_dt <= i_data;
491                end
492                cp <= cp + 1;
493            end
494            2: begin
495                reg_w8 <= 1;
496                reg_id <= opcode[5:4] == 2'b11 ? 7 : {opcode[5:4], 1'b0};
497                reg_dt <= i_data;
498                {set_prefix, t_state, bus} <= 0; delay <= 10-3;
499            end
500        endcase
501        // 1T/4T: EXX
502        8'b11_011_001: case (t_state)
503            0: begin {set_prefix, t_state} <= 0; exxw <= spec_exx; delay <= 4-1; end
504        endcase
505        // 1T/4T: JP (HL)
506        8'b11_101_001: case (t_state)
507            0: begin pc <= hlx; {set_prefix, t_state} <= 0; delay <= 4-1; end
508        endcase
509        // 1T/6T: LD SP, HL
510        8'b11_111_001: case (t_state)
511            0: begin
512                reg_w16 <= 1;
513                reg_dt  <= hlx;
514                reg_id  <= 3;
515                {set_prefix, t_state} <= 0; delay <= 6-1;
516            end
517        endcase
518        // 2/3T|10T: JP ccc, **; JP **
519        8'b11_000_011,
520        8'b11_xxx_010: case (t_state)
521            0: begin
522                set_prefix <= 0;
523                // Условие не сработало, к следующей инструкции
524                // Если opcode[0]=1, то переход безусловный
525                if (condition[ opcode[5:3] ] && (opcode[0] == 1'b0)) begin
526                    pc      <= pc + 2;
527                    t_state <= 3;
528                end
529            end
530            1: begin reg_dt <= i_data; pc <= pc + 1; end
531            2: begin hptr <= i_data; pc <= {i_data, reg_dt[7:0]}; t_state <= 0; delay <= 10-3; end
532            // Необходимо для получения HPTR
533            3: begin hptr <= i_data; pc <= pc + 1; t_state <= 0; delay <= 10-2; end
534        endcase
535        // CB: Битовые инструкции
536        // 4T/8T:  <opcode> r8
537        // 5T/15T: <opcode> (HL)
538        // 5T/23T: <opcode> (IX+*)
539        // 4T/12T: BIT n,(HL)
540        // 4T/20T: BIT n,(IX+*)
541        8'b11_001_011: case (t_state)
542            // Чтение опкода или смещения
543            1: begin
544                pc  <= pc + 1;
545                cp  <= prefix ? hlx + signex : hl;
546                bus <= prefix ? 0 : 1; // Если (Ixy+*), дочитать PC+1
547                opcode_ext <= i_data;
548                ir[6:0]    <= ir[6:0] + 1;
549                if (prefix == 0) t_state <= 3;
550            end
551            // Считывание опкода для префиксированной инструкции
552            2: begin opcode_ext <= i_data; pc <= pc + 1; bus <= 1; end
553            // Чтение данных из памяти или регистра
554            3: begin
555                op1     <= prefix ? i_data : reg8_cb20;
556                op2     <= opcode_ext[6:3];
557                alu_m   <= opcode_ext[5:3] + alu_rlc;
558                // Убрать префиксирование для BIT
559                t_pref     <= prefix ? 1 : 0;
560                set_prefix <= 0;
561            end
562            // Исполнение и сохранение
563            4: casex (opcode_ext[7:6])
564                // BIT n, r8
565                // BIT n, (HL)
566                8'b01: begin
567                    reg_wfex <= 1;
568                    flag_ex  <= t_pref ? bit_flags_xx : bit_flags;
569                    // BIT n, (HL)
570                    if (t_pref == 0 && opcode_ext[2:0] == 6)
571                        {flag_ex[5],flag_ex[3]} <= {hptr[5],hptr[3]};
572                    // Все префиксированные выполняются за 20T
573                    {bus, t_state} <= 0;
574                    delay <= t_pref ? 20-4-5 : (opcode_ext[2:0] == 6 ? 12-4 : 8-4);
575                end
576                // SHIFT|RES|SET n, reg|idata
577                // Сохранение в регистры и в память (если выбрано)
578                8'b00,
579                8'b1x: begin
580                    // Кроме HL и префиксированных
581                    we      <= (opcode_ext[2:0] == 6) || t_pref;
582                    reg_w8  <= (opcode_ext[2:0] != 6);
583                    reg_id  <=  opcode_ext[2:0];
584                    // Если это RES|SET, то из rsop, иначе из alu_r
585                    reg_dt  <= opcode_ext[7] ? rsop : alu_r;
586                    o_data  <= opcode_ext[7] ? rsop : alu_r;
587                    // Операции сдвига меняют флаги
588                    if (opcode_ext[7] == 1'b0) reg_wf <= 1;
589                    // Нет префикса и нет (HL)
590                    if (t_pref == 0 && (opcode_ext[2:0] != 6)) begin
591                        {bus, t_state} <= 0; delay <= 8-4;
592                    end
593                end
594            endcase
595            // Завершение записи для инструкции [00-3F,80-FF]
596            5: begin {bus, t_state} <= 0; delay <= t_pref ? 23-4-6 : 15-5; end
597        endcase
598        // 3T/11T: OUT (*), A
599        8'b11_010_011: case (t_state)
600            1: begin
601                bus     <= 1;
602                portwe  <= 1;
603                o_data  <= af[7:0];
604                hptr    <= af[7:0];
605                cp      <= {af[7:0], i_data};
606                pc      <= pc + 1;
607            end
608            2: begin {set_prefix, t_state, bus} <= 0; delay <= 11-3; end
609        endcase
610        // 3T/11T: IN A,(*)
611        8'b11_011_011: case (t_state)
612            1: begin bus <= 1; cp <= {af[7:0], i_data}; hptr <= af[7:0]; pc <= pc + 1; end
613            2: begin
614                reg_id <= 7;
615                reg_w8 <= 1;
616                reg_dt <= portin;
617                {set_prefix, t_state, bus} <= 0; delay <= 11-3;
618            end
619        endcase
620        // 5T/19T: EX (SP), HL
621        8'b11_100_011: case (t_state)
622            0: begin bus <= 1; cp <= sp; end
623            1: begin reg_dt[ 7:0] <= i_data; cp <= cp + 1; end
624            2: begin reg_dt[15:8] <= i_data; cp <= cp - 1; we <= 1; o_data <= hlx[7:0]; end
625            3: begin
626                reg_w16 <= 1;
627                reg_id  <= 2;
628                we <= 1;
629                cp <= cp + 1;
630                o_data <= hlx[15:8];
631            end
632            4: begin {set_prefix, t_state, bus} <= 0; delay <= 19-5; end
633        endcase
634        // 1T/4T: EX DE,HL
635        8'b11_101_011: case (t_state)
636            0: begin {set_prefix, t_state} <= 0; exxw <= spec_exdehl; delay <= 4-1; end
637        endcase
638        // 1T/4T: DI/EI
639        8'b11_11x_011: case (t_state)
640            // Срабатывает активация iff1/2 через одну инструкцию
641            0: begin
642                iff1_ <= opcode[3];
643                iff2_ <= opcode[3];
644                {set_prefix, t_state} <= 0; delay <= 4-1;
645            end
646        endcase
647        // 2/5T|10/17T: CALL ccc, **; CALL **
648        8'b11_001_101,
649        8'b11_xxx_100: case (t_state)
650            0: begin
651                set_prefix <= 0;
652                // Условие не сработало, к следующей инструкции
653                // Если opcode[0]=1, то переход безусловный
654                if (condition[ opcode[5:3] ] && (opcode[0] == 1'b0)) begin
655                    pc      <= pc + 2;
656                    t_state <= 5;
657                end
658                // Иначе считывать адрес памяти
659                else begin
660                    reg_w16 <= 1;
661                    reg_dt  <= sp - 2;
662                    reg_id  <= 3;
663                end
664            end
665            1: begin reg_dt <= i_data; pc <= pc + 1; end
666            2: begin
667                bus     <= 1;
668                we      <= 1;
669                cp      <= sp;
670                pc      <= {i_data, reg_dt[7:0]};
671                hptr    <= i_data;
672                o_data  <= pc1[7:0];
673                reg_dt  <= pc1;
674            end
675            3: begin
676                we      <= 1;
677                cp      <= cp + 1;
678                o_data  <= reg_dt[15:8];
679            end
680            4: begin {t_state, bus} <= 0; delay <= 17-5; end
681            // Для получения HPTR
682            5: begin hptr <= i_data; pc <= pc + 1; t_state <= 0; delay <= 10-2; end
683        endcase
684        // 3T|11T: PUSH r16
685        8'b11_xx0_101: case (t_state)
686            // Запись младшего байта
687            0: begin
688                bus <= 1;
689                we  <= 1;
690                cp  <= sp - 2;
691                // sp = sp - 2
692                reg_w16 <= 1;
693                reg_dt  <= sp - 2;
694                reg_id  <= 3;
695                case (opcode[5:4])
696                    0: o_data <=  bc[ 7:0];
697                    1: o_data <=  de[ 7:0];
698                    2: o_data <= hlx[ 7:0];
699                    3: o_data <=  af[15:8]; // Флаги (LO)
700                endcase
701            end
702            // Запись старшего байта
703            1: begin
704                we <= 1;
705                cp <= cp + 1;
706                case (opcode[5:4])
707                    0: o_data <=  bc[15:8];
708                    1: o_data <=  de[15:8];
709                    2: o_data <= hlx[15:8];
710                    3: o_data <=  af[ 7:0]; // Аккумулятор (HI)
711                endcase
712            end
713            2: begin {set_prefix, t_state, bus} <= 0; delay <= 11-3; end
714        endcase
715        // EXTENDED
716        8'b11_101_101: case (t_state)
717            0: begin set_prefix <= 0; n_state <= 0; end
718            1: begin
719                pc <= pc + 1;
720                opcode_ext <= i_data;
721                casex (i_data)
722                    // IN r8, (C)
723                    8'b01_xxx_000: begin cp <= bc; bus <= 1; end
724                    // OUT (C), r8
725                    8'b01_xxx_001: begin
726                        bus     <= 1;
727                        portwe  <= 1;
728                        cp      <= bc;
729                        o_data  <= reg8_outc;
730                     end
731                    // 2T: SBC|ADC hl, r16
732                    8'b01_xxx_010: begin
733                        reg_w16  <= 1;
734                        reg_wfex <= 1;
735                        reg_id   <= 2; // HL
736                        reg_dt   <= i_data[3] ? ed_hl_adc   : ed_hl_sbc;
737                        flag_ex  <= i_data[3] ? hl_adc_flag : hl_sbc_flag;
738                        t_state <= 0; delay <= 15-2;
739                    end
740                    // 6T: LD (**),r16 | r16,(**)
741                    8'b01_xxx_011: begin /* nothing */ end
742                    // NEG
743                    8'b01_xxx_100: begin
744                        op1   <= 0;
745                        op2   <= af[7:0];
746                        alu_m <= alu_sub;
747                    end
748                    // RETN/RETI
749                    8'b01_xxx_101: begin
750                        bus     <= 1;
751                        cp      <= sp;
752                        reg_w16 <= 1;
753                        reg_dt  <= sp + 2;
754                        reg_id  <= 3;
755                        // RETN, кроме RETI
756                        if (i_data[5:3] != 3'b001) begin
757                            iff1  <= iff2;
758                            iff1_ <= iff2_;
759                        end
760                    end
761                    // IM n: [00120012]
762                    8'b01_xxx_110: begin
763                        i_mode <= i_data[4] ? (i_data[3] ? 2 : 1) : 0;
764                        t_state <= 0; delay <= 8-2;
765                    end
766                    // LD i|r, a
767                    // LD a, i|r
768                    8'b01_0xx_111: begin
769                        reg_id <= 7;
770                        reg_dt <= i_data[3] ? ir[7:0] : ir[15:8];
771                        if      (i_data[4]) reg_w8 <= 1;
772                        else if (i_data[3]) ir[7:0] <= af[7:0]; else ir[15:8] <= af[7:0];
773                        // LD A, I|R записывает флаги
774                        if (i_data[4]) begin
775                            reg_wfex <= 1;
776                            if (i_data[3]) // Если выполняется прерывание то PV=0
777                                 flag_ex <= {ir[ 7], ir[ 7:0] == 0, ir[ 5], 1'b0, ir[ 3], (irqcause ? 1'b0 : iff2), 1'b0, af[CF]};
778                            else flag_ex <= {ir[15], ir[15:8] == 0, ir[13], 1'b0, ir[11], (irqcause ? 1'b0 : iff2), 1'b0, af[CF]};
779                        end
780                        t_state <= 0; delay <= 9-2;
781                    end
782                    // RRD |RLD
783                    // LDI |LDD |LDIR|LDDR
784                    // CPI |CPD |CPIR|CPDR
785                    // OUTI|OUTD|OTIR|OTDR
786                    8'b01_10x_111,
787                    8'b10_1xx_00x,
788                    8'b10_1xx_011: begin cp <= hl; bus <= 1; end
789                    // INI |IND |INIR|INDR
790                    8'b10_1xx_010: begin
791                        cp      <= {b_dec, bc[7:0]};
792                        bus     <= 1;
793                        alu_m   <= alu_dec;
794                        op1     <= bc[15:8];
795                        op2     <= 1;
796                    end
797                    // NOP инструкция
798                    default: begin t_state <= 0; delay <= 8-2; end
799                endcase
800            end
801            2: begin
802                t_state <= 2;
803                n_state <= n_state + 1;
804                casex (opcode_ext)
805                // 3T: IN r8, (C)
806                8'b01_xxx_000: begin
807                    reg_w8   <= 1;
808                    reg_wfex <= 1;
809                    // При записи в 6-й регистр ничего не происходит
810                    reg_id <= opcode_ext[5:3];
811                    reg_dt <= portin;
812                    // Вычисление флагов
813                    flag_ex <= {
814                        portin[7],      // S
815                        portin == 0,    // Z
816                        portin[5],      // F5
817                        1'b0,           // H
818                        portin[3],      // F3
819                        ~^portin[7:0],  // P
820                        1'b0,           // N
821                        af[CF]          // C
822                    };
823                    {t_state, bus} <= 0; delay <= 12-3;
824                end
825                // 3T: OUT (C), r8
826                8'b01_xxx_001: begin {t_state, bus} <= 0; delay <= 12-3; end
827                // 6T: LD (**), r16
828                8'b01_xx0_011: case (n_state)
829                    0: begin cp[7:0] <= i_data; pc <= pc + 1; end
830                    // Запись младшего байта
831                    1: begin
832                        cp[15:8] <= i_data;
833                        hptr     <= i_data;
834                        pc  <= pc + 1;
835                        bus <= 1;
836                        we  <= 1;
837                        case (opcode_ext[5:4])
838                            2'b00: o_data <= bc[7:0];
839                            2'b01: o_data <= de[7:0];
840                            2'b10: o_data <= hl[7:0];
841                            2'b11: o_data <= sp[7:0];
842                        endcase
843                    end
844                    // Запись старшего байта
845                    2: begin
846                        we <= 1;
847                        cp <= cp + 1;
848                        case (opcode_ext[5:4])
849                            2'b00: o_data <= bc[15:8];
850                            2'b01: o_data <= de[15:8];
851                            2'b10: o_data <= hl[15:8];
852                            2'b11: o_data <= sp[15:8];
853                        endcase
854                    end
855                    // Завершение записи
856                    3: begin {t_state, bus} <= 0; delay <= 20-6; end
857                endcase
858                // 6T: LD r16, (**)
859                8'b01_xx1_011: case (n_state)
860                    0: begin cp[ 7:0] <= i_data; pc <= pc + 1; end
861                    1: begin cp[15:8] <= i_data; pc <= pc + 1; bus <= 1; hptr <= i_data; end
862                    2: begin reg_dt[7:0] <= i_data; cp <= cp + 1; end
863                    3: begin
864                        reg_w16 <= 1;
865                        reg_id  <= opcode_ext[5:4];
866                        reg_dt[15:8] <= i_data;
867                        {t_state, bus} <= 0; delay <= 20-6;
868                    end
869                endcase
870                // 4T: RETN/RETI
871                8'b01_xxx_101: case (n_state)
872                    0: begin pc[ 7:0] <= i_data; cp <= cp + 1; end
873                    1: begin pc[15:8] <= i_data; {t_state, bus} <= 0; delay <= 14-4; end
874                endcase
875                // 3T: NEG
876                8'b01_xxx_100: begin
877                    reg_id <= 7;
878                    reg_wf <= 1;
879                    reg_w8 <= 1;
880                    reg_dt <= alu_r;
881                    t_state <= 0; delay <= 8-3;
882                end
883                // 4T: RRD|RLD
884                8'b01_10x_111: case (n_state)
885                    0: begin
886                        we       <= 1; // Запись в память
887                        reg_w8   <= 1; // Запись в регистр A
888                        reg_wfex <= 1; // Писать кастомные флаги
889                        reg_id   <= 7;
890                        o_data   <= opcode_ext[3] ? rld_w : rrd_w;
891                        reg_dt   <= opcode_ext[3] ? rld_a : rrd_a;
892                        flag_ex <= opcode_ext[3] ? {
893                            rld_a[7],   rld_a == 0, rld_a[5], 1'b0,
894                            rld_a[3], ~^rld_a[7:0],     1'b0, af[CF]
895                        } : {
896                            rrd_a[7],   rrd_a == 0, rrd_a[5], 1'b0,
897                            rrd_a[3], ~^rrd_a[7:0],     1'b0, af[CF]
898                        };
899                    end
900                    1: begin {t_state, bus} <= 0; delay <= 18-4; end
901                endcase
902                // 4T: LDI|LDD|LDIR|LDDR
903                8'b10_1xx_000: case (n_state)
904                    // Запись в память
905                    0: begin
906                        we       <= 1;
907                        cp       <= de;
908                        o_data   <= i_data;
909                        reg_wfex <= 1;
910                        flag_ex  <= {
911                            af[SF],   af[ZF],  ldixy[1], 1'b0,
912                            ldixy[3], bc != 1, 1'b0,     af[CF]
913                        };
914                        // Уменьшить BC--; икремент/декремент HL/DE
915                        ldcmd <= opcode_ext[3] ? ldcmd_ldd : ldcmd_ldi;
916                    end
917                    // Завершение инструкции
918                    1: begin
919                        delay <= 16-4;
920                        // Если это LDIR, LDDR то проверить BC на 0
921                        if (opcode_ext[4] && bc) begin pc <= pc - 2; delay <= 21-4; end
922                        {t_state, bus} <= 0;
923                    end
924                endcase
925                // 4T: CPI|CPD|CPIR|CPDR
926                8'b10_1xx_001: case (n_state)
927                    // Запрос к АЛУ на вычисление CP
928                    0: begin
929                        alu_m <= alu_cp;
930                        op1   <= af[7:0];
931                        op2   <= i_data;
932                        ldcmd <= opcode_ext[3] ? ldcmd_cpd : ldcmd_cpi;
933                    end
934                    // Обновление флагов
935                    1: begin
936                        reg_wfex <= 1;
937                        flag_ex  <= {
938                            alu_f[7], alu_f[6], cpixy[1], alu_f[4],
939                            cpixy[3], bc != 0,  1'b1,     af[CF]
940                        };
941                        delay <= 16-4;
942                        // Если это CPIR, CPDR то проверить BC на 0 и чтобы ZF=0
943                        if (opcode_ext[4] && !alu_f[6] && bc)
944                        begin pc <= pc - 2; delay <= 21-4; end
945                        {t_state, bus} <= 0;
946                    end
947                endcase
948                // 4T: INI|IND|INIR|INDR
949                8'b10_1xx_010: case (n_state)
950                    0: begin
951                        // Чтение из порта
952                        we      <= 1;
953                        cp      <= hl;
954                        o_data  <= portin;
955                        // Обновление B
956                        reg_wf  <= 1;
957                        reg_w8  <= 1;
958                        reg_id  <= 0;
959                        reg_dt  <= alu_r;
960                    end
961                    1: begin
962                        // Икремент или декремент HL
963                        reg_w16 <= 1;
964                        reg_id  <= 2;
965                        reg_dt  <= opcode_ext[3] ? hl - 1 : hl + 1;
966                        delay  <= 16-4;
967                        // Если это CPIR, CPDR то проверить B на 0
968                        if (opcode_ext[4] && alu_r[7:0]) begin pc <= pc - 2; delay <= 21-4; end
969                        {t_state, bus} <= 0;
970                    end
971                endcase
972                // 4T: OUTI|OUTD|OTIR|OTDR
973                8'b10_1xx_011: case (n_state)
974                    // Запись в порт, HL++/--, декремент B
975                    0: begin
976                        // Запись в порт значения из памяти
977                        portwe  <= 1;
978                        cp      <= bc;
979                        o_data  <= i_data;
980                        // Инкремент или декремент HL
981                        reg_w16 <= 1;
982                        reg_id  <= 2;
983                        reg_dt  <= opcode_ext[3] ? hl - 1 : hl + 1;
984                        // Декремент B через АЛУ
985                        alu_m <= alu_dec;
986                        op1   <= bc[15:8];
987                        op2   <= 1;
988                    end
989                    1: begin
990                        reg_wf <= 1;
991                        reg_w8 <= 1;
992                        reg_dt <= alu_r;
993                        reg_id <= 0;
994                        delay  <= 16-4;
995                        // Если это CPIR, CPDR то проверить B на 0
996                        if (opcode_ext[4] && alu_r[7:0]) begin pc <= pc - 2; delay <= 21-4; end
997                        {t_state, bus} <= 0;
998                    end
999                endcase
1000                endcase
1001            end
1002        endcase
1003        // 3T|7T: <ALU> a,*
1004        8'b11_xxx_110: case (t_state)
1005            0: begin op1 <= af[7:0]; alu_m <= opcode[5:3]; end
1006            1: begin op2 <= i_data; pc <= pc + 1; end
1007            2: begin
1008                reg_wf <= 1;
1009                reg_id <= 7;
1010                reg_w8 <= opcode[5:3] != alu_cp;
1011                reg_dt <= alu_r[7:0];
1012                {set_prefix, t_state} <= 0; delay <= 7-3;
1013            end
1014        endcase
1015        // 3T|11T: RST #n
1016        8'b11_xxx_111: case (t_state)
1017            0: begin
1018                bus <= 1;
1019                we  <= 1;
1020                cp  <= sp - 2;
1021                o_data <= pc1[7:0];
1022                reg_w16 <= 1;
1023                reg_dt  <= sp - 2;
1024                reg_id  <= 3;
1025                set_prefix <= 0;
1026            end
1027            1: begin we <= 1; o_data <= pc[15:8]; cp <= cp + 1; end
1028            2: begin pc <= {opcode[5:3], 3'b000}; {t_state, bus} <= 0; delay <= 11-3; end
1029        endcase
1030        // 1T|4T: Префиксы IX и IY
1031        8'b1101_1101: begin t_state <= 0; set_prefix <= 1; delay <= 4-1; end
1032        8'b1111_1101: begin t_state <= 0; set_prefix <= 2; delay <= 4-1; end
1033        // Пропуск инструкции
1034        default: begin {set_prefix, t_state} <= 0; delay <= 4-1; end
1035    endcase
1036    // В "быстром режиме" работы нет задержек
1037    if (compat == 0) delay <= 0;
1038end
1039end
1040// Регистры процессора z80
1041// -----------------------------------------------------------------------------
1042// Основной и дополнительный наборы регистров
1043reg [15:0]  bc = 16'h03EF; reg [15:0] bc_prime = 16'h0000;
1044reg [15:0]  de = 16'h4732; reg [15:0] de_prime = 16'h0000;
1045reg [15:0]  hl = 16'h4005; reg [15:0] hl_prime = 16'h0000;
1046reg [15:0]  af = 16'h0120; reg [15:0] af_prime = 16'h1234;
1047// Индексные регистры
1048reg [15:0]  ix = 16'h000E; reg [15:0] iy = 16'h0306;
1049// Регистры управления программой
1050reg [15:0]  pc = 16'h0000;
1051reg [15:0]  sp = 16'hFFFE;
1052reg [15:0]  ir = 16'h0000;
1053// Предварительные инициализации
1054// -----------------------------------------------------------------------------
1055initial begin o_data = 0; we = 0; portwe = 0; end
1056// Состояние процессора
1057// -----------------------------------------------------------------------------
1058reg [ 3:0]  t_state     = 0;        // Фаза исполнения опкода
1059reg [ 2:0]  n_state     = 0;        // Фаза исполнения EDh опкода
1060reg [ 4:0]  delay       = 0;        // Задержка для совместимости
1061reg         bus         = 1'b0;     // Выбор источника адреса
1062reg [15:0]  cp          = 16'h0000; // CurrentPointer: альтернативный address
1063reg [ 7:0]  opcode_latch;           // Защелка для опкода
1064reg [ 7:0]  opcode_ext;             // Дополнительный опкод
1065reg [ 1:0]  set_prefix  = 0;        // Команда для установки префикса на обратном фронте
1066reg [ 1:0]  prefix      = 0;        // Текущий префикс, 0=нет, 1=IX, 2=IY
1067reg         t_pref      = 0;        // Наличие префикса в запросе инструкции
1068reg [ 1:0]  exxw        = 0;        // Специальная запись в регистры
1069reg [ 2:0]  ldcmd       = 0;        // =1 HL++,DE++,BC--; =2 HL++,BC--;
1070                                    // =3 HL--,DE--,BC--; =4 HL--,BC--
1071reg         reg_w8      = 0;        // Писать результат в регистр 8 бит
1072reg         reg_w16     = 0;        // Писать результат в регистр 16 бит
1073reg         reg_wfex    = 0;        // Запись специальных флагов
1074reg         reg_wf      = 0;        // Запись флагов из alu_f в af[15:8]
1075reg [ 3:0]  reg_id      = 0;        // Номер регистра для записи
1076reg [15:0]  reg_dt      = 0;        // Данные для записи в регистр
1077reg [ 7:0]  flag_ex     = 0;        // Специальные флаги для reg_wfex=1
1078reg [ 7:0]  hptr        = 0;        // Специальный регистр для BIT n,(HL)
1079// Аппаратное прерывание
1080// -----------------------------------------------------------------------------
1081reg [ 1:0]  i_mode      = 2'b00;
1082reg         iff1        = 1'b0;
1083reg         iff2        = 1'b0;
1084reg         iff1_       = 1'b0;
1085reg         iff2_       = 1'b1;
1086reg         irq_latch   = 1'b0;
1087reg         irq_process = 1'b0;
1088// Вычисление проводов
1089// -----------------------------------------------------------------------------
1090// Выбор опкода
1091wire [7:0]  opcode   = t_state? opcode_latch : i_data;
1092wire [15:0] hlx      = prefix == 1 ? ix : (prefix == 2 ? iy : hl);
1093wire [15:0] signex   = {{8{i_data[7]}}, i_data[7:0]};
1094wire        irqcause = irq ^ irq_latch;
1095// Выбор регистра из opcode[2:0]
1096wire [7:0] reg8_20 =
1097    opcode[2:0] == 0 ?  bc[15:8] : opcode[2:0] == 1 ?  bc[ 7:0] :
1098    opcode[2:0] == 2 ?  de[15:8] : opcode[2:0] == 3 ?  de[ 7:0] :
1099    opcode[2:0] == 4 ? hlx[15:8] : opcode[2:0] == 5 ? hlx[ 7:0] :
1100    opcode[2:0] == 6 ? i_data    : af[7:0];
1101// Выбор регистра из opcode[5:3]
1102wire [7:0] reg8_53 =
1103    opcode[5:3] == 0 ?  bc[15:8] : opcode[5:3] == 1 ?  bc[ 7:0] :
1104    opcode[5:3] == 2 ?  de[15:8] : opcode[5:3] == 3 ?  de[ 7:0] :
1105    opcode[5:3] == 4 ? hlx[15:8] : opcode[5:3] == 5 ? hlx[ 7:0] :
1106    opcode[5:3] == 6 ? i_data    : af[7:0];
1107// Для префикса CB **
1108wire [7:0] reg8_cb20 =
1109    opcode_ext[2:0] == 0 ? bc[15:8] : opcode_ext[2:0] == 1 ? bc[ 7:0] :
1110    opcode_ext[2:0] == 2 ? de[15:8] : opcode_ext[2:0] == 3 ? de[ 7:0] :
1111    opcode_ext[2:0] == 4 ? hl[15:8] : opcode_ext[2:0] == 5 ? hl[ 7:0] :
1112    opcode_ext[2:0] == 6 ? i_data   : af[7:0];
1113// Для OUT (C), r8
1114wire [7:0] reg8_outc =
1115    i_data[5:3] == 0 ? bc[15:8] : i_data[5:3] == 1 ? bc[ 7:0] :
1116    i_data[5:3] == 2 ? de[15:8] : i_data[5:3] == 3 ? de[ 7:0] :
1117    i_data[5:3] == 4 ? hl[15:8] : i_data[5:3] == 5 ? hl[ 7:0] :
1118    i_data[5:3] == 6 ? 0        : af[7:0];
1119// Выбор оригинального H,L при префиксированных инструкциях
1120wire [7:0] hl20_org = opcode[2:0] == 4 ? hl[15:8] :
1121                      opcode[2:0] == 5 ? hl[ 7:0] : reg8_20;
1122wire [15:0] pc1 = pc + 1;
1123// 0-nz, 1-z,  2-nc, 3-c
1124// 4-po, 5-pe, 6-p,  7-m
1125wire [7:0] condition = {
1126    ~af[SF], af[SF], // 7,6 s
1127    ~af[PF], af[PF], // 5,4 p
1128    ~af[CF], af[CF], // 3,2 c
1129    ~af[ZF], af[ZF]  // 1,0 Z
1130};
1131// АЛУ
1132// -----------------------------------------------------------------------------
1133reg  [4:0] alu_m;   // Режим работы АЛУ
1134reg  [7:0] op1;     // Операнды
1135reg  [7:0] op2;
1136wire zf8 = alu_r[7:0]==0;           // Zero
1137wire pf8 = ~^alu_r[7:0];            // Parity
1138wire sf8 = alu_r[7];                // Sign
1139wire cf8 = alu_r[8];                // Carry
1140wire f58 = alu_r[5];                // H5 Undocumented
1141wire f38 = alu_r[3];                // H3 Undocumented
1142wire hf8 = alu_r[4]^op1[4]^op2[4];  // Half-Carry
1143wire oa8 = (op1[7] == op2[7]) & (op1[7] != alu_r[7]);
1144wire os8 = (op1[7] != op2[7]) & (op1[7] != alu_r[7]);
1145// Специальный расчет флага H
1146wire [4:0] ha8 = op1[3:0] + op2[3:0] + af[CF];
1147wire [4:0] hs8 = op1[3:0] - op2[3:0] - af[CF];
1148// Вычисление результата
1149wire [8:0] alu_r =
1150    alu_m == alu_add  ? op1 + op2 :
1151    alu_m == alu_adc  ? op1 + op2 + af[CF] :
1152    alu_m == alu_sub  ? op1 - op2 :
1153    alu_m == alu_sbc  ? op1 - op2 - af[CF] :
1154    alu_m == alu_and  ? op1 & op2 :
1155    alu_m == alu_xor  ? op1 ^ op2 :
1156    alu_m == alu_or   ? op1 | op2 :
1157    alu_m == alu_cp   ? op1 - op2 :
1158    alu_m == alu_inc  ? op1 + op2 :
1159    alu_m == alu_dec  ? op1 - op2 :
1160    // Сдвиговые операции
1161    alu_m == alu_rlca || alu_m == alu_rlc ? {op1[6:0], op1[7]}   : // a << 1
1162    alu_m == alu_rrca || alu_m == alu_rrc ? {op1[0],   op1[7:1]} : // a >> 1
1163    alu_m == alu_rla  || alu_m == alu_rl  ? {op1[6:0], af[CF]}   : // a << 1
1164    alu_m == alu_rra  || alu_m == alu_rr  ? {af[CF],   op1[7:1]} : // a >> 1
1165    alu_m == alu_sla ? {op1[6:0], 1'b0}   : // a << 1
1166    alu_m == alu_sll ? {op1[6:0], 1'b1}   : // a << 1
1167    alu_m == alu_sra ? {op1[7], op1[7:1]} : // a >> 1
1168    alu_m == alu_srl ? {1'b0,   op1[7:1]} : // a >> 1
1169    // Коррекции
1170    alu_m == alu_daa  ? daa_2 :
1171    alu_m == alu_cpl  ? ~op1 :
1172    // Все остальные
1173    op1;
1174// Результат флаговых вычислений [S Z F5 H F3 P/V N C]
1175wire [7:0] alu_f =
1176    // Группа ADD, ADC
1177    (alu_m == alu_add) ? {sf8, zf8, f58,    hf8,    f38,    oa8, 1'b0, cf8} :
1178    (alu_m == alu_adc) ? {sf8, zf8, f58,    ha8[4], f38,    oa8, 1'b0, cf8} :
1179    (alu_m == alu_sbc) ? {sf8, zf8, f58,    hs8[4], f38,    os8, 1'b1, cf8} :
1180    (alu_m == alu_sub) ? {sf8, zf8, f58,    hf8,    f38,    os8, 1'b1, cf8} :
1181    (alu_m == alu_cp)  ? {sf8, zf8, op2[5], hf8,    op2[3], os8, 1'b1, cf8} :
1182    // Для AND выставляет H=1
1183    (alu_m == alu_and) ? {sf8, zf8, f58, 1'b1, f38, pf8, 2'b00} :
1184    // Другие логические (XOR|OR)
1185    (alu_m == alu_xor || alu_m == alu_or) ? {sf8, zf8, f58, 1'b0, f38, pf8, 2'b00} :
1186    // INC, DEC не меняют флаг CF
1187    (alu_m == alu_inc)  ? {sf8, zf8, f58, hf8, f38, oa8, 1'b0, af[CF]} :
1188    (alu_m == alu_dec)  ? {sf8, zf8, f58, hf8, f38, os8, 1'b1, af[CF]} :
1189    // Сдвиговые
1190    (alu_m == alu_rlca || alu_m == alu_rla) ?
1191        {af[SF], af[ZF], f58, 1'b0, f38, af[PF], 1'b0, op1[7]} :
1192    (alu_m == alu_rrca || alu_m == alu_rra) ?
1193        {af[SF], af[ZF], f58, 1'b0, f38, af[PF], 1'b0, op1[0]} :
1194    (alu_m == alu_rlc || alu_m == alu_rl || alu_m == alu_sla || alu_m == alu_sll) ?
1195        {sf8, zf8, f58, 1'b0, f38, pf8, 1'b0, op1[7]} :
1196    (alu_m == alu_rrc || alu_m == alu_rr || alu_m == alu_sra || alu_m == alu_srl) ?
1197        {sf8, zf8, f58, 1'b0, f38, pf8, 1'b0, op1[0]} :
1198    // Специальные
1199    (alu_m == alu_daa) ? {sf8, zf8, f58, af[4]^daa_2[4], f38, pf8, af[NF], daa_cf} :
1200    (alu_m == alu_cpl) ? {af[SF], af[ZF], f58, 1'b1,   f38, af[PF], 1'b1, af[CF]} :
1201    (alu_m == alu_scf) ? {af[SF], af[ZF], f58, 1'b0,   f38, af[PF], 1'b0, 1'b1} :
1202    (alu_m == alu_ccf) ? {af[SF], af[ZF], f58, af[CF], f38, af[PF], 1'b0, ~af[CF]} :
1203    // Все остальные
1204        af[15:8];
1205// DAA
1206// -----------------------------------------------------------------------------
1207wire daa_hf = af[HF] | (af[3:0] > 8'h09);
1208wire daa_cf = af[CF] | (af[7:0] > 8'h99);
1209// Первый этап
1210wire [7:0] daa_1 =
1211    af[NF] ? (daa_hf ? af[7:0] - 6 : af[7:0]) : // SUB
1212             (daa_hf ? af[7:0] + 6 : af[7:0]);  // ADD
1213// Второй этап
1214wire [7:0] daa_2 =
1215    af[NF] ? (daa_cf ? daa_1 - 16'h60 : daa_1) : // SUB
1216             (daa_cf ? daa_1 + 16'h60 : daa_1);  // ADD
1217// 16-битная операция HL +/- r16
1218// -----------------------------------------------------------------------------
1219// Второй операнд для ADD HL, r16
1220wire [15:0] do_hl_op2 =
1221    opcode[5:4] == 2'b00 ? bc :
1222    opcode[5:4] == 2'b01 ? de :
1223    opcode[5:4] == 2'b10 ? hlx : sp;
1224// Второй операнд для ADC|SBC HL, r16
1225wire [16:0] ed_hl_op2 = (
1226    i_data[5:4] == 2'b00 ? bc :
1227    i_data[5:4] == 2'b01 ? de :
1228    i_data[5:4] == 2'b10 ? hl : sp) + af[CF];
1229// Расчет результата
1230wire [16:0] do_hl_add = hlx + do_hl_op2;
1231wire [16:0] ed_hl_adc = hl  + ed_hl_op2;
1232wire [16:0] ed_hl_sbc = hl  - ed_hl_op2;
1233// Расстановка флагов
1234wire [ 7:0] do_hl_flag = {
1235    af[SF],
1236    af[ZF],
1237    do_hl_add[5+8],
1238    hlx[12]^do_hl_op2[12]^do_hl_add[12], // H
1239    do_hl_add[3+8],
1240    af[PF],
1241    1'b0,           // N=0
1242    do_hl_add[16]   // C=x
1243};
1244// Флаги после сложения HL + r16
1245wire [ 7:0] hl_adc_flag = {
1246    ed_hl_adc[15],
1247    ed_hl_adc[15:0] == 0,
1248    ed_hl_adc[13],
1249    ed_hl_adc[12]^hl[12]^ed_hl_op2[12],
1250    ed_hl_adc[11],
1251    (hl[15] == ed_hl_op2[15]) && (ed_hl_adc[15] ^ hl[15]),
1252    1'b0,
1253    ed_hl_adc[16]
1254};
1255// Флаги после вычитания HL - r16
1256wire [ 7:0] hl_sbc_flag = {
1257    ed_hl_sbc[15],
1258    ed_hl_sbc[15:0] == 0,
1259    ed_hl_sbc[13],
1260    ed_hl_sbc[12]^hl[12]^ed_hl_op2[12],
1261    ed_hl_sbc[11],
1262    (hl[15] ^ ed_hl_op2[15]) && (ed_hl_sbc[15] ^ hl[15]),
1263    1'b1,
1264    ed_hl_sbc[16]
1265};
1266// RLD|RRD
1267// -----------------------------------------------------------------------------
1268wire [7:0] rrd_w = {af[3:0], i_data[7:4]};
1269wire [7:0] rrd_a = {af[7:4], i_data[3:0]};
1270wire [7:0] rld_w = {i_data[3:0], af[3:0]};
1271wire [7:0] rld_a = {af[7:4], i_data[7:4]};
1272// LDI, CPI, INI, OUTI
1273// -----------------------------------------------------------------------------
1274wire [3:0] ldixy = af[7:0] + i_data;
1275wire [3:0] cpixy = op1 - op2 - alu_f[4];
1276wire [7:0] b_dec = bc[15:8] - 1;
1277// BIT
1278// -----------------------------------------------------------------------------
1279wire bit_zf = ~op1[ op2[2:0] ];
1280wire bit_sf = (op2[2:0] == 7) && !bit_zf;
1281// Не префиксированные BITs устанавливают Y/X флаги
1282wire [7:0] bit_flags    = {bit_sf, bit_zf, op1[5],  1'b1, op1[3],  bit_zf, 1'b0, af[CF]};
1283wire [7:0] bit_flags_xx = {bit_sf, bit_zf, af[F5F], 1'b1, af[F3F], bit_zf, 1'b0, af[CF]};
1284// RES|SET, зависит от op2[3]
1285// -----------------------------------------------------------------------------
1286wire [7:0] rsop =
1287    op2[2:0] == 0 ? {op1[7:1], op2[3]} :
1288    op2[2:0] == 1 ? {op1[7:2], op2[3], op1[  0]} :
1289    op2[2:0] == 2 ? {op1[7:3], op2[3], op1[1:0]} :
1290    op2[2:0] == 3 ? {op1[7:4], op2[3], op1[2:0]} :
1291    op2[2:0] == 4 ? {op1[7:5], op2[3], op1[3:0]} :
1292    op2[2:0] == 5 ? {op1[7:6], op2[3], op1[4:0]} :
1293    op2[2:0] == 6 ? {op1[7],   op2[3], op1[5:0]} :
1294                   {           op2[3], op1[6:0]};
1295// Запись в регистры на обратном фронте
1296// -----------------------------------------------------------------------------
1297always @(negedge clock)
1298if (reset_n == 1'b0) begin
1299    af <= 16'hFFFF;
1300    sp <= 16'hFFFF;
1301end
1302else if (hold) begin
1303    // Особая запись в регистры
1304    if (exxw)
1305    case (exxw)
1306        // EX AF, AF'
1307        spec_exaf: begin af <= af_prime; af_prime <= af; end
1308        // EXX
1309        spec_exx: begin
1310            bc_prime <= bc; bc <= bc_prime;
1311            de_prime <= de; de <= de_prime;
1312            hl_prime <= hl; hl <= hl_prime;
1313        end
1314        // EX DE, HL
1315        spec_exdehl: begin de <= hl; hl <= de; end
1316    endcase
1317    // Работа со строками
1318    else if (ldcmd)
1319    case (ldcmd)
1320        ldcmd_ldi: begin bc <= bc - 1; hl <= hl + 1; de <= de + 1; end
1321        ldcmd_ldd: begin bc <= bc - 1; hl <= hl - 1; de <= de - 1; end
1322        ldcmd_cpi: begin bc <= bc - 1; hl <= hl + 1; end
1323        ldcmd_cpd: begin bc <= bc - 1; hl <= hl - 1; end
1324    endcase
1325    // Запись результата в 16-битный регистр
1326    else if (reg_w16)
1327    case (reg_id)
1328        0: bc <= reg_dt;
1329        1: de <= reg_dt;
1330        2: case (prefix) 0: hl <= reg_dt; 1: ix <= reg_dt; 2: iy <= reg_dt; endcase
1331        3: sp <= reg_dt;
1332    endcase
1333    // Запись в 8-битный регистр
1334    else if (reg_w8)
1335    case (reg_id)
1336        0: bc[15:8] <= reg_dt;
1337        1: bc[ 7:0] <= reg_dt;
1338        2: de[15:8] <= reg_dt;
1339        3: de[ 7:0] <= reg_dt;
1340        4: case (prefix) 0: hl[15:8] <= reg_dt; 1: ix[15:8] <= reg_dt; 2: iy[15:8] <= reg_dt; endcase
1341        5: case (prefix) 0: hl[ 7:0] <= reg_dt; 1: ix[ 7:0] <= reg_dt; 2: iy[ 7:0] <= reg_dt; endcase
1342        7: af[ 7:0] <= reg_dt;
1343    endcase
1344    // Запись флагов из АЛУ
1345    if      (reg_wfex) af[15:8] <= flag_ex;
1346    else if (reg_wf)   af[15:8] <= alu_f;
1347    // Установка следующего префикса
1348    prefix <= set_prefix;
1349end
1350endmodule