1 |
3 |
gdevic |
//=========================================================================================
|
2 |
8 |
gdevic |
// This file contains substitute strings for macro expansions. Macros are defined in an
|
3 |
|
|
// Excel timing spreadsheet 'Timings.xlsm' and exported to a .csv file which is then read
|
4 |
|
|
// and processed by genmatrix.py script to generate exec_matrix.vh include file.
|
5 |
3 |
gdevic |
//
|
6 |
8 |
gdevic |
// Macro format:
|
7 |
3 |
gdevic |
//
|
8 |
8 |
gdevic |
// * Each key is prefixed by ':' and corresponds to a spreadsheet *column* name.
|
9 |
|
|
// * A key may contain several different macros, one per line.
|
10 |
|
|
// * A macro may span multiple lines; use the '\' character to continue on the next line.
|
11 |
|
|
// * Multi-line macros end when a line does not start with a space character.
|
12 |
3 |
gdevic |
// //-style comments are wrapped within /* ... */ if they don't start a line.
|
13 |
|
|
//=========================================================================================
|
14 |
|
|
|
15 |
|
|
//-----------------------------------------------------------------------------------------
|
16 |
8 |
gdevic |
// CPU machine state
|
17 |
|
|
//-----------------------------------------------------------------------------------------
|
18 |
3 |
gdevic |
:Function
|
19 |
|
|
//Fetch is M1
|
20 |
|
|
fMFetch
|
21 |
|
|
fMRead fMRead=1;
|
22 |
|
|
fMWrite fMWrite=1;
|
23 |
|
|
fIORead fIORead=1;
|
24 |
|
|
fIOWrite fIOWrite=1;
|
25 |
|
|
|
26 |
|
|
//-----------------------------------------------------------------------------------------
|
27 |
|
|
// Basic timing control
|
28 |
|
|
//-----------------------------------------------------------------------------------------
|
29 |
|
|
:valid
|
30 |
8 |
gdevic |
Y validPLA=1;
|
31 |
3 |
gdevic |
:nextM
|
32 |
8 |
gdevic |
Y nextM=1;
|
33 |
3 |
gdevic |
mr nextM=1; ctl_mRead=1;
|
34 |
|
|
mw nextM=1; ctl_mWrite=1;
|
35 |
|
|
ior nextM=1; ctl_iorw=1;
|
36 |
|
|
iow nextM=1; ctl_iorw=1;
|
37 |
8 |
gdevic |
CC nextM=~flags_cond_true;
|
38 |
3 |
gdevic |
INT nextM=1; ctl_mRead=in_intr & im2; // RST38 interrupt extension
|
39 |
|
|
:setM1
|
40 |
8 |
gdevic |
Y setM1=1;
|
41 |
|
|
SS setM1=~flags_cond_true;
|
42 |
|
|
CC setM1=~flags_cond_true;
|
43 |
|
|
ZF setM1=flags_zf; // Used in DJNZ
|
44 |
|
|
BR setM1=nonRep | ~repeat_en;
|
45 |
|
|
BRZ setM1=nonRep | ~repeat_en | flags_zf;
|
46 |
7 |
gdevic |
BZ setM1=nonRep | flags_zf;
|
47 |
8 |
gdevic |
INT setM1=~(in_intr & im2); // RST38 interrupt extension
|
48 |
3 |
gdevic |
|
49 |
|
|
//-----------------------------------------------------------------------------------------
|
50 |
|
|
// Register file, address (downstream) endpoint
|
51 |
|
|
//-----------------------------------------------------------------------------------------
|
52 |
|
|
:A:reg rd
|
53 |
|
|
// General purpose registers
|
54 |
|
|
A ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10; ctl_sw_4d=1; // Read 8-bit general purpose A register, enable SW4 downstream
|
55 |
|
|
r16 ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit general purpose register, enable SW4 downstream
|
56 |
|
|
BC ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit BC, enable SW4 downstream
|
57 |
|
|
DE ctl_reg_gp_sel=`GP_REG_DE; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit DE, enable SW4 downstream
|
58 |
|
|
HL ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit HL, enable SW4 downstream
|
59 |
|
|
SP ctl_reg_use_sp=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1;// Read 16-bit SP, enable SW4 downstream
|
60 |
|
|
|
61 |
|
|
// System registers
|
62 |
8 |
gdevic |
WZ ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4d=1; // Select 16-bit WZ
|
63 |
|
|
IR ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit IR
|
64 |
|
|
I* ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4d=1; // Select 8-bit I register
|
65 |
|
|
PC ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit PC
|
66 |
3 |
gdevic |
|
67 |
|
|
// Conditional assertions of WZ, HL instead of PC
|
68 |
8 |
gdevic |
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;
|
69 |
|
|
// Alternate format:
|
70 |
|
|
// if (flags_cond_true) begin // If cc is true, use WZ instead of PC (for jumps)
|
71 |
|
|
// ctl_reg_not_pc=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4d=1;
|
72 |
|
|
// end
|
73 |
3 |
gdevic |
|
74 |
|
|
:A:reg wr
|
75 |
|
|
// General purpose registers
|
76 |
|
|
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
|
77 |
|
|
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
|
78 |
|
|
DE ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_DE; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit BC, enable SW4 upstream
|
79 |
|
|
HL ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit HL, enable SW4 upstream
|
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
|
81 |
|
|
// System registers
|
82 |
|
|
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
|
83 |
|
|
IR ctl_reg_sys_we=1; ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Write 16-bit IR
|
84 |
|
|
// PC will not be incremented if we are in HALT, INTR or NMI state
|
85 |
8 |
gdevic |
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
|
86 |
3 |
gdevic |
> ctl_sw_4u=1;
|
87 |
|
|
|
88 |
|
|
//-----------------------------------------------------------------------------------------
|
89 |
|
|
// Controls the address latch incrementer, the address latch and the address pin mux
|
90 |
|
|
//-----------------------------------------------------------------------------------------
|
91 |
|
|
:inc/dec
|
92 |
8 |
gdevic |
+ ctl_inc_cy=~pc_inc_hold; // Increment
|
93 |
|
|
- ctl_inc_cy=~pc_inc_hold; ctl_inc_dec=1; // Decrement
|
94 |
|
|
op3 ctl_inc_cy=~pc_inc_hold; ctl_inc_dec=op3; // Decrement if op3 is set; increment otherwise
|
95 |
3 |
gdevic |
|
96 |
|
|
:A:latch
|
97 |
|
|
W ctl_al_we=1; // Write a value from the register bus to the address latch
|
98 |
|
|
R ctl_bus_inc_oe=1; // Output enable incrementer to the register bus
|
99 |
|
|
P ctl_apin_mux=1; // Apin sourced from incrementer
|
100 |
|
|
RL ctl_bus_inc_oe=1; ctl_apin_mux2=1; // Apin sourced from AL
|
101 |
|
|
|
102 |
|
|
//-----------------------------------------------------------------------------------------
|
103 |
|
|
// Register file, data (upstream) endpoint
|
104 |
|
|
//-----------------------------------------------------------------------------------------
|
105 |
|
|
:D:reg rd
|
106 |
|
|
//----- General purpose registers -----
|
107 |
|
|
A ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
108 |
|
|
AF ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11;
|
109 |
|
|
B ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
110 |
|
|
H ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b10;
|
111 |
|
|
L ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b01;
|
112 |
8 |
gdevic |
r8 ctl_reg_gp_sel=op21; ctl_reg_gp_hilo={~rsel0,rsel0};// Read 8-bit GP register selected by op[2:0]
|
113 |
|
|
r8' \ // r8 addressing does not allow reading F register (indices of A and F are also swapped) (ex. in OUT (c),r)
|
114 |
|
|
if (op4 & op5 & ~op3) begin ctl_bus_zero_oe=1; end // Trying to read flags? Put 0 on the bus instead.
|
115 |
|
|
if (~(op4 & op5 & ~op3)) begin ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={~rsel3,rsel3}; end // Read 8-bit GP register
|
116 |
3 |
gdevic |
rh ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Read 8-bit GP register high byte
|
117 |
|
|
rl ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Read 8-bit GP register low byte
|
118 |
|
|
//----- System registers -----
|
119 |
|
|
WZ ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4u=1;
|
120 |
|
|
Z ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1; // Selecting strictly Z
|
121 |
8 |
gdevic |
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)
|
122 |
3 |
gdevic |
PCh ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4u=1;
|
123 |
|
|
PCl ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1;
|
124 |
|
|
|
125 |
|
|
:D:reg wr
|
126 |
|
|
? // Which register to be written is decided elsewhere
|
127 |
|
|
//----- General purpose registers -----
|
128 |
|
|
A ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
129 |
|
|
F ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b01;
|
130 |
|
|
B ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
131 |
8 |
gdevic |
r8 ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={~rsel3,rsel3}; // Write 8-bit GP register
|
132 |
|
|
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]
|
133 |
3 |
gdevic |
rh ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Write 8-bit GP register high byte
|
134 |
|
|
rl ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Write 8-bit GP register low byte
|
135 |
|
|
//----- System registers -----
|
136 |
8 |
gdevic |
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)
|
137 |
3 |
gdevic |
WZ ctl_reg_sys_we=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11;
|
138 |
8 |
gdevic |
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
|
139 |
|
|
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
|
140 |
|
|
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
|
141 |
3 |
gdevic |
|
142 |
|
|
//-----------------------------------------------------------------------------------------
|
143 |
|
|
// Controls the register file gate connecting it with the ALU and data bus
|
144 |
|
|
//-----------------------------------------------------------------------------------------
|
145 |
|
|
:Reg gate
|
146 |
|
|
< ctl_reg_in_hi=1; ctl_reg_in_lo=1; // From the ALU side into the register file
|
147 |
|
|
|
148 |
|
|
|
149 |
|
|
|
150 |
8 |
gdevic |
> ctl_reg_out_hi=1; ctl_reg_out_lo=1; // From the register file into the FLAGT and ALU
|
151 |
|
|
|
152 |
|
|
// Enables a register gate (high/low) corresponding to the selected 8-bit register
|
153 |
|
|
>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
|
154 |
|
|
>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
|
155 |
|
|
|
156 |
|
|
>l ctl_reg_out_lo=1; // From the register file onto the db1 (sw2 + FLAGT + sw1)
|
157 |
|
|
>h ctl_reg_out_hi=1; // From the register file onto the db2 (sw2 + ALU)
|
158 |
|
|
|
159 |
3 |
gdevic |
//-----------------------------------------------------------------------------------------
|
160 |
|
|
// Switches on the data bus for each direction (upstream, downstream)
|
161 |
|
|
//-----------------------------------------------------------------------------------------
|
162 |
|
|
:SW2
|
163 |
|
|
d ctl_sw_2d=1;
|
164 |
|
|
u ctl_sw_2u=1;
|
165 |
8 |
gdevic |
- // Controlled by register gate
|
166 |
3 |
gdevic |
|
167 |
|
|
:SW1
|
168 |
|
|
< ctl_sw_1d=1;
|
169 |
|
|
> ctl_sw_1u=1;
|
170 |
|
|
|
171 |
|
|
//-----------------------------------------------------------------------------------------
|
172 |
|
|
// Data bus latches and pads control
|
173 |
|
|
//-----------------------------------------------------------------------------------------
|
174 |
|
|
:DB pads
|
175 |
|
|
R ctl_bus_db_oe=1; // Read DB pads to internal data bus
|
176 |
|
|
W ctl_bus_db_we=1; // Write DB pads with internal data bus value
|
177 |
|
|
00 ctl_bus_zero_oe=1; // Force 0x00 on the data bus
|
178 |
|
|
FF ctl_bus_ff_oe=1; // Force 0xFF on the data bus
|
179 |
|
|
|
180 |
|
|
//-----------------------------------------------------------------------------------------
|
181 |
|
|
// ALU
|
182 |
|
|
//-----------------------------------------------------------------------------------------
|
183 |
|
|
:ALU
|
184 |
|
|
// Controls the master ALU output enable and the ALU input, only one can be active at a time
|
185 |
|
|
// >bs if set, will override >s0 which is used by bit instructions to override default M1/T3 load
|
186 |
|
|
< ctl_alu_oe=1; // Enable ALU onto the data bus
|
187 |
8 |
gdevic |
>s0 ctl_alu_shift_oe=~ctl_alu_bs_oe; // Shifter unit without shift-enable
|
188 |
3 |
gdevic |
>s1 ctl_alu_shift_oe=1; ctl_shift_en=1; // Shifter unit AND shift enable!
|
189 |
|
|
>bs ctl_alu_bs_oe=1; // Bit-selector unit
|
190 |
|
|
|
191 |
|
|
:ALU bus
|
192 |
|
|
// Controls the writer to the internal ALU bus
|
193 |
|
|
op1 ctl_alu_op1_oe=1; // OP1 latch
|
194 |
|
|
op2 ctl_alu_op2_oe=1; // OP2 latch
|
195 |
|
|
res ctl_alu_res_oe=1; // Result latch
|
196 |
|
|
|
197 |
|
|
:op2 latch
|
198 |
|
|
// Controls a MUX to select the input to the OP2 latch
|
199 |
|
|
bus ctl_alu_op2_sel_bus=1; // Internal bus
|
200 |
|
|
lq ctl_alu_op2_sel_lq=1; // Cross-bus wire (see schematic)
|
201 |
|
|
|
202 |
|
|
|
203 |
|
|
:op1 latch
|
204 |
|
|
// Controls a MUX to select the input to the OP1 latch
|
205 |
|
|
bus ctl_alu_op1_sel_bus=1; // Internal bus
|
206 |
|
|
low ctl_alu_op1_sel_low=1; // Write low nibble with a high nibble
|
207 |
|
|
|
208 |
|
|
|
209 |
|
|
:operation
|
210 |
8 |
gdevic |
// Defines the ALU core compute operation
|
211 |
|
|
// The listing is also showing their alternate formats (using if/then)
|
212 |
|
|
//-----------------------------------------------------------------------------------------
|
213 |
|
|
CP ctl_alu_sel_op2_neg=1; ctl_flags_cf_set|=ctl_alu_op_low; ctl_alu_core_hf|=~ctl_alu_op_low;
|
214 |
|
|
// ctl_alu_sel_op2_neg=1;
|
215 |
|
|
// if (ctl_alu_op_low) begin
|
216 |
|
|
// ctl_flags_cf_set=1;
|
217 |
|
|
// end else begin
|
218 |
|
|
// ctl_alu_core_hf=1;
|
219 |
|
|
// end
|
220 |
|
|
//-----------------------------------------------------------------------------------------
|
221 |
|
|
SUB ctl_alu_sel_op2_neg=1; ctl_flags_cf_set|=ctl_alu_op_low; ctl_alu_core_hf|=~ctl_alu_op_low;
|
222 |
|
|
// ctl_alu_sel_op2_neg=1;
|
223 |
|
|
// if (ctl_alu_op_low) begin
|
224 |
|
|
// ctl_flags_cf_set=1;
|
225 |
|
|
// end else begin
|
226 |
|
|
// ctl_alu_core_hf=1;
|
227 |
|
|
// end
|
228 |
|
|
//-----------------------------------------------------------------------------------------
|
229 |
|
|
SBC ctl_alu_sel_op2_neg=1; ctl_flags_cf_cpl|=ctl_alu_op_low; ctl_alu_core_hf|=~ctl_alu_op_low;
|
230 |
|
|
// ctl_alu_sel_op2_neg=1;
|
231 |
|
|
// if (ctl_alu_op_low) begin
|
232 |
|
|
// ctl_flags_cf_cpl=1;
|
233 |
|
|
// end else begin
|
234 |
|
|
// ctl_alu_core_hf=1;
|
235 |
|
|
// end
|
236 |
|
|
//-----------------------------------------------------------------------------------------
|
237 |
|
|
SBCh ctl_alu_sel_op2_neg=1; ctl_alu_core_hf|=~ctl_alu_op_low;
|
238 |
|
|
// ctl_alu_sel_op2_neg=1;
|
239 |
|
|
// if (~ctl_alu_op_low) begin
|
240 |
|
|
// ctl_alu_core_hf=1;
|
241 |
|
|
// end
|
242 |
|
|
//-----------------------------------------------------------------------------------------
|
243 |
|
|
ADC ctl_alu_core_hf|=~ctl_alu_op_low;
|
244 |
|
|
// if (~ctl_alu_op_low) begin
|
245 |
|
|
// ctl_alu_core_hf=1;
|
246 |
|
|
// end
|
247 |
|
|
//-----------------------------------------------------------------------------------------
|
248 |
|
|
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;
|
249 |
|
|
// if (ctl_alu_op_low) begin
|
250 |
|
|
// ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
251 |
|
|
// end else begin
|
252 |
|
|
// ctl_alu_core_hf=1;
|
253 |
|
|
// end
|
254 |
|
|
//-----------------------------------------------------------------------------------------
|
255 |
|
|
AND ctl_alu_core_S=1; ctl_flags_cf_set=1;
|
256 |
3 |
gdevic |
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;
|
257 |
8 |
gdevic |
XOR ctl_alu_core_R=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
258 |
|
|
NAND ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_alu_sel_op2_neg=1;
|
259 |
3 |
gdevic |
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;
|
260 |
8 |
gdevic |
//-----------------------------------------------------------------------------------------
|
261 |
3 |
gdevic |
|
262 |
|
|
PLA ctl_state_alu=1; // Assert the ALU PLA modifier to determine operation
|
263 |
|
|
|
264 |
|
|
:nibble
|
265 |
8 |
gdevic |
// ALU compute phase: working on low nibble or high nibble
|
266 |
3 |
gdevic |
L ctl_alu_op_low=1; // Activate ALU operation on low nibble
|
267 |
|
|
H ctl_alu_sel_op2_high=1; // Activate ALU operation on high nibble
|
268 |
|
|
|
269 |
|
|
//-----------------------------------------------------------------------------------------
|
270 |
|
|
// FLAGT
|
271 |
|
|
//-----------------------------------------------------------------------------------------
|
272 |
|
|
:FLAGT
|
273 |
|
|
< ctl_flags_oe=1; // Enable FLAGT onto the data bus
|
274 |
|
|
> ctl_flags_bus=1; // Load FLAGT from the data bus
|
275 |
|
|
alu ctl_flags_alu=1; // Load FLAGT from the ALU
|
276 |
|
|
|
277 |
|
|
// Write enables for various flag bits and segments
|
278 |
|
|
:SZ
|
279 |
|
|
* ctl_flags_sz_we=1;
|
280 |
|
|
:XY
|
281 |
|
|
* ctl_flags_xy_we=1;
|
282 |
|
|
?
|
283 |
|
|
:HF
|
284 |
|
|
* ctl_flags_hf_we=1;
|
285 |
|
|
W2 ctl_flags_hf2_we=1; // Write HF2 flag (DAA only)
|
286 |
|
|
:PF
|
287 |
|
|
* ctl_flags_pf_we=1;
|
288 |
|
|
P ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_P;
|
289 |
|
|
V ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_V;
|
290 |
|
|
iff2 ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_IFF2;
|
291 |
|
|
REP ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_REP;
|
292 |
|
|
?
|
293 |
|
|
:NF
|
294 |
|
|
* ctl_flags_nf_we=1; // Previous NF, to be used when loading FLAGT
|
295 |
|
|
|
296 |
|
|
1 ctl_flags_nf_we=1; ctl_flags_nf_set=1;
|
297 |
|
|
S ctl_flags_nf_we=1; // Sign bit, to be used with FLAGT source set to "alu"
|
298 |
|
|
?
|
299 |
|
|
:CF
|
300 |
|
|
* ctl_flags_cf_we=1;
|
301 |
|
|
|
302 |
|
|
1 ctl_flags_cf_set=1; // Set CF going into the ALU core
|
303 |
|
|
^ ctl_flags_cf_we=1; ctl_flags_cf_cpl=1; // CCF
|
304 |
|
|
:CF2
|
305 |
|
|
R ctl_flags_use_cf2=1;
|
306 |
8 |
gdevic |
W ctl_flags_cf2_we=1;
|
307 |
|
|
W.sh ctl_flags_cf2_we=1; ctl_flags_cf2_sel_shift=1;
|
308 |
|
|
W.daa ctl_flags_cf2_we=1; ctl_flags_cf2_sel_daa=1;
|
309 |
3 |
gdevic |
|
310 |
8 |
gdevic |
//------------------------------------------------------------------------------------------
|
311 |
|
|
// Macros for some special cases; also simplifies control logic for a number of instructions
|
312 |
|
|
//------------------------------------------------------------------------------------------
|
313 |
3 |
gdevic |
:Special
|
314 |
|
|
USE_SP ctl_reg_use_sp=1; // For 16-bit loads: use SP instead of AF
|
315 |
|
|
|
316 |
|
|
// A few more specific states and instructions:
|
317 |
|
|
Ex_DE_HL ctl_reg_ex_de_hl=1; // EX DE,HL
|
318 |
|
|
Ex_AF_AF' ctl_reg_ex_af=1; // EX AF,AF'
|
319 |
|
|
EXX ctl_reg_exx=1; // EXX
|
320 |
|
|
HALT ctl_state_halt_set=1; // Enter HALT state
|
321 |
|
|
DI_EI ctl_iffx_bit=op3; ctl_iffx_we=1; // DI/EI
|
322 |
|
|
IM ctl_im_we=1; // IM n ('n' is read by opcode[4:3])
|
323 |
|
|
|
324 |
|
|
WZ=IX+d ixy_d=1; // Compute WZ=IX+d
|
325 |
|
|
IX_IY ctl_state_ixiy_we=1; ctl_state_iy_set=op5; setIXIY=1; // IX/IY prefix
|
326 |
13 |
gdevic |
CLR_IX_IY ctl_state_ixiy_we=1; ctl_state_ixiy_clr=~setIXIY; // Clear IX/IY flag if not explicitly set
|
327 |
3 |
gdevic |
|
328 |
13 |
gdevic |
CB ctl_state_tbl_we=1; ctl_state_tbl_cb_set=1; // CB-table prefix
|
329 |
|
|
ED ctl_state_tbl_we=1; ctl_state_tbl_ed_set=1; // ED-table prefix
|
330 |
|
|
CLR_CB_ED ctl_state_tbl_we=1; // Clear CB/ED prefix if not explicitly set
|
331 |
3 |
gdevic |
|
332 |
|
|
// If the NF is set, complement HF and CF on the way out to the bus
|
333 |
|
|
// This is used to correctly set those flags after subtraction operations
|
334 |
|
|
?NF_HF_CF ctl_flags_hf_cpl=flags_nf; ctl_flags_cf_cpl=flags_nf;
|
335 |
|
|
?NF_HF ctl_flags_hf_cpl=flags_nf;
|
336 |
8 |
gdevic |
?~CF_HF ctl_flags_hf_cpl=~flags_cf; // Used for CCF
|
337 |
3 |
gdevic |
?SF_NEG ctl_alu_sel_op2_neg=flags_sf;
|
338 |
|
|
NEG_OP2 ctl_alu_sel_op2_neg=1;
|
339 |
8 |
gdevic |
?NF_SUB ctl_alu_sel_op2_neg=flags_nf; ctl_flags_cf_cpl=~flags_nf;
|
340 |
3 |
gdevic |
|
341 |
|
|
// M1 opcode read cycle and the refresh register increment cycle
|
342 |
|
|
// Write opcode into the instruction register through internal db0 bus:
|
343 |
|
|
OpcodeToIR ctl_ir_we=1;
|
344 |
8 |
gdevic |
|
345 |
3 |
gdevic |
// At the common instruction load M1/T3, override opcode byte when servicing interrupts:
|
346 |
|
|
// 1. We are in HALT mode: push NOP (0x00) instead
|
347 |
|
|
// 2. We are in INTR mode (IM1 or IM2): push RST38 (0xFF) instead
|
348 |
|
|
// 3. We are in NMI mode: push RST38 (0xFF) instead
|
349 |
|
|
OverrideIR ctl_bus_zero_oe=in_halt; ctl_bus_ff_oe=(in_intr & (im1 | im2)) | in_nmi;
|
350 |
|
|
|
351 |
8 |
gdevic |
// RST instruction uses opcode[5:3] to specify a vector and this macro passes those 3 bits through
|
352 |
|
|
MASK_543 ctl_sw_mask543_en=~((in_intr & im2) | in_nmi);
|
353 |
|
|
// Based on the in_nmi state:
|
354 |
3 |
gdevic |
// 1. Disable SW1 so the opcode will not get onto db1 bus
|
355 |
|
|
// 2. Generate 0x66 on the db1 bus which will be used as the target vector address
|
356 |
|
|
// 3. Clear IFF1 (done by the nmi logic on posedge of in_nmi)
|
357 |
8 |
gdevic |
RST_NMI ctl_sw_1d=~in_nmi; ctl_66_oe=in_nmi;
|
358 |
|
|
// Based on the in_intr state:
|
359 |
3 |
gdevic |
// 1. IM1 mode, force 0xFF on the db0 bus
|
360 |
|
|
// 2. Clear IFF1 and IFF2 (done by the intr logic on posedge of in_intr)
|
361 |
|
|
RST_INT ctl_bus_ff_oe=in_intr & im1;
|
362 |
|
|
RETN ctl_iff1_iff2=1; // RETN copies IFF2 into IFF1
|
363 |
|
|
NO_INTS ctl_no_ints=1; // Disable interrupt generation for this opcode (DI/EI/CB/ED/DD/FD)
|
364 |
|
|
|
365 |
|
|
EvalCond ctl_eval_cond=1; // Evaluate flags condition based on the opcode[5:3]
|
366 |
|
|
CondShort ctl_cond_short=1; // M1/T3 only: force a short flags condition (SS)
|
367 |
|
|
Limit6 ctl_inc_limit6=1; // Limit the incrementer to 6 bits
|
368 |
|
|
DAA ctl_daa_oe=1; // Write DAA correction factor to the bus
|
369 |
|
|
ZERO_16BIT ctl_alu_zero_16bit=1; // 16-bit arithmetic operation uses ZF calculated over 2 bytes
|
370 |
|
|
NonRep nonRep=1; // Non-repeating block instruction
|
371 |
|
|
WriteBC=1 ctl_repeat_we=1; // Update repeating flag latch with BC=1 status
|
372 |
|
|
NOT_PC! ctl_reg_not_pc=1; // For M1/T1 load from a register other than PC
|