//
|
//
|
// TV80 8-Bit Microprocessor Core
|
// TV80 8-Bit Microprocessor Core
|
// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
|
// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
|
//
|
//
|
// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
|
// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
|
//
|
//
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
// to deal in the Software without restriction, including without limitation
|
// to deal in the Software without restriction, including without limitation
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// and/or sell copies of the Software, and to permit persons to whom the
|
// and/or sell copies of the Software, and to permit persons to whom the
|
// Software is furnished to do so, subject to the following conditions:
|
// Software is furnished to do so, subject to the following conditions:
|
//
|
//
|
// The above copyright notice and this permission notice shall be included
|
// The above copyright notice and this permission notice shall be included
|
// in all copies or substantial portions of the Software.
|
// in all copies or substantial portions of the Software.
|
//
|
//
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
module tv80_core (/*AUTOARG*/
|
module tv80_core (/*AUTOARG*/
|
// Outputs
|
// Outputs
|
m1_n, iorq, no_read, write, rfsh_n, halt_n, busak_n, A, dout, mc,
|
m1_n, iorq, no_read, write, rfsh_n, halt_n, busak_n, A, dout, mc,
|
ts, intcycle_n, IntE, stop,
|
ts, intcycle_n, IntE, stop,
|
// Inputs
|
// Inputs
|
reset_n, clk, cen, wait_n, int_n, nmi_n, busrq_n, dinst, di
|
reset_n, clk, cen, wait_n, int_n, nmi_n, busrq_n, dinst, di
|
);
|
);
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
// End of automatics
|
// End of automatics
|
|
|
parameter Mode = 1; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
|
parameter Mode = 1; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
|
parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle
|
parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle
|
parameter Flag_C = 0;
|
parameter Flag_C = 0;
|
parameter Flag_N = 1;
|
parameter Flag_N = 1;
|
parameter Flag_P = 2;
|
parameter Flag_P = 2;
|
parameter Flag_X = 3;
|
parameter Flag_X = 3;
|
parameter Flag_H = 4;
|
parameter Flag_H = 4;
|
parameter Flag_Y = 5;
|
parameter Flag_Y = 5;
|
parameter Flag_Z = 6;
|
parameter Flag_Z = 6;
|
parameter Flag_S = 7;
|
parameter Flag_S = 7;
|
|
|
input reset_n;
|
input reset_n;
|
input clk;
|
input clk;
|
input cen;
|
input cen;
|
input wait_n;
|
input wait_n;
|
input int_n;
|
input int_n;
|
input nmi_n;
|
input nmi_n;
|
input busrq_n;
|
input busrq_n;
|
output m1_n;
|
output m1_n;
|
output iorq;
|
output iorq;
|
output no_read;
|
output no_read;
|
output write;
|
output write;
|
output rfsh_n;
|
output rfsh_n;
|
output halt_n;
|
output halt_n;
|
output busak_n;
|
output busak_n;
|
output [15:0] A;
|
output [15:0] A;
|
input [7:0] dinst;
|
input [7:0] dinst;
|
input [7:0] di;
|
input [7:0] di;
|
output [7:0] dout;
|
output [7:0] dout;
|
output [6:0] mc;
|
output [6:0] mc;
|
output [6:0] ts;
|
output [6:0] ts;
|
output intcycle_n;
|
output intcycle_n;
|
output IntE;
|
output IntE;
|
output stop;
|
output stop;
|
|
|
reg m1_n;
|
reg m1_n;
|
reg iorq;
|
reg iorq;
|
`ifdef TV80_REFRESH
|
`ifdef TV80_REFRESH
|
reg rfsh_n;
|
reg rfsh_n;
|
`endif
|
`endif
|
reg halt_n;
|
reg halt_n;
|
reg busak_n;
|
reg busak_n;
|
reg [15:0] A;
|
reg [15:0] A;
|
reg [7:0] dout;
|
reg [7:0] dout;
|
reg [6:0] mc;
|
reg [6:0] mc;
|
reg [6:0] ts;
|
reg [6:0] ts;
|
reg intcycle_n;
|
reg intcycle_n;
|
reg IntE;
|
reg IntE;
|
reg stop;
|
reg stop;
|
|
|
parameter aNone = 3'b111;
|
parameter aNone = 3'b111;
|
parameter aBC = 3'b000;
|
parameter aBC = 3'b000;
|
parameter aDE = 3'b001;
|
parameter aDE = 3'b001;
|
parameter aXY = 3'b010;
|
parameter aXY = 3'b010;
|
parameter aIOA = 3'b100;
|
parameter aIOA = 3'b100;
|
parameter aSP = 3'b101;
|
parameter aSP = 3'b101;
|
parameter aZI = 3'b110;
|
parameter aZI = 3'b110;
|
|
|
// Registers
|
// Registers
|
reg [7:0] ACC, F;
|
reg [7:0] ACC, F;
|
reg [7:0] Ap, Fp;
|
reg [7:0] Ap, Fp;
|
reg [7:0] I;
|
reg [7:0] I;
|
`ifdef TV80_REFRESH
|
`ifdef TV80_REFRESH
|
reg [7:0] R;
|
reg [7:0] R;
|
`endif
|
`endif
|
reg [15:0] SP, PC;
|
reg [15:0] SP, PC;
|
reg [7:0] RegDIH;
|
reg [7:0] RegDIH;
|
reg [7:0] RegDIL;
|
reg [7:0] RegDIL;
|
wire [15:0] RegBusA;
|
wire [15:0] RegBusA;
|
wire [15:0] RegBusB;
|
wire [15:0] RegBusB;
|
wire [15:0] RegBusC;
|
wire [15:0] RegBusC;
|
reg [2:0] RegAddrA_r;
|
reg [2:0] RegAddrA_r;
|
reg [2:0] RegAddrA;
|
reg [2:0] RegAddrA;
|
reg [2:0] RegAddrB_r;
|
reg [2:0] RegAddrB_r;
|
reg [2:0] RegAddrB;
|
reg [2:0] RegAddrB;
|
reg [2:0] RegAddrC;
|
reg [2:0] RegAddrC;
|
reg RegWEH;
|
reg RegWEH;
|
reg RegWEL;
|
reg RegWEL;
|
reg Alternate;
|
reg Alternate;
|
|
|
// Help Registers
|
// Help Registers
|
reg [15:0] TmpAddr; // Temporary address register
|
reg [15:0] TmpAddr; // Temporary address register
|
reg [7:0] IR; // Instruction register
|
reg [7:0] IR; // Instruction register
|
reg [1:0] ISet; // Instruction set selector
|
reg [1:0] ISet; // Instruction set selector
|
reg [15:0] RegBusA_r;
|
reg [15:0] RegBusA_r;
|
|
|
reg [15:0] ID16;
|
reg [15:0] ID16;
|
reg [7:0] Save_Mux;
|
reg [7:0] Save_Mux;
|
|
|
reg [6:0] tstate;
|
reg [6:0] tstate;
|
reg [6:0] mcycle;
|
reg [6:0] mcycle;
|
reg last_mcycle, last_tstate;
|
reg last_mcycle, last_tstate;
|
reg IntE_FF1;
|
reg IntE_FF1;
|
reg IntE_FF2;
|
reg IntE_FF2;
|
reg Halt_FF;
|
reg Halt_FF;
|
reg BusReq_s;
|
reg BusReq_s;
|
reg BusAck;
|
reg BusAck;
|
reg ClkEn;
|
reg ClkEn;
|
reg NMI_s;
|
reg NMI_s;
|
reg INT_s;
|
reg INT_s;
|
reg [1:0] IStatus;
|
reg [1:0] IStatus;
|
|
|
reg [7:0] DI_Reg;
|
reg [7:0] DI_Reg;
|
reg T_Res;
|
reg T_Res;
|
reg [1:0] XY_State;
|
reg [1:0] XY_State;
|
reg [2:0] Pre_XY_F_M;
|
reg [2:0] Pre_XY_F_M;
|
reg NextIs_XY_Fetch;
|
reg NextIs_XY_Fetch;
|
reg XY_Ind;
|
reg XY_Ind;
|
reg No_BTR;
|
reg No_BTR;
|
reg BTR_r;
|
reg BTR_r;
|
reg Auto_Wait;
|
reg Auto_Wait;
|
reg Auto_Wait_t1;
|
reg Auto_Wait_t1;
|
reg Auto_Wait_t2;
|
reg Auto_Wait_t2;
|
reg IncDecZ;
|
reg IncDecZ;
|
|
|
// ALU signals
|
// ALU signals
|
reg [7:0] BusB;
|
reg [7:0] BusB;
|
reg [7:0] BusA;
|
reg [7:0] BusA;
|
wire [7:0] ALU_Q;
|
wire [7:0] ALU_Q;
|
wire [7:0] F_Out;
|
wire [7:0] F_Out;
|
|
|
// Registered micro code outputs
|
// Registered micro code outputs
|
reg [4:0] Read_To_Reg_r;
|
reg [4:0] Read_To_Reg_r;
|
reg Arith16_r;
|
reg Arith16_r;
|
reg Z16_r;
|
reg Z16_r;
|
reg [3:0] ALU_Op_r;
|
reg [3:0] ALU_Op_r;
|
reg Save_ALU_r;
|
reg Save_ALU_r;
|
reg PreserveC_r;
|
reg PreserveC_r;
|
reg [2:0] mcycles;
|
reg [2:0] mcycles;
|
|
|
// Micro code outputs
|
// Micro code outputs
|
wire [2:0] mcycles_d;
|
wire [2:0] mcycles_d;
|
wire [2:0] tstates;
|
wire [2:0] tstates;
|
reg IntCycle;
|
reg IntCycle;
|
reg NMICycle;
|
reg NMICycle;
|
wire Inc_PC;
|
wire Inc_PC;
|
wire Inc_WZ;
|
wire Inc_WZ;
|
wire [3:0] IncDec_16;
|
wire [3:0] IncDec_16;
|
wire [1:0] Prefix;
|
wire [1:0] Prefix;
|
wire Read_To_Acc;
|
wire Read_To_Acc;
|
wire Read_To_Reg;
|
wire Read_To_Reg;
|
wire [3:0] Set_BusB_To;
|
wire [3:0] Set_BusB_To;
|
wire [3:0] Set_BusA_To;
|
wire [3:0] Set_BusA_To;
|
wire [3:0] ALU_Op;
|
wire [3:0] ALU_Op;
|
wire Save_ALU;
|
wire Save_ALU;
|
wire PreserveC;
|
wire PreserveC;
|
wire Arith16;
|
wire Arith16;
|
wire [2:0] Set_Addr_To;
|
wire [2:0] Set_Addr_To;
|
wire Jump;
|
wire Jump;
|
wire JumpE;
|
wire JumpE;
|
wire JumpXY;
|
wire JumpXY;
|
wire Call;
|
wire Call;
|
wire RstP;
|
wire RstP;
|
wire LDZ;
|
wire LDZ;
|
wire LDW;
|
wire LDW;
|
wire LDSPHL;
|
wire LDSPHL;
|
wire iorq_i;
|
wire iorq_i;
|
wire [2:0] Special_LD;
|
wire [2:0] Special_LD;
|
wire ExchangeDH;
|
wire ExchangeDH;
|
wire ExchangeRp;
|
wire ExchangeRp;
|
wire ExchangeAF;
|
wire ExchangeAF;
|
wire ExchangeRS;
|
wire ExchangeRS;
|
wire I_DJNZ;
|
wire I_DJNZ;
|
wire I_CPL;
|
wire I_CPL;
|
wire I_CCF;
|
wire I_CCF;
|
wire I_SCF;
|
wire I_SCF;
|
wire I_RETN;
|
wire I_RETN;
|
wire I_BT;
|
wire I_BT;
|
wire I_BC;
|
wire I_BC;
|
wire I_BTR;
|
wire I_BTR;
|
wire I_RLD;
|
wire I_RLD;
|
wire I_RRD;
|
wire I_RRD;
|
wire I_INRC;
|
wire I_INRC;
|
wire SetDI;
|
wire SetDI;
|
wire SetEI;
|
wire SetEI;
|
wire [1:0] IMode;
|
wire [1:0] IMode;
|
wire Halt;
|
wire Halt;
|
|
|
reg [15:0] PC16;
|
reg [15:0] PC16;
|
reg [15:0] PC16_B;
|
reg [15:0] PC16_B;
|
reg [15:0] SP16, SP16_A, SP16_B;
|
reg [15:0] SP16, SP16_A, SP16_B;
|
reg [15:0] ID16_B;
|
reg [15:0] ID16_B;
|
reg Oldnmi_n;
|
reg Oldnmi_n;
|
|
|
tv80_mcode #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_mcode
|
tv80_mcode #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_mcode
|
(
|
(
|
.IR (IR),
|
.IR (IR),
|
.ISet (ISet),
|
.ISet (ISet),
|
.MCycle (mcycle),
|
.MCycle (mcycle),
|
.F (F),
|
.F (F),
|
.NMICycle (NMICycle),
|
.NMICycle (NMICycle),
|
.IntCycle (IntCycle),
|
.IntCycle (IntCycle),
|
.MCycles (mcycles_d),
|
.MCycles (mcycles_d),
|
.TStates (tstates),
|
.TStates (tstates),
|
.Prefix (Prefix),
|
.Prefix (Prefix),
|
.Inc_PC (Inc_PC),
|
.Inc_PC (Inc_PC),
|
.Inc_WZ (Inc_WZ),
|
.Inc_WZ (Inc_WZ),
|
.IncDec_16 (IncDec_16),
|
.IncDec_16 (IncDec_16),
|
.Read_To_Acc (Read_To_Acc),
|
.Read_To_Acc (Read_To_Acc),
|
.Read_To_Reg (Read_To_Reg),
|
.Read_To_Reg (Read_To_Reg),
|
.Set_BusB_To (Set_BusB_To),
|
.Set_BusB_To (Set_BusB_To),
|
.Set_BusA_To (Set_BusA_To),
|
.Set_BusA_To (Set_BusA_To),
|
.ALU_Op (ALU_Op),
|
.ALU_Op (ALU_Op),
|
.Save_ALU (Save_ALU),
|
.Save_ALU (Save_ALU),
|
.PreserveC (PreserveC),
|
.PreserveC (PreserveC),
|
.Arith16 (Arith16),
|
.Arith16 (Arith16),
|
.Set_Addr_To (Set_Addr_To),
|
.Set_Addr_To (Set_Addr_To),
|
.IORQ (iorq_i),
|
.IORQ (iorq_i),
|
.Jump (Jump),
|
.Jump (Jump),
|
.JumpE (JumpE),
|
.JumpE (JumpE),
|
.JumpXY (JumpXY),
|
.JumpXY (JumpXY),
|
.Call (Call),
|
.Call (Call),
|
.RstP (RstP),
|
.RstP (RstP),
|
.LDZ (LDZ),
|
.LDZ (LDZ),
|
.LDW (LDW),
|
.LDW (LDW),
|
.LDSPHL (LDSPHL),
|
.LDSPHL (LDSPHL),
|
.Special_LD (Special_LD),
|
.Special_LD (Special_LD),
|
.ExchangeDH (ExchangeDH),
|
.ExchangeDH (ExchangeDH),
|
.ExchangeRp (ExchangeRp),
|
.ExchangeRp (ExchangeRp),
|
.ExchangeAF (ExchangeAF),
|
.ExchangeAF (ExchangeAF),
|
.ExchangeRS (ExchangeRS),
|
.ExchangeRS (ExchangeRS),
|
.I_DJNZ (I_DJNZ),
|
.I_DJNZ (I_DJNZ),
|
.I_CPL (I_CPL),
|
.I_CPL (I_CPL),
|
.I_CCF (I_CCF),
|
.I_CCF (I_CCF),
|
.I_SCF (I_SCF),
|
.I_SCF (I_SCF),
|
.I_RETN (I_RETN),
|
.I_RETN (I_RETN),
|
.I_BT (I_BT),
|
.I_BT (I_BT),
|
.I_BC (I_BC),
|
.I_BC (I_BC),
|
.I_BTR (I_BTR),
|
.I_BTR (I_BTR),
|
.I_RLD (I_RLD),
|
.I_RLD (I_RLD),
|
.I_RRD (I_RRD),
|
.I_RRD (I_RRD),
|
.I_INRC (I_INRC),
|
.I_INRC (I_INRC),
|
.SetDI (SetDI),
|
.SetDI (SetDI),
|
.SetEI (SetEI),
|
.SetEI (SetEI),
|
.IMode (IMode),
|
.IMode (IMode),
|
.Halt (Halt),
|
.Halt (Halt),
|
.NoRead (no_read),
|
.NoRead (no_read),
|
.Write (write)
|
.Write (write)
|
);
|
);
|
|
|
tv80_alu #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_alu
|
tv80_alu #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_alu
|
(
|
(
|
.Arith16 (Arith16_r),
|
.Arith16 (Arith16_r),
|
.Z16 (Z16_r),
|
.Z16 (Z16_r),
|
.ALU_Op (ALU_Op_r),
|
.ALU_Op (ALU_Op_r),
|
.IR (IR[5:0]),
|
.IR (IR[5:0]),
|
.ISet (ISet),
|
.ISet (ISet),
|
.BusA (BusA),
|
.BusA (BusA),
|
.BusB (BusB),
|
.BusB (BusB),
|
.F_In (F),
|
.F_In (F),
|
.Q (ALU_Q),
|
.Q (ALU_Q),
|
.F_Out (F_Out)
|
.F_Out (F_Out)
|
);
|
);
|
|
|
function [6:0] number_to_bitvec;
|
function [6:0] number_to_bitvec;
|
input [2:0] num;
|
input [2:0] num;
|
begin
|
begin
|
case (num)
|
case (num)
|
1 : number_to_bitvec = 7'b0000001;
|
1 : number_to_bitvec = 7'b0000001;
|
2 : number_to_bitvec = 7'b0000010;
|
2 : number_to_bitvec = 7'b0000010;
|
3 : number_to_bitvec = 7'b0000100;
|
3 : number_to_bitvec = 7'b0000100;
|
4 : number_to_bitvec = 7'b0001000;
|
4 : number_to_bitvec = 7'b0001000;
|
5 : number_to_bitvec = 7'b0010000;
|
5 : number_to_bitvec = 7'b0010000;
|
6 : number_to_bitvec = 7'b0100000;
|
6 : number_to_bitvec = 7'b0100000;
|
7 : number_to_bitvec = 7'b1000000;
|
7 : number_to_bitvec = 7'b1000000;
|
default : number_to_bitvec = 7'bx;
|
default : number_to_bitvec = 7'bx;
|
endcase // case(num)
|
endcase // case(num)
|
end
|
end
|
endfunction // number_to_bitvec
|
endfunction // number_to_bitvec
|
|
|
function [2:0] mcyc_to_number;
|
function [2:0] mcyc_to_number;
|
input [6:0] mcyc;
|
input [6:0] mcyc;
|
begin
|
begin
|
casez (mcyc)
|
casez (mcyc)
|
7'b1zzzzzz : mcyc_to_number = 3'h7;
|
7'b1zzzzzz : mcyc_to_number = 3'h7;
|
7'b01zzzzz : mcyc_to_number = 3'h6;
|
7'b01zzzzz : mcyc_to_number = 3'h6;
|
7'b001zzzz : mcyc_to_number = 3'h5;
|
7'b001zzzz : mcyc_to_number = 3'h5;
|
7'b0001zzz : mcyc_to_number = 3'h4;
|
7'b0001zzz : mcyc_to_number = 3'h4;
|
7'b00001zz : mcyc_to_number = 3'h3;
|
7'b00001zz : mcyc_to_number = 3'h3;
|
7'b000001z : mcyc_to_number = 3'h2;
|
7'b000001z : mcyc_to_number = 3'h2;
|
7'b0000001 : mcyc_to_number = 3'h1;
|
7'b0000001 : mcyc_to_number = 3'h1;
|
default : mcyc_to_number = 3'h1;
|
default : mcyc_to_number = 3'h1;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
always @(/*AUTOSENSE*/mcycle or mcycles or tstate or tstates)
|
always @(/*AUTOSENSE*/mcycle or mcycles or tstate or tstates)
|
begin
|
begin
|
case (mcycles)
|
case (mcycles)
|
1 : last_mcycle = mcycle[0];
|
1 : last_mcycle = mcycle[0];
|
2 : last_mcycle = mcycle[1];
|
2 : last_mcycle = mcycle[1];
|
3 : last_mcycle = mcycle[2];
|
3 : last_mcycle = mcycle[2];
|
4 : last_mcycle = mcycle[3];
|
4 : last_mcycle = mcycle[3];
|
5 : last_mcycle = mcycle[4];
|
5 : last_mcycle = mcycle[4];
|
6 : last_mcycle = mcycle[5];
|
6 : last_mcycle = mcycle[5];
|
7 : last_mcycle = mcycle[6];
|
7 : last_mcycle = mcycle[6];
|
default : last_mcycle = 1'bx;
|
default : last_mcycle = 1'bx;
|
endcase // case(mcycles)
|
endcase // case(mcycles)
|
|
|
case (tstates)
|
case (tstates)
|
0 : last_tstate = tstate[0];
|
0 : last_tstate = tstate[0];
|
1 : last_tstate = tstate[1];
|
1 : last_tstate = tstate[1];
|
2 : last_tstate = tstate[2];
|
2 : last_tstate = tstate[2];
|
3 : last_tstate = tstate[3];
|
3 : last_tstate = tstate[3];
|
4 : last_tstate = tstate[4];
|
4 : last_tstate = tstate[4];
|
5 : last_tstate = tstate[5];
|
5 : last_tstate = tstate[5];
|
6 : last_tstate = tstate[6];
|
6 : last_tstate = tstate[6];
|
default : last_tstate = 1'bx;
|
default : last_tstate = 1'bx;
|
endcase
|
endcase
|
end // always @ (...
|
end // always @ (...
|
|
|
|
|
always @(/*AUTOSENSE*/ALU_Q or BusAck or BusB or DI_Reg
|
always @(/*AUTOSENSE*/ALU_Q or BusAck or BusB or DI_Reg
|
or ExchangeRp or IR or Save_ALU_r or Set_Addr_To or XY_Ind
|
or ExchangeRp or IR or Save_ALU_r or Set_Addr_To or XY_Ind
|
or XY_State or cen or last_tstate or mcycle)
|
or XY_State or cen or last_tstate or mcycle)
|
begin
|
begin
|
ClkEn = cen && ~ BusAck;
|
ClkEn = cen && ~ BusAck;
|
|
|
if (last_tstate)
|
if (last_tstate)
|
T_Res = 1'b1;
|
T_Res = 1'b1;
|
else T_Res = 1'b0;
|
else T_Res = 1'b0;
|
|
|
if (XY_State != 2'b00 && XY_Ind == 1'b0 &&
|
if (XY_State != 2'b00 && XY_Ind == 1'b0 &&
|
((Set_Addr_To == aXY) ||
|
((Set_Addr_To == aXY) ||
|
(mcycle[0] && IR == 8'b11001011) ||
|
(mcycle[0] && IR == 8'b11001011) ||
|
(mcycle[0] && IR == 8'b00110110)))
|
(mcycle[0] && IR == 8'b00110110)))
|
NextIs_XY_Fetch = 1'b1;
|
NextIs_XY_Fetch = 1'b1;
|
else
|
else
|
NextIs_XY_Fetch = 1'b0;
|
NextIs_XY_Fetch = 1'b0;
|
|
|
if (ExchangeRp)
|
if (ExchangeRp)
|
Save_Mux = BusB;
|
Save_Mux = BusB;
|
else if (!Save_ALU_r)
|
else if (!Save_ALU_r)
|
Save_Mux = DI_Reg;
|
Save_Mux = DI_Reg;
|
else
|
else
|
Save_Mux = ALU_Q;
|
Save_Mux = ALU_Q;
|
end // always @ *
|
end // always @ *
|
|
|
always @ (posedge clk or negedge reset_n)
|
always @ (posedge clk or negedge reset_n)
|
begin
|
begin
|
if (reset_n == 1'b0 )
|
if (reset_n == 1'b0 )
|
begin
|
begin
|
PC <= #1 0; // Program Counter
|
PC <= #1 0; // Program Counter
|
A <= #1 0;
|
A <= #1 0;
|
TmpAddr <= #1 0;
|
TmpAddr <= #1 0;
|
IR <= #1 8'b00000000;
|
IR <= #1 8'b00000000;
|
ISet <= #1 2'b00;
|
ISet <= #1 2'b00;
|
XY_State <= #1 2'b00;
|
XY_State <= #1 2'b00;
|
IStatus <= #1 2'b00;
|
IStatus <= #1 2'b00;
|
mcycles <= #1 3'b000;
|
mcycles <= #1 3'b000;
|
dout <= #1 8'b00000000;
|
dout <= #1 8'b00000000;
|
|
|
ACC <= #1 8'hFF;
|
ACC <= #1 8'hFF;
|
F <= #1 8'hFF;
|
F <= #1 8'hFF;
|
Ap <= #1 8'hFF;
|
Ap <= #1 8'hFF;
|
Fp <= #1 8'hFF;
|
Fp <= #1 8'hFF;
|
I <= #1 0;
|
I <= #1 0;
|
`ifdef TV80_REFRESH
|
`ifdef TV80_REFRESH
|
R <= #1 0;
|
R <= #1 0;
|
`endif
|
`endif
|
SP <= #1 16'hFFFF;
|
SP <= #1 16'hFFFF;
|
Alternate <= #1 1'b0;
|
Alternate <= #1 1'b0;
|
|
|
Read_To_Reg_r <= #1 5'b00000;
|
Read_To_Reg_r <= #1 5'b00000;
|
Arith16_r <= #1 1'b0;
|
Arith16_r <= #1 1'b0;
|
BTR_r <= #1 1'b0;
|
BTR_r <= #1 1'b0;
|
Z16_r <= #1 1'b0;
|
Z16_r <= #1 1'b0;
|
ALU_Op_r <= #1 4'b0000;
|
ALU_Op_r <= #1 4'b0000;
|
Save_ALU_r <= #1 1'b0;
|
Save_ALU_r <= #1 1'b0;
|
PreserveC_r <= #1 1'b0;
|
PreserveC_r <= #1 1'b0;
|
XY_Ind <= #1 1'b0;
|
XY_Ind <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
|
|
if (ClkEn == 1'b1 )
|
if (ClkEn == 1'b1 )
|
begin
|
begin
|
|
|
ALU_Op_r <= #1 4'b0000;
|
ALU_Op_r <= #1 4'b0000;
|
Save_ALU_r <= #1 1'b0;
|
Save_ALU_r <= #1 1'b0;
|
Read_To_Reg_r <= #1 5'b00000;
|
Read_To_Reg_r <= #1 5'b00000;
|
|
|
mcycles <= #1 mcycles_d;
|
mcycles <= #1 mcycles_d;
|
|
|
if (IMode != 2'b11 )
|
if (IMode != 2'b11 )
|
begin
|
begin
|
IStatus <= #1 IMode;
|
IStatus <= #1 IMode;
|
end
|
end
|
|
|
Arith16_r <= #1 Arith16;
|
Arith16_r <= #1 Arith16;
|
PreserveC_r <= #1 PreserveC;
|
PreserveC_r <= #1 PreserveC;
|
if (ISet == 2'b10 && ALU_Op[2] == 1'b0 && ALU_Op[0] == 1'b1 && mcycle[2] )
|
if (ISet == 2'b10 && ALU_Op[2] == 1'b0 && ALU_Op[0] == 1'b1 && mcycle[2] )
|
begin
|
begin
|
Z16_r <= #1 1'b1;
|
Z16_r <= #1 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
Z16_r <= #1 1'b0;
|
Z16_r <= #1 1'b0;
|
end
|
end
|
|
|
if (mcycle[0] && (tstate[1] | tstate[2] | tstate[3] ))
|
if (mcycle[0] && (tstate[1] | tstate[2] | tstate[3] ))
|
begin
|
begin
|
// mcycle == 1 && tstate == 1, 2, || 3
|
// mcycle == 1 && tstate == 1, 2, || 3
|
if (tstate[2] && wait_n == 1'b1 )
|
if (tstate[2] && wait_n == 1'b1 )
|
begin
|
begin
|
`ifdef TV80_REFRESH
|
`ifdef TV80_REFRESH
|
if (Mode < 2 )
|
if (Mode < 2 )
|
begin
|
begin
|
A[7:0] <= #1 R;
|
A[7:0] <= #1 R;
|
A[15:8] <= #1 I;
|
A[15:8] <= #1 I;
|
R[6:0] <= #1 R[6:0] + 1;
|
R[6:0] <= #1 R[6:0] + 1;
|
end
|
end
|
`endif
|
`endif
|
if (Jump == 1'b0 && Call == 1'b0 && NMICycle == 1'b0 && IntCycle == 1'b0 && ~ (Halt_FF == 1'b1 || Halt == 1'b1) )
|
if (Jump == 1'b0 && Call == 1'b0 && NMICycle == 1'b0 && IntCycle == 1'b0 && ~ (Halt_FF == 1'b1 || Halt == 1'b1) )
|
begin
|
begin
|
PC <= #1 PC16;
|
PC <= #1 PC16;
|
end
|
end
|
|
|
if (IntCycle == 1'b1 && IStatus == 2'b01 )
|
if (IntCycle == 1'b1 && IStatus == 2'b01 )
|
begin
|
begin
|
IR <= #1 8'b11111111;
|
IR <= #1 8'b11111111;
|
end
|
end
|
else if (Halt_FF == 1'b1 || (IntCycle == 1'b1 && IStatus == 2'b10) || NMICycle == 1'b1 )
|
else if (Halt_FF == 1'b1 || (IntCycle == 1'b1 && IStatus == 2'b10) || NMICycle == 1'b1 )
|
begin
|
begin
|
IR <= #1 8'b00000000;
|
IR <= #1 8'b00000000;
|
TmpAddr[7:0] <= #1 dinst; // Special M1 vector fetch
|
TmpAddr[7:0] <= #1 dinst; // Special M1 vector fetch
|
end
|
end
|
else
|
else
|
begin
|
begin
|
IR <= #1 dinst;
|
IR <= #1 dinst;
|
end
|
end
|
|
|
ISet <= #1 2'b00;
|
ISet <= #1 2'b00;
|
if (Prefix != 2'b00 )
|
if (Prefix != 2'b00 )
|
begin
|
begin
|
if (Prefix == 2'b11 )
|
if (Prefix == 2'b11 )
|
begin
|
begin
|
if (IR[5] == 1'b1 )
|
if (IR[5] == 1'b1 )
|
begin
|
begin
|
XY_State <= #1 2'b10;
|
XY_State <= #1 2'b10;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
XY_State <= #1 2'b01;
|
XY_State <= #1 2'b01;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (Prefix == 2'b10 )
|
if (Prefix == 2'b10 )
|
begin
|
begin
|
XY_State <= #1 2'b00;
|
XY_State <= #1 2'b00;
|
XY_Ind <= #1 1'b0;
|
XY_Ind <= #1 1'b0;
|
end
|
end
|
ISet <= #1 Prefix;
|
ISet <= #1 Prefix;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
XY_State <= #1 2'b00;
|
XY_State <= #1 2'b00;
|
XY_Ind <= #1 1'b0;
|
XY_Ind <= #1 1'b0;
|
end
|
end
|
end // if (tstate == 2 && wait_n == 1'b1 )
|
end // if (tstate == 2 && wait_n == 1'b1 )
|
|
|
|
|
end
|
end
|
else
|
else
|
begin
|
begin
|
// either (mcycle > 1) OR (mcycle == 1 AND tstate > 3)
|
// either (mcycle > 1) OR (mcycle == 1 AND tstate > 3)
|
|
|
if (mcycle[5] )
|
if (mcycle[5] )
|
begin
|
begin
|
XY_Ind <= #1 1'b1;
|
XY_Ind <= #1 1'b1;
|
if (Prefix == 2'b01 )
|
if (Prefix == 2'b01 )
|
begin
|
begin
|
ISet <= #1 2'b01;
|
ISet <= #1 2'b01;
|
end
|
end
|
end
|
end
|
|
|
if (T_Res == 1'b1 )
|
if (T_Res == 1'b1 )
|
begin
|
begin
|
BTR_r <= #1 (I_BT || I_BC || I_BTR) && ~ No_BTR;
|
BTR_r <= #1 (I_BT || I_BC || I_BTR) && ~ No_BTR;
|
if (Jump == 1'b1 )
|
if (Jump == 1'b1 )
|
begin
|
begin
|
A[15:8] <= #1 DI_Reg;
|
A[15:8] <= #1 DI_Reg;
|
A[7:0] <= #1 TmpAddr[7:0];
|
A[7:0] <= #1 TmpAddr[7:0];
|
PC[15:8] <= #1 DI_Reg;
|
PC[15:8] <= #1 DI_Reg;
|
PC[7:0] <= #1 TmpAddr[7:0];
|
PC[7:0] <= #1 TmpAddr[7:0];
|
end
|
end
|
else if (JumpXY == 1'b1 )
|
else if (JumpXY == 1'b1 )
|
begin
|
begin
|
A <= #1 RegBusC;
|
A <= #1 RegBusC;
|
PC <= #1 RegBusC;
|
PC <= #1 RegBusC;
|
end else if (Call == 1'b1 || RstP == 1'b1 )
|
end else if (Call == 1'b1 || RstP == 1'b1 )
|
begin
|
begin
|
A <= #1 TmpAddr;
|
A <= #1 TmpAddr;
|
PC <= #1 TmpAddr;
|
PC <= #1 TmpAddr;
|
end
|
end
|
else if (last_mcycle && NMICycle == 1'b1 )
|
else if (last_mcycle && NMICycle == 1'b1 )
|
begin
|
begin
|
A <= #1 16'b0000000001100110;
|
A <= #1 16'b0000000001100110;
|
PC <= #1 16'b0000000001100110;
|
PC <= #1 16'b0000000001100110;
|
end
|
end
|
else if (mcycle[2] && IntCycle == 1'b1 && IStatus == 2'b10 )
|
else if (mcycle[2] && IntCycle == 1'b1 && IStatus == 2'b10 )
|
begin
|
begin
|
A[15:8] <= #1 I;
|
A[15:8] <= #1 I;
|
A[7:0] <= #1 TmpAddr[7:0];
|
A[7:0] <= #1 TmpAddr[7:0];
|
PC[15:8] <= #1 I;
|
PC[15:8] <= #1 I;
|
PC[7:0] <= #1 TmpAddr[7:0];
|
PC[7:0] <= #1 TmpAddr[7:0];
|
end
|
end
|
else
|
else
|
begin
|
begin
|
case (Set_Addr_To)
|
case (Set_Addr_To)
|
aXY :
|
aXY :
|
begin
|
begin
|
if (XY_State == 2'b00 )
|
if (XY_State == 2'b00 )
|
begin
|
begin
|
A <= #1 RegBusC;
|
A <= #1 RegBusC;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (NextIs_XY_Fetch == 1'b1 )
|
if (NextIs_XY_Fetch == 1'b1 )
|
begin
|
begin
|
A <= #1 PC;
|
A <= #1 PC;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
A <= #1 TmpAddr;
|
A <= #1 TmpAddr;
|
end
|
end
|
end // else: !if(XY_State == 2'b00 )
|
end // else: !if(XY_State == 2'b00 )
|
end // case: aXY
|
end // case: aXY
|
|
|
aIOA :
|
aIOA :
|
begin
|
begin
|
if (Mode == 3 )
|
if (Mode == 3 )
|
begin
|
begin
|
// Memory map I/O on GBZ80
|
// Memory map I/O on GBZ80
|
A[15:8] <= #1 8'hFF;
|
A[15:8] <= #1 8'hFF;
|
end
|
end
|
else if (Mode == 2 )
|
else if (Mode == 2 )
|
begin
|
begin
|
// Duplicate I/O address on 8080
|
// Duplicate I/O address on 8080
|
A[15:8] <= #1 DI_Reg;
|
A[15:8] <= #1 DI_Reg;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
A[15:8] <= #1 ACC;
|
A[15:8] <= #1 ACC;
|
end
|
end
|
A[7:0] <= #1 DI_Reg;
|
A[7:0] <= #1 DI_Reg;
|
end // case: aIOA
|
end // case: aIOA
|
|
|
|
|
aSP :
|
aSP :
|
begin
|
begin
|
A <= #1 SP;
|
A <= #1 SP;
|
end
|
end
|
|
|
aBC :
|
aBC :
|
begin
|
begin
|
if (Mode == 3 && iorq_i == 1'b1 )
|
if (Mode == 3 && iorq_i == 1'b1 )
|
begin
|
begin
|
// Memory map I/O on GBZ80
|
// Memory map I/O on GBZ80
|
A[15:8] <= #1 8'hFF;
|
A[15:8] <= #1 8'hFF;
|
A[7:0] <= #1 RegBusC[7:0];
|
A[7:0] <= #1 RegBusC[7:0];
|
end
|
end
|
else
|
else
|
begin
|
begin
|
A <= #1 RegBusC;
|
A <= #1 RegBusC;
|
end
|
end
|
end // case: aBC
|
end // case: aBC
|
|
|
aDE :
|
aDE :
|
begin
|
begin
|
A <= #1 RegBusC;
|
A <= #1 RegBusC;
|
end
|
end
|
|
|
aZI :
|
aZI :
|
begin
|
begin
|
if (Inc_WZ == 1'b1 )
|
if (Inc_WZ == 1'b1 )
|
begin
|
begin
|
A <= #1 TmpAddr + 1;
|
A <= #1 TmpAddr + 1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
A[15:8] <= #1 DI_Reg;
|
A[15:8] <= #1 DI_Reg;
|
A[7:0] <= #1 TmpAddr[7:0];
|
A[7:0] <= #1 TmpAddr[7:0];
|
end
|
end
|
end // case: aZI
|
end // case: aZI
|
|
|
default :
|
default :
|
begin
|
begin
|
A <= #1 PC;
|
A <= #1 PC;
|
end
|
end
|
endcase // case(Set_Addr_To)
|
endcase // case(Set_Addr_To)
|
|
|
end // else: !if(mcycle[2] && IntCycle == 1'b1 && IStatus == 2'b10 )
|
end // else: !if(mcycle[2] && IntCycle == 1'b1 && IStatus == 2'b10 )
|
|
|
|
|
Save_ALU_r <= #1 Save_ALU;
|
Save_ALU_r <= #1 Save_ALU;
|
ALU_Op_r <= #1 ALU_Op;
|
ALU_Op_r <= #1 ALU_Op;
|
|
|
if (I_CPL == 1'b1 )
|
if (I_CPL == 1'b1 )
|
begin
|
begin
|
// CPL
|
// CPL
|
ACC <= #1 ~ ACC;
|
ACC <= #1 ~ ACC;
|
F[Flag_Y] <= #1 ~ ACC[5];
|
F[Flag_Y] <= #1 ~ ACC[5];
|
F[Flag_H] <= #1 1'b1;
|
F[Flag_H] <= #1 1'b1;
|
F[Flag_X] <= #1 ~ ACC[3];
|
F[Flag_X] <= #1 ~ ACC[3];
|
F[Flag_N] <= #1 1'b1;
|
F[Flag_N] <= #1 1'b1;
|
end
|
end
|
if (I_CCF == 1'b1 )
|
if (I_CCF == 1'b1 )
|
begin
|
begin
|
// CCF
|
// CCF
|
F[Flag_C] <= #1 ~ F[Flag_C];
|
F[Flag_C] <= #1 ~ F[Flag_C];
|
F[Flag_Y] <= #1 ACC[5];
|
F[Flag_Y] <= #1 ACC[5];
|
F[Flag_H] <= #1 F[Flag_C];
|
F[Flag_H] <= #1 F[Flag_C];
|
F[Flag_X] <= #1 ACC[3];
|
F[Flag_X] <= #1 ACC[3];
|
F[Flag_N] <= #1 1'b0;
|
F[Flag_N] <= #1 1'b0;
|
end
|
end
|
if (I_SCF == 1'b1 )
|
if (I_SCF == 1'b1 )
|
begin
|
begin
|
// SCF
|
// SCF
|
F[Flag_C] <= #1 1'b1;
|
F[Flag_C] <= #1 1'b1;
|
F[Flag_Y] <= #1 ACC[5];
|
F[Flag_Y] <= #1 ACC[5];
|
F[Flag_H] <= #1 1'b0;
|
F[Flag_H] <= #1 1'b0;
|
F[Flag_X] <= #1 ACC[3];
|
F[Flag_X] <= #1 ACC[3];
|
F[Flag_N] <= #1 1'b0;
|
F[Flag_N] <= #1 1'b0;
|
end
|
end
|
end // if (T_Res == 1'b1 )
|
end // if (T_Res == 1'b1 )
|
|
|
|
|
if (tstate[2] && wait_n == 1'b1 )
|
if (tstate[2] && wait_n == 1'b1 )
|
begin
|
begin
|
if (ISet == 2'b01 && mcycle[6] )
|
if (ISet == 2'b01 && mcycle[6] )
|
begin
|
begin
|
IR <= #1 dinst;
|
IR <= #1 dinst;
|
end
|
end
|
if (JumpE == 1'b1 )
|
if (JumpE == 1'b1 )
|
begin
|
begin
|
PC <= #1 PC16;
|
PC <= #1 PC16;
|
end
|
end
|
else if (Inc_PC == 1'b1 )
|
else if (Inc_PC == 1'b1 )
|
begin
|
begin
|
//PC <= #1 PC + 1;
|
//PC <= #1 PC + 1;
|
PC <= #1 PC16;
|
PC <= #1 PC16;
|
end
|
end
|
if (BTR_r == 1'b1 )
|
if (BTR_r == 1'b1 )
|
begin
|
begin
|
//PC <= #1 PC - 2;
|
//PC <= #1 PC - 2;
|
PC <= #1 PC16;
|
PC <= #1 PC16;
|
end
|
end
|
if (RstP == 1'b1 )
|
if (RstP == 1'b1 )
|
begin
|
begin
|
TmpAddr <= #1 { 10'h0, IR[5:3], 3'h0 };
|
TmpAddr <= #1 { 10'h0, IR[5:3], 3'h0 };
|
//TmpAddr <= #1 (others =>1'b0);
|
//TmpAddr <= #1 (others =>1'b0);
|
//TmpAddr[5:3] <= #1 IR[5:3];
|
//TmpAddr[5:3] <= #1 IR[5:3];
|
end
|
end
|
end
|
end
|
if (tstate[3] && mcycle[5] )
|
if (tstate[3] && mcycle[5] )
|
begin
|
begin
|
TmpAddr <= #1 SP16;
|
TmpAddr <= #1 SP16;
|
end
|
end
|
|
|
if ((tstate[2] && wait_n == 1'b1) || (tstate[4] && mcycle[0]) )
|
if ((tstate[2] && wait_n == 1'b1) || (tstate[4] && mcycle[0]) )
|
begin
|
begin
|
if (IncDec_16[2:0] == 3'b111 )
|
if (IncDec_16[2:0] == 3'b111 )
|
begin
|
begin
|
SP <= #1 SP16;
|
SP <= #1 SP16;
|
end
|
end
|
end
|
end
|
|
|
if (LDSPHL == 1'b1 )
|
if (LDSPHL == 1'b1 )
|
begin
|
begin
|
SP <= #1 RegBusC;
|
SP <= #1 RegBusC;
|
end
|
end
|
if (ExchangeAF == 1'b1 )
|
if (ExchangeAF == 1'b1 )
|
begin
|
begin
|
Ap <= #1 ACC;
|
Ap <= #1 ACC;
|
ACC <= #1 Ap;
|
ACC <= #1 Ap;
|
Fp <= #1 F;
|
Fp <= #1 F;
|
F <= #1 Fp;
|
F <= #1 Fp;
|
end
|
end
|
if (ExchangeRS == 1'b1 )
|
if (ExchangeRS == 1'b1 )
|
begin
|
begin
|
Alternate <= #1 ~ Alternate;
|
Alternate <= #1 ~ Alternate;
|
end
|
end
|
end // else: !if(mcycle == 3'b001 && tstate(2) == 1'b0 )
|
end // else: !if(mcycle == 3'b001 && tstate(2) == 1'b0 )
|
|
|
|
|
if (tstate[3] )
|
if (tstate[3] )
|
begin
|
begin
|
if (LDZ == 1'b1 )
|
if (LDZ == 1'b1 )
|
begin
|
begin
|
TmpAddr[7:0] <= #1 DI_Reg;
|
TmpAddr[7:0] <= #1 DI_Reg;
|
end
|
end
|
if (LDW == 1'b1 )
|
if (LDW == 1'b1 )
|
begin
|
begin
|
TmpAddr[15:8] <= #1 DI_Reg;
|
TmpAddr[15:8] <= #1 DI_Reg;
|
end
|
end
|
|
|
if (Special_LD[2] == 1'b1 )
|
if (Special_LD[2] == 1'b1 )
|
begin
|
begin
|
case (Special_LD[1:0])
|
case (Special_LD[1:0])
|
2'b00 :
|
2'b00 :
|
begin
|
begin
|
ACC <= #1 I;
|
ACC <= #1 I;
|
F[Flag_P] <= #1 IntE_FF2;
|
F[Flag_P] <= #1 IntE_FF2;
|
F[Flag_Z] <= (I == 0);
|
F[Flag_Z] <= (I == 0);
|
F[Flag_S] <= I[7];
|
F[Flag_S] <= I[7];
|
F[Flag_H] <= 0;
|
F[Flag_H] <= 0;
|
F[Flag_N] <= 0;
|
F[Flag_N] <= 0;
|
end
|
end
|
|
|
2'b01 :
|
2'b01 :
|
begin
|
begin
|
`ifdef TV80_REFRESH
|
`ifdef TV80_REFRESH
|
ACC <= #1 R;
|
ACC <= #1 R;
|
`else
|
`else
|
ACC <= #1 0;
|
ACC <= #1 0;
|
`endif
|
`endif
|
F[Flag_P] <= #1 IntE_FF2;
|
F[Flag_P] <= #1 IntE_FF2;
|
F[Flag_Z] <= (I == 0);
|
F[Flag_Z] <= (I == 0);
|
F[Flag_S] <= I[7];
|
F[Flag_S] <= I[7];
|
F[Flag_H] <= 0;
|
F[Flag_H] <= 0;
|
F[Flag_N] <= 0;
|
F[Flag_N] <= 0;
|
end
|
end
|
|
|
2'b10 :
|
2'b10 :
|
I <= #1 ACC;
|
I <= #1 ACC;
|
|
|
`ifdef TV80_REFRESH
|
`ifdef TV80_REFRESH
|
default :
|
default :
|
R <= #1 ACC;
|
R <= #1 ACC;
|
`else
|
`else
|
default : ;
|
default : ;
|
`endif
|
`endif
|
endcase
|
endcase
|
end
|
end
|
end // if (tstate == 3 )
|
end // if (tstate == 3 )
|
|
|
|
|
if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 )
|
if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 )
|
begin
|
begin
|
if (Mode == 3 )
|
if (Mode == 3 )
|
begin
|
begin
|
F[6] <= #1 F_Out[6];
|
F[6] <= #1 F_Out[6];
|
F[5] <= #1 F_Out[5];
|
F[5] <= #1 F_Out[5];
|
F[7] <= #1 F_Out[7];
|
F[7] <= #1 F_Out[7];
|
if (PreserveC_r == 1'b0 )
|
if (PreserveC_r == 1'b0 )
|
begin
|
begin
|
F[4] <= #1 F_Out[4];
|
F[4] <= #1 F_Out[4];
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
F[7:1] <= #1 F_Out[7:1];
|
F[7:1] <= #1 F_Out[7:1];
|
if (PreserveC_r == 1'b0 )
|
if (PreserveC_r == 1'b0 )
|
begin
|
begin
|
F[Flag_C] <= #1 F_Out[0];
|
F[Flag_C] <= #1 F_Out[0];
|
end
|
end
|
end
|
end
|
end // if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 )
|
end // if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 )
|
|
|
if (T_Res == 1'b1 && I_INRC == 1'b1 )
|
if (T_Res == 1'b1 && I_INRC == 1'b1 )
|
begin
|
begin
|
F[Flag_H] <= #1 1'b0;
|
F[Flag_H] <= #1 1'b0;
|
F[Flag_N] <= #1 1'b0;
|
F[Flag_N] <= #1 1'b0;
|
if (DI_Reg[7:0] == 8'b00000000 )
|
if (DI_Reg[7:0] == 8'b00000000 )
|
begin
|
begin
|
F[Flag_Z] <= #1 1'b1;
|
F[Flag_Z] <= #1 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
F[Flag_Z] <= #1 1'b0;
|
F[Flag_Z] <= #1 1'b0;
|
end
|
end
|
F[Flag_S] <= #1 DI_Reg[7];
|
F[Flag_S] <= #1 DI_Reg[7];
|
F[Flag_P] <= #1 ~ (^DI_Reg[7:0]);
|
F[Flag_P] <= #1 ~ (^DI_Reg[7:0]);
|
end // if (T_Res == 1'b1 && I_INRC == 1'b1 )
|
end // if (T_Res == 1'b1 && I_INRC == 1'b1 )
|
|
|
|
|
if (tstate[1] && Auto_Wait_t1 == 1'b0 )
|
if (tstate[1] && Auto_Wait_t1 == 1'b0 )
|
begin
|
begin
|
dout <= #1 BusB;
|
dout <= #1 BusB;
|
if (I_RLD == 1'b1 )
|
if (I_RLD == 1'b1 )
|
begin
|
begin
|
dout[3:0] <= #1 BusA[3:0];
|
dout[3:0] <= #1 BusA[3:0];
|
dout[7:4] <= #1 BusB[3:0];
|
dout[7:4] <= #1 BusB[3:0];
|
end
|
end
|
if (I_RRD == 1'b1 )
|
if (I_RRD == 1'b1 )
|
begin
|
begin
|
dout[3:0] <= #1 BusB[7:4];
|
dout[3:0] <= #1 BusB[7:4];
|
dout[7:4] <= #1 BusA[3:0];
|
dout[7:4] <= #1 BusA[3:0];
|
end
|
end
|
end
|
end
|
|
|
if (T_Res == 1'b1 )
|
if (T_Res == 1'b1 )
|
begin
|
begin
|
Read_To_Reg_r[3:0] <= #1 Set_BusA_To;
|
Read_To_Reg_r[3:0] <= #1 Set_BusA_To;
|
Read_To_Reg_r[4] <= #1 Read_To_Reg;
|
Read_To_Reg_r[4] <= #1 Read_To_Reg;
|
if (Read_To_Acc == 1'b1 )
|
if (Read_To_Acc == 1'b1 )
|
begin
|
begin
|
Read_To_Reg_r[3:0] <= #1 4'b0111;
|
Read_To_Reg_r[3:0] <= #1 4'b0111;
|
Read_To_Reg_r[4] <= #1 1'b1;
|
Read_To_Reg_r[4] <= #1 1'b1;
|
end
|
end
|
end
|
end
|
|
|
if (tstate[1] && I_BT == 1'b1 )
|
if (tstate[1] && I_BT == 1'b1 )
|
begin
|
begin
|
F[Flag_X] <= #1 ALU_Q[3];
|
F[Flag_X] <= #1 ALU_Q[3];
|
F[Flag_Y] <= #1 ALU_Q[1];
|
F[Flag_Y] <= #1 ALU_Q[1];
|
F[Flag_H] <= #1 1'b0;
|
F[Flag_H] <= #1 1'b0;
|
F[Flag_N] <= #1 1'b0;
|
F[Flag_N] <= #1 1'b0;
|
end
|
end
|
if (I_BC == 1'b1 || I_BT == 1'b1 )
|
if (I_BC == 1'b1 || I_BT == 1'b1 )
|
begin
|
begin
|
F[Flag_P] <= #1 IncDecZ;
|
F[Flag_P] <= #1 IncDecZ;
|
end
|
end
|
|
|
if ((tstate[1] && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||
|
if ((tstate[1] && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||
|
(Save_ALU_r == 1'b1 && ALU_Op_r != 4'b0111) )
|
(Save_ALU_r == 1'b1 && ALU_Op_r != 4'b0111) )
|
begin
|
begin
|
case (Read_To_Reg_r)
|
case (Read_To_Reg_r)
|
5'b10111 :
|
5'b10111 :
|
ACC <= #1 Save_Mux;
|
ACC <= #1 Save_Mux;
|
5'b10110 :
|
5'b10110 :
|
dout <= #1 Save_Mux;
|
dout <= #1 Save_Mux;
|
5'b11000 :
|
5'b11000 :
|
SP[7:0] <= #1 Save_Mux;
|
SP[7:0] <= #1 Save_Mux;
|
5'b11001 :
|
5'b11001 :
|
SP[15:8] <= #1 Save_Mux;
|
SP[15:8] <= #1 Save_Mux;
|
5'b11011 :
|
5'b11011 :
|
F <= #1 Save_Mux;
|
F <= #1 Save_Mux;
|
default : ;
|
default : ;
|
endcase
|
endcase
|
end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||...
|
end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||...
|
end // if (ClkEn == 1'b1 )
|
end // if (ClkEn == 1'b1 )
|
end // else: !if(reset_n == 1'b0 )
|
end // else: !if(reset_n == 1'b0 )
|
end
|
end
|
|
|
|
|
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
//
|
//
|
// BC('), DE('), HL('), IX && IY
|
// BC('), DE('), HL('), IX && IY
|
//
|
//
|
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (ClkEn == 1'b1 )
|
if (ClkEn == 1'b1 )
|
begin
|
begin
|
// Bus A / Write
|
// Bus A / Write
|
RegAddrA_r <= #1 { Alternate, Set_BusA_To[2:1] };
|
RegAddrA_r <= #1 { Alternate, Set_BusA_To[2:1] };
|
if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusA_To[2:1] == 2'b10 )
|
if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusA_To[2:1] == 2'b10 )
|
begin
|
begin
|
RegAddrA_r <= #1 { XY_State[1], 2'b11 };
|
RegAddrA_r <= #1 { XY_State[1], 2'b11 };
|
end
|
end
|
|
|
// Bus B
|
// Bus B
|
RegAddrB_r <= #1 { Alternate, Set_BusB_To[2:1] };
|
RegAddrB_r <= #1 { Alternate, Set_BusB_To[2:1] };
|
if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusB_To[2:1] == 2'b10 )
|
if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusB_To[2:1] == 2'b10 )
|
begin
|
begin
|
RegAddrB_r <= #1 { XY_State[1], 2'b11 };
|
RegAddrB_r <= #1 { XY_State[1], 2'b11 };
|
end
|
end
|
|
|
// Address from register
|
// Address from register
|
RegAddrC <= #1 { Alternate, Set_Addr_To[1:0] };
|
RegAddrC <= #1 { Alternate, Set_Addr_To[1:0] };
|
// Jump (HL), LD SP,HL
|
// Jump (HL), LD SP,HL
|
if ((JumpXY == 1'b1 || LDSPHL == 1'b1) )
|
if ((JumpXY == 1'b1 || LDSPHL == 1'b1) )
|
begin
|
begin
|
RegAddrC <= #1 { Alternate, 2'b10 };
|
RegAddrC <= #1 { Alternate, 2'b10 };
|
end
|
end
|
if (((JumpXY == 1'b1 || LDSPHL == 1'b1) && XY_State != 2'b00) || (mcycle[5]) )
|
if (((JumpXY == 1'b1 || LDSPHL == 1'b1) && XY_State != 2'b00) || (mcycle[5]) )
|
begin
|
begin
|
RegAddrC <= #1 { XY_State[1], 2'b11 };
|
RegAddrC <= #1 { XY_State[1], 2'b11 };
|
end
|
end
|
|
|
if (I_DJNZ == 1'b1 && Save_ALU_r == 1'b1 && Mode < 2 )
|
if (I_DJNZ == 1'b1 && Save_ALU_r == 1'b1 && Mode < 2 )
|
begin
|
begin
|
IncDecZ <= #1 F_Out[Flag_Z];
|
IncDecZ <= #1 F_Out[Flag_Z];
|
end
|
end
|
if ((tstate[2] || (tstate[3] && mcycle[0])) && IncDec_16[2:0] == 3'b100 )
|
if ((tstate[2] || (tstate[3] && mcycle[0])) && IncDec_16[2:0] == 3'b100 )
|
begin
|
begin
|
if (ID16 == 0 )
|
if (ID16 == 0 )
|
begin
|
begin
|
IncDecZ <= #1 1'b0;
|
IncDecZ <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
IncDecZ <= #1 1'b1;
|
IncDecZ <= #1 1'b1;
|
end
|
end
|
end
|
end
|
|
|
RegBusA_r <= #1 RegBusA;
|
RegBusA_r <= #1 RegBusA;
|
end
|
end
|
|
|
end // always @ (posedge clk)
|
end // always @ (posedge clk)
|
|
|
|
|
always @(/*AUTOSENSE*/Alternate or ExchangeDH or IncDec_16
|
always @(/*AUTOSENSE*/Alternate or ExchangeDH or IncDec_16
|
or RegAddrA_r or RegAddrB_r or XY_State or mcycle or tstate)
|
or RegAddrA_r or RegAddrB_r or XY_State or mcycle or tstate)
|
begin
|
begin
|
if ((tstate[2] || (tstate[3] && mcycle[0] && IncDec_16[2] == 1'b1)) && XY_State == 2'b00)
|
if ((tstate[2] || (tstate[3] && mcycle[0] && IncDec_16[2] == 1'b1)) && XY_State == 2'b00)
|
RegAddrA = { Alternate, IncDec_16[1:0] };
|
RegAddrA = { Alternate, IncDec_16[1:0] };
|
else if ((tstate[2] || (tstate[3] && mcycle[0] && IncDec_16[2] == 1'b1)) && IncDec_16[1:0] == 2'b10)
|
else if ((tstate[2] || (tstate[3] && mcycle[0] && IncDec_16[2] == 1'b1)) && IncDec_16[1:0] == 2'b10)
|
RegAddrA = { XY_State[1], 2'b11 };
|
RegAddrA = { XY_State[1], 2'b11 };
|
else if (ExchangeDH == 1'b1 && tstate[3])
|
else if (ExchangeDH == 1'b1 && tstate[3])
|
RegAddrA = { Alternate, 2'b10 };
|
RegAddrA = { Alternate, 2'b10 };
|
else if (ExchangeDH == 1'b1 && tstate[4])
|
else if (ExchangeDH == 1'b1 && tstate[4])
|
RegAddrA = { Alternate, 2'b01 };
|
RegAddrA = { Alternate, 2'b01 };
|
else
|
else
|
RegAddrA = RegAddrA_r;
|
RegAddrA = RegAddrA_r;
|
|
|
if (ExchangeDH == 1'b1 && tstate[3])
|
if (ExchangeDH == 1'b1 && tstate[3])
|
RegAddrB = { Alternate, 2'b01 };
|
RegAddrB = { Alternate, 2'b01 };
|
else
|
else
|
RegAddrB = RegAddrB_r;
|
RegAddrB = RegAddrB_r;
|
end // always @ *
|
end // always @ *
|
|
|
|
|
always @(/*AUTOSENSE*/ALU_Op_r or Auto_Wait_t1 or ExchangeDH
|
always @(/*AUTOSENSE*/ALU_Op_r or Auto_Wait_t1 or ExchangeDH
|
or IncDec_16 or Read_To_Reg_r or Save_ALU_r or mcycle
|
or IncDec_16 or Read_To_Reg_r or Save_ALU_r or mcycle
|
or tstate or wait_n)
|
or tstate or wait_n)
|
begin
|
begin
|
RegWEH = 1'b0;
|
RegWEH = 1'b0;
|
RegWEL = 1'b0;
|
RegWEL = 1'b0;
|
if ((tstate[1] && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||
|
if ((tstate[1] && ~Save_ALU_r && ~Auto_Wait_t1) ||
|
(Save_ALU_r == 1'b1 && ALU_Op_r != 4'b0111) )
|
(Save_ALU_r && (ALU_Op_r != 4'b0111)) )
|
begin
|
begin
|
case (Read_To_Reg_r)
|
case (Read_To_Reg_r)
|
5'b10000 , 5'b10001 , 5'b10010 , 5'b10011 , 5'b10100 , 5'b10101 :
|
5'b10000 , 5'b10001 , 5'b10010 , 5'b10011 , 5'b10100 , 5'b10101 :
|
begin
|
begin
|
RegWEH = ~ Read_To_Reg_r[0];
|
RegWEH = ~ Read_To_Reg_r[0];
|
RegWEL = Read_To_Reg_r[0];
|
RegWEL = Read_To_Reg_r[0];
|
end // UNMATCHED !!
|
end // UNMATCHED !!
|
default : ;
|
default : ;
|
endcase // case(Read_To_Reg_r)
|
endcase // case(Read_To_Reg_r)
|
|
|
end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||...
|
end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||...
|
|
|
|
|
if (ExchangeDH == 1'b1 && (tstate[3] || tstate[4]) )
|
if (ExchangeDH && (tstate[3] || tstate[4]) )
|
begin
|
begin
|
RegWEH = 1'b1;
|
RegWEH = 1'b1;
|
RegWEL = 1'b1;
|
RegWEL = 1'b1;
|
end
|
end
|
|
|
if (IncDec_16[2] && ((tstate[2] && ~wait_n && ~mcycle[0]) || (tstate[3] && mcycle[0])) )
|
if (IncDec_16[2] && ((tstate[2] && wait_n && ~mcycle[0]) || (tstate[3] && mcycle[0])) )
|
begin
|
begin
|
case (IncDec_16[1:0])
|
case (IncDec_16[1:0])
|
2'b00 , 2'b01 , 2'b10 :
|
2'b00 , 2'b01 , 2'b10 :
|
begin
|
begin
|
RegWEH = 1'b1;
|
RegWEH = 1'b1;
|
RegWEL = 1'b1;
|
RegWEL = 1'b1;
|
end // UNMATCHED !!
|
end // UNMATCHED !!
|
default : ;
|
default : ;
|
endcase
|
endcase
|
end
|
end
|
end // always @ *
|
end // always @ *
|
|
|
|
|
always @(/*AUTOSENSE*/ExchangeDH or ID16 or IncDec_16 or RegBusA_r
|
always @(/*AUTOSENSE*/ExchangeDH or ID16 or IncDec_16 or RegBusA_r
|
or RegBusB or Save_Mux or mcycle or tstate)
|
or RegBusB or Save_Mux or mcycle or tstate)
|
begin
|
begin
|
RegDIH = Save_Mux;
|
RegDIH = Save_Mux;
|
RegDIL = Save_Mux;
|
RegDIL = Save_Mux;
|
|
|
if (ExchangeDH == 1'b1 && tstate[3] )
|
if (ExchangeDH == 1'b1 && tstate[3] )
|
begin
|
begin
|
RegDIH = RegBusB[15:8];
|
RegDIH = RegBusB[15:8];
|
RegDIL = RegBusB[7:0];
|
RegDIL = RegBusB[7:0];
|
end
|
end
|
else if (ExchangeDH == 1'b1 && tstate[4] )
|
else if (ExchangeDH == 1'b1 && tstate[4] )
|
begin
|
begin
|
RegDIH = RegBusA_r[15:8];
|
RegDIH = RegBusA_r[15:8];
|
RegDIL = RegBusA_r[7:0];
|
RegDIL = RegBusA_r[7:0];
|
end
|
end
|
else if (IncDec_16[2] == 1'b1 && ((tstate[2] && ~mcycle[0]) || (tstate[3] && mcycle[0])) )
|
else if (IncDec_16[2] == 1'b1 && ((tstate[2] && ~mcycle[0]) || (tstate[3] && mcycle[0])) )
|
begin
|
begin
|
RegDIH = ID16[15:8];
|
RegDIH = ID16[15:8];
|
RegDIL = ID16[7:0];
|
RegDIL = ID16[7:0];
|
end
|
end
|
end
|
end
|
|
|
tv80_reg i_reg
|
tv80_reg i_reg
|
(
|
(
|
.clk (clk),
|
.clk (clk),
|
.CEN (ClkEn),
|
.CEN (ClkEn),
|
.WEH (RegWEH),
|
.WEH (RegWEH),
|
.WEL (RegWEL),
|
.WEL (RegWEL),
|
.AddrA (RegAddrA),
|
.AddrA (RegAddrA),
|
.AddrB (RegAddrB),
|
.AddrB (RegAddrB),
|
.AddrC (RegAddrC),
|
.AddrC (RegAddrC),
|
.DIH (RegDIH),
|
.DIH (RegDIH),
|
.DIL (RegDIL),
|
.DIL (RegDIL),
|
.DOAH (RegBusA[15:8]),
|
.DOAH (RegBusA[15:8]),
|
.DOAL (RegBusA[7:0]),
|
.DOAL (RegBusA[7:0]),
|
.DOBH (RegBusB[15:8]),
|
.DOBH (RegBusB[15:8]),
|
.DOBL (RegBusB[7:0]),
|
.DOBL (RegBusB[7:0]),
|
.DOCH (RegBusC[15:8]),
|
.DOCH (RegBusC[15:8]),
|
.DOCL (RegBusC[7:0])
|
.DOCL (RegBusC[7:0])
|
);
|
);
|
|
|
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
//
|
//
|
// Buses
|
// Buses
|
//
|
//
|
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
|
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (ClkEn == 1'b1 )
|
if (ClkEn == 1'b1 )
|
begin
|
begin
|
case (Set_BusB_To)
|
case (Set_BusB_To)
|
4'b0111 :
|
4'b0111 :
|
BusB <= #1 ACC;
|
BusB <= #1 ACC;
|
4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 :
|
4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 :
|
begin
|
begin
|
if (Set_BusB_To[0] == 1'b1 )
|
if (Set_BusB_To[0] == 1'b1 )
|
begin
|
begin
|
BusB <= #1 RegBusB[7:0];
|
BusB <= #1 RegBusB[7:0];
|
end
|
end
|
else
|
else
|
begin
|
begin
|
BusB <= #1 RegBusB[15:8];
|
BusB <= #1 RegBusB[15:8];
|
end
|
end
|
end
|
end
|
4'b0110 :
|
4'b0110 :
|
BusB <= #1 DI_Reg;
|
BusB <= #1 DI_Reg;
|
4'b1000 :
|
4'b1000 :
|
BusB <= #1 SP[7:0];
|
BusB <= #1 SP[7:0];
|
4'b1001 :
|
4'b1001 :
|
BusB <= #1 SP[15:8];
|
BusB <= #1 SP[15:8];
|
4'b1010 :
|
4'b1010 :
|
BusB <= #1 8'b00000001;
|
BusB <= #1 8'b00000001;
|
4'b1011 :
|
4'b1011 :
|
BusB <= #1 F;
|
BusB <= #1 F;
|
4'b1100 :
|
4'b1100 :
|
BusB <= #1 PC[7:0];
|
BusB <= #1 PC[7:0];
|
4'b1101 :
|
4'b1101 :
|
BusB <= #1 PC[15:8];
|
BusB <= #1 PC[15:8];
|
4'b1110 :
|
4'b1110 :
|
BusB <= #1 8'b00000000;
|
BusB <= #1 8'b00000000;
|
default :
|
default :
|
BusB <= #1 8'h0;
|
BusB <= #1 8'h0;
|
endcase
|
endcase
|
|
|
case (Set_BusA_To)
|
case (Set_BusA_To)
|
4'b0111 :
|
4'b0111 :
|
BusA <= #1 ACC;
|
BusA <= #1 ACC;
|
4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 :
|
4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 :
|
begin
|
begin
|
if (Set_BusA_To[0] == 1'b1 )
|
if (Set_BusA_To[0] == 1'b1 )
|
begin
|
begin
|
BusA <= #1 RegBusA[7:0];
|
BusA <= #1 RegBusA[7:0];
|
end
|
end
|
else
|
else
|
begin
|
begin
|
BusA <= #1 RegBusA[15:8];
|
BusA <= #1 RegBusA[15:8];
|
end
|
end
|
end
|
end
|
4'b0110 :
|
4'b0110 :
|
BusA <= #1 DI_Reg;
|
BusA <= #1 DI_Reg;
|
4'b1000 :
|
4'b1000 :
|
BusA <= #1 SP[7:0];
|
BusA <= #1 SP[7:0];
|
4'b1001 :
|
4'b1001 :
|
BusA <= #1 SP[15:8];
|
BusA <= #1 SP[15:8];
|
4'b1010 :
|
4'b1010 :
|
BusA <= #1 8'b00000000;
|
BusA <= #1 8'b00000000;
|
default :
|
default :
|
BusA <= #1 8'h0;
|
BusA <= #1 8'h0;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
//
|
//
|
// Generate external control signals
|
// Generate external control signals
|
//
|
//
|
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
`ifdef TV80_REFRESH
|
`ifdef TV80_REFRESH
|
always @ (posedge clk or negedge reset_n)
|
always @ (posedge clk or negedge reset_n)
|
begin
|
begin
|
if (reset_n == 1'b0 )
|
if (reset_n == 1'b0 )
|
begin
|
begin
|
rfsh_n <= #1 1'b1;
|
rfsh_n <= #1 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (cen == 1'b1 )
|
if (cen == 1'b1 )
|
begin
|
begin
|
if (mcycle[0] && ((tstate[2] && wait_n == 1'b1) || tstate[3]) )
|
if (mcycle[0] && ((tstate[2] && wait_n == 1'b1) || tstate[3]) )
|
begin
|
begin
|
rfsh_n <= #1 1'b0;
|
rfsh_n <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
rfsh_n <= #1 1'b1;
|
rfsh_n <= #1 1'b1;
|
end
|
end
|
end
|
end
|
end
|
end
|
end // always @ (posedge clk or negedge reset_n)
|
end // always @ (posedge clk or negedge reset_n)
|
`else // !`ifdef TV80_REFRESH
|
`else // !`ifdef TV80_REFRESH
|
assign rfsh_n = 1'b1;
|
assign rfsh_n = 1'b1;
|
`endif
|
`endif
|
|
|
always @(/*AUTOSENSE*/BusAck or Halt_FF or I_DJNZ or IntCycle
|
always @(/*AUTOSENSE*/BusAck or Halt_FF or I_DJNZ or IntCycle
|
or IntE_FF1 or di or iorq_i or mcycle or tstate)
|
or IntE_FF1 or di or iorq_i or mcycle or tstate)
|
begin
|
begin
|
mc = mcycle;
|
mc = mcycle;
|
ts = tstate;
|
ts = tstate;
|
DI_Reg = di;
|
DI_Reg = di;
|
halt_n = ~ Halt_FF;
|
halt_n = ~ Halt_FF;
|
busak_n = ~ BusAck;
|
busak_n = ~ BusAck;
|
intcycle_n = ~ IntCycle;
|
intcycle_n = ~ IntCycle;
|
IntE = IntE_FF1;
|
IntE = IntE_FF1;
|
iorq = iorq_i;
|
iorq = iorq_i;
|
stop = I_DJNZ;
|
stop = I_DJNZ;
|
end
|
end
|
|
|
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
//
|
//
|
// Syncronise inputs
|
// Syncronise inputs
|
//
|
//
|
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
|
|
always @ (posedge clk or negedge reset_n)
|
always @ (posedge clk or negedge reset_n)
|
begin : sync_inputs
|
begin : sync_inputs
|
if (~reset_n)
|
if (~reset_n)
|
begin
|
begin
|
BusReq_s <= #1 1'b0;
|
BusReq_s <= #1 1'b0;
|
INT_s <= #1 1'b0;
|
INT_s <= #1 1'b0;
|
NMI_s <= #1 1'b0;
|
NMI_s <= #1 1'b0;
|
Oldnmi_n <= #1 1'b0;
|
Oldnmi_n <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (cen == 1'b1 )
|
if (cen == 1'b1 )
|
begin
|
begin
|
BusReq_s <= #1 ~ busrq_n;
|
BusReq_s <= #1 ~ busrq_n;
|
INT_s <= #1 ~ int_n;
|
INT_s <= #1 ~ int_n;
|
if (NMICycle == 1'b1 )
|
if (NMICycle == 1'b1 )
|
begin
|
begin
|
NMI_s <= #1 1'b0;
|
NMI_s <= #1 1'b0;
|
end
|
end
|
else if (nmi_n == 1'b0 && Oldnmi_n == 1'b1 )
|
else if (nmi_n == 1'b0 && Oldnmi_n == 1'b1 )
|
begin
|
begin
|
NMI_s <= #1 1'b1;
|
NMI_s <= #1 1'b1;
|
end
|
end
|
Oldnmi_n <= #1 nmi_n;
|
Oldnmi_n <= #1 nmi_n;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
//
|
//
|
// Main state machine
|
// Main state machine
|
//
|
//
|
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
|
|
always @ (posedge clk or negedge reset_n)
|
always @ (posedge clk or negedge reset_n)
|
begin
|
begin
|
if (reset_n == 1'b0 )
|
if (reset_n == 1'b0 )
|
begin
|
begin
|
mcycle <= #1 7'b0000001;
|
mcycle <= #1 7'b0000001;
|
tstate <= #1 7'b0000001;
|
tstate <= #1 7'b0000001;
|
Pre_XY_F_M <= #1 3'b000;
|
Pre_XY_F_M <= #1 3'b000;
|
Halt_FF <= #1 1'b0;
|
Halt_FF <= #1 1'b0;
|
BusAck <= #1 1'b0;
|
BusAck <= #1 1'b0;
|
NMICycle <= #1 1'b0;
|
NMICycle <= #1 1'b0;
|
IntCycle <= #1 1'b0;
|
IntCycle <= #1 1'b0;
|
IntE_FF1 <= #1 1'b0;
|
IntE_FF1 <= #1 1'b0;
|
IntE_FF2 <= #1 1'b0;
|
IntE_FF2 <= #1 1'b0;
|
No_BTR <= #1 1'b0;
|
No_BTR <= #1 1'b0;
|
Auto_Wait_t1 <= #1 1'b0;
|
Auto_Wait_t1 <= #1 1'b0;
|
Auto_Wait_t2 <= #1 1'b0;
|
Auto_Wait_t2 <= #1 1'b0;
|
m1_n <= #1 1'b1;
|
m1_n <= #1 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (cen == 1'b1 )
|
if (cen == 1'b1 )
|
begin
|
begin
|
if (T_Res == 1'b1 )
|
if (T_Res == 1'b1 )
|
begin
|
begin
|
Auto_Wait_t1 <= #1 1'b0;
|
Auto_Wait_t1 <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
Auto_Wait_t1 <= #1 Auto_Wait || (iorq_i & ~Auto_Wait_t2);
|
Auto_Wait_t1 <= #1 Auto_Wait || (iorq_i & ~Auto_Wait_t2);
|
end
|
end
|
Auto_Wait_t2 <= #1 Auto_Wait_t1 & !T_Res;
|
Auto_Wait_t2 <= #1 Auto_Wait_t1 & !T_Res;
|
No_BTR <= #1 (I_BT && (~ IR[4] || ~ F[Flag_P])) ||
|
No_BTR <= #1 (I_BT && (~ IR[4] || ~ F[Flag_P])) ||
|
(I_BC && (~ IR[4] || F[Flag_Z] || ~ F[Flag_P])) ||
|
(I_BC && (~ IR[4] || F[Flag_Z] || ~ F[Flag_P])) ||
|
(I_BTR && (~ IR[4] || F[Flag_Z]));
|
(I_BTR && (~ IR[4] || F[Flag_Z]));
|
if (tstate[2] )
|
if (tstate[2] )
|
begin
|
begin
|
if (SetEI == 1'b1 )
|
if (SetEI == 1'b1 )
|
begin
|
begin
|
if (!NMICycle)
|
if (!NMICycle)
|
IntE_FF1 <= #1 1'b1;
|
IntE_FF1 <= #1 1'b1;
|
IntE_FF2 <= #1 1'b1;
|
IntE_FF2 <= #1 1'b1;
|
end
|
end
|
if (I_RETN == 1'b1 )
|
if (I_RETN == 1'b1 )
|
begin
|
begin
|
IntE_FF1 <= #1 IntE_FF2;
|
IntE_FF1 <= #1 IntE_FF2;
|
end
|
end
|
end
|
end
|
if (tstate[3] )
|
if (tstate[3] )
|
begin
|
begin
|
if (SetDI == 1'b1 )
|
if (SetDI == 1'b1 )
|
begin
|
begin
|
IntE_FF1 <= #1 1'b0;
|
IntE_FF1 <= #1 1'b0;
|
IntE_FF2 <= #1 1'b0;
|
IntE_FF2 <= #1 1'b0;
|
end
|
end
|
end
|
end
|
if (IntCycle == 1'b1 || NMICycle == 1'b1 )
|
if (IntCycle == 1'b1 || NMICycle == 1'b1 )
|
begin
|
begin
|
Halt_FF <= #1 1'b0;
|
Halt_FF <= #1 1'b0;
|
end
|
end
|
if (mcycle[0] && tstate[2] && wait_n == 1'b1 )
|
if (mcycle[0] && tstate[2] && wait_n == 1'b1 )
|
begin
|
begin
|
m1_n <= #1 1'b1;
|
m1_n <= #1 1'b1;
|
end
|
end
|
if (BusReq_s == 1'b1 && BusAck == 1'b1 )
|
if (BusReq_s == 1'b1 && BusAck == 1'b1 )
|
begin
|
begin
|
end
|
end
|
else
|
else
|
begin
|
begin
|
BusAck <= #1 1'b0;
|
BusAck <= #1 1'b0;
|
if (tstate[2] && wait_n == 1'b0 )
|
if (tstate[2] && wait_n == 1'b0 )
|
begin
|
begin
|
end
|
end
|
else if (T_Res == 1'b1 )
|
else if (T_Res == 1'b1 )
|
begin
|
begin
|
if (Halt == 1'b1 )
|
if (Halt == 1'b1 )
|
begin
|
begin
|
Halt_FF <= #1 1'b1;
|
Halt_FF <= #1 1'b1;
|
end
|
end
|
if (BusReq_s == 1'b1 )
|
if (BusReq_s == 1'b1 )
|
begin
|
begin
|
BusAck <= #1 1'b1;
|
BusAck <= #1 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
tstate <= #1 7'b0000010;
|
tstate <= #1 7'b0000010;
|
if (NextIs_XY_Fetch == 1'b1 )
|
if (NextIs_XY_Fetch == 1'b1 )
|
begin
|
begin
|
mcycle <= #1 7'b0100000;
|
mcycle <= #1 7'b0100000;
|
Pre_XY_F_M <= #1 mcyc_to_number(mcycle);
|
Pre_XY_F_M <= #1 mcyc_to_number(mcycle);
|
if (IR == 8'b00110110 && Mode == 0 )
|
if (IR == 8'b00110110 && Mode == 0 )
|
begin
|
begin
|
Pre_XY_F_M <= #1 3'b010;
|
Pre_XY_F_M <= #1 3'b010;
|
end
|
end
|
end
|
end
|
else if ((mcycle[6]) || (mcycle[5] && Mode == 1 && ISet != 2'b01) )
|
else if ((mcycle[6]) || (mcycle[5] && Mode == 1 && ISet != 2'b01) )
|
begin
|
begin
|
mcycle <= #1 number_to_bitvec(Pre_XY_F_M + 1);
|
mcycle <= #1 number_to_bitvec(Pre_XY_F_M + 1);
|
end
|
end
|
else if ((last_mcycle) ||
|
else if ((last_mcycle) ||
|
No_BTR == 1'b1 ||
|
No_BTR == 1'b1 ||
|
(mcycle[1] && I_DJNZ == 1'b1 && IncDecZ == 1'b1) )
|
(mcycle[1] && I_DJNZ == 1'b1 && IncDecZ == 1'b1) )
|
begin
|
begin
|
m1_n <= #1 1'b0;
|
m1_n <= #1 1'b0;
|
mcycle <= #1 7'b0000001;
|
mcycle <= #1 7'b0000001;
|
IntCycle <= #1 1'b0;
|
IntCycle <= #1 1'b0;
|
NMICycle <= #1 1'b0;
|
NMICycle <= #1 1'b0;
|
if (NMI_s == 1'b1 && Prefix == 2'b00 )
|
if (NMI_s == 1'b1 && Prefix == 2'b00 )
|
begin
|
begin
|
NMICycle <= #1 1'b1;
|
NMICycle <= #1 1'b1;
|
IntE_FF1 <= #1 1'b0;
|
IntE_FF1 <= #1 1'b0;
|
end
|
end
|
else if ((IntE_FF1 == 1'b1 && INT_s == 1'b1) && Prefix == 2'b00 && SetEI == 1'b0 )
|
else if ((IntE_FF1 == 1'b1 && INT_s == 1'b1) && Prefix == 2'b00 && SetEI == 1'b0 )
|
begin
|
begin
|
IntCycle <= #1 1'b1;
|
IntCycle <= #1 1'b1;
|
IntE_FF1 <= #1 1'b0;
|
IntE_FF1 <= #1 1'b0;
|
IntE_FF2 <= #1 1'b0;
|
IntE_FF2 <= #1 1'b0;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
mcycle <= #1 { mcycle[5:0], mcycle[6] };
|
mcycle <= #1 { mcycle[5:0], mcycle[6] };
|
end
|
end
|
end
|
end
|
end
|
end
|
else
|
else
|
begin // verilog has no "nor" operator
|
begin // verilog has no "nor" operator
|
if ( ~(Auto_Wait == 1'b1 && Auto_Wait_t2 == 1'b0) &&
|
if ( ~(Auto_Wait == 1'b1 && Auto_Wait_t2 == 1'b0) &&
|
~(IOWait == 1 && iorq_i == 1'b1 && Auto_Wait_t1 == 1'b0) )
|
~(IOWait == 1 && iorq_i == 1'b1 && Auto_Wait_t1 == 1'b0) )
|
begin
|
begin
|
tstate <= #1 { tstate[5:0], tstate[6] };
|
tstate <= #1 { tstate[5:0], tstate[6] };
|
end
|
end
|
end
|
end
|
end
|
end
|
if (tstate[0])
|
if (tstate[0])
|
begin
|
begin
|
m1_n <= #1 1'b0;
|
m1_n <= #1 1'b0;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
always @(/*AUTOSENSE*/BTR_r or DI_Reg or IncDec_16 or JumpE or PC
|
always @(/*AUTOSENSE*/BTR_r or DI_Reg or IncDec_16 or JumpE or PC
|
or RegBusA or RegBusC or SP or tstate)
|
or RegBusA or RegBusC or SP or tstate)
|
begin
|
begin
|
if (JumpE == 1'b1 )
|
if (JumpE == 1'b1 )
|
begin
|
begin
|
PC16_B = { {8{DI_Reg[7]}}, DI_Reg };
|
PC16_B = { {8{DI_Reg[7]}}, DI_Reg };
|
end
|
end
|
else if (BTR_r == 1'b1 )
|
else if (BTR_r == 1'b1 )
|
begin
|
begin
|
PC16_B = -2;
|
PC16_B = -2;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
PC16_B = 1;
|
PC16_B = 1;
|
end
|
end
|
|
|
if (tstate[3])
|
if (tstate[3])
|
begin
|
begin
|
SP16_A = RegBusC;
|
SP16_A = RegBusC;
|
SP16_B = { {8{DI_Reg[7]}}, DI_Reg };
|
SP16_B = { {8{DI_Reg[7]}}, DI_Reg };
|
end
|
end
|
else
|
else
|
begin
|
begin
|
// suspect that ID16 and SP16 could be shared
|
// suspect that ID16 and SP16 could be shared
|
SP16_A = SP;
|
SP16_A = SP;
|
|
|
if (IncDec_16[3] == 1'b1)
|
if (IncDec_16[3] == 1'b1)
|
SP16_B = -1;
|
SP16_B = -1;
|
else
|
else
|
SP16_B = 1;
|
SP16_B = 1;
|
end
|
end
|
|
|
if (IncDec_16[3])
|
if (IncDec_16[3])
|
ID16_B = -1;
|
ID16_B = -1;
|
else
|
else
|
ID16_B = 1;
|
ID16_B = 1;
|
|
|
ID16 = RegBusA + ID16_B;
|
ID16 = RegBusA + ID16_B;
|
PC16 = PC + PC16_B;
|
PC16 = PC + PC16_B;
|
SP16 = SP16_A + SP16_B;
|
SP16 = SP16_A + SP16_B;
|
end // always @ *
|
end // always @ *
|
|
|
|
|
always @(/*AUTOSENSE*/IntCycle or NMICycle or mcycle)
|
always @(/*AUTOSENSE*/IntCycle or NMICycle or mcycle)
|
begin
|
begin
|
Auto_Wait = 1'b0;
|
Auto_Wait = 1'b0;
|
if (IntCycle == 1'b1 || NMICycle == 1'b1 )
|
if (IntCycle == 1'b1 || NMICycle == 1'b1 )
|
begin
|
begin
|
if (mcycle[0] )
|
if (mcycle[0] )
|
begin
|
begin
|
Auto_Wait = 1'b1;
|
Auto_Wait = 1'b1;
|
end
|
end
|
end
|
end
|
end // always @ *
|
end // always @ *
|
|
|
endmodule // T80
|
endmodule // T80
|
|
|
|
|