/****************************************** Simple 80 Processor (my80) V1.0 (C)Copyright by Naohiko Shimizu, 2001. All rights are reserved. I place this file for the evaluation purposes only. Any commercial use of this code must have a written acknowledgement from Naohiko Shimizu. Contact information: Dr. Naohiko Shimizu School of Information Technology and Electronics, Tokai University 1117 Kitakaname, Hiratsuka-city, Kanagawa, 259-1292, Japan email: nshimizu@keyaki.cc.u-tokai.ac.jp URL: http://shimizu-lab.et.u-tokai.ac.jp/ Update informations: 10-May-2001: POP A/CMP carry, Kon 13-Feb-2001: subtract borrow, SHMZ 13-Feb-2001: inc16/inxdcx, Yanaba 11-Feb-2001: DAD destination, Ishikawa 10-Feb-2001: CMP flags wrong, Kouyama 10-Feb-2001: ALU instructions does not set flags, Kon 08-Feb-2001: Interruption architecture change SHMZ 07-Feb-2001: Change inc/dec for less gates SHMZ 07-Feb-2001: MVI M,xx support SHMZ 06-Feb-2001: Change data lines bidirectional SHMZ 05-Feb-2001: JC decode miss. SHMZ 30-Jan-2001: Generated from the SN/1 ******************************************/ %i %i declare my80 { bidirect data<8> ; bidirect adrs<16> ; instrin extint; instrout memory_read; instrout memory_write; instrout io_read; instrout io_write; } declare alu80 { input op<3> ; input in1<8> ; input in2<8> ; input ci ; output out<8> ; output s,z,a,p,c; instrin do; instr_arg do(op,in1,in2,ci); } declare cpa { input in1, in2, ci; output out, co; instrin do; instr_arg do(in1,in2,ci); } declare cpa4 { input in1<4>, in2<4>, ci; output out<4>, co; instrin do; instr_arg do(in1,in2,ci); } declare cpa8 { input in1<8>, in2<8>, ci; output out<8>, co, ca; instrin do; instr_arg do(in1,in2,ci); } module cpa { input in1, in2, ci; output out, co; instrin do; instruct do par { out = in1 @ in2 @ ci; co = (in1&in2)|(in1&ci)|(in2&ci); } } module cpa4 { input in1<4>, in2<4>, ci; output out<4>, co; cpa a1,a2,a3,a4; instrin do; instruct do par { out = a4.do(in1<3>,in2<3>,a3.co).out || a3.do(in1<2>,in2<2>,a2.co).out || a2.do(in1<1>,in2<1>,a1.co).out || a1.do(in1<0>,in2<0>,ci).out; co = a4.co; } } module cpa8 { input in1<8>, in2<8>, ci; output out<8>, co, ca; cpa4 a1,a2; instrin do; instruct do par { out = a2.do(in1<7:4>,in2<7:4>,a1.co).out || a1.do(in1<3:0>,in2<3:0>,ci).out; co = a2.co; ca = a1.co; } } declare ha { input in, ci, dec; output out, co; instrin do; instr_arg do(in,ci,dec); } declare inc4 { input in<4>, ci,dec; output out<4>, co; instrin do; instr_arg do(in,ci,dec); } declare inc8 { input in<8>, ci,dec; output out<8>, co; instrin do; instr_arg do(in,ci,dec); } declare inc16 { input in<16>, dec; output out<16>; instrin do; instr_arg do(in,dec); } module ha { input in, ci,dec; output out, co; instrin do; instruct do par { out = in @ ci; co = ((in @ dec)&ci); } } module inc4 { input in<4>, ci, dec; output out<4>, co; ha a1,a2,a3,a4; instrin do; instruct do par { out = a4.do(in<3>,a3.co,dec).out || a3.do(in<2>,a2.co,dec).out || a2.do(in<1>,a1.co,dec).out || a1.do(in<0>,ci,dec).out; co = a4.co; } } module inc8 { input in<8>, ci,dec; output out<8>, co, ca; inc4 a1,a2; instrin do; instruct do par { out = a2.do(in<7:4>,a1.co,dec).out || a1.do(in<3:0>,ci,dec).out; co = a2.co; } } module inc16 { input in<16>, dec; output out<16>; inc8 a1,a2; instrin do; instruct do par { out = a2.do(in<15:8>,a1.co,dec).out || a1.do(in<7:0>,0b1,dec).out; } } module alu80 { input op<3> ; input in1<8> ; input in2<8> ; input ci ; output out<8> ; output s,z,a,p,c; instrin do; cpa8 cpa; instruct do par { any { op == 0b000: par { out = cpa.do(in1, in2, 0b0).out; c = cpa.co; a=cpa.ca; s = out<7>; z = ^/| out; p = ^/@ out; } op == 0b001: par { out = cpa.do(in1, in2, ci).out; c = cpa.co; a=cpa.ca; s = out<7>; z = ^/| out; p = ^/@ out; } op == 0b010: par { out = cpa.do(in1, ^in2, 0b1).out; c = ^cpa.co; a=^cpa.ca; s = out<7>; z = ^/| out; p = ^/@ out; } op == 0b011: par { out = cpa.do(in1, ^in2, ^ci).out; c = ^cpa.co; a=^cpa.ca; s = out<7>; z = ^/| out; p = ^/@ out; } op == 0b100: par { out = in1 & in2; c = 0b0; a=0b0; s = out<7>; z = ^/| out; p = ^/@ out; } op == 0b101: par { out = in1 @ in2; c = 0b0; a=0b0; s = out<7>; z = ^/| out; p = ^/@ out; } op == 0b110: par { out = in1 | in2; c = 0b0; a=0b0; s = out<7>; z = ^/| out; p = ^/@ out; } op == 0b111: par { out = in1; cpa.do(in1, ^in2, 0b1); c = ^cpa.co; a=^cpa.ca; s = cpa.out<7>; z = ^/| cpa.out; p = ^/@ cpa.out; } } } } declare ram { input adr<8>; bidirect data<8>; instrin read; instrin write; instr_arg read(adr); instr_arg write(adr,data); } module ram { input adr<8>; bidirect data<8>; r256_8 m; instrin read; instrin write; instruct read data = m.read(adr).dout; instruct write m.write(adr,data); } module top { output outp<8>; output adrs<16>; input inp<8>; my80 cpu; ram ram; instruct cpu.memory_read cpu.data = ram.read(cpu.adrs<7:0>).data ; instruct cpu.memory_write ram.write(cpu.adrs<7:0>,cpu.data); instruct cpu.io_read cpu.data = inp; instruct cpu.io_write outp = cpu.data; } module my80 { bidirect data<8> ; bidirect adrs<16> ; instrin extint; instrself start, setreg, getreg, setrxl, setrxh, getrx, flagchk, dec1op; instrout memory_read, memory_write; instrout io_read, io_write; reg pc<16>; /* program counter */ reg sp<16>; reg a<8>,f<8>,b<8>,c<8>,d<8>,e<8>,h<8>,l<8>; reg tc, imask, op0<8>, op1<8>, op2<8>; reg_wr st0 ; reg st1,st2 ; inc16 inc ; alu80 alu ; sel_v hi<8>, lo<8>, flg, rs<3>, rg<3>, xs<2>, xg<2>, v<8> ; sel dmov,dalu,dinr,ddad,dinx,dpop,dpush,dldax,dstax,dretc,drst, dalum,dret,dxthl,dpchl,dsphl,dxchg,ddi,dei,dnop; sel dmvi,dalui,din,dout,dcc,dcall,djmp,djc,dlxi,dlda, dlhld,dshld,dsta, as; instr_arg memory_read(adrs); instr_arg memory_write(adrs,data); instr_arg io_read(adrs); instr_arg io_write(adrs,data); instr_arg setreg(rs,v); instr_arg getreg(rg); instr_arg setrxh(xs,v,as); instr_arg setrxl(xs,v,as); instr_arg getrx(xg,as); instr_arg flagchk(rs); instr_arg dec1op(); stage_name int { task intt() ; } stage_name if { task ift(pc) ; } /* Common operations for every stages must be described here */ par{ st0 := 0b1; st1 := st0; st2 := st1; if ((st2 == 0b0) & (st1 == 0b1)) start(); } instruct extint generate int.intt(); instruct start par { /* start instruction fetch */ generate if.ift(0x0000); imask := 0b1; } instruct setreg any { rs == 0b000: b:=v; rs == 0b001: c:=v; rs == 0b010: d:=v; rs == 0b011: e:=v; rs == 0b100: h:=v; rs == 0b101: l:=v; rs == 0b110: f:=v; rs == 0b111: a:=v; } instruct getreg any { rg == 0b000: lo = b; rg == 0b001: lo = c; rg == 0b010: lo = d; rg == 0b011: lo = e; rg == 0b100: lo = h; rg == 0b101: lo = l; rg == 0b110: lo = f; rg == 0b111: lo = a; } instruct setrxh any { xs == 0b00: b := v; xs == 0b01: d := v; xs == 0b10: h := v; xs == 0b11: any { as: sp := v || sp<7:0>; ^as: f := v; } } instruct setrxl any { xs == 0b00: c := v; xs == 0b01: e := v; xs == 0b10: l := v; xs == 0b11: any { as: sp := sp<15:8> || v; ^as: a := v; } } instruct getrx any { xg == 0b00: par {lo = c; hi = b;} xg == 0b01: par {lo = e; hi = d;} xg == 0b10: par {lo = l; hi = h;} xg == 0b11: any { as: par {lo = sp<7:0>; hi = sp<15:8>;} ^as: par {lo = a; hi = f; } } } instruct flagchk any { rs == 0b000: flg = ^f<6>; rs == 0b001: flg = f<6>; rs == 0b010: flg = ^f<0>; rs == 0b011: flg = f<0>; rs == 0b100: flg = ^f<2>; rs == 0b101: flg = f<2>; rs == 0b110: flg = ^f<7>; rs == 0b111: flg = f<7>; } instruct dec1op par { dmov = op0<7:6> == 0b01; dalu = op0<7:6> == 0b10; dinr = (op0<7:6> || op0<2:1>) == 0b0010; ddad = (op0<7:6> || op0<3:0>) == 0b001001; dinx = (op0<7:6> || op0<2:0>) == 0b00011; dpop = (op0<7:6> || op0<3:0>) == 0b110001; dpush = (op0<7:6> || op0<3:0>) == 0b110101; dldax = (op0<7:5> || op0<3:0>) == 0b0001010; dstax = (op0<7:5> || op0<3:0>) == 0b0000010; dretc = (op0<7:6> || op0<2:0>) == 0b11000; drst = (op0<7:6> || op0<2:0>) == 0b11111; dalum = (op0<7:6> || op0<2:0>) == 0b00111; dret = op0 == 0xc9; dxthl = op0 == 0xe3; dpchl = op0 == 0xe9; dsphl = op0 == 0xf9; dxchg = op0 == 0xeb; ddi = op0 == 0xf3; dei = op0 == 0xfb; dnop = op0 == 0x00; dmvi = (op0<7:6>||op0<2:0>) == 0b00110; dalui = (op0<7:6>||op0<2:0>) == 0b11110; din = op0 == 0xdb; dout = op0 == 0xd3; dcc = (op0<7:6>||op0<2:0>) == 0b11100; djc = (op0<7:6>||op0<2:0>) == 0b11010; dlxi = (op0<7:6>||op0<3:0>) == 0b000001; dcall = op0 == 0xcd; djmp = op0 == 0xc3; dlda = op0 == 0x3a; dlhld = op0 == 0x2a; dshld = op0 == 0x22; dsta = op0 == 0x32; } stage int { state_name external_int; first_state external_int; state external_int finish; } stage if { state_name if, f1, f2, f3, mov, alu, incdec,inxdcx,dad, pop,push,push1,ret,ret1,call,call1,xthl,xthl1, xthl2,lhld,shld, daa; first_state if ; dec1op(); state if any { ^imask & int.intt: par { imask := 0b1; op0 := 0xcf; goto f1; } imask | ^int.intt: par { op0 := memory_read(pc).data; pc := inc.do(pc,0b0).out; goto f1; } } /* any */ state f1 par { any { dmov: par { /* MOV, HLT */ any { op0<5:0> == 0b110110: par { pc := inc.do(pc,0b1).out; goto if; } else: alt { (op0<2:0> == 0b110): par { op2 := memory_read(h||l).data; goto mov; } (op0<5:3> == 0b110): par { memory_write(h||l, getreg(op0<2:0>).lo); goto if; } else: par { setreg(op0<5:3>,getreg(op0<2:0>).lo); goto if; } } } } dalu: any { /* ALU */ (op0<2:0> == 0b110): par { op2 := memory_read(h||l).data; goto alu; } else: par { op2 := getreg(op0<2:0>).lo; goto alu; } } dinr: any { /* INR,DCR */ (op0<5:3> == 0b110): par { op2 := memory_read(h||l).data; goto incdec; } else: par { setreg(op0<5:3>, alu.do(0b0||op0<0>||0b0, getreg(op0<5:3>).lo, 0x01, 0b0).out); f:=alu.s||alu.z||0b0||alu.a||0b0||alu.p||0b0||f<0>; goto if; } } ddad: par { /* DAD */ setrxl(0b10, alu.do(0b000, getrx(op0<5:4>, 0b1).lo, l, 0b0).out, 0b1); tc := alu.c; goto dad; } dinx: par { /* INX,DCX */ setrxl(op0<5:4>, alu.do(0b0||op0<3>||0b0, getrx(op0<5:4>, 0b1).lo, 0x01, 0b0).out, 0b1); tc := alu.c; goto inxdcx; } dpop: par { /* POP */ setrxl(op0<5:4>, memory_read(sp).data, 0b0); sp := inc.do(sp,0b0).out; goto pop; } dpush: par { /* PUSH */ sp := inc.do(sp,0b1).out; goto push; } dldax: par { /* LDAX */ any { ^op0<4>: a:=memory_read(b||c).data; else: a:=memory_read(d||e).data; } goto if; } dstax: par { /* STAX */ any { ^op0<4>: memory_write(b||c,a); else: memory_write(d||e,a); } goto if; } dretc: any { /* RETC */ flagchk(op0<5:3>).flg : par { op2 := memory_read(sp).data; sp := inc.do(sp,0b0).out; goto ret; } else: goto if; } drst: par { /* RST */ op1 := 0b00 || op0<5:3> || 0b000; op2 := 0x00; sp := inc.do(sp,0b1).out; goto call; } dalum: par { /* ALU MISC */ any { op0<5:3> == 0b000: par { /* RLC */ a:=a<6:0>||a<7>; f:=f<7:1> || a<7>; goto if; } op0<5:3> == 0b001: par { /* RRC */ a:=a<0>||a<7:1>; f:=f<7:1> || a<0>; goto if; } op0<5:3> == 0b010: par { /* RAL */ a:=a<6:0>||f<0>; f:=f<7:1> || a<7>; goto if; } op0<5:3> == 0b011: par { /* RAR */ a:=f<0>||a<7:1>; f:=f<7:1> || a<0>; goto if; } op0<5:3> == 0b100: par { /* DAA */ if(a<3> & (a<2> | a<1>) | f<4>) par { a:=alu.do(0b000, a, 0x06, 0b0).out; f:=alu.s||alu.z||0b0||alu.a||0b0||alu.p||0b0||alu.c; } goto daa; } op0<5:3> == 0b101: par { /* CMA */ a:=^a; goto if; } op0<5:3> == 0b110: par { /* STC */ f:=f<7:1> || 0b1; goto if; } op0<5:3> == 0b111: par { /* CMC */ f:=f<7:1> || ^f<0>; goto if; } } } dret: par { /* RET */ op2 := memory_read(sp).data; sp := inc.do(sp,0b0).out; goto ret; } dxthl: par { /* XTHL */ op2:=memory_read(sp).data; goto xthl; } dpchl: par { /* PCHL */ pc := h || l; goto if; } dsphl: par { /* SPHL */ sp := h || l; goto if; } dxchg: par { /* XCHG */ h := d; l := e; d := h; e := l; goto if; } ddi: par { /* DI */ imask := 0b1; goto if; } dei: par { /* EI */ imask := 0b0; goto if; } dnop: par { /* NOP */ goto if; } else: par { /* 2 or 3bytes op */ op1 := memory_read(pc).data; pc := inc.do(pc,0b0).out; goto f2; } } /* any */ } /* par */ state f2 par { any { dmvi: par { /* MVI */ any { op0<5:3> == 0b110: memory_write(h||l,op1); else: setreg(op0<5:3>,op1); } goto if; } dalui: par { /* ALU */ setreg(0b111, alu.do(op0<5:3>, a, op1, f<0>).out); f:=alu.s||alu.z||0b0||alu.a||0b0||alu.p||0b0||alu.c; goto if; } din: par { /* IN */ a := io_read(0x00 || op1).data; goto if; } dout: par { /* OUT */ io_write(0x00 || op1,a); goto if; } dlxi: par { /* LXI */ setrxl(op0<5:4>, op1, 0b1); op2 := memory_read(pc).data; pc := inc.do(pc,0b0).out; goto f3; } else: par { op2 := memory_read(pc).data; pc := inc.do(pc,0b0).out; goto f3; } } /* any */ } /* par */ state f3 par { any { dcc: any { /* CC */ flagchk(op0<5:3>).flg: par { sp := inc.do(sp,0b1).out; goto call; } else: goto if; } dcall: par { /* CALL */ sp := inc.do(sp,0b1).out; goto call; } djmp: par { /* JMP */ pc := op2 || op1; goto if; } djc: par { /* JC */ if(flagchk(op0<5:3>).flg) pc := op2 || op1; goto if; } dlxi: par { /* LXI */ setrxh(op0<5:4>, op2, 0b1); goto if; } dlda: par { /* LDA */ a:=memory_read(op2 || op1).data; goto if; } dlhld: par { /* LHLD */ l:=memory_read(op2 || op1).data; op2 := inc.do(op2 || op1,0b0).out<15:8>; op1 := inc.out<7:0>; goto lhld; } dshld: par { /* SHLD */ memory_write(op2||op1,l); op2 := inc.do(op2 || op1,0b0).out<15:8>; op1 := inc.out<7:0>; goto shld; } dsta: par { /* STA */ memory_write(op2||op1,a); goto if; } } } /* par */ state mov par { setreg(op0<5:3>,op2); goto if; } state alu par { setreg(0b111, alu.do(op0<5:3>, a, op2, f<0>).out); f:=alu.s||alu.z||0b0||alu.a||0b0||alu.p||0b0||alu.c; goto if; } state incdec par { memory_write(h||l, alu.do(0b0||op0<0>||0b0, op2, 0x01, 0b0).out); f:=alu.s||alu.z||0b0||alu.a||0b0||alu.p||0b0||f<0>; goto if; } state pop par { setrxh(op0<5:4>, memory_read(sp).data, 0b0); sp := inc.do(sp,0b0).out; goto if; } state push par { memory_write(sp, getrx(op0<5:4>, 0b0).hi); sp := inc.do(sp,0b1).out; goto push1; } state push1 par { memory_write(sp, getrx(op0<5:4>, 0b0).lo); goto if; } state dad par { setrxh(0b10, alu.do(0b001, getrx(op0<5:4>, 0b1).hi, h, tc).out, 0b1); f:=f<7:1>||alu.c; goto if; } state inxdcx par { setrxh(op0<5:4>, alu.do(0b0||op0<3>||0b1, getrx(op0<5:4>, 0b1).hi, 0x00, tc@op0<3>).out, 0b1); goto if; } state ret par { pc := memory_read(sp).data || op2; sp := inc.do(sp,0b0).out; goto if; } state call par { memory_write(sp, pc<15:8>); sp := inc.do(sp,0b1).out; goto call1; } state call1 par { memory_write(sp, pc<7:0>); pc := op2 || op1; goto if; } state xthl par { memory_write(sp, l); l := op2; sp:=inc.do(sp,0b0).out; goto xthl1; } state xthl1 par { op2:=memory_read(sp).data; goto xthl2; } state xthl2 par { h := op2; memory_write(sp, h); sp:=inc.do(sp,0b1).out; goto if; } state lhld par { h:=memory_read(op2||op1).data; goto if; } state shld par { memory_write(op2||op1, h); goto if; } state daa par { if(a<7> & (a<6> | a<5>) | f<0>) par { a:=alu.do(0b000, a, 0x60, 0b0).out; f:=alu.s||alu.z||0b0||alu.a||0b0||alu.p||0b0||alu.c; } goto if; } } /* stage */ } /* module */