§ Код процессора
Ревизия 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,
psw = 8'b00000011;
reg sw;
reg [15:0] cp;
reg [ 7:0] opcode;
reg [ 4:0] t;
reg b;
reg w;
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;
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 :
opc[5:3] == ADC ? a + op20 + psw[CF] :
opc[5:3] == SBB ? a - op20 - psw[CF] :
opc[5:3] == AND ? a & op20 :
opc[5:3] == XOR ? a ^ op20 :
opc[5:3] == OR ? a | op20 :
a - op20;
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} :
{sf, zf, 1'b0, hf, 1'b0, pf, 1'b1, cf};
always @(posedge clock)
if (reset_n == 0) begin
t <= 0;
sw <= 0;
pc <= 16'hF800;
iff1 <= 0;
end
else if (ce) begin
t <= t + 1;
b <= 0;
w <= 0;
we <= 0;
port_we <= 0;
if (m0) begin opcode <= in; pc <= pcn; end
casex (opc)
8'b0000_0000: case (t)
3: begin t <= 0; end
endcase
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
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
8'b000x_0010: case (t)
0: begin we <= 1; out <= a; cp <= r16; sw <= 1; end
6: begin sw <= 0; t <= 0; end
endcase
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
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
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
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
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
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
8'b00xx_x110: case (t)
1: begin
pc <= pcn;
cp <= hl;
n <= opc[5:3];
b <= !m53;
we <= m53;
sw <= m53;
d <= in;
out <= in;
end
6: begin t <= sw ? 7 : 0; sw <= 0; end
9: begin t <= 0; end
endcase
8'b000x_x111: case (t)
0: begin
b <= 1;
n <= 7;
case (opc[4:3])
2'b00: d <= {a[6:0], a[7]};
2'b01: d <= {a[0], a[7:1]};
2'b10: d <= {a[6:0], psw[CF]};
2'b11: d <= {psw[CF], a[7:1]};
endcase
psw[CF] <= a[opc[3] ? 0 : 7];
end
3: begin t <= 0; end
endcase
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
8'b0010_1111: case (t)
0: begin d <= ~a; b <= 1; n <= 7; end
3: begin t <= 0; end
endcase
8'b0011_x111: case (t)
0: begin psw[CF] <= opc[3] ? ~psw[CF] : 1'b1; end
3: begin t <= 0; end
endcase
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
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
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
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
8'b1110_1001: case (t)
4: begin pc <= hl; t <= 0; end
endcase
8'b1111_1001: case (t)
0: begin d <= hl; w <= 1; n <= 3; end
4: begin t <= 0; end
endcase
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
8'b1111_x011: case (t)
0: begin iff1 <= opc[3]; end
3: begin t <= 0; end
endcase
8'b1101_0011: case (t)
1: begin port <= in; port_we <= 1; out <= a; pc <= pcn; end
9: begin t <= 0; end
endcase
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
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
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
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
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
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
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
if (b)
case (n)
0: bc[15:8] <= d[7:0]; 1: bc[ 7:0] <= d[7:0];
2: de[15:8] <= d[7:0]; 3: de[ 7:0] <= d[7:0];
4: hl[15:8] <= d[7:0]; 5: hl[ 7:0] <= d[7:0];
7: a <= d[7:0];
endcase
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