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

Ревизия 2024 июн 5
1module KR580VM80ALite
2(
3    input               clock,
4    input               reset_n,
5    input               ce,
6    output              m0,
7    output      [15:0]  address,
8    output reg  [ 7:0]  port,
9    input       [ 7:0]  in,
10    input       [ 7:0]  port_in,
11    output reg  [ 7:0]  out,
12    output reg          we,
13    output reg          port_we,
14    output reg          iff1
15);
16
17assign address = sw ? cp : pc;
18assign m0 = (t == 0);
19
20localparam
21    CF = 0, PF = 2, HF = 4, ZF = 6, SF = 7;
22
23localparam
24    ADD = 0, ADC = 1, SUB = 2, SBB = 3,
25    AND = 4, XOR = 5, OR  = 6, CMP = 7;
26
27// ----------------------------------------------
28reg [15:0]  pc;
29reg [15:0]  bc  = 16'h10FF,
30            de  = 16'hBEEF,
31            hl  = 16'hFF13,
32            sp  = 16'h00FF;
33reg [ 7:0]  a   = 8'h9A,
34            //       NZ H P C
35            psw = 8'b00000011;
36// ----------------------------------------------
37reg         sw;     // =1 Адрес указывает на CP, иначе =0 PC
38reg [15:0]  cp;     // Адрес для считывания данных из памяти
39reg [ 7:0]  opcode; // Сохраненный опкод
40reg [ 4:0]  t;      // Исполняемый такт опкода [0..31]
41// ----------------------------------------------
42reg         b;      // =1 Запись d в 8-битный регистр n
43reg         w;      // =1 Запись d в 16-битный регистр n
44reg [16:0]  d;      // Данные
45reg [ 2:0]  n;      // Номер регистра для записи
46// ----------------------------------------------
47wire [ 7:0] opc = t ? opcode : in;
48wire [15:0] r16 =
49    opc[5:4] == 2'b00 ? bc :
50    opc[5:4] == 2'b01 ? de :
51    opc[5:4] == 2'b10 ? hl : sp;
52
53// Выбор 8-битного регистра
54wire [ 7:0] op53 =
55    opc[5:3] == 3'b000 ? bc[15:8] : opc[5:3] == 3'b001 ? bc[ 7:0] :
56    opc[5:3] == 3'b010 ? de[15:8] : opc[5:3] == 3'b011 ? de[ 7:0] :
57    opc[5:3] == 3'b100 ? hl[15:8] : opc[5:3] == 3'b101 ? hl[ 7:0] :
58    opc[5:3] == 3'b110 ? in       : a;
59
60wire [ 7:0] op20 =
61    opc[2:0] == 3'b000 ? bc[15:8] : opc[2:0] == 3'b001 ? bc[ 7:0] :
62    opc[2:0] == 3'b010 ? de[15:8] : opc[2:0] == 3'b011 ? de[ 7:0] :
63    opc[2:0] == 3'b100 ? hl[15:8] : opc[2:0] == 3'b101 ? hl[ 7:0] :
64    opc[2:0] == 3'b110 ? in       : a;
65// ----------------------------------------------
66wire [15:0] pcn = pc + 1;
67wire [15:0] cpn = cp + 1;
68wire        m53 = opc[5:3] == 3'b110;
69wire        m20 = opc[2:0] == 3'b110;
70wire        daa1 = psw[HF] || a[3:0] > 9;
71wire        daa2 = psw[CF] || a[7:4] > 9 || (a[7:4] >= 9 && a[3:0] > 9);
72wire [3:0]  cond = {psw[SF], psw[PF], psw[CF], psw[ZF]};
73wire        ccc  = (cond[ opc[5:4] ] == opc[3]) || (opc == 8'hC9) || (opc == 8'hCD);
74// ----------------------------------------------
75wire [8:0]  alur =
76    opc[5:3] == ADD ? a + op20 :             // ADD
77    opc[5:3] == ADC ? a + op20 + psw[CF] :   // ADC
78    opc[5:3] == SBB ? a - op20 - psw[CF] :   // SBB
79    opc[5:3] == AND ? a & op20 :             // ANA
80    opc[5:3] == XOR ? a ^ op20 :             // XRA
81    opc[5:3] == OR  ? a | op20 :             // ORA
82                      a - op20;              // SUB|CMP
83
84wire sf =   alur[7];
85wire zf =   alur[7:0] == 0;
86wire hf =   a[4] ^ op20[4] ^ alur[4];
87wire af =  (a[4] | op20[4]) & (opc[5:3] == AND);
88wire pf = ~^alur[7:0];
89wire cf =   alur[8];
90
91wire [7:0] aluf =
92    opc[5:3] == AND || opc[5:3] == XOR || opc[5:3] == OR ?
93        {sf, zf, 1'b0, af, 1'b0, pf, 1'b1, 1'b0} : // AND, XOR, OR
94        {sf, zf, 1'b0, hf, 1'b0, pf, 1'b1,   cf};  // ADD, ADC, SUB, SBB, CMP
95
96always @(posedge clock)
97if (reset_n == 0) begin
98    t  <= 0;        // Установить чтение кода на начало
99    sw <= 0;        // Позиционировать память к PC
100    pc <= 16'hF800; // Указатель на программу "Монитор"
101    iff1 <= 0;       // Отключение прерываний
102end
103else if (ce) begin
104
105    t  <= t + 1;    // Счетчик микрооперации
106    b  <= 0;        // Выключить запись в регистр (по умолчанию) 8bit
107    w  <= 0;        // Выключить запись в регистр (по умолчанию) 16bit
108    we <= 0;        // Аналогично, выключить запись в память (по умолчанию)
109    port_we <= 0;   // Запись в порт
110
111    // Запись опкода на первом такте выполнения инструкции
112    if (m0) begin opcode <= in; pc <= pcn; end
113
114    // Исполнение инструкции
115    casex (opc)
116
117    // ==========================
118    // ДИАПАЗОН ИНСТРУКЦИИ 00-3F
119    // ==========================
120
121    // 4T NOP
122    8'b0000_0000: case (t)
123
124        3: begin t <= 0; end
125
126    endcase
127    // 10T LXI R,**
128    8'b00xx_0001: case (t)
129
130        1: begin pc <= pcn; d[ 7:0] <= in; n <= opcode[5:4]; end
131        2: begin pc <= pcn; d[15:8] <= in; w <= 1; end
132        9: begin t <= 0; end
133
134    endcase
135    // 10T DAD R
136    8'b00xx_1001: case (t)
137
138        0: begin d <= hl + r16; w <= 1; n <= 2; end
139        1: begin psw[CF] <= d[16]; end
140        9: begin t <= 0; end
141
142    endcase
143    // 7T STAX B|D
144    8'b000x_0010: case (t)
145
146        0: begin we <= 1; out <= a; cp <= r16; sw <= 1; end
147        6: begin sw <= 0; t <= 0; end
148
149    endcase
150    // 7T LDAX B|D
151    8'b000x_1010: case (t)
152
153        0: begin cp <= r16; sw <= 1; end
154        1: begin b  <= 1; n <= 7; d <= in; end
155        6: begin sw <= 0; t <= 0; end
156
157    endcase
158    // 16T [22] SHLD **
159    8'b0010_0010: case (t)
160
161        1: begin cp[ 7:0] <= in; pc <= pcn; end
162        2: begin cp[15:8] <= in; pc <= pcn; sw <= 1; end
163        3: begin we <= 1; out <= hl[ 7:0]; end
164        4: begin we <= 1; out <= hl[15:8]; cp <= cpn; end
165        15: begin sw <= 0; t <= 0; end
166
167    endcase
168    // 16T [2A] LDHL **
169    8'b0010_1010: case (t)
170
171        1: begin cp[ 7:0] <= in; pc <= pcn; end
172        2: begin cp[15:8] <= in; pc <= pcn; sw <= 1; end
173        3: begin d [ 7:0] <= in; cp <= cpn; end
174        4: begin d [15:8] <= in; w <= 1; n <= 2; sw <= 0; end
175        15: begin t <= 0; end
176
177    endcase
178    // 13T [32,3A] STA|LDA **
179    8'b0011_x010: case (t)
180
181        1: begin cp[ 7:0] <= in; pc <= pcn; end
182        2: begin cp[15:8] <= in; pc <= pcn; sw <= 1; we <= ~opc[3]; out <= a; end
183        3: begin d <= in; b <= opc[3]; n <= 7; sw <= 0; end
184        12: begin t <= 0; end
185
186    endcase
187    // 5T DCX|INX R
188    8'b00xx_x011: case (t)
189
190        0: begin w <= 1; n <= in[5:4]; d <= in[3] ? r16 - 1 : r16 + 1; end
191        4: begin t <= 0; end
192
193    endcase
194    // 5/10T INR|DCR RM
195    8'b00xx_x10x: case (t)
196
197        0: begin cp <= hl; sw <= 1; end
198        1: begin d <= opc[0] ? op53 - 1 : op53 + 1; end
199        2: begin
200
201            psw[SF] <= d[7];
202            psw[ZF] <= d[7:0] == 0;
203            psw[HF] <= d[3:0] == (opc[0] ? 4'hF : 4'h0);
204            psw[PF] <= ~^d[7:0];
205
206            n   <= opc[5:3];
207            b   <= ~m53;        // Либо в регистр запись
208            we  <= m53;         // Либо запись в память
209            out <= d;
210
211        end
212        4: begin sw <= 0; t <= m53 ? 5 : 0; end
213        9: begin t <= 0; end
214
215    endcase
216    // 7T MVI RM,*
217    8'b00xx_x110: case (t)
218
219        1: begin
220
221            pc  <= pcn;      // PC = PC + 1
222            cp  <= hl;       // Указатель HL
223            n   <= opc[5:3]; // Номер регистра
224            b   <= !m53;     // Запись в регистр, если не M
225            we  <= m53;      // Запись в память,  если M
226            sw  <= m53;      // Активация указателя CP
227            d   <= in;       // Данные для записи в регистр
228            out <= in;       // Данные для записи в память
229
230        end
231        6: begin t <= sw ? 7 : 0; sw <= 0; end
232        9: begin t <= 0; end
233
234    endcase
235    // 4T [07] RLC, [0F] RRC, [17] RAL, [1F] RAR
236    8'b000x_x111: case (t)
237
238        0: begin
239
240            b <= 1;
241            n <= 7;
242
243            case (opc[4:3])
244            2'b00: d <= {a[6:0],  a[7]};    // RLC
245            2'b01: d <= {a[0],    a[7:1]};  // RRC
246            2'b10: d <= {a[6:0],  psw[CF]}; // RAL
247            2'b11: d <= {psw[CF], a[7:1]};  // RAR
248            endcase
249
250            psw[CF] <= a[opc[3] ? 0 : 7];
251
252        end
253
254        3: begin t <= 0; end
255
256    endcase
257    // 4T [27] DAA
258    8'b0010_0111: case (t)
259
260        0: begin d[15:8] <= (daa1 ? 6 : 0) + (daa2 ? 8'h60 : 0); end
261        1: begin d[ 7:0] <= a + d[15:8]; end
262        2: begin
263
264            psw[SF] <= d[7];
265            psw[ZF] <= d[7:0] == 0;
266            psw[HF] <= a[4] ^ d[4] ^ d[12];
267            psw[PF] <= ~^d[7:0];
268            psw[CF] <= daa2 | psw[0];
269
270            b <= 1;
271            n <= 7;
272
273        end
274        3: begin t <= 0; end
275
276    endcase
277    // 4T [2F] CMA
278    8'b0010_1111: case (t)
279
280        0: begin d <= ~a; b <= 1; n <= 7; end
281        3: begin t <= 0; end
282
283    endcase
284    // 4T [37] STC [3F] CMC
285    8'b0011_x111: case (t)
286
287        0: begin psw[CF] <= opc[3] ? ~psw[CF] : 1'b1; end
288        3: begin t <= 0; end
289
290    endcase
291
292    // ==========================
293    // ДИАПАЗОН ИНСТРУКЦИИ 40-BF
294    // ==========================
295    // 5/7T MOV x,x
296    8'b01xx_xxxx: case (t)
297
298        0: begin cp <= hl; sw <= 1; if (m53 && m20) pc <= pc; end
299        1: begin
300
301            n   <= opc[5:3];
302            b   <= !m53;
303            we  <=  m53;
304            d   <= op20;
305            out <= op20;
306
307        end
308        4: begin sw <= 0; t <= (m53 || m20) ? 5 : 0; end
309        6: begin t <= 0; end
310
311    endcase
312    // 5/7T [ALU] Op
313    8'b10xx_xxxx: case (t)
314
315        0: begin cp <= hl; sw <= 1; end
316        1: begin d  <= alur; b <= (opc[5:3] != CMP); n <= 7; psw <= aluf; end
317        4: begin sw <= 0; t <= m20 ? 5 : 0; end
318        6: begin t  <= 0; end
319
320    endcase
321
322    // ==========================
323    // ДИАПАЗОН ИНСТРУКЦИИ С0-FF
324    // ==========================
325
326    // 5/11T RET ccc
327    8'b11xx_x000,
328    8'b1100_1001: case (t)
329
330        0: begin d <= sp + 2; w <= ccc; n <= 3; sw <= 1; cp <= sp; end
331        1: begin d[ 7:0] <= in; cp <= cpn; end
332        2: begin d[15:8] <= in; sw <= 0; end
333        4: begin t <= ccc ? 5 : 0; end
334        10: begin t <= 0; pc <= d; end
335
336    endcase
337    // 11T POP
338    8'b11xx_0001: case (t)
339
340        0: begin d <= sp + 2; w <= 1; n <= 3; sw <= 1; cp <= sp; end
341        1: begin d[ 7:0] <= in; cp <= cpn; end
342        2: begin d[15:8] <= in; sw <= 0; n <= opc[5:4]; w <= opc[5:4] != 3; end
343        3: begin if (opc[5:4] == 3) begin d[7:0] <= d[15:8]; psw <= d[7:0]; b <= 1; n <= 7; end end
344        10: begin t <= 0; end
345
346    endcase
347    // 5T [E9] PCHL
348    8'b1110_1001: case (t)
349
350        4: begin pc <= hl; t <= 0; end
351
352    endcase
353    // 5T [F9] SPHL
354    8'b1111_1001: case (t)
355
356        0: begin d <= hl; w <= 1; n <= 3; end
357        4: begin t <= 0; end
358
359    endcase
360    // 10T JMP ccc, **
361    8'b11xx_x010,
362    8'b1100_0011: case (t)
363
364        1: begin cp[ 7:0] <= in; pc <= pcn; end
365        2: begin cp[15:8] <= in; pc <= pcn; end
366        9: begin t <= 0; if (ccc || opc[0]) pc <= cp; end
367
368    endcase
369    // 4T DI, EI
370    8'b1111_x011: case (t)
371
372        0: begin iff1 <= opc[3]; end
373        3: begin t <= 0; end
374
375    endcase
376    // 10T OUT (*), A
377    8'b1101_0011: case (t)
378
379        1: begin port <= in; port_we <= 1; out <= a; pc <= pcn; end
380        9: begin t <= 0; end
381
382    endcase
383    // 10T IN A, (*)
384    8'b1101_1011: case (t)
385
386        1: begin port <= in; pc <= pcn; end
387        2: begin b <= 1; n <= 7; d <= port_in; end
388        9: begin t <= 0; end
389
390    endcase
391    // 18T XTHL
392    8'b1110_0011: case (t)
393
394        0: begin sw <= 1; cp <= sp; end
395        1: begin d[ 7:0] <= in; cp <= cpn; end
396        2: begin d[15:8] <= in; w <= 1; n <= 2; cp <= hl; end
397        3: begin we <= 1; out <= cp[7:0]; d[7:0] <= cp[15:8]; cp <= sp; end
398        4: begin we <= 1; out <= d[7:0]; cp <= cpn; end
399        17: begin sw <= 0; t <= 0; end
400
401    endcase
402    // 4T XCHG
403    8'b1110_1011: case (t)
404
405        0: begin d <= de; n <= 2; w <= 1; cp <= hl; end
406        1: begin d <= cp; n <= 1; w <= 1; end
407        3: begin t <= 0; end
408
409    endcase
410    // 11/17T CALL ccc
411    8'b11xx_x100,
412    8'b1100_1101: case (t)
413
414        1: begin d[ 7:0] <= in; pc <= pcn; end
415        2: begin d[15:8] <= in; pc <= pcn; end
416        3: begin we <= ccc; out <= pc[ 7:0]; sw <= 1; cp <= sp - 2; end
417        4: begin we <= ccc; out <= pc[15:8]; cp <= cpn; end
418        5: begin if (ccc) pc <= d[15:0]; end
419        6: begin w <= ccc; d <= sp - 2; n <= 3; end
420        10: begin t <= ccc ? 11 : 0; end
421        16: begin t <= 0; end
422
423    endcase
424    // 11T PUSH
425    8'b11xx_0101: case (t)
426
427        0: begin d <= sp - 2; w <= 1; n <= 3; sw <= 1; cp <= sp - 2; end
428        1: begin d <= opc[5:4] == 2'b11 ? {a, (psw & 8'b11010101) | 2'b10} : r16; end
429        2: begin we <= 1; out <= d[ 7:0]; end
430        3: begin we <= 1; out <= d[15:8]; cp <= cpn; end
431        10: begin sw <= 0; t <= 0; end
432
433    endcase
434    // 7T [ALU] Imm
435    8'b11xx_x110: case (t)
436
437        1: begin d <= alur; pc <= pcn; b <= (opc[5:3] != CMP); n <= 7; psw <= aluf; end
438        6: begin t <= 0; end
439
440    endcase
441    // 11T RST
442    8'b11xx_x111: case (t)
443
444        1: begin we <= 1; d <= sp - 2; n <= 3; w <= 1; cp <= sp - 2; sw <= 1; out <= pc[7:0]; end
445        2: begin we <= 1; out <= pc[15:8]; cp <= cpn; pc <= {opc[5:3], 3'b000}; end
446        10: begin sw <= 0; t <= 0; end
447
448    endcase
449
450    endcase
451
452end
453
454// Запись данных в регистры
455always @(posedge clock)
456if (reset_n && ce) begin
457
458    // 8-bit
459    if (b)
460    case (n)
461    0: bc[15:8] <= d[7:0]; 1: bc[ 7:0] <= d[7:0]; // BC
462    2: de[15:8] <= d[7:0]; 3: de[ 7:0] <= d[7:0]; // DE
463    4: hl[15:8] <= d[7:0]; 5: hl[ 7:0] <= d[7:0]; // HL
464    7:  a       <= d[7:0];
465    endcase
466
467    // 16-bit
468    if (w)
469    case (n)
470    2'b00: bc <= d[15:0];
471    2'b01: de <= d[15:0];
472    2'b10: hl <= d[15:0];
473    2'b11: sp <= d[15:0];
474    endcase
475
476end
477
478endmodule