1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-31 22:02:00 +00:00
Files
Gehstock.Mist_FPGA/common/k580wm80a.v
2019-07-22 23:42:05 +02:00

474 lines
10 KiB
Verilog

// ====================================================================
// Bashkiria-2M FPGA REPLICA
//
// Copyright (C) 2010 Dmitry Tselikov
//
// This core is distributed under modified BSD license.
// For complete licensing information see LICENSE.TXT.
// --------------------------------------------------------------------
//
// An open implementation of Bashkiria-2M home computer
//
// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
//
// Design File: k580wm80a.v
//
// Processor k580wm80a core design file of Bashkiria-2M replica.
module k580wm80a(
input clk,
input ce,
input reset,
input intr,
input [7:0] idata,
output reg [15:0] addr,
output reg sync,
output rd,
output reg wr_n,
output inta_n,
output reg [7:0] odata,
output inte_o);
reg M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16,M17,T5;
reg[2:0] state;
wire M1n = M2|M3|M4|M5|M6|M7|M8|M9|M10|M11|M12|M13|M14|M15|M16|M17;
reg[15:0] PC;
reg[15:0] SP;
reg[7:0] B,C,D,E,H,L,A;
reg[7:0] W,Z,IR;
reg[9:0] ALU;
reg FS,FZ,FA,FP,FC,_FA;
reg rd_,intproc;
assign rd = rd_&~intproc;
assign inta_n = ~(rd_&intproc);
assign inte_o = inte[1];
reg[1:0] inte;
reg jmp,call,halt;
reg save_alu,save_a,save_r,save_rp,read_r,read_rp;
reg incdec,xthl,xchg,sphl,daa;
reg ccc;
always @(*) begin
casex (IR[5:3])
3'b00x: ALU = {1'b0,A,1'b1}+{1'b0,Z,FC&IR[3]};
3'b01x: ALU = {1'b0,A,1'b0}-{1'b0,Z,FC&IR[3]};
3'b100: ALU = {1'b0,A & Z,1'b0};
3'b101: ALU = {1'b0,A ^ Z,1'b0};
3'b110: ALU = {1'b0,A | Z,1'b0};
3'b111: ALU = {1'b0,A,1'b0}-{1'b0,Z,1'b0};
endcase
end
always @(*) begin
casex (IR[5:3])
3'b00x: _FA = A[4]^Z[4]^ALU[5];
3'b100: _FA = A[3]|Z[3];
3'b101: _FA = 1'b0;
3'b110: _FA = 1'b0;
default: _FA = ~(A[4]^Z[4]^ALU[5]);
endcase
end
always @(*) begin
// SZ.A.P.C
case(idata[5:3])
3'h0: ccc = ~FZ;
3'h1: ccc = FZ;
3'h2: ccc = ~FC;
3'h3: ccc = FC;
3'h4: ccc = ~FP;
3'h5: ccc = FP;
3'h6: ccc = ~FS;
3'h7: ccc = FS;
endcase
end
wire[7:0] F = {FS,FZ,1'b0,FA,1'b0,FP,1'b1,FC};
wire[7:0] Z1 = incdec ? Z+{{7{IR[0]}},1'b1} : Z;
wire[15:0] WZ1 = incdec ? {W,Z}+{{15{IR[3]}},1'b1} : {W,Z};
wire[3:0] daaZL = FA!=0 || A[3:0] > 4'h9 ? 4'h6 : 4'h0;
wire[3:0] daaZH = FC!=0 || A[7:4] > {3'b100, A[3:0]>4'h9 ? 1'b0 : 1'b1} ? 4'h6 : 4'h0;
always @(posedge clk or posedge reset)
begin
if (reset) begin
{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16,M17} <= 0;
state <= 0; PC <= 0; {FS,FZ,FA,FP,FC} <= 0; {addr,odata} <= 0;
{sync,rd_,jmp,halt,inte,save_alu,save_a,save_r,save_rp,incdec,intproc} <= 0;
wr_n <= 1'b1;
end else if (ce) begin
sync <= 0; rd_ <= 0; wr_n <= 1'b1;
if (halt&~(M1|(intr&inte[1]))) begin
sync <= 1'b1; // state: rd in m1 out hlt stk ~wr int
odata <= 8'b10001010; // rd? hlt ~wr
end else
if (M1|~M1n) begin
case (state)
3'b000: begin
halt <= 0; intproc <= intr&inte[1]; inte[1] <= inte[0];
M1 <= 1'b1;
sync <= 1'b1;
odata <= {7'b1010001,intr&inte[1]}; // rd m1 ~wr
addr <= jmp ? {W,Z} : PC;
state <= 3'b001;
if (intr&inte[1]) inte <= 2'b0;
if (save_alu) begin
FS <= ALU[8];
FZ <= ~|ALU[8:1];
FA <= _FA;
FP <= ~^ALU[8:1];
FC <= ALU[9]|(FC&daa);
if (IR[5:3]!=3'b111) A <= ALU[8:1];
end else
if (save_a) begin
A <= Z1;
end else
if (save_r) begin
case (IR[5:3])
3'b000: B <= Z1;
3'b001: C <= Z1;
3'b010: D <= Z1;
3'b011: E <= Z1;
3'b100: H <= Z1;
3'b101: L <= Z1;
3'b111: A <= Z1;
endcase
if (incdec) begin
FS <= Z1[7];
FZ <= ~|Z1;
FA <= IR[0] ? Z1[3:0]!=4'b1111 : Z1[3:0]==0;
FP <= ~^Z1;
end
end else
if (save_rp) begin
case (IR[5:4])
2'b00: {B,C} <= WZ1;
2'b01: {D,E} <= WZ1;
2'b10: {H,L} <= WZ1;
2'b11:
if (sphl || !IR[7]) begin
SP <= WZ1;
end else begin
{A,FS,FZ,FA,FP,FC} <= {WZ1[15:8],WZ1[7],WZ1[6],WZ1[4],WZ1[2],WZ1[0]};
end
endcase
end
end
3'b001: begin
rd_ <= 1'b1;
PC <= addr+{15'b0,~intproc};
state <= 3'b010;
end
3'b010: begin
IR <= idata;
{jmp,call,save_alu,save_a,save_r,save_rp,read_r,read_rp,incdec,xthl,xchg,sphl,T5,daa} <= 0;
casex (idata)
8'b00xx0001: {save_rp,M2,M3} <= 3'b111;
8'b00xx1001: {read_rp,M16,M17} <= 3'b111;
8'b000x0010: {read_rp,M14} <= 2'b11;
8'b00100010: {M2,M3,M14,M15} <= 4'b1111;
8'b00110010: {M2,M3,M14} <= 3'b111;
8'b000x1010: {read_rp,save_a,M12} <= 3'b111;
8'b00101010: {save_rp,M2,M3,M12,M13} <= 5'b11111;
8'b00111010: {save_a,M2,M3,M12} <= 4'b1111;
8'b00xxx011: {read_rp,save_rp,incdec,T5} <= 4'b1111;
8'b00xxx10x: {read_r,save_r,incdec,T5} <= {3'b111,idata[5:3]!=3'b110};
8'b00xxx110: {save_r,M2} <= 2'b11;
8'b00000111: {FC,A} <= {A,A[7]};
8'b00001111: {A,FC} <= {A[0],A};
8'b00010111: {FC,A} <= {A,FC};
8'b00011111: {A,FC} <= {FC,A};
8'b00100111: {daa,save_alu,IR[5:3],Z} <= {5'b11000,daaZH,daaZL};
8'b00101111: A <= ~A;
8'b00110111: FC <= 1'b1;
8'b00111111: FC <= ~FC;
8'b01xxxxxx: if (idata[5:0]==6'b110110) halt <= 1'b1; else {read_r,save_r,T5} <= {2'b11,~(idata[5:3]==3'b110||idata[2:0]==3'b110)};
8'b10xxxxxx: {read_r,save_alu} <= 2'b11;
8'b11xxx000: {jmp,M8,M9} <= {3{ccc}};
8'b11xx0001: {save_rp,M8,M9} <= 3'b111;
8'b110x1001: {jmp,M8,M9} <= 3'b111;
8'b11101001: {read_rp,jmp,T5} <= 3'b111;
8'b11111001: {read_rp,save_rp,T5,sphl} <= 4'b1111;
8'b11xxx010: {jmp,M2,M3} <= {ccc,2'b11};
8'b1100x011: {jmp,M2,M3} <= 3'b111;
8'b11010011: {M2,M7} <= 2'b11;
8'b11011011: {M2,M6} <= 2'b11;
8'b11100011: {save_rp,M8,M9,M10,M11,xthl} <= 6'b111111;
8'b11101011: {read_rp,save_rp,xchg} <= 3'b111;
8'b1111x011: inte <= idata[3] ? 2'b1 : 2'b0;
8'b11xxx100: {jmp,M2,M3,T5,M10,M11,call} <= {ccc,3'b111,{3{ccc}}};
8'b11xx0101: {read_rp,T5,M10,M11} <= 4'b1111;
8'b11xx1101: {jmp,M2,M3,T5,M10,M11,call} <= 7'b1111111;
8'b11xxx110: {save_alu,M2} <= 2'b11;
8'b11xxx111: {jmp,T5,M10,M11,call,W,Z} <= {5'b11111,10'b0,idata[5:3],3'b0};
endcase
state <= 3'b011;
end
3'b011: begin
if (read_rp) begin
case (IR[5:4])
2'b00: {W,Z} <= {B,C};
2'b01: {W,Z} <= {D,E};
2'b10: {W,Z} <= xchg ? {D,E} : {H,L};
2'b11: {W,Z} <= sphl ? {H,L} : IR[7] ? {A,F} : SP;
endcase
if (xchg) {D,E} <= {H,L};
end else
if (~(jmp|daa)) begin
case (incdec?IR[5:3]:IR[2:0])
3'b000: Z <= B;
3'b001: Z <= C;
3'b010: Z <= D;
3'b011: Z <= E;
3'b100: Z <= H;
3'b101: Z <= L;
3'b110: M4 <= read_r;
3'b111: Z <= A;
endcase
M5 <= save_r && IR[5:3]==3'b110;
end
state <= T5 ? 3'b100 : 0;
M1 <= T5;
end
3'b100: begin
if (M10) SP <= SP-16'b1;
state <= 0;
M1 <= 0;
end
endcase
end else
if (M2 || M3) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000001,intproc}; // rd ~wr
addr <= PC;
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
PC <= addr+{15'b0,~intproc};
state <= 3'b010;
end
3'b010: begin
if (M2) begin
Z <= idata;
M2 <= 0;
end else begin
W <= idata;
M3 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M4) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000001,intproc}; // rd ~wr
addr <= {H,L};
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
state <= 3'b010;
end
3'b010: begin
Z <= idata;
M4 <= 0;
state <= 3'b000;
end
endcase
end else
if (M5) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000000,intproc}; // ~wr=0
addr <= {H,L};
state <= 3'b001;
end
3'b001: begin
odata <= Z1;
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
M5 <= 0;
state <= 3'b000;
end
endcase
end else
if (M6) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0100001,intproc}; // in ~wr
addr <= {Z,Z};
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
state <= 3'b010;
end
3'b010: begin
A <= idata;
M6 <= 0;
state <= 3'b000;
end
endcase
end else
if (M7) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0001000,intproc}; // out
addr <= {Z,Z};
state <= 3'b001;
end
3'b001: begin
odata <= A;
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
M7 <= 0;
state <= 3'b000;
end
endcase
end else
if (M8 || M9) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000011,intproc}; // rd stk ~wr
addr <= SP;
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
if (M8 || !xthl) SP <= SP+16'b1;
state <= 3'b010;
end
3'b010: begin
if (M8) begin
Z <= idata;
M8 <= 0;
end else begin
W <= idata;
M9 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M10 || M11) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000010,intproc}; // stk
addr <= SP;
state <= 3'b001;
end
3'b001: begin
if (M10) begin
SP <= SP-16'b1;
odata <= xthl ? H : call ? PC[15:8] : W;
end else begin
odata <= xthl ? L : call ? PC[7:0] : Z;
end
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
if (M10) begin
M10 <= 0;
end else begin
M11 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M12 || M13) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b1000001,intproc}; // rd ~wr
addr <= M12 ? {W,Z} : addr+16'b1;
state <= 3'b001;
end
3'b001: begin
rd_ <= 1'b1;
state <= 3'b010;
end
3'b010: begin
if (M12) begin
Z <= idata;
M12 <= 0;
end else begin
W <= idata;
M13 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M14 || M15) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000000,intproc}; // ~wr=0
addr <= M14 ? {W,Z} : addr+16'b1;
state <= 3'b001;
end
3'b001: begin
if (M14) begin
odata <= M15 ? L : A;
end else begin
odata <= H;
end
wr_n <= 1'b0;
state <= 3'b010;
end
3'b010: begin
if (M14) begin
M14 <= 0;
end else begin
M15 <= 0;
end
state <= 3'b000;
end
endcase
end else
if (M16 || M17) begin
case (state)
3'b000: begin
sync <= 1'b1;
odata <= {7'b0000001,intproc}; // ~wr
state <= 3'b001;
end
3'b001: begin
state <= 3'b010;
end
3'b010: begin
if (M16) begin
M16 <= 0;
end else begin
{FC,H,L} <= {1'b0,H,L}+{1'b0,W,Z};
M17 <= 0;
end
state <= 3'b000;
end
endcase
end
end
end
endmodule