Line 1... |
Line 1... |
//=========================================================================================
|
//=========================================================================================
|
// This file contains substitute strings for macros used in the Excel timing table and
|
// This file contains substitute strings for macro expansions. Macros are defined in an
|
// is read and processed by genmatrix.py script to generate exec_matrix.vh include file.
|
// Excel timing spreadsheet 'Timings.xlsm' and exported to a .csv file which is then read
|
|
// and processed by genmatrix.py script to generate exec_matrix.vh include file.
|
//
|
//
|
// Format of the file:
|
// Macro format:
|
//
|
//
|
// * Each key is prefixed by ':' and corresponds to a spreadsheet column name.
|
// * Each key is prefixed by ':' and corresponds to a spreadsheet *column* name.
|
// * A column (key) contains a number of macros, each starting at its own line.
|
// * A key may contain several different macros, one per line.
|
// * A macro may span multiple lines, in which case use the '\' character after the name to
|
// * A macro may span multiple lines; use the '\' character to continue on the next line.
|
// continue on the next line.
|
// * Multi-line macros end when a line does not start with a space character.
|
// * Multiline macros end when a line does not _start_ with a space character.
|
|
// //-style comments are wrapped within /* ... */ if they don't start a line.
|
// //-style comments are wrapped within /* ... */ if they don't start a line.
|
//=========================================================================================
|
//=========================================================================================
|
|
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
:Function
|
// CPU machine state
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
|
:Function
|
//Fetch is M1
|
//Fetch is M1
|
fMFetch
|
fMFetch
|
fMRead fMRead=1;
|
fMRead fMRead=1;
|
fMWrite fMWrite=1;
|
fMWrite fMWrite=1;
|
fIORead fIORead=1;
|
fIORead fIORead=1;
|
Line 24... |
Line 25... |
|
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
// Basic timing control
|
// Basic timing control
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
:valid
|
:valid
|
1 validPLA=1;
|
Y validPLA=1;
|
:nextM
|
:nextM
|
1 nextM=1;
|
Y nextM=1;
|
mr nextM=1; ctl_mRead=1;
|
mr nextM=1; ctl_mRead=1;
|
mw nextM=1; ctl_mWrite=1;
|
mw nextM=1; ctl_mWrite=1;
|
ior nextM=1; ctl_iorw=1;
|
ior nextM=1; ctl_iorw=1;
|
iow nextM=1; ctl_iorw=1;
|
iow nextM=1; ctl_iorw=1;
|
CC nextM=!flags_cond_true;
|
CC nextM=~flags_cond_true;
|
INT nextM=1; ctl_mRead=in_intr & im2; // RST38 interrupt extension
|
INT nextM=1; ctl_mRead=in_intr & im2; // RST38 interrupt extension
|
:setM1
|
:setM1
|
1 setM1=1;
|
Y setM1=1;
|
SS setM1=!flags_cond_true;
|
SS setM1=~flags_cond_true;
|
CC setM1=!flags_cond_true;
|
CC setM1=~flags_cond_true;
|
ZF setM1=flags_zf; // Used in DJNZ
|
ZF setM1=flags_zf; // Used in DJNZ
|
BR setM1=nonRep | !repeat_en;
|
BR setM1=nonRep | ~repeat_en;
|
BRZ setM1=nonRep | !repeat_en | flags_zf;
|
BRZ setM1=nonRep | ~repeat_en | flags_zf;
|
BZ setM1=nonRep | flags_zf;
|
BZ setM1=nonRep | flags_zf;
|
INT setM1=!(in_intr & im2); // RST38 interrupt extension
|
INT setM1=~(in_intr & im2); // RST38 interrupt extension
|
|
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
// Register file, address (downstream) endpoint
|
// Register file, address (downstream) endpoint
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
:A:reg rd
|
:A:reg rd
|
Line 62... |
Line 63... |
IR ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit IR
|
IR ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit IR
|
I* ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4d=1; // Select 8-bit I register
|
I* ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4d=1; // Select 8-bit I register
|
PC ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit PC
|
PC ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit PC
|
|
|
// Conditional assertions of WZ, HL instead of PC
|
// Conditional assertions of WZ, HL instead of PC
|
WZ? \
|
WZ? ctl_reg_not_pc|=flags_cond_true; ctl_reg_sel_wz|=flags_cond_true; ctl_reg_sys_hilo|={flags_cond_true,flags_cond_true}; ctl_sw_4d|=flags_cond_true;
|
if (flags_cond_true) begin // If cc is true, use WZ instead of PC (for jumps)
|
// Alternate format:
|
ctl_reg_not_pc=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4d=1;
|
// if (flags_cond_true) begin // If cc is true, use WZ instead of PC (for jumps)
|
end
|
// ctl_reg_not_pc=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4d=1;
|
|
// end
|
|
|
:A:reg wr
|
:A:reg wr
|
// General purpose registers
|
// General purpose registers
|
r16 ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit general purpose register, enable SW4 upstream
|
r16 ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit general purpose register, enable SW4 upstream
|
BC ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit BC, enable SW4 upstream
|
BC ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit BC, enable SW4 upstream
|
Line 78... |
Line 80... |
SP ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11; ctl_reg_use_sp=1; ctl_sw_4u=1; // Write 16-bit SP, enable SW4 upstream
|
SP ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11; ctl_reg_use_sp=1; ctl_sw_4u=1; // Write 16-bit SP, enable SW4 upstream
|
// System registers
|
// System registers
|
WZ ctl_reg_sys_we=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit WZ, enable SW4 upstream
|
WZ ctl_reg_sys_we=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit WZ, enable SW4 upstream
|
IR ctl_reg_sys_we=1; ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Write 16-bit IR
|
IR ctl_reg_sys_we=1; ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Write 16-bit IR
|
// PC will not be incremented if we are in HALT, INTR or NMI state
|
// PC will not be incremented if we are in HALT, INTR or NMI state
|
PC ctl_reg_sys_we=1; ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b11; pc_inc=!(in_halt | in_intr | in_nmi); // Write 16-bit PC and control incrementer
|
PC ctl_reg_sys_we=1; ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b11; pc_inc_hold=(in_halt | in_intr | in_nmi); // Write 16-bit PC and control incrementer
|
> ctl_sw_4u=1;
|
> ctl_sw_4u=1;
|
|
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
// Controls the address latch incrementer, the address latch and the address pin mux
|
// Controls the address latch incrementer, the address latch and the address pin mux
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
:inc/dec
|
:inc/dec
|
+ ctl_inc_cy=pc_inc; // Increment
|
+ ctl_inc_cy=~pc_inc_hold; // Increment
|
- ctl_inc_cy=pc_inc; ctl_inc_dec=1; // Decrement
|
- ctl_inc_cy=~pc_inc_hold; ctl_inc_dec=1; // Decrement
|
op3 ctl_inc_cy=pc_inc; ctl_inc_dec=op3; // Decrement if op3 is set; increment otherwise
|
op3 ctl_inc_cy=~pc_inc_hold; ctl_inc_dec=op3; // Decrement if op3 is set; increment otherwise
|
|
|
:A:latch
|
:A:latch
|
W ctl_al_we=1; // Write a value from the register bus to the address latch
|
W ctl_al_we=1; // Write a value from the register bus to the address latch
|
R ctl_bus_inc_oe=1; // Output enable incrementer to the register bus
|
R ctl_bus_inc_oe=1; // Output enable incrementer to the register bus
|
P ctl_apin_mux=1; // Apin sourced from incrementer
|
P ctl_apin_mux=1; // Apin sourced from incrementer
|
Line 105... |
Line 107... |
A ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
A ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
AF ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11;
|
AF ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11;
|
B ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
B ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
H ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b10;
|
H ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b10;
|
L ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b01;
|
L ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b01;
|
r8 \ // r8 addressing does not allow reading F register (A and F are also indexed as swapped) (ex. in OUT (c),r)
|
r8 ctl_reg_gp_sel=op21; ctl_reg_gp_hilo={~rsel0,rsel0};// Read 8-bit GP register selected by op[2:0]
|
if (op4 & op5 & !op3) ctl_bus_zero_oe=1; // Trying to read flags? Put 0 on the bus instead.
|
r8' \ // r8 addressing does not allow reading F register (indices of A and F are also swapped) (ex. in OUT (c),r)
|
else begin ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={!rsel3,rsel3}; end // Read 8-bit GP register
|
if (op4 & op5 & ~op3) begin ctl_bus_zero_oe=1; end // Trying to read flags? Put 0 on the bus instead.
|
r8' ctl_reg_gp_sel=op21; ctl_reg_gp_hilo={!rsel0,rsel0};// Read 8-bit GP register selected by op[2:0]
|
if (~(op4 & op5 & ~op3)) begin ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={~rsel3,rsel3}; end // Read 8-bit GP register
|
rh ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Read 8-bit GP register high byte
|
rh ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Read 8-bit GP register high byte
|
rl ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Read 8-bit GP register low byte
|
rl ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Read 8-bit GP register low byte
|
//----- System registers -----
|
//----- System registers -----
|
WZ ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4u=1;
|
WZ ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4u=1;
|
Z ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1; // Selecting strictly Z
|
Z ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1; // Selecting strictly Z
|
I/R ctl_reg_sel_ir=1; ctl_reg_sys_hilo={!op3,op3}; ctl_sw_4u=1; // Read either I or R based on op3 (0 or 1)
|
I/R ctl_reg_sel_ir=1; ctl_reg_sys_hilo={~op3,op3}; ctl_sw_4u=1; // Read either I or R based on op3 (0 or 1)
|
PCh ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4u=1;
|
PCh ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4u=1;
|
PCl ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1;
|
PCl ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1;
|
|
|
:D:reg wr
|
:D:reg wr
|
? // Which register to be written is decided elsewhere
|
? // Which register to be written is decided elsewhere
|
//----- General purpose registers -----
|
//----- General purpose registers -----
|
A ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
A ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
F ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b01;
|
F ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b01;
|
B ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
B ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
r8 ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={!rsel3,rsel3}; // Write 8-bit GP register
|
r8 ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={~rsel3,rsel3}; // Write 8-bit GP register
|
r8' ctl_reg_gp_we=1; ctl_reg_gp_sel=op21; ctl_reg_gp_hilo={!rsel0,rsel0}; // Write 8-bit GP register selected by op[2:0]
|
r8' ctl_reg_gp_we=1; ctl_reg_gp_sel=op21; ctl_reg_gp_hilo={~rsel0,rsel0}; // Write 8-bit GP register selected by op[2:0]
|
rh ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Write 8-bit GP register high byte
|
rh ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Write 8-bit GP register high byte
|
rl ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Write 8-bit GP register low byte
|
rl ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Write 8-bit GP register low byte
|
//----- System registers -----
|
//----- System registers -----
|
I/R ctl_reg_sys_we=1; ctl_reg_sel_ir=1; ctl_reg_sys_hilo={!op3,op3}; ctl_sw_4d=1; // Write either I or R based on op3 (0 or 1)
|
I/R ctl_reg_sys_we=1; ctl_reg_sel_ir=1; ctl_reg_sys_hilo={~op3,op3}; ctl_sw_4d=1; // Write either I or R based on op3 (0 or 1)
|
WZ ctl_reg_sys_we=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11;
|
WZ ctl_reg_sys_we=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11;
|
W ctl_reg_sys_we_hi=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo[1]=1; // Selecting only W
|
W ctl_reg_sys_we_hi=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo={1'b1,ctl_reg_sys_hilo[0]}; // Selecting only W
|
W? ctl_reg_sys_we_hi=flags_cond_true; ctl_reg_sel_wz=flags_cond_true; ctl_reg_sys_hilo[1]=1; // Conditionally selecting only W
|
W? ctl_reg_sys_we_hi=flags_cond_true; ctl_reg_sel_wz=flags_cond_true; ctl_reg_sys_hilo={1'b1,ctl_reg_sys_hilo[0]}; // Conditionally selecting only W
|
Z ctl_reg_sys_we_lo=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo[0]=1; // Selecting only Z
|
Z ctl_reg_sys_we_lo=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo={ctl_reg_sys_hilo[1],1'b1}; // Selecting only Z
|
|
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
// Controls the register file gate connecting it with the ALU and data bus
|
// Controls the register file gate connecting it with the ALU and data bus
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
:Reg gate
|
:Reg gate
|
< ctl_reg_in_hi=1; ctl_reg_in_lo=1; // From the ALU side into the register file
|
< ctl_reg_in_hi=1; ctl_reg_in_lo=1; // From the ALU side into the register file
|
|
|
|
|
> ctl_reg_out_hi=1; ctl_reg_out_lo=1; // From the register file into the ALU
|
|
>l ctl_reg_out_lo=1; // From the register file into the ALU low byte only
|
> ctl_reg_out_hi=1; ctl_reg_out_lo=1; // From the register file into the FLAGT and ALU
|
>h ctl_reg_out_hi=1; // From the register file into the ALU high byte only
|
|
|
// Enables a register gate (high/low) corresponding to the selected 8-bit register
|
|
>r8 ctl_reg_out_hi=~rsel0; ctl_reg_out_lo=rsel0; ctl_sw_2u=~rsel0; ctl_sw_2d=rsel0; // Enable register gate based on the rsel0
|
|
>r8' ctl_reg_out_hi=~rsel3; ctl_reg_out_lo=rsel3; ctl_sw_2u=~rsel3; ctl_sw_2d=rsel3; // Enable register gate based on the rsel3
|
|
|
|
>l ctl_reg_out_lo=1; // From the register file onto the db1 (sw2 + FLAGT + sw1)
|
|
>h ctl_reg_out_hi=1; // From the register file onto the db2 (sw2 + ALU)
|
|
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
// Switches on the data bus for each direction (upstream, downstream)
|
// Switches on the data bus for each direction (upstream, downstream)
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
:SW2
|
:SW2
|
d ctl_sw_2d=1;
|
d ctl_sw_2d=1;
|
u ctl_sw_2u=1;
|
u ctl_sw_2u=1;
|
|
- // Controlled by register gate
|
|
|
:SW1
|
:SW1
|
< ctl_sw_1d=1;
|
< ctl_sw_1d=1;
|
> ctl_sw_1u=1;
|
> ctl_sw_1u=1;
|
|
|
Line 173... |
Line 182... |
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
:ALU
|
:ALU
|
// Controls the master ALU output enable and the ALU input, only one can be active at a time
|
// Controls the master ALU output enable and the ALU input, only one can be active at a time
|
// >bs if set, will override >s0 which is used by bit instructions to override default M1/T3 load
|
// >bs if set, will override >s0 which is used by bit instructions to override default M1/T3 load
|
< ctl_alu_oe=1; // Enable ALU onto the data bus
|
< ctl_alu_oe=1; // Enable ALU onto the data bus
|
>s0 ctl_alu_shift_oe=!ctl_alu_bs_oe; // Shifter unit without shift-enable
|
>s0 ctl_alu_shift_oe=~ctl_alu_bs_oe; // Shifter unit without shift-enable
|
>s1 ctl_alu_shift_oe=1; ctl_shift_en=1; // Shifter unit AND shift enable!
|
>s1 ctl_alu_shift_oe=1; ctl_shift_en=1; // Shifter unit AND shift enable!
|
>bs ctl_alu_bs_oe=1; // Bit-selector unit
|
>bs ctl_alu_bs_oe=1; // Bit-selector unit
|
|
|
:ALU bus
|
:ALU bus
|
// Controls the writer to the internal ALU bus
|
// Controls the writer to the internal ALU bus
|
Line 196... |
Line 205... |
bus ctl_alu_op1_sel_bus=1; // Internal bus
|
bus ctl_alu_op1_sel_bus=1; // Internal bus
|
low ctl_alu_op1_sel_low=1; // Write low nibble with a high nibble
|
low ctl_alu_op1_sel_low=1; // Write low nibble with a high nibble
|
0 ctl_alu_op1_sel_zero=1; // Zero
|
0 ctl_alu_op1_sel_zero=1; // Zero
|
|
|
:operation
|
:operation
|
// Sets the ALU core operation
|
// Defines the ALU core compute operation
|
//--------------------------------------------------------------------------------------------------------------------------
|
// The listing is also showing their alternate formats (using if/then)
|
CP \
|
//-----------------------------------------------------------------------------------------
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
CP ctl_alu_sel_op2_neg=1; ctl_flags_cf_set|=ctl_alu_op_low; ctl_alu_core_hf|=~ctl_alu_op_low;
|
if (ctl_alu_op_low) begin
|
// ctl_alu_sel_op2_neg=1;
|
ctl_flags_cf_set=1;
|
// if (ctl_alu_op_low) begin
|
end else begin
|
// ctl_flags_cf_set=1;
|
ctl_alu_core_hf=1;
|
// end else begin
|
end
|
// ctl_alu_core_hf=1;
|
//--------------------------------------------------------------------------------------------------------------------------
|
// end
|
SUB \
|
//-----------------------------------------------------------------------------------------
|
|
SUB ctl_alu_sel_op2_neg=1; ctl_flags_cf_set|=ctl_alu_op_low; ctl_alu_core_hf|=~ctl_alu_op_low;
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
// ctl_alu_sel_op2_neg=1;
|
if (ctl_alu_op_low) begin
|
// if (ctl_alu_op_low) begin
|
ctl_flags_cf_set=1;
|
// ctl_flags_cf_set=1;
|
end else begin
|
// end else begin
|
ctl_alu_core_hf=1;
|
// ctl_alu_core_hf=1;
|
end
|
// end
|
//--------------------------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
SBC \
|
SBC ctl_alu_sel_op2_neg=1; ctl_flags_cf_cpl|=ctl_alu_op_low; ctl_alu_core_hf|=~ctl_alu_op_low;
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
// ctl_alu_sel_op2_neg=1;
|
if (ctl_alu_op_low) begin
|
// if (ctl_alu_op_low) begin
|
ctl_flags_cf_cpl=1;
|
// ctl_flags_cf_cpl=1;
|
end else begin
|
// end else begin
|
ctl_alu_core_hf=1;
|
// ctl_alu_core_hf=1;
|
end
|
// end
|
//--------------------------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
SBCh \
|
SBCh ctl_alu_sel_op2_neg=1; ctl_alu_core_hf|=~ctl_alu_op_low;
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
// ctl_alu_sel_op2_neg=1;
|
if (!ctl_alu_op_low) begin
|
// if (~ctl_alu_op_low) begin
|
ctl_alu_core_hf=1;
|
// ctl_alu_core_hf=1;
|
end
|
// end
|
//--------------------------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
ADC \
|
ADC ctl_alu_core_hf|=~ctl_alu_op_low;
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0;
|
// if (~ctl_alu_op_low) begin
|
if (!ctl_alu_op_low) begin
|
// ctl_alu_core_hf=1;
|
ctl_alu_core_hf=1;
|
// end
|
end
|
//-----------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------------------
|
ADD ctl_flags_cf_set|=ctl_alu_op_low; ctl_flags_cf_cpl|=ctl_alu_op_low; ctl_alu_core_hf|=~ctl_alu_op_low;
|
ADD \
|
// if (ctl_alu_op_low) begin
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0;
|
// ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
if (ctl_alu_op_low) begin
|
// end else begin
|
ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
// ctl_alu_core_hf=1;
|
end else begin
|
// end
|
ctl_alu_core_hf=1;
|
//-----------------------------------------------------------------------------------------
|
end
|
AND ctl_alu_core_S=1; ctl_flags_cf_set=1;
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
AND ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=1; ctl_flags_cf_set=1;
|
|
OR ctl_alu_core_R=1; ctl_alu_core_V=1; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
OR ctl_alu_core_R=1; ctl_alu_core_V=1; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
XOR ctl_alu_core_R=1; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
XOR ctl_alu_core_R=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
|
NAND ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_alu_sel_op2_neg=1;
|
NAND ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_alu_sel_op2_neg=1;
|
|
NOR ctl_alu_core_R=1; ctl_alu_core_V=1; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1; ctl_alu_sel_op2_neg=1;
|
NOR ctl_alu_core_R=1; ctl_alu_core_V=1; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1; ctl_alu_sel_op2_neg=1;
|
//--------------------------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
|
|
PLA ctl_state_alu=1; // Assert the ALU PLA modifier to determine operation
|
PLA ctl_state_alu=1; // Assert the ALU PLA modifier to determine operation
|
|
|
:nibble
|
:nibble
|
// ALU computational phase: low nibble or high nibble
|
// ALU compute phase: working on low nibble or high nibble
|
L ctl_alu_op_low=1; // Activate ALU operation on low nibble
|
L ctl_alu_op_low=1; // Activate ALU operation on low nibble
|
H ctl_alu_sel_op2_high=1; // Activate ALU operation on high nibble
|
H ctl_alu_sel_op2_high=1; // Activate ALU operation on high nibble
|
|
|
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
// FLAGT
|
// FLAGT
|
Line 295... |
Line 301... |
0 ctl_flags_cf_set=1; ctl_flags_cf_cpl=1; // Clear CF going into the ALU core
|
0 ctl_flags_cf_set=1; ctl_flags_cf_cpl=1; // Clear CF going into the ALU core
|
1 ctl_flags_cf_set=1; // Set CF going into the ALU core
|
1 ctl_flags_cf_set=1; // Set CF going into the ALU core
|
^ ctl_flags_cf_we=1; ctl_flags_cf_cpl=1; // CCF
|
^ ctl_flags_cf_we=1; ctl_flags_cf_cpl=1; // CCF
|
:CF2
|
:CF2
|
R ctl_flags_use_cf2=1;
|
R ctl_flags_use_cf2=1;
|
W ctl_flags_cf2_we=1; ctl_flags_cf2_sel=0;
|
W ctl_flags_cf2_we=1;
|
W.sh ctl_flags_cf2_we=1; ctl_flags_cf2_sel=1;
|
W.sh ctl_flags_cf2_we=1; ctl_flags_cf2_sel_shift=1;
|
W.daa ctl_flags_cf2_we=1; ctl_flags_cf2_sel=2;
|
W.daa ctl_flags_cf2_we=1; ctl_flags_cf2_sel_daa=1;
|
W.0 ctl_flags_cf2_we=1; ctl_flags_cf2_sel=3;
|
|
|
//------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
// Macros for some special cases; also simplifies control logic for a number of instructions
|
// Special sequence macros for some instructions make it simpler for all other entries
|
//------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
|
:Special
|
:Special
|
USE_SP ctl_reg_use_sp=1; // For 16-bit loads: use SP instead of AF
|
USE_SP ctl_reg_use_sp=1; // For 16-bit loads: use SP instead of AF
|
|
|
// A few more specific states and instructions:
|
// A few more specific states and instructions:
|
Ex_DE_HL ctl_reg_ex_de_hl=1; // EX DE,HL
|
Ex_DE_HL ctl_reg_ex_de_hl=1; // EX DE,HL
|
Line 316... |
Line 321... |
DI_EI ctl_iffx_bit=op3; ctl_iffx_we=1; // DI/EI
|
DI_EI ctl_iffx_bit=op3; ctl_iffx_we=1; // DI/EI
|
IM ctl_im_we=1; // IM n ('n' is read by opcode[4:3])
|
IM ctl_im_we=1; // IM n ('n' is read by opcode[4:3])
|
|
|
WZ=IX+d ixy_d=1; // Compute WZ=IX+d
|
WZ=IX+d ixy_d=1; // Compute WZ=IX+d
|
IX_IY ctl_state_ixiy_we=1; ctl_state_iy_set=op5; setIXIY=1; // IX/IY prefix
|
IX_IY ctl_state_ixiy_we=1; ctl_state_iy_set=op5; setIXIY=1; // IX/IY prefix
|
CLR_IX_IY ctl_state_ixiy_we=1; ctl_state_ixiy_clr=!setIXIY; // Clear IX/IY flag
|
CLR_IX_IY ctl_state_ixiy_we=1; ctl_state_ixiy_clr=~setIXIY; // Clear IX/IY flag
|
|
|
CB ctl_state_tbl_cb_set=1; setCBED=1; // CB-table prefix
|
CB ctl_state_tbl_cb_set=1; setCBED=1; // CB-table prefix
|
ED ctl_state_tbl_ed_set=1; setCBED=1; // ED-table prefix
|
ED ctl_state_tbl_ed_set=1; setCBED=1; // ED-table prefix
|
CLR_CB_ED ctl_state_tbl_clr=!setCBED; // Clear CB/ED prefix
|
CLR_CB_ED ctl_state_tbl_clr=~setCBED; // Clear CB/ED prefix
|
|
|
// If the NF is set, complement HF and CF on the way out to the bus
|
// If the NF is set, complement HF and CF on the way out to the bus
|
// This is used to correctly set those flags after subtraction operations
|
// This is used to correctly set those flags after subtraction operations
|
?NF_HF_CF ctl_flags_hf_cpl=flags_nf; ctl_flags_cf_cpl=flags_nf;
|
?NF_HF_CF ctl_flags_hf_cpl=flags_nf; ctl_flags_cf_cpl=flags_nf;
|
?NF_HF ctl_flags_hf_cpl=flags_nf;
|
?NF_HF ctl_flags_hf_cpl=flags_nf;
|
?~CF_HF ctl_flags_hf_cpl=!flags_cf; // Used for CCF
|
?~CF_HF ctl_flags_hf_cpl=~flags_cf; // Used for CCF
|
?SF_NEG ctl_alu_sel_op2_neg=flags_sf;
|
?SF_NEG ctl_alu_sel_op2_neg=flags_sf;
|
NEG_OP2 ctl_alu_sel_op2_neg=1;
|
NEG_OP2 ctl_alu_sel_op2_neg=1;
|
?NF_SUB ctl_alu_sel_op2_neg=flags_nf; ctl_flags_cf_cpl=!flags_nf;
|
?NF_SUB ctl_alu_sel_op2_neg=flags_nf; ctl_flags_cf_cpl=~flags_nf;
|
|
|
// M1 opcode read cycle and the refresh register increment cycle
|
// M1 opcode read cycle and the refresh register increment cycle
|
// Write opcode into the instruction register through internal db0 bus:
|
// Write opcode into the instruction register through internal db0 bus:
|
OpcodeToIR ctl_ir_we=1;
|
OpcodeToIR ctl_ir_we=1;
|
|
|
// At the common instruction load M1/T3, override opcode byte when servicing interrupts:
|
// At the common instruction load M1/T3, override opcode byte when servicing interrupts:
|
// 1. We are in HALT mode: push NOP (0x00) instead
|
// 1. We are in HALT mode: push NOP (0x00) instead
|
// 2. We are in INTR mode (IM1 or IM2): push RST38 (0xFF) instead
|
// 2. We are in INTR mode (IM1 or IM2): push RST38 (0xFF) instead
|
// 3. We are in NMI mode: push RST38 (0xFF) instead
|
// 3. We are in NMI mode: push RST38 (0xFF) instead
|
OverrideIR ctl_bus_zero_oe=in_halt; ctl_bus_ff_oe=(in_intr & (im1 | im2)) | in_nmi;
|
OverrideIR ctl_bus_zero_oe=in_halt; ctl_bus_ff_oe=(in_intr & (im1 | im2)) | in_nmi;
|
|
|
// RST instruction uses opcode[5:3] to specify a vector and this control passes those 3 bits through
|
// RST instruction uses opcode[5:3] to specify a vector and this macro passes those 3 bits through
|
MASK_543 ctl_sw_mask543_en=!((in_intr & im2) | in_nmi);
|
MASK_543 ctl_sw_mask543_en=~((in_intr & im2) | in_nmi);
|
// Based on the in_nmi state, several things are set:
|
// Based on the in_nmi state:
|
// 1. Disable SW1 so the opcode will not get onto db1 bus
|
// 1. Disable SW1 so the opcode will not get onto db1 bus
|
// 2. Generate 0x66 on the db1 bus which will be used as the target vector address
|
// 2. Generate 0x66 on the db1 bus which will be used as the target vector address
|
// 3. Clear IFF1 (done by the nmi logic on posedge of in_nmi)
|
// 3. Clear IFF1 (done by the nmi logic on posedge of in_nmi)
|
RST_NMI ctl_sw_1d=!in_nmi; ctl_66_oe=in_nmi;
|
RST_NMI ctl_sw_1d=~in_nmi; ctl_66_oe=in_nmi;
|
// Based on the in_intr state, several things are set:
|
// Based on the in_intr state:
|
// 1. IM1 mode, force 0xFF on the db0 bus
|
// 1. IM1 mode, force 0xFF on the db0 bus
|
// 2. Clear IFF1 and IFF2 (done by the intr logic on posedge of in_intr)
|
// 2. Clear IFF1 and IFF2 (done by the intr logic on posedge of in_intr)
|
RST_INT ctl_bus_ff_oe=in_intr & im1;
|
RST_INT ctl_bus_ff_oe=in_intr & im1;
|
RETN ctl_iff1_iff2=1; // RETN copies IFF2 into IFF1
|
RETN ctl_iff1_iff2=1; // RETN copies IFF2 into IFF1
|
NO_INTS ctl_no_ints=1; // Disable interrupt generation for this opcode (DI/EI/CB/ED/DD/FD)
|
NO_INTS ctl_no_ints=1; // Disable interrupt generation for this opcode (DI/EI/CB/ED/DD/FD)
|