Главная » Радио86-РК » Глава 6b. Код процессора 8080
§ Код процессора
Ревизия 5 июня 2024 годаmodule KR580VM80ALite ( input clock, input reset_n, input ce, output m0, output [15:0] address, output reg [ 7:0] port, input [ 7:0] in, input [ 7:0] port_in, output reg [ 7:0] out, output reg we, output reg port_we, output reg iff1 ); assign address = sw ? cp : pc; assign m0 = (t == 0); localparam CF = 0, PF = 2, HF = 4, ZF = 6, SF = 7; localparam ADD = 0, ADC = 1, SUB = 2, SBB = 3, AND = 4, XOR = 5, OR = 6, CMP = 7; // ---------------------------------------------- reg [15:0] pc; reg [15:0] bc = 16'h10FF, de = 16'hBEEF, hl = 16'hFF13, sp = 16'h00FF; reg [ 7:0] a = 8'h9A, // NZ H P C psw = 8'b00000011; // ---------------------------------------------- reg sw; // =1 Адрес указывает на CP, иначе =0 PC reg [15:0] cp; // Адрес для считывания данных из памяти reg [ 7:0] opcode; // Сохраненный опкод reg [ 4:0] t; // Исполняемый такт опкода [0..31] // ---------------------------------------------- reg b; // =1 Запись d в 8-битный регистр n reg w; // =1 Запись d в 16-битный регистр n reg [16:0] d; // Данные reg [ 2:0] n; // Номер регистра для записи // ---------------------------------------------- wire [ 7:0] opc = t ? opcode : in; wire [15:0] r16 = opc[5:4] == 2'b00 ? bc : opc[5:4] == 2'b01 ? de : opc[5:4] == 2'b10 ? hl : sp; // Выбор 8-битного регистра wire [ 7:0] op53 = opc[5:3] == 3'b000 ? bc[15:8] : opc[5:3] == 3'b001 ? bc[ 7:0] : opc[5:3] == 3'b010 ? de[15:8] : opc[5:3] == 3'b011 ? de[ 7:0] : opc[5:3] == 3'b100 ? hl[15:8] : opc[5:3] == 3'b101 ? hl[ 7:0] : opc[5:3] == 3'b110 ? in : a; wire [ 7:0] op20 = opc[2:0] == 3'b000 ? bc[15:8] : opc[2:0] == 3'b001 ? bc[ 7:0] : opc[2:0] == 3'b010 ? de[15:8] : opc[2:0] == 3'b011 ? de[ 7:0] : opc[2:0] == 3'b100 ? hl[15:8] : opc[2:0] == 3'b101 ? hl[ 7:0] : opc[2:0] == 3'b110 ? in : a; // ---------------------------------------------- wire [15:0] pcn = pc + 1; wire [15:0] cpn = cp + 1; wire m53 = opc[5:3] == 3'b110; wire m20 = opc[2:0] == 3'b110; wire daa1 = psw[HF] || a[3:0] > 9; wire daa2 = psw[CF] || a[7:4] > 9 || (a[7:4] >= 9 && a[3:0] > 9); wire [3:0] cond = {psw[SF], psw[PF], psw[CF], psw[ZF]}; wire ccc = (cond[ opc[5:4] ] == opc[3]) || (opc == 8'hC9) || (opc == 8'hCD); // ---------------------------------------------- wire [8:0] alur = opc[5:3] == ADD ? a + op20 : // ADD opc[5:3] == ADC ? a + op20 + psw[CF] : // ADC opc[5:3] == SBB ? a - op20 - psw[CF] : // SBB opc[5:3] == AND ? a & op20 : // ANA opc[5:3] == XOR ? a ^ op20 : // XRA opc[5:3] == OR ? a | op20 : // ORA a - op20; // SUB|CMP wire sf = alur[7]; wire zf = alur[7:0] == 0; wire hf = a[4] ^ op20[4] ^ alur[4]; wire af = (a[4] | op20[4]) & (opc[5:3] == AND); wire pf = ~^alur[7:0]; wire cf = alur[8]; wire [7:0] aluf = opc[5:3] == AND || opc[5:3] == XOR || opc[5:3] == OR ? {sf, zf, 1'b0, af, 1'b0, pf, 1'b1, 1'b0} : // AND, XOR, OR {sf, zf, 1'b0, hf, 1'b0, pf, 1'b1, cf}; // ADD, ADC, SUB, SBB, CMP always @(posedge clock) if (reset_n == 0) begin t <= 0; // Установить чтение кода на начало sw <= 0; // Позиционировать память к PC pc <= 16'hF800; // Указатель на программу "Монитор" iff1 <= 0; // Отключение прерываний end else if (ce) begin t <= t + 1; // Счетчик микрооперации b <= 0; // Выключить запись в регистр (по умолчанию) 8bit w <= 0; // Выключить запись в регистр (по умолчанию) 16bit we <= 0; // Аналогично, выключить запись в память (по умолчанию) port_we <= 0; // Запись в порт // Запись опкода на первом такте выполнения инструкции if (m0) begin opcode <= in; pc <= pcn; end // Исполнение инструкции casex (opc) // ========================== // ДИАПАЗОН ИНСТРУКЦИИ 00-3F // ========================== // 4T NOP 8'b0000_0000: case (t) 3: begin t <= 0; end endcase // 10T LXI R,** 8'b00xx_0001: case (t) 1: begin pc <= pcn; d[ 7:0] <= in; n <= opcode[5:4]; end 2: begin pc <= pcn; d[15:8] <= in; w <= 1; end 9: begin t <= 0; end endcase // 10T DAD R 8'b00xx_1001: case (t) 0: begin d <= hl + r16; w <= 1; n <= 2; end 1: begin psw[CF] <= d[16]; end 9: begin t <= 0; end endcase // 7T STAX B|D 8'b000x_0010: case (t) 0: begin we <= 1; out <= a; cp <= r16; sw <= 1; end 6: begin sw <= 0; t <= 0; end endcase // 7T LDAX B|D 8'b000x_1010: case (t) 0: begin cp <= r16; sw <= 1; end 1: begin b <= 1; n <= 7; d <= in; end 6: begin sw <= 0; t <= 0; end endcase // 16T [22] SHLD ** 8'b0010_0010: case (t) 1: begin cp[ 7:0] <= in; pc <= pcn; end 2: begin cp[15:8] <= in; pc <= pcn; sw <= 1; end 3: begin we <= 1; out <= hl[ 7:0]; end 4: begin we <= 1; out <= hl[15:8]; cp <= cpn; end 15: begin sw <= 0; t <= 0; end endcase // 16T [2A] LDHL ** 8'b0010_1010: case (t) 1: begin cp[ 7:0] <= in; pc <= pcn; end 2: begin cp[15:8] <= in; pc <= pcn; sw <= 1; end 3: begin d [ 7:0] <= in; cp <= cpn; end 4: begin d [15:8] <= in; w <= 1; n <= 2; sw <= 0; end 15: begin t <= 0; end endcase // 13T [32,3A] STA|LDA ** 8'b0011_x010: case (t) 1: begin cp[ 7:0] <= in; pc <= pcn; end 2: begin cp[15:8] <= in; pc <= pcn; sw <= 1; we <= ~opc[3]; out <= a; end 3: begin d <= in; b <= opc[3]; n <= 7; sw <= 0; end 12: begin t <= 0; end endcase // 5T DCX|INX R 8'b00xx_x011: case (t) 0: begin w <= 1; n <= in[5:4]; d <= in[3] ? r16 - 1 : r16 + 1; end 4: begin t <= 0; end endcase // 5/10T INR|DCR RM 8'b00xx_x10x: case (t) 0: begin cp <= hl; sw <= 1; end 1: begin d <= opc[0] ? op53 - 1 : op53 + 1; end 2: begin psw[SF] <= d[7]; psw[ZF] <= d[7:0] == 0; psw[HF] <= d[3:0] == (opc[0] ? 4'hF : 4'h0); psw[PF] <= ~^d[7:0]; n <= opc[5:3]; b <= ~m53; // Либо в регистр запись we <= m53; // Либо запись в память out <= d; end 4: begin sw <= 0; t <= m53 ? 5 : 0; end 9: begin t <= 0; end endcase // 7T MVI RM,* 8'b00xx_x110: case (t) 1: begin pc <= pcn; // PC = PC + 1 cp <= hl; // Указатель HL n <= opc[5:3]; // Номер регистра b <= !m53; // Запись в регистр, если не M we <= m53; // Запись в память, если M sw <= m53; // Активация указателя CP d <= in; // Данные для записи в регистр out <= in; // Данные для записи в память end 6: begin t <= sw ? 7 : 0; sw <= 0; end 9: begin t <= 0; end endcase // 4T [07] RLC, [0F] RRC, [17] RAL, [1F] RAR 8'b000x_x111: case (t) 0: begin b <= 1; n <= 7; case (opc[4:3]) 2'b00: d <= {a[6:0], a[7]}; // RLC 2'b01: d <= {a[0], a[7:1]}; // RRC 2'b10: d <= {a[6:0], psw[CF]}; // RAL 2'b11: d <= {psw[CF], a[7:1]}; // RAR endcase psw[CF] <= a[opc[3] ? 0 : 7]; end 3: begin t <= 0; end endcase // 4T [27] DAA 8'b0010_0111: case (t) 0: begin d[15:8] <= (daa1 ? 6 : 0) + (daa2 ? 8'h60 : 0); end 1: begin d[ 7:0] <= a + d[15:8]; end 2: begin psw[SF] <= d[7]; psw[ZF] <= d[7:0] == 0; psw[HF] <= a[4] ^ d[4] ^ d[12]; psw[PF] <= ~^d[7:0]; psw[CF] <= daa2 | psw[0]; b <= 1; n <= 7; end 3: begin t <= 0; end endcase // 4T [2F] CMA 8'b0010_1111: case (t) 0: begin d <= ~a; b <= 1; n <= 7; end 3: begin t <= 0; end endcase // 4T [37] STC [3F] CMC 8'b0011_x111: case (t) 0: begin psw[CF] <= opc[3] ? ~psw[CF] : 1'b1; end 3: begin t <= 0; end endcase // ========================== // ДИАПАЗОН ИНСТРУКЦИИ 40-BF // ========================== // 5/7T MOV x,x 8'b01xx_xxxx: case (t) 0: begin cp <= hl; sw <= 1; if (m53 && m20) pc <= pc; end 1: begin n <= opc[5:3]; b <= !m53; we <= m53; d <= op20; out <= op20; end 4: begin sw <= 0; t <= (m53 || m20) ? 5 : 0; end 6: begin t <= 0; end endcase // 5/7T [ALU] Op 8'b10xx_xxxx: case (t) 0: begin cp <= hl; sw <= 1; end 1: begin d <= alur; b <= (opc[5:3] != CMP); n <= 7; psw <= aluf; end 4: begin sw <= 0; t <= m20 ? 5 : 0; end 6: begin t <= 0; end endcase // ========================== // ДИАПАЗОН ИНСТРУКЦИИ С0-FF // ========================== // 5/11T RET ccc 8'b11xx_x000, 8'b1100_1001: case (t) 0: begin d <= sp + 2; w <= ccc; n <= 3; sw <= 1; cp <= sp; end 1: begin d[ 7:0] <= in; cp <= cpn; end 2: begin d[15:8] <= in; sw <= 0; end 4: begin t <= ccc ? 5 : 0; end 10: begin t <= 0; pc <= d; end endcase // 11T POP 8'b11xx_0001: case (t) 0: begin d <= sp + 2; w <= 1; n <= 3; sw <= 1; cp <= sp; end 1: begin d[ 7:0] <= in; cp <= cpn; end 2: begin d[15:8] <= in; sw <= 0; n <= opc[5:4]; w <= opc[5:4] != 3; end 3: begin if (opc[5:4] == 3) begin d[7:0] <= d[15:8]; psw <= d[7:0]; b <= 1; n <= 7; end end 10: begin t <= 0; end endcase // 5T [E9] PCHL 8'b1110_1001: case (t) 4: begin pc <= hl; t <= 0; end endcase // 5T [F9] SPHL 8'b1111_1001: case (t) 0: begin d <= hl; w <= 1; n <= 3; end 4: begin t <= 0; end endcase // 10T JMP ccc, ** 8'b11xx_x010, 8'b1100_0011: case (t) 1: begin cp[ 7:0] <= in; pc <= pcn; end 2: begin cp[15:8] <= in; pc <= pcn; end 9: begin t <= 0; if (ccc || opc[0]) pc <= cp; end endcase // 4T DI, EI 8'b1111_x011: case (t) 0: begin iff1 <= opc[3]; end 3: begin t <= 0; end endcase // 10T OUT (*), A 8'b1101_0011: case (t) 1: begin port <= in; port_we <= 1; out <= a; pc <= pcn; end 9: begin t <= 0; end endcase // 10T IN A, (*) 8'b1101_1011: case (t) 1: begin port <= in; pc <= pcn; end 2: begin b <= 1; n <= 7; d <= port_in; end 9: begin t <= 0; end endcase // 18T XTHL 8'b1110_0011: case (t) 0: begin sw <= 1; cp <= sp; end 1: begin d[ 7:0] <= in; cp <= cpn; end 2: begin d[15:8] <= in; w <= 1; n <= 2; cp <= hl; end 3: begin we <= 1; out <= cp[7:0]; d[7:0] <= cp[15:8]; cp <= sp; end 4: begin we <= 1; out <= d[7:0]; cp <= cpn; end 17: begin sw <= 0; t <= 0; end endcase // 4T XCHG 8'b1110_1011: case (t) 0: begin d <= de; n <= 2; w <= 1; cp <= hl; end 1: begin d <= cp; n <= 1; w <= 1; end 3: begin t <= 0; end endcase // 11/17T CALL ccc 8'b11xx_x100, 8'b1100_1101: case (t) 1: begin d[ 7:0] <= in; pc <= pcn; end 2: begin d[15:8] <= in; pc <= pcn; end 3: begin we <= ccc; out <= pc[ 7:0]; sw <= 1; cp <= sp - 2; end 4: begin we <= ccc; out <= pc[15:8]; cp <= cpn; end 5: begin if (ccc) pc <= d[15:0]; end 6: begin w <= ccc; d <= sp - 2; n <= 3; end 10: begin t <= ccc ? 11 : 0; end 16: begin t <= 0; end endcase // 11T PUSH 8'b11xx_0101: case (t) 0: begin d <= sp - 2; w <= 1; n <= 3; sw <= 1; cp <= sp - 2; end 1: begin d <= opc[5:4] == 2'b11 ? {a, (psw & 8'b11010101) | 2'b10} : r16; end 2: begin we <= 1; out <= d[ 7:0]; end 3: begin we <= 1; out <= d[15:8]; cp <= cpn; end 10: begin sw <= 0; t <= 0; end endcase // 7T [ALU] Imm 8'b11xx_x110: case (t) 1: begin d <= alur; pc <= pcn; b <= (opc[5:3] != CMP); n <= 7; psw <= aluf; end 6: begin t <= 0; end endcase // 11T RST 8'b11xx_x111: case (t) 1: begin we <= 1; d <= sp - 2; n <= 3; w <= 1; cp <= sp - 2; sw <= 1; out <= pc[7:0]; end 2: begin we <= 1; out <= pc[15:8]; cp <= cpn; pc <= {opc[5:3], 3'b000}; end 10: begin sw <= 0; t <= 0; end endcase endcase end // Запись данных в регистры always @(posedge clock) if (reset_n && ce) begin // 8-bit if (b) case (n) 0: bc[15:8] <= d[7:0]; 1: bc[ 7:0] <= d[7:0]; // BC 2: de[15:8] <= d[7:0]; 3: de[ 7:0] <= d[7:0]; // DE 4: hl[15:8] <= d[7:0]; 5: hl[ 7:0] <= d[7:0]; // HL 7: a <= d[7:0]; endcase // 16-bit if (w) case (n) 2'b00: bc <= d[15:0]; 2'b01: de <= d[15:0]; 2'b10: hl <= d[15:0]; 2'b11: sp <= d[15:0]; endcase end endmodule
06 июн 2024, 04:04
© 2011-2025 Отличная вещь пропадала