OpenCores
URL https://opencores.org/ocsvn/next186/next186/trunk

Subversion Repositories next186

[/] [next186/] [trunk/] [Next186_CPU.v] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
2
//
3
// This file is part of the Next186 project
4
// http://opencores.org/project,next186
5
//
6
// Filename: Next186_CPU.v
7
// Description: Implementation of 80186 instruction compatible CPU
8
// Version 1.0
9
// Creation date: 24Mar2011 - 07Jun2011
10
//
11
// Author: Nicolae Dumitrache 
12
// e-mail: ndumitrache@opencores.org
13
//
14
/////////////////////////////////////////////////////////////////////////////////
15
// 
16
// Copyright (C) 2011 Nicolae Dumitrache
17
// 
18
// This source file may be used and distributed without 
19
// restriction provided that this copyright statement is not 
20
// removed from the file and that any derivative work contains 
21
// the original copyright notice and the associated disclaimer.
22
// 
23
// This source file is free software; you can redistribute it 
24
// and/or modify it under the terms of the GNU Lesser General 
25
// Public License as published by the Free Software Foundation;
26
// either version 2.1 of the License, or (at your option) any 
27
// later version. 
28
// 
29
// This source is distributed in the hope that it will be 
30
// useful, but WITHOUT ANY WARRANTY; without even the implied 
31
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
32
// PURPOSE. See the GNU Lesser General Public License for more 
33
// details. 
34
// 
35
// You should have received a copy of the GNU Lesser General 
36
// Public License along with this source; if not, download it 
37
// from http://www.opencores.org/lgpl.shtml 
38
// 
39
///////////////////////////////////////////////////////////////////////////////////
40
//
41
// Comments:
42
// This project was developed and tested on a XILINX Spartan3AN board.
43
//
44
//      Next186 processor features:
45
//              All 80186 intstructions are implemented according with the 80186 specifications
46
//              Designed with 2 buses: 16bit/20bit data/data_address and 48bit/20bit instruction/instruction_address.
47
//              This allows most instructions to be executed in one clock cycle.
48
//              In order to couple the CPU unit with a single bus, these sepparate data/instruction buses must be multiplexed by
49
//                      a dedicated bus interface unit (BIU).
50
//              It is able to execute up to 40Mips on Spartan XC3S700AN speed grade -4, performances comparable with a 486 CPU.
51
//              Small size, the CPU + BIU requires ~25%  or 1500 slices - on Spartan XC3S700AN
52
// 
53
///////////////////////////////////////////////////////////////////////////////////
54
`timescale 1ns / 1ps
55
 
56
module Next186_CPU(
57
    output [19:0] ADDR,
58
    input [15:0] DIN,
59
    output [15:0] DOUT,
60
         input CLK,
61
         input CE,
62
         input INTR,
63
         input NMI,
64
         input RST,
65
         output reg MREQ,
66
         output wire IORQ,
67
         output reg INTA,
68
         output reg WR,
69
         output reg WORD,
70
         output LOCK,
71
         output [19:0]IADDR,
72
         input [47:0]INSTR,
73
         output reg IFETCH,
74
         output FLUSH,
75
         output reg [2:0]ISIZE,
76
         output reg HALT
77
    );
78
 
79
// connections  
80
        wire [15:0]RA;
81
        wire [15:0]RB;
82
        wire [15:0]TMP16;
83
        wire [15:0]SP;
84
        wire [15:0]IP;
85
        wire [15:0]AX;
86
        wire [15:0]BX;
87
        wire [15:0]BP;
88
        wire [15:0]SI;
89
        wire [15:0]DI;
90
        wire [15:0]DX;
91
        wire [15:0]FLAGS;
92
        wire [15:0]FIN;
93
        wire [15:0]ALUOUT;
94
        wire [15:0]AIMM1;
95
        reg [15:0]DIMM1;
96
        wire [15:0]RS;
97
        wire [15:0]ADDR16;
98
        wire [15:0]CS;
99
        wire ALUCONT;
100
        wire NULLSHIFT;
101
        wire [1:0]CXZ;
102
        wire COUT; // adder carry out
103
        wire DIVEXC; // exit carry for unsigned DIV 
104
        wire SOUT; // adder sign out
105
 
106
// Registers
107
        reg [7:0]FETCH[5:0];
108
        reg [6:0]STAGE = 0;
109
        reg [5:0]CPUStatus = 0;   //1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=LOCK
110
        reg TZF = 0, TLF = 0;
111
        reg SRST = 0;
112
        reg SNMI = 0, FNMI = 0;
113
        reg SINTR = 0;
114
        reg [15:0]CRTIP; // current instruction ptr (used by interrupts)
115
        reg DIVQSGN;
116
        reg RDIVEXC;
117
 
118
// control      
119
        reg [2:0]RASEL;
120
        reg [2:0]RBSEL;
121
        reg BASEL;
122
        reg [1:0]BBSEL;
123
        reg [1:0]RSSEL;
124
        reg [4:0]WE; // 4=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
125
        reg [4:0]ALUOP;
126
        reg [3:0]EAC;
127
        reg [1:0]DISEL;
128
        reg [1:0]ISEL;
129
        reg ASEL;
130
        reg AEXT;
131
        reg DEXT;
132
        reg [1:0]DOSEL;
133
        reg IPWSEL;
134
        reg [5:0]status; //1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=lock
135
        reg NOBP;
136
        reg ALUSTAGE;   // inc STAGE with 2
137
        reg DIVSTAGE;  // inc STAGE with 4
138
        reg DISP16;
139
        reg DECCX;
140
        reg IRQ;
141
        reg [2:0]IRQL;
142
        reg REPINT;
143
        reg [5:0]ICODE1 = 23;
144
        reg NULLSEG;
145
        reg DIVOP;
146
 
147
// signals
148
        assign IORQ = &EAC;
149
        assign LOCK = CPUStatus[5];
150
        assign FLUSH = ~IPWSEL || (ISIZE == 3'b000);
151
        wire [15:0]IPADD = ISIZE == 3'b000 ? CRTIP : IP + ISIZE;
152
        wire [15:0]IPIN = IPWSEL ? IPADD : ALUOUT;
153
        wire [1:0]MOD = FETCH[1][7:6];
154
        wire [2:0]REG = FETCH[1][5:3];
155
        wire [2:0]RM  = FETCH[1][2:0];
156
        wire USEBP = RM[1] && ~&RM;
157
        wire POP = {EAC[3], EAC[1:0]} == 3'b101;
158
        wire [15:0]ADDR16_SP = POP ? SP : ADDR16;
159
        wire [1:0]WBIT = {WORD | RASEL[2], WORD | !RASEL[2]};
160
        wire [1:0]ISELS = {DISP16 | AEXT, DISP16 | ~AEXT};
161
        wire [2:0]ISIZES = DISP16 ? 4 : AEXT ? 3 : 2;
162
        reg  [2:0]ISIZEW;
163
        reg  [2:0]ISIZEI;        // ise imm
164
        wire [1:0]WRBIT = WR ? 2'b00 : WBIT;
165
        wire RCXZ = CPUStatus[4] && ~|CXZ;
166
        wire NRORCXLE1 = ~CPUStatus[4] || ~CXZ[1];
167
        wire [7:0]JMPC = {(FLAGS[7] ^ FLAGS[11]) | FLAGS[6], FLAGS[7] ^ FLAGS[11], FLAGS[2], FLAGS[7], FLAGS[0] | FLAGS[6], FLAGS[6], FLAGS[0], FLAGS[11]};
168
        wire [3:0]LOOPC = {CXZ != 2'b00, CXZ == 2'b01, CXZ == 2'b01 || !FLAGS[6], CXZ == 2'b01 || FLAGS[6]};
169
        wire IDIV = FETCH[0][1] & FETCH[1][3];
170
        wire DIVRSGN = (WORD ? FETCH[3][7] : FETCH[2][7]) & IDIV;
171
        wire DIVSGN = DIVQSGN ^ DIVRSGN;
172
        wire DIVEND = FETCH[0][0] ? STAGE[6] : STAGE[5];
173
        wire DIVC = ((COUT & ~RDIVEXC) ^ ~DIVRSGN);
174
        wire QSGN = (WORD ? DX[15] : AX[15]) & IDIV;
175
// interrupts
176
        wire SAMPLEINT = ~(WE[2] & RASEL[1:0] == 2'b10) & ~status[2] & ~status[4] & ~status[5]; // not load SS, no prefix
177
        wire NMIACK = SNMI & ~FNMI;     // NMI acknowledged
178
        wire INTRACK = FLAGS[9] & (~WE[4] | FIN[9]) & SINTR;                    // INTR acknowledged (IF and not CLI in progress)
179
        wire IACK = IRQ | (SAMPLEINT & (NMIACK | INTRACK)) | (~WE[2] & ~HALT & FLAGS[8]); // interrupt acknowledged
180
 
181
        Next186_Regs REGS (
182
    .RASEL(RASEL),
183
    .RBSEL(RBSEL),
184
    .BASEL(BASEL),
185
    .BBSEL(BBSEL),
186
    .RSSEL(RSSEL),
187
    .DIN(DIN),
188
         .ALUOUT(ALUOUT),
189
         .ADDR16(ADDR16),
190
         .DIMM(DEXT ? {{8{DIMM1[7]}}, DIMM1[7:0]} : DIMM1),
191
    .WE(WE),
192
         .IFETCH(IFETCH),
193
    .RA(RA),
194
    .RB(RB),
195
    .TMP16(TMP16),
196
    .SP(SP),
197
    .IP(IP),
198
         .AX(AX),
199
         .BX(BX),
200
         .BP(BP),
201
         .SI(SI),
202
         .DI(DI),
203
         .DX(DX),
204
         .RS(RS),
205
         .FIN(FIN),
206
         .FOUT(FLAGS),
207
         .DISEL(DISEL),
208
         .WORD(WORD | &DISEL),
209
         .IPIN(IPIN),
210
         .CLK(CLK),
211
         .CLKEN(CE),
212
         .CS(CS),
213
         .INCSP(POP),
214
         .CXZ(CXZ),
215
         .DECCX(DECCX),
216
         .DIVOP(DIVOP),
217
         .DIVEND(DIVEND),
218
         .DIVSGN(DIVSGN),
219
         .DIVC(DIVC),
220
         .DIVEXC(DIVEXC)
221
    );
222
 
223
        Next186_ALU ALU16 (
224
         .RA(DOSEL == 2'b01 ? IPADD : RA),
225
         .RB(RB),
226
         .TMP16(TMP16),
227
         .FETCH23({FETCH[3], FETCH[2]}),
228
         .FIN(FLAGS),
229
         .FOUT(FIN),
230
         .ALUOP(ALUOP),
231
         .EXOP(FETCH[1][5:3]),
232
         .FLAGOP(FETCH[0][3:0]),
233
         .ALUOUT(ALUOUT),
234
         .WORD(WORD),
235
         .ALUCONT(ALUCONT),
236
         .NULLSHIFT(NULLSHIFT),
237
         .STAGE(STAGE[2:0]),
238
         .INC2(&DISEL), // when DISEL == 2'b11, inc/dec value is 2 if WORD and 1 if ~WORD
239
         .COUT(COUT),
240
         .SOUT(SOUT),
241
         .CLK(CLK)
242
         );
243
 
244
        Next186_EA EA (
245
    .SP(SP),
246
    .BX(BX),
247
    .BP(NOBP ? 16'h0000 : BP),
248
    .SI(SI),
249
    .DI(DI),
250
         .PIO(FETCH[0][3] ? DX : {8'h00, FETCH[1]}),
251
         .TMP16(TMP16),
252
         .AL(AX[7:0]),
253
    .AIMM(AEXT ? {{8{AIMM1[7]}}, AIMM1[7:0]} : (DISP16 ? AIMM1 : 16'h0000)),
254
    .ADDR16(ADDR16),
255
         .EAC(EAC)
256
    );
257
 
258
         assign DOUT = DOSEL[1] ? DOSEL[0] ? AX : TMP16 : DOSEL[0] ? IPADD : ALUOUT;
259
         assign ADDR = {{NULLSEG ? 16'h0000 : RS} + {4'b0000, ADDR16_SP[15:4]}, ADDR16_SP[3:0]};
260
         assign IADDR = {CS + {4'b0000, IPIN[15:4]}, IPIN[3:0]};
261
         assign AIMM1 = ASEL ? {FETCH[3], FETCH[2]} : {FETCH[2], FETCH[1]};
262
 
263
         always @(posedge CLK)
264
                if(CE) begin
265
                        if(SRST) begin          // reset
266
//                              FETCH[0] <= 8'h0f;
267
                                FETCH[0][0] <= 1'b1; // for word=1
268
                                ICODE1 <= 54;
269
                                FETCH[5][1:0] <= 2'b01;  // RESET
270
                                STAGE <= 4'b1000;
271
                        end else begin
272
                                if(IACK & (IFETCH | HALT | REPINT)) begin // interrupt sampled and acknowledged
273
                                        FETCH[0][1:0] <= 2'b11;
274
                                        ICODE1 <= 54;
275
                                        STAGE <= 4'b1000;
276
                                        FETCH[5][2:0] <= {HALT, 2'b00};
277
                                        if(IRQ) FETCH[2] <= IRQL != 3'b010 ? {5'b00000, IRQL} : FETCH[1];
278
                                        else if(NMIACK) begin
279
                                                FETCH[2] <= 8'h02;
280
                                                FNMI <= 1'b1;
281
                                        end else if(INTRACK) FETCH[5][1:0] <= 2'b10;
282
                                        else FETCH[2] <= 8'h01; // trap
283
                                end else if(IFETCH) begin               // no interrupt, fetch
284
                                        FETCH[5] <= INSTR[47:40];
285
                                        FETCH[4] <= INSTR[39:32];
286
                                        FETCH[3] <= INSTR[31:24];
287
                                        FETCH[2] <= INSTR[23:16];
288
                                        FETCH[1] <= INSTR[15:8];
289
                                        FETCH[0] <= INSTR[7:0];
290
                                        STAGE <= 0;
291
                                        CPUStatus[5:0] <= status[5:0];
292
                                        TZF <= status[3];
293
                                        ICODE1 <= ICODE(INSTR[7:0]);
294
                                end else begin          // no interrupt, no fetch
295
                                        STAGE <= STAGE + {DIVSTAGE, ALUSTAGE} + 1;
296
                                        if(&DOSEL) {FETCH[3], FETCH[2]} <= |DISEL ? DIN : RB;
297
                                        TZF <= FIN[6];          // zero flag for REP
298
                                        TLF <= FIN[7] != FIN[11];       // less flag for BOUND
299
                                end
300
                        end
301
                        if(IFETCH & ~status[2] & ~status[4] & ~status[5]) CRTIP <= IPIN; // no prefix
302
                        SRST <= RST;                            // level detection RST
303
                        SINTR <= INTR;                          // level detection INTR
304
                        if(NMI) SNMI <= 1'b1;   // edge detection NMI
305
                        else if(FNMI) begin
306
                                SNMI <= 1'b0;
307
                                FNMI <= 1'b0;
308
                        end
309
                        if(~|STAGE[1:0]) DIVQSGN <= QSGN;
310
                        RDIVEXC <= DIVOP & DIVEXC & ~IDIV; // bit 8/16 for unsigned DIV
311
                end
312
 
313
        always @(ISEL, FETCH[0], FETCH[1], FETCH[2], FETCH[3], FETCH[4], FETCH[5])
314
                case(ISEL)
315
                        2'b00: DIMM1 = {FETCH[2], FETCH[1]};
316
                        2'b01: DIMM1 = {FETCH[3], FETCH[2]};
317
                        2'b10: DIMM1 = {FETCH[4], FETCH[3]};
318
                        2'b11: DIMM1 = {FETCH[5], FETCH[4]};
319
                endcase
320
 
321
        always @(FETCH[0], WORD, DISP16, AEXT) begin
322
                case({WORD, DISP16, AEXT})
323
                        3'b000: ISIZEW = 3;
324
                        3'b001, 3'b100: ISIZEW = 4;
325
                        3'b010, 3'b101: ISIZEW = 5;
326
                        default: ISIZEW = 6;
327
                endcase
328
                case({FETCH[0][1:0] == 2'b01, DISP16, AEXT})
329
                        3'b000: ISIZEI = 3;
330
                        3'b001, 3'b100: ISIZEI = 4;
331
                        3'b110: ISIZEI = 6;
332
                        default: ISIZEI = 5;
333
                endcase
334
        end
335
 
336
         always @(FETCH[0], FETCH[1], FETCH[2], FETCH[3], FETCH[4], FETCH[5], MOD, REG, RM, CPUStatus, USEBP, NOBP, RASEL, ISIZEI, TLF, EAC, COUT, DIVEND, DIVC, QSGN,
337
                                 WBIT, ISIZES, ISELS, WRBIT, ISIZEW, STAGE, NULLSHIFT, ALUCONT, FLAGS, CXZ, RCXZ, NRORCXLE1, TZF, JMPC, LOOPC, ICODE1, DIVQSGN, DIVSGN, DIVRSGN, SOUT) begin
338
                WORD = FETCH[0][0];
339
                BASEL = FETCH[0][1] | &MOD;
340
                RASEL = FETCH[0][1] ? REG : RM; // destination
341
                BBSEL = {1'b0, !FETCH[0][1] | &MOD};
342
                RBSEL = FETCH[0][1] ? RM : REG; // source
343
                RSSEL = CPUStatus[2] ? CPUStatus[1:0] : (USEBP && !NOBP ? 2'b10 : 2'b11);
344
                WE = 5'b00000;          // 5=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
345
                ALUOP = 5'bxxxxx;
346
                EAC = {1'b0, RM};
347
                DISEL = 2'b01;          // ALU
348
                ISEL = 2'bxx;
349
                ASEL = 1'bx;
350
                AEXT = MOD == 2'b01;
351
                DEXT = 1'b0;
352
                DOSEL = 2'b00;  // ALU   
353
                MREQ = 1'b1;
354
                WR = 1'b0;
355
                ISIZE = 3'bxxx;
356
                IPWSEL = 1'b1;          // IP + ISIZE
357
                IFETCH = 1'b1;
358
                status = 6'b00x0xx;
359
 
360
                DISP16 = MOD == 2'b10 || NOBP;
361
                NOBP = {MOD, RM} == 5'b00110;
362
                HALT = 1'b0;
363
                INTA = 1'b0;
364
                ALUSTAGE = 1'b0;
365
                DIVSTAGE = 1'b0;
366
                DECCX = 1'b0;
367
                IRQ = 1'b0;
368
                IRQL = 3'b110;  // unused opcode
369
                REPINT = 1'b0;
370
                NULLSEG = 1'b0;
371
                DIVOP = 1'b0;
372
 
373
                case(ICODE1) // one hot synthesis
374
// --------------------------------  mov R/M to/from R/SR  --------------------------------
375
                        0: begin
376
                                if(FETCH[0][2]) WORD = 1'b1;
377
                                if(FETCH[0][2:1] == 2'b10) BBSEL = 2'b11; // RB = SR
378
                                ALUOP = 31;     // PASS B
379
                                DISEL = {1'b0, &MOD};
380
                                ASEL = 1'b1;
381
                                MREQ = ~&MOD;
382
                                WR = MREQ & !FETCH[0][1];
383
                                WE = WR ? 5'b00000 : &FETCH[0][2:1] ? {2'b00, FETCH[1][4:3] != 2'b01, 2'b00} : {3'b000, WBIT};           // RSSEL, RASEL_HI/RASEL_LO
384
                                ISIZE = ISIZES;
385
                        end
386
// --------------------------------  mov IMM to R/M  --------------------------------
387
                        1: begin
388
                                RASEL = RM; // destination
389
                                BBSEL = 2'b10;
390
                                ALUOP = 31;     // PASS B
391
                                ISEL = ISELS;
392
                                ASEL = 1'b1;
393
                                MREQ = ~&MOD;
394
                                WR = MREQ;
395
                                WE[1:0] = WRBIT;         // RASEL_HI/RASEL_LO
396
                                ISIZE = ISIZEW;
397
                        end
398
// --------------------------------  mov IMM to R --------------------------------
399
                        2: begin
400
                                WORD = FETCH[0][3];
401
                                RASEL = FETCH[0][2:0]; // destination
402
                                BBSEL = 2'b10;                          // imm
403
                                WE[1:0] = WBIT;          // RASEL_HI/RASEL_LO
404
                                ALUOP = 31;     // PASS B
405
                                ISEL = 2'b00;
406
                                MREQ = 1'b0;
407
                                ISIZE = WORD ? 3 : 2;
408
                        end
409
// --------------------------------  mov mem to/from ACC --------------------------------
410
                        3: begin
411
                                RASEL = 0; // ACC
412
                                BBSEL = 2'b01;          // reg
413
                                RBSEL = 0; // ACC
414
                                ALUOP = 31;     // PASS B
415
                                EAC = 4'b0110;
416
                                DISEL = 2'b00;
417
                                ASEL = 1'b0;
418
                                AEXT = 1'b0;
419
                                MREQ = 1'b1;
420
                                WR = FETCH[0][1];
421
                                WE[1:0] = WRBIT;         // IP, RASEL_HI/RASEL_LO
422
                                ISIZE = 3;
423
                                NOBP = 1'b1;
424
                        end
425
// --------------------------------  segment override prefix --------------------------------
426
                        4: begin
427
                                status = {CPUStatus[5:3], 1'b1, FETCH[0][4:3]};
428
                                MREQ = 1'b0;
429
                                ISIZE = 1;
430
                        end
431
// --------------------------------  rep prefix --------------------------------
432
                        5: begin
433
                                status = {CPUStatus[5], 1'b1, FETCH[0][0], CPUStatus[2:0]};
434
                                MREQ = 1'b0;
435
                                ISIZE = 1;
436
                        end
437
// --------------------------------  lock prefix --------------------------------
438
                        6: begin
439
                                status = {1'b1, CPUStatus[4:0]};
440
                                MREQ = 1'b0;
441
                                ISIZE = 1;
442
                        end
443
// --------------------------------  FF block --------------------------------
444
                        7:      begin
445
                                ISIZE = ISIZES;
446
                                case({FETCH[0][0], REG})
447
                // --------------------------------  push R/M --------------------------------
448
                                        4'b1110:
449
                                                if(!(&MOD || STAGE[0])) begin    // stage1, read data in TMP16
450
                                                        WE[3] = 1'b1;           // TMP16
451
                                                        DISEL = 2'b00;
452
                                                        ASEL = 1'b1;
453
                                                        IFETCH = 1'b0;
454
                                                end else begin          // stage2, push R/TMP16
455
                                                        RASEL = 3'b100;         // write SP
456
                                                        RSSEL = 2'b10;                  // SS
457
                                                        ALUOP = 31;     // PASS B
458
                                                        WE[1:0] = 2'b11;         // RASEL_HI/RASEL_LO
459
                                                        EAC = 4'b1000;                  // SP - 2
460
                                                        DISEL = 2'b10;                  // ADDR
461
                                                        WR = 1'b1;
462
                                                end
463
                // --------------------------------  inc/dec R/M --------------------------------
464
                                        4'b0000, 4'b1000, 4'b0001, 4'b1001: begin
465
                                                ASEL = 1'b1;
466
                                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
467
                                                        WE[3] = 1'b1;           // TMP16
468
                                                        DISEL = 2'b00;                  // DIN
469
                                                        IFETCH = 1'b0;
470
                                                end else begin                                          // stage2, execute and write            
471
                                                        BASEL = &MOD;
472
                                                        RASEL = RM;                     // destination
473
                                                        ALUOP = {2'b01, FETCH[1][5:3]};
474
                                                        MREQ = ~BASEL;
475
                                                        WR = MREQ;
476
                                                        WE = {3'b100, WRBIT};           // flags, IP, RASEL_HI, RASEL_LO
477
                                                end
478
                                        end
479
                // --------------------------------  call/jmp near R/M --------------------------------
480
                                        4'b1010, 4'b1100: begin
481
                                                if(!STAGE[0] && ~&MOD) begin     // stage1, load op in TMP16
482
                                                        ASEL = 1'b1;
483
                                                        WE[3] = 1'b1;           // TMP16
484
                                                        DISEL = 2'b00;                  // DIN
485
                                                        IFETCH = 1'b0;
486
                                                end else begin          // stage2, push IP, jump
487
                                                        RASEL = 3'b100;         // write SP
488
                                                        RSSEL = 2'b10;          // SS
489
                                                        ALUOP = 31;     // PASS B
490
                                                        EAC = 4'b1000;          // SP - 2
491
                                                        DISEL = 2'b10;          // ADDR
492
                                                        DOSEL = 2'b01;  // IP    
493
                                                        MREQ = REG[1];
494
                                                        WR = MREQ;
495
                                                        WE[1:0] = {WR, WR};
496
                                                        IPWSEL = 1'b0;          // ALU
497
                                                end
498
                                        end
499
                // --------------------------------  call/jmp far R/M --------------------------------
500
                                        4'b1011, 4'b1101: begin
501
                                                ALUOP = 31;                             // PASS B
502
                                                IRQ = &MOD;
503
                                                case({STAGE[1:0], REG[1]})
504
                                                        3'b001: begin   // stage1, push CS
505
                                                                RASEL = 3'b100;         // write SP
506
                                                                BBSEL = 2'b11;
507
                                                                RBSEL = 3'b001;                 // CS
508
                                                                RSSEL = 2'b10;                  // SS
509
                                                                EAC = 4'b1000;                  // SP - 2
510
                                                                DISEL = 2'b10;                  // ADDR
511
                                                                MREQ = ~IRQ;
512
                                                                WR = MREQ;
513
                                                                IFETCH = IRQ;
514
                                                                WE[1:0] = IRQ ? 2'b00 : 2'b11;                   // RASEL_HI/RASEL_LO
515
                                                                ISIZE = 0;
516
                                                        end
517
                                                        3'b011, 3'b000: begin   // stage2, read offset in FETCH, ADDR16 in TMP16
518
                                                                RASEL = 3'b100;                 // SP   - write SP to SP for getting ADDR16 to TMP16
519
                                                                BBSEL = 2'b01;
520
                                                                RBSEL = 3'b100;                 // SP
521
                                                                WE[3:0] = IRQ ? 4'b0000 : 4'b1011;                       // TMP16, RASEL_HI, RASEL_LO
522
                                                                ASEL = 1'b1;
523
                                                                DOSEL = 2'b11;                  // load FETCH with DIN
524
                                                                IFETCH = IRQ;
525
                                                                MREQ = ~IRQ;
526
                                                                ISIZE = 0;
527
                                                        end
528
                                                        3'b101, 3'b010: begin   // stage3, read CS
529
                                                                RASEL = 3'b001;                 // CS
530
                                                                WE[2] = 1'b1;                   // RSSEL
531
                                                                EAC = 4'b1011;                  // TMP16 + 2
532
                                                                DISEL = 2'b00;                  // DIN
533
                                                                IFETCH = 1'b0;
534
                                                        end
535
                                                        3'b111, 3'b100: begin   // stage4, push IP, jump
536
                                                                RASEL = 3'b100;         // write SP
537
                                                                BBSEL = 2'b10;          // imm
538
                                                                RSSEL = 2'b10;          // SS
539
                                                                EAC = 4'b1000;          // SP - 2
540
                                                                DISEL = 2'b10;          // ADDR
541
                                                                DOSEL = 2'b01;          // IP    
542
                                                                ISEL = 2'b01;
543
                                                                MREQ = REG[1];
544
                                                                WR = MREQ;
545
                                                                WE[1:0] = {WR, WR};
546
                                                                IPWSEL = 1'b0;          // ALU
547
                                                        end
548
                                                endcase
549
                                        end
550
                // --------------------------------  bad opcode --------------------------------
551
                                        default: begin
552
                                                MREQ = 1'b0;
553
                                                IRQ = 1'b1;
554
                                                ISIZE = 0;
555
                                        end
556
                                endcase
557
                        end
558
// --------------------------------  push R/SR --------------------------------
559
                        8: begin
560
                                WORD = 1'b1;
561
                                RASEL = 3'b100;         // write SP
562
                                BBSEL = {~FETCH[0][6], 1'b1};
563
                                RBSEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // source
564
                                RSSEL = 2'b10;                  // SS
565
                                EAC = 4'b1000;                  // SP - 2
566
                                DISEL = 2'b10;                  // ADDR
567
                                WE[1:0] = 2'b11;         // RASEL_HI/RASEL_LO
568
                                ALUOP = 31;                             // PASS B
569
                                WR = 1'b1;
570
                                ISIZE = 1;
571
                        end
572
// --------------------------------  push Imm --------------------------------
573
                        9: begin
574
                                WORD = 1'b1;
575
                                RASEL = 3'b100;         // write SP
576
                                BBSEL = 2'b10;                  // imm
577
                                RSSEL = 2'b10;                  // SS
578
                                WE[1:0] = 2'b11;         // RASEL_HI/RASEL_LO
579
                                ALUOP = 31;                             // PASS B
580
                                EAC = 4'b1000;                  // SP - 2
581
                                DISEL = 2'b10;                  // ADDR
582
                                ISEL = 2'b00;
583
                                DEXT = FETCH[0][1];
584
                                WR = 1'b1;
585
                                ISIZE = FETCH[0][1] ? 2 : 3;
586
                        end
587
// --------------------------------  pusha --------------------------------
588
                        10: begin
589
                                WORD = 1'b1;
590
                                RASEL = 3'b100;         // write SP
591
                                RBSEL = STAGE[2:0];  // source
592
                                RSSEL = 2'b10;                  // SS
593
                                ALUOP = 31;                             // PASS B
594
                                EAC = 4'b1000;                  // SP - 2
595
                                DISEL = 2'b10;                  // ADDR
596
                                WR = 1'b1;
597
                                ISIZE = 1;
598
                                IFETCH = &STAGE[2:0];
599
                                WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
600
                        end
601
// --------------------------------  pop R/M --------------------------------
602
                        11:
603
                                case(REG)
604
                                        3'b000: begin
605
                                                ISIZE = ISIZES;
606
                                                if(!STAGE[0]) begin      // pop TMP16/REG
607
                                                        RASEL = RM;             // destination
608
                                                        RSSEL = 2'b10;                  // SS
609
                                                        EAC = 4'b1001;                  // SP
610
                                                        DISEL = 2'b00;                  // DIN
611
                                                        IFETCH = &MOD;
612
                                                        WE[3:0] = IFETCH ? 4'b0011 : 4'b1000;            // TMP16, RASEL_HI, RASEL_LO
613
                                                end else begin                  // R/M <- TMP16
614
                                                        RASEL = RM; // destination
615
                                                        BBSEL = 2'b00;                  // TMP
616
                                                        ALUOP = 31;                             // PASS B
617
                                                        ASEL = 1'b1;
618
                                                        MREQ = ~&MOD;
619
                                                        WR = MREQ;
620
                                                        WE[1:0] = WR ? 2'b00 : 2'b11;            // RASEL_HI, RASEL_LO
621
                                                end
622
                                        end
623
                                        default:        begin           // bad opcode
624
                                                MREQ = 1'b0;
625
                                                ISIZE = 0;
626
                                                IRQ = 1'b1;
627
                                        end
628
                                endcase
629
// --------------------------------  pop R / SR --------------------------------
630
                        12: begin
631
                                WORD = 1'b1;
632
                                RASEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // destination
633
                                RSSEL = 2'b10;                  // SS
634
                                WE[2:0] = FETCH[0][6] ? 3'b011 : 3'b100;          // RSSEL, RASEL_HI, RASEL_LO
635
                                EAC = 4'b1001;                  // SP
636
                                DISEL = 2'b00;                  // DIN
637
                                ISIZE = 1;
638
                        end
639
// --------------------------------  popa --------------------------------
640
                        13: begin
641
                                RASEL = ~STAGE[2:0]; // destination
642
                                RSSEL = 2'b10;                  // SS
643
                                EAC = 4'b1001;                  // SP
644
                                DISEL = 2'b00;                  // DIN
645
                                ISIZE = 1;
646
                                IFETCH = &STAGE[2:0];
647
                                WE[1:0] = {STAGE[2:0] == 3'b011 ? 2'b00 : 2'b11};         // IP, RASEL_HI, RASEL_LO (skip SP)
648
                        end
649
// --------------------------------  xchg R with R/M/Acc --------------------------------
650
                        14: begin
651
                                WORD = FETCH[0][0] | FETCH[0][4];
652
                                ASEL = 1'b1;
653
                                MREQ = ~&MOD && !FETCH[0][4];
654
                                ALUOP = 31;                             // PASS B
655
                                ISIZE = FETCH[0][4] ? 1 : ISIZES;
656
                                if(!STAGE[0]) begin              // stage1, R/M/Acc -> REG -> TMP16
657
                                        BASEL = 1'b1;
658
                                        RASEL = FETCH[0][4] ? FETCH[0][2:0] : REG; // destination
659
                                        BBSEL = 2'b01;          // reg
660
                                        RBSEL = FETCH[0][4] ? 3'b000 : RM; // source
661
                                        DISEL = {1'b0, !MREQ};
662
                                        WE[1:0] = WBIT;          // RASEL_HI, RASEL_LO
663
                                        IFETCH = ~|FETCH[0][2:0]; // nop
664
                                end else begin          // stage2, TMP16 -> R/M/Acc
665
                                        RASEL = FETCH[0][4] ? 3'b000 : RM; // destination
666
                                        BBSEL = 2'b00;          // TMP16
667
                                        WR = MREQ;
668
                                        WE[1:0] = WRBIT;         // RASEL_HI, RASEL_LO
669
                                end
670
                        end
671
// --------------------------------  in --------------------------------
672
                        15:     begin
673
                                RASEL = 3'b000; // AX/AL
674
                                WE[1:0] = {WORD, 1'b1};          // RASEL_HI, RASEL_LO
675
                                DISEL = 2'b00;  //DIN
676
                                MREQ = 1'b0;
677
                                ISIZE = FETCH[0][3] ? 1 : 2;
678
                                EAC = 4'b1111;
679
                                NULLSEG = 1'b1;
680
                        end
681
// --------------------------------  out --------------------------------
682
                        16:     begin
683
                                DOSEL = 2'b11;  // AX
684
                                MREQ = 1'b0;
685
                                WR = 1'b1;
686
                                ISIZE = FETCH[0][3] ? 1 : 2;
687
                                EAC = 4'b1111;
688
                                NULLSEG = 1'b1;
689
                        end
690
// --------------------------------  xlat --------------------------------
691
                        17: begin
692
                                WORD = 1'b0;
693
                                RASEL = 3'b000;         // AL
694
                                WE[0] = 1'b1;            // RASEL_LO
695
                                EAC = 4'b1010;          // XLAT
696
                                DISEL = 2'b00;          // DIN 
697
                                ISIZE = 1;
698
                                NOBP = 1'b1;    // for RSSEL
699
                        end
700
// --------------------------------  lea --------------------------------
701
                        18: begin
702
                                RASEL = REG;                    // destination
703
                                WE[1:0] = {&MOD ? 2'b00 : 2'b11};                // RASEL_HI, RASEL_LO
704
                                DISEL = 2'b10;                  // EA
705
                                ASEL = 1'b1;
706
                                MREQ = 1'b0;
707
                                ISIZE = ISIZES;
708
                        end
709
// --------------------------------  lds, les --------------------------------
710
                        19: begin
711
                                WORD = 1'b1;
712
                                DISEL = 2'b00;                  // DIN
713
                                ASEL = 1'b1;
714
                                if(!STAGE[0]) begin              // stage1, load offset
715
                                        RASEL = REG;                    // destination
716
                                        IFETCH = &MOD;                  // bad opcode
717
                                        IRQ = IFETCH;
718
                                        ISIZE = 0;
719
                                        WE[3:0] = {2'b10, IFETCH ? 2'b00 : 2'b11};               // TMP16, RASEL_HI, RASEL_LO
720
                                end else begin                          // stage2, load segment
721
                                        RASEL = FETCH[0][0] ? 3'b011 : 3'b000; // ds/es
722
                                        WE[2] = 1'b1;                   // RSSEL
723
                                        EAC = 4'b1011;                  // TMP16 + 2
724
                                        ISIZE = ISIZES;
725
                                end
726
                        end
727
// --------------------------------  lahf, sahf --------------------------------
728
                        20: begin
729
                                WORD = 1'b0;
730
                                RASEL = 3'b100;                 // AH
731
                                WE = {!FETCH[0][0], 2'b00, FETCH[0][0], 1'b0};              // FLAGS, IP, RASEL_HI
732
                                ALUOP = FETCH[0][0] ? 30 : 31;                    // PASS/STORE FLAGS
733
                                MREQ = 1'b0;
734
                                ISIZE = 1;
735
                        end
736
// --------------------------------  pushf --------------------------------
737
                        21: begin
738
                                WORD = 1'b1;
739
                                RASEL = 3'b100;         // write SP
740
                                RSSEL = 2'b10;                  // SS
741
                                WE[1:0] = 2'b11;
742
                                ALUOP = 30;                             // pass flags
743
                                EAC = 4'b1000;                  // SP - 2
744
                                DISEL = 2'b10;                  // ADDR
745
                                WR = 1'b1;
746
                                ISIZE = 1;
747
                        end
748
// --------------------------------  popf --------------------------------
749
                        22: begin
750
                                ISIZE = 1;
751
                                IFETCH = STAGE[0];
752
                                if(!STAGE[0]) begin      // stage1, pop TMP16
753
                                        RSSEL = 2'b10;                  // SS
754
                                        WE[3] = 1'b1;                   // TMP16
755
                                        EAC = 4'b1001;                  // SP
756
                                        DISEL = 2'b00;
757
                                end else begin                  // stage2, TMP16 to FLAGS
758
                                        BASEL = 1'b0;
759
                                        WE[4] = 1'b1;                   // flags
760
                                        ALUOP = 31;                             // store flags
761
                                        MREQ = 1'b0;
762
                                end
763
                        end
764
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
765
                        23: begin
766
                                ASEL = 1'b1;
767
                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
768
                                        WE[3] = 1'b1;           // TMP16
769
                                        DISEL = 2'b00;                  // DIN
770
                                        IFETCH = 1'b0;
771
                                end else begin                                          // stage2, execute and write                    
772
                                        ALUOP = {2'b00, FETCH[0][2] ? 3'b100 : FETCH[0][5:3]};    // test = and
773
                                        MREQ = ~&MOD & ~|FETCH[0][2:1] & ~&FETCH[0][5:3];         // no cmp or test
774
                                        WR = MREQ;
775
                                        WE = {3'b100, WR | &FETCH[0][5:3] | FETCH[0][2] ? 2'b00 : WBIT};          // flags, RASEL_HI, RASEL_LO
776
                                        ISIZE = ISIZES;
777
                                end
778
                        end
779
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
780
                        24: begin
781
                                ASEL = 1'b1;
782
                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
783
                                        WE[3] = 1'b1;                   // TMP16
784
                                        DISEL = 2'b00;                  // DIN
785
                                        IFETCH = 1'b0;
786
                                end else begin                                          // stage2, execute and write            
787
                                        BASEL = &MOD;
788
                                        RASEL = RM;
789
                                        BBSEL = 2'b10;                  // imm
790
                                        ALUOP = {2'b00, FETCH[1][5:3]};
791
                                        ISEL = ISELS;
792
                                        DEXT = FETCH[0][1];
793
                                        MREQ = ~BASEL & ~&FETCH[1][5:3];
794
                                        WR = MREQ;
795
                                        WE = {3'b100, WR  | &FETCH[1][5:3]? 2'b00 : WBIT};              // flags, RASEL_HI, RASEL_LO
796
                                        ISIZE = ISIZEI;
797
                                end
798
                        end
799
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
800
                        25: begin // test
801
                                BASEL = 1'b1;
802
                                RASEL = 3'b000;         // acc
803
                                BBSEL = 2'b10;                                  // imm
804
                                WE = {3'b100, &FETCH[0][5:3] | FETCH[0][7] ? 2'b00 : WBIT};               // flags, RASEL_HI, RASEL_LO
805
                                ALUOP = {2'b00, FETCH[0][7] ? 3'b100 : FETCH[0][5:3]};
806
                                ISEL = 2'b00;
807
                                MREQ = 1'b0;
808
                                ISIZE = WORD ? 3 : 2;
809
                        end
810
// --------------------------------  inc/dec R16 --------------------------------
811
                        26: begin
812
                                WORD = 1'b1;
813
                                BASEL = 1'b1;
814
                                RASEL = FETCH[0][2:0]; // destination
815
                                WE = 5'b10011;          // flags, RASEL_HI, RASEL_LO
816
                                ALUOP = {2'b01, FETCH[0][5:3]};
817
                                MREQ = 1'b0;
818
                                ISIZE = 1;
819
                        end
820
// --------------------------------  test/???/not/neg/mul/imul/div/idiv --------------------------------
821
                        27: begin
822
                                ASEL = 1'b1;
823
                                case(REG)
824
                                        3'b000: begin           // TEST R/M with Imm
825
                                                if(!(&MOD || |STAGE[1:0])) begin // stage1, load op from memory in TMP16
826
                                                        DISEL = 2'b00;
827
                                                        WE[3] = 1'b1;                                   // mem in TMP16
828
                                                        IFETCH = 1'b0;
829
                                                end else begin
830
                                                        BASEL = &MOD;
831
                                                        RASEL = RM;     // destination
832
                                                        BBSEL = 2'b10;                  // imm
833
                                                        ALUOP = 5'b00100;               // AND
834
                                                        ISEL = ISELS;
835
                                                        MREQ = 1'b0;
836
                                                        WE[4] = 1'b1;                   // flags
837
                                                        ISIZE = ISIZEW;
838
                                                end
839
                                        end
840
                                        3'b010, 3'b011: begin   // NOT/NEG R/M
841
                                                if(!(&MOD || |STAGE[1:0])) begin // stage1, load op from memory in TMP16
842
                                                        DISEL = 2'b00;
843
                                                        WE[3] = 1'b1;                                   // mem in TMP16
844
                                                        IFETCH = 1'b0;
845
                                                end else begin
846
                                                        BASEL = &MOD;
847
                                                        RASEL = RM;     // destination
848
                                                        ALUOP = {2'b01, REG};
849
                                                        MREQ = ~&MOD;
850
                                                        WR = MREQ;
851
                                                        WE = {REG[0], 2'b00, WRBIT};             // flags, RASEL_HI, RASEL_LO
852
                                                        ISIZE = ISIZES;
853
                                                end
854
                                        end
855
                                        3'b100, 3'b101: begin   // MUL, IMUL
856
                                                ISIZE = ISIZES;
857
                                                ALUOP = {4'b1000, REG[0]};               // BASEL = FETCH[0][1] = 1
858
                                                case(STAGE[1:0])
859
                                                        2'b00: begin            // stage1, RA -> TMP16, RB (mem) -> FETCH
860
                                                                MREQ = ~&MOD;
861
                                                                DISEL = {1'b0, MREQ};
862
                                                                RASEL = 3'b000; // AX
863
                                                                DOSEL = 2'b11;
864
                                                                IFETCH = 1'b0;
865
                                                        end
866
                                                        2'b01: begin                            // stage2, write AX
867
                                                                WE[1:0] = 2'b11;
868
                                                                RASEL = 3'b000; // AX
869
                                                                MREQ = 1'b0;
870
                                                                IFETCH = ~FETCH[0][0];
871
                                                        end
872
                                                        2'b10: begin                    // stage 2, write DX
873
                                                                WE = 5'b10011;
874
                                                                RASEL = 3'b010; // DX
875
                                                                MREQ = 1'b0;
876
                                                        end
877
                                                endcase
878
                                        end
879
                                        3'b110, 3'b111: begin   // div, idiv
880
                                                ISIZE = ISIZES;
881
                                                IRQL = 3'b000;  // divide overflow
882
                                                MREQ = 1'b0;
883
                                                case({DIVEND, STAGE[1:0]})
884
                                                        3'b000: begin           // stage1, RB (mem) -> FETCH
885
                                                                MREQ = ~&MOD;
886
                                                                DISEL = {1'b0, MREQ};
887
                                                                DOSEL = 2'b11;
888
                                                                IFETCH = 1'b0;
889
                                                                DIVSTAGE = ~QSGN;
890
                                                        end
891
                                                        3'b001: begin   // stage2, pre dec AX
892
//                                                              WORD = 1'b1;
893
                                                                RASEL = 3'b000; // AX
894
                                                                WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
895
                                                                ALUOP = 5'b01001;               // DEC
896
                                                                IFETCH = 1'b0;
897
                                                                ALUSTAGE = ~(DIVQSGN && FETCH[0][0] && COUT);
898
                                                        end
899
                                                        3'b010: begin // stage3, pre dec DX
900
                                                                RASEL = 3'b010;         // DX
901
                                                                WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
902
                                                                ALUOP = 5'b01001;               // DEC
903
                                                                IFETCH = 1'b0;
904
                                                        end
905
                                                        3'b011, 3'b111: begin   // stage4, div loop
906
                                                                RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
907
                                                                BBSEL = 2'b10;          // imm
908
                                                                WE[1:0] = {1'b1, WORD};          // RASEL_HI, RASEL_LO
909
                                                                ALUOP = {2'b00, DIVSGN ? 3'b000 : 3'b101};      // add/sub
910
                                                                ISEL = 2'b01;
911
                                                                DIVSTAGE = ~DIVEND;
912
                                                                ALUSTAGE = ~DIVEND | ~DIVQSGN;
913
                                                                DIVOP = 1'b1;
914
                                                                IRQ = ~|STAGE[6:3] & DIVC & ~(STAGE[2] & DIVSGN); // early overflow for positive quotient
915
                                                                IFETCH = (DIVEND && ~DIVQSGN && ~DIVRSGN) || IRQ;
916
                                                        end
917
                                                        3'b100: begin           // stage5, post inc R
918
                                                                RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
919
                                                                WE[1:0] = {1'b1, WORD};          // RASEL_HI, RASEL_LO
920
                                                                ALUOP = 5'b01000;       // inc
921
                                                                IFETCH = ~DIVSGN;
922
                                                        end
923
                                                        default: begin  // stage6, post inc Q
924
                                                                RASEL = 3'b000; // AX/AL
925
                                                                WE[1:0] = {WORD, 1'b1};          // RASEL_HI, RASEL_LO
926
                                                                ALUOP = 5'b01000;       // inc
927
                                                                IRQ = SOUT ^ DIVSGN;    // overflow for negative quotient
928
                                                        end
929
                                                endcase
930
                                        end
931
                                        default: begin          // bad opcode
932
                                                MREQ = 1'b0;
933
                                                ISIZE = 0;
934
                                                IRQ = 1'b1;
935
                                        end
936
                                endcase
937
                        end
938
// --------------------------------  imul imm --------------------------------
939
                        28: begin
940
                                ASEL = 1'b1;
941
                                if(!STAGE[0]) begin      // stage1, load op from memory (or RA) in TMP16
942
                                        RASEL = RM;
943
                                        DISEL = 2'b00;                  // DIN
944
                                        DOSEL = 2'b11;
945
                                        ISEL = ISELS;
946
                                        DEXT = FETCH[0][1];
947
                                        BBSEL = 2'b10;                  // imm
948
                                        MREQ = ~&MOD;
949
                                        WE[3] = MREQ;                   // TMP16
950
                                        IFETCH = 1'b0;
951
                                end else begin                                          // stage2, execute and write            
952
                                        RASEL = REG;
953
                                        ALUOP = 5'b10001;               // imul
954
                                        MREQ = 1'b0;
955
                                        WE = 5'b10011;          // flags, RASEL_HI, RASEL_LO
956
                                        ISIZE = ISIZEI;
957
                                end
958
                        end
959
// --------------------------------  aad --------------------------------
960
                        29: begin
961
                                MREQ = 1'b0;
962
                                WORD = 1'b0;
963
                                BASEL = 1'b1;
964
                                IFETCH = &STAGE[1:0];
965
                                case(STAGE[1:0])
966
                                        2'b00: begin    // stage1, load AH in TMP16, move imm in FETCH
967
                                                RASEL = 3'b100;         // AH
968
                                                DISEL = 2'b00;                  // DIN
969
                                                DOSEL = 2'b11;                  // write FETCH
970
                                                ISEL = 2'b00;                   // RB -> FETCH
971
                                                BBSEL = 2'b10;                  // imm
972
                                        end
973
                                        2'b01: begin                            // stage2, TMP16 <- TMP16 * 10
974
                                                ALUOP = 5'b10000;               // mul
975
                                                WE[3] = 1'b1;                   // TMP16
976
                                        end
977
                                        2'b10: begin                    // stage3, AL <- TMP16 + AL
978
                                                RASEL = 3'b000;         // AL
979
                                                BBSEL = 2'b00;          // TMP16
980
                                                WE = 5'b10001;          // flags, RASEL_LO
981
                                                ALUOP = 5'b00000;       // ADD
982
                                        end
983
                                        2'b11: begin                    // stage4, AH <- 0
984
                                                RASEL = 3'b100;         // AH
985
                                                RBSEL = 3'b100;         // AH
986
                                                WE[1] = 1'b1;           // RASEL_HI
987
                                                ALUOP = 5'b00101;       // SUB
988
                                                ISIZE = 2;
989
                                        end
990
                                endcase
991
                        end
992
// --------------------------------  daa, das, aaa, aas --------------------------------
993
                        30: begin
994
                                WORD = FETCH[0][4];
995
                                RASEL = 3'b000;         // AX,AL
996
                                WE = {3'b100, FETCH[0][4], 1'b1};                // flags, RASEL_HI, RASEL_LO
997
                                ALUOP = {2'b01, FETCH[0][5:3]};
998
                                MREQ = 1'b0;
999
                                ISIZE = 1;
1000
                        end
1001
// --------------------------------  shift/rot --------------------------------
1002
                        31: begin       // imm
1003
                                ALUOP = {4'b1110, FETCH[0][4:1] != 4'b1000};
1004
                                ASEL = 1'b1;
1005
                                if(!(&MOD || STAGE[0])) begin    // stage1, load op from memory in TMP16
1006
                                        WE[3] = 1'b1;                   // TMP16
1007
                                        DISEL = 2'b00;                  // DIN
1008
                                        IFETCH = 1'b0;
1009
                                end else begin                                          // stage2, execute and write            
1010
                                        BASEL = &MOD && ~|STAGE[2:1];
1011
                                        RASEL = RM;
1012
                                        BBSEL = FETCH[0][1] ? 2'b01 : 2'b10; // imm/reg
1013
                                        RBSEL = 3'b001;         // CL
1014
                                        ISEL = ISELS;
1015
                                        IRQ = REG == 3'b110;
1016
                                        MREQ = ~&MOD && ~NULLSHIFT && ~ALUCONT && ~IRQ;
1017
                                        WR = MREQ;
1018
                                        WE = NULLSHIFT || IRQ ? 5'b00000 : ALUCONT ? 5'b11000 : {3'b100, WRBIT};                // flags, TMP16, RASEL_HI, RASEL_LO
1019
                                        IFETCH = ~ALUCONT || IRQ;
1020
                                        ALUSTAGE = 1'b1;
1021
                                        if(IRQ) ISIZE = 0;
1022
                                        else case({|FETCH[0][4:1], DISP16, AEXT})
1023
                                                3'b100: ISIZE = 2;
1024
                                                3'b000, 3'b101: ISIZE = 3;
1025
                                                3'b001, 3'b110: ISIZE = 4;
1026
                                                default: ISIZE = 5;
1027
                                        endcase
1028
                                end
1029
                        end
1030
// --------------------------------  (rep)movs --------------------------------
1031
                        32: begin
1032
                                BASEL = 1'b1;
1033
                                AEXT = 1'b0;
1034
                                DISP16 = 1'b0;
1035
                                NOBP = 1'b1;    // for RSSEL
1036
                                if(!STAGE[0]) begin              // stage1, read DS:[SI] in TMP16, inc/dec SI
1037
                                        RASEL = 3'b110;         // SI
1038
                                        ALUOP = {4'b0100, FLAGS[10]};
1039
                                        EAC = 4'b0100;          // SI+DISP
1040
                                        DISEL = 2'b11;          // ALU 16bit
1041
                                        IFETCH = RCXZ;  // REP & CX==0
1042
                                        MREQ = ~RCXZ;
1043
                                        WE = IFETCH ? 5'b00000 : 5'b01011;              // TMP16, RASEL_HI, RASEL_LO
1044
                                end else begin                  // stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
1045
                                        RASEL = 3'b111;         // DI
1046
                                        RSSEL = 2'b00;          // ES
1047
                                        WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
1048
                                        ALUOP = {4'b0100, FLAGS[10]};
1049
                                        EAC = 4'b0101;          // DI + DISP
1050
                                        DISEL = 2'b11;          // ALU 16bit
1051
                                        DOSEL = 2'b10;          // TMP16                
1052
                                        WR = 1'b1;
1053
                                        IFETCH = NRORCXLE1;  // not REP or CX<=1
1054
                                        DECCX = CPUStatus[4];
1055
                                        REPINT = 1'b1;
1056
                                end
1057
                                ISIZE = IFETCH ? 1 : 0;
1058
                        end
1059
// --------------------------------  (rep)cmps --------------------------------
1060
                        33: begin
1061
                                DISP16 = 1'b0;
1062
                                AEXT = 1'b0;
1063
                                NOBP = 1'b1;    // for RSSEL
1064
                                case(STAGE[1:0])
1065
                                        2'b00: begin            // stage1, read ES:[DI] in FETCH[2:1], inc/dec DI
1066
                                                RASEL = 3'b111;         // SI
1067
                                                RSSEL = 2'b00;          // ES
1068
                                                ALUOP = {4'b0100, FLAGS[10]};
1069
                                                EAC = 4'b0101;          // DI+DISP
1070
                                                DISEL = 2'b11;          // ALU 16bit
1071
                                                DOSEL = 2'b11;          // read data to FETCH
1072
                                                IFETCH = CPUStatus[4] && (~|CXZ || (CPUStatus[3] ^ TZF));       // REP & CX==0
1073
                                                MREQ = ~IFETCH;
1074
                                                WE[1:0] = IFETCH ? 2'b00 : 2'b11;                // RASEL_HI, RASEL_LO
1075
                                        end
1076
                                        2'b01: begin            // stage2, read DS:[SI] in TMP16, inc/dec SI
1077
                                                RASEL = 3'b110;         // DI
1078
                                                ALUOP = {4'b0100, FLAGS[10]};
1079
                                                EAC = 4'b0100;          // SI+DISP
1080
                                                DISEL = 2'b11;          // ALU 16bit
1081
                                                IFETCH = 1'b0;
1082
                                                WE[3:0] = 4'b1011;               // RASEL_HI, RASEL_LO
1083
                                        end
1084
                                        2'b10: begin            // stage3, compare TMP16 wit imm, set flags, dec CX
1085
                                                BASEL = 1'b0;                   // TMP16
1086
                                                BBSEL = 2'b10;                  // imm
1087
                                                ISEL = 2'b01;
1088
                                                WE[4] = 1'b1;                   // flags
1089
                                                ALUOP = 5'b00111;               // cmp
1090
                                                MREQ = 1'b0;
1091
                                                IFETCH = ~CPUStatus[4];
1092
                                                DECCX = CPUStatus[4];
1093
                                                ALUSTAGE = 1'b1;
1094
                                                REPINT = 1'b1;
1095
                                        end
1096
                                endcase
1097
                                ISIZE = IFETCH ? 1 : 0;
1098
                        end
1099
// --------------------------------  (rep)scas --------------------------------
1100
                        34: begin
1101
                                DISP16 = 1'b0;
1102
                                AEXT = 1'b0;
1103
                                NOBP = 1'b1;    // for RSSEL (not really necesary, but with it the synthesis generates better speed)
1104
                                if(!STAGE[0]) begin      // stage1, read ES:[DI] in TMP16, inc/dec DI
1105
                                        RASEL = 3'b111;         // DI
1106
                                        RSSEL = 2'b00;          // ES
1107
                                        ALUOP = {4'b0100, FLAGS[10]};
1108
                                        EAC = 4'b0101;          // DI+DISP
1109
                                        DISEL = 2'b11;          // ALU 16bit
1110
                                        IFETCH = CPUStatus[4] && (~|CXZ || (CPUStatus[3] ^ TZF));       // REP & CX==0
1111
                                        MREQ = ~IFETCH;
1112
                                        WE[3:0] = IFETCH ? 4'b0000 : 4'b1011;            // TMP16, RASEL_HI, RASEL_LO
1113
                                end else begin  //stage2, compare AL/AX with TMP16, set flags, dec CX
1114
                                        RASEL = 3'b000;         // AL/AX
1115
                                        BBSEL = 2'b00;                  // TMP16
1116
                                        WE[4] = 1'b1;                   // flags
1117
                                        ALUOP = 5'b00111;               // cmp
1118
                                        MREQ = 1'b0;
1119
                                        IFETCH = ~CPUStatus[4];
1120
                                        DECCX = CPUStatus[4];
1121
                                        REPINT = 1'b1;
1122
                                end
1123
                                ISIZE = IFETCH ? 1 : 0;
1124
                        end
1125
// --------------------------------  (rep)lods --------------------------------
1126
                        35: begin
1127
                                BASEL = 1'b1;
1128
                                DISP16 = 1'b0;
1129
                                AEXT = 1'b0;
1130
                                NOBP = 1'b1;    // for RSSEL
1131
                                if(!STAGE[0]) begin              // stage1, read DS:[SI] in AL/AX
1132
                                        RASEL = 3'b000;         // AX
1133
                                        EAC = 4'b0100;          // SI+DISP
1134
                                        DISEL = 2'b00;          // DIN
1135
                                        IFETCH = RCXZ;  // REP & CX==0
1136
                                        MREQ = ~RCXZ;
1137
                                        WE[1:0] = IFETCH ? 2'b00 : {WORD, 1'b1};         // RASEL_HI, RASEL_LO
1138
                                end else begin          // stage2, inc/dec SI, dec CX
1139
                                        RASEL = 3'b110;         // SI
1140
                                        ALUOP = {4'b0100, FLAGS[10]};
1141
                                        DISEL = 2'b11;          // ALU 16bit
1142
                                        IFETCH = NRORCXLE1;  // nor REP or CX<=1
1143
                                        MREQ = 1'b0;
1144
                                        WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
1145
                                        DECCX = CPUStatus[4];
1146
                                        REPINT = 1'b1;
1147
                                end
1148
                                ISIZE = IFETCH ? 1 : 0;
1149
                        end
1150
// --------------------------------  (rep)stos --------------------------------
1151
                        36: begin  // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
1152
                                BASEL = 1'b1;
1153
                                DISP16 = 1'b0;
1154
                                AEXT = 1'b0;
1155
                                RASEL = 3'b111;         // DI
1156
                                RSSEL = 2'b00;          // ES
1157
                                ALUOP = {4'b0100, FLAGS[10]};
1158
                                EAC = 4'b0101;          // DI + DISP
1159
                                DISEL = 2'b11;          // ALU 16bit
1160
                                DOSEL = 2'b11;          // AX
1161
                                IFETCH = NRORCXLE1;  // not REP or CX<=1
1162
                                MREQ = ~RCXZ;
1163
                                WR = ~RCXZ;
1164
                                WE[1:0] = {MREQ, MREQ};          // RASEL_HI, RASEL_LO
1165
                                DECCX = CPUStatus[4] && |CXZ;
1166
                                REPINT = 1'b1;
1167
                                ISIZE = IFETCH ? 1 : 0;
1168
                        end
1169
// --------------------------------  (rep)ins --------------------------------
1170
                        37: begin
1171
                                BASEL = 1'b1;
1172
                                DISP16 = 1'b0;
1173
                                AEXT = 1'b0;
1174
                                if(!STAGE[0]) begin      // stage1, input in TMP16
1175
                                        WE[3] = 1'b1;           // TMP16
1176
                                        DISEL = 2'b00;          //DIN
1177
                                        IFETCH = RCXZ;          // REP & CX==0
1178
                                        MREQ = 1'b0;
1179
                                        EAC = {~RCXZ, 3'b111};
1180
                                        NULLSEG = 1'b1;
1181
                                end else begin                  // stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
1182
                                        RASEL = 3'b111;         // DI
1183
                                        RSSEL = 2'b00;          // ES
1184
                                        WE[1:0] = 2'b11;         // RASEL_HI, RASEL_LO
1185
                                        ALUOP = {4'b0100, FLAGS[10]};
1186
                                        EAC = 4'b0101;          // DI + DISP
1187
                                        DISEL = 2'b11;          // ALU 16bit
1188
                                        DOSEL = 2'b10;          // TMP16                
1189
                                        WR = 1'b1;
1190
                                        IFETCH = NRORCXLE1;  // not REP or CX<=1
1191
                                        DECCX = CPUStatus[4];
1192
                                        REPINT = 1'b1;
1193
                                end
1194
                                ISIZE = IFETCH ? 1 : 0;
1195
                        end
1196
// --------------------------------  (rep)outs --------------------------------
1197
                        38: begin
1198
                                BASEL = 1'b1;
1199
                                DISP16 = 1'b0;
1200
                                NOBP = 1'b1;    // for RSSEL
1201
                                if(!STAGE[0]) begin              // stage1, read DS:[SI] in TMP16, inc/dec SI
1202
                                        AEXT = 1'b0;            // tweak for speed (can be moved outside <if>)
1203
                                        RASEL = 3'b110;         // SI
1204
                                        ALUOP = {4'b0100, FLAGS[10]};
1205
                                        EAC = 4'b0100;          // SI+DISP
1206
                                        DISEL = 2'b11;          // ALU 16bit
1207
                                        IFETCH = RCXZ;  // REP & CX==0
1208
                                        MREQ = ~RCXZ;
1209
                                        WE[3:0] = IFETCH ? 4'b0000 : 4'b1011;            // TMP16, RASEL_HI, RASEL_LO
1210
                                end else begin                  // stage2, out TMP16 at port DX, dec CX
1211
                                        DOSEL = 2'b10;          // TMP16                
1212
                                        MREQ = 1'b0;
1213
                                        EAC = 4'b1111;
1214
                                        WR = 1'b1;
1215
                                        IFETCH = NRORCXLE1;  // not REP or CX<=1
1216
                                        DECCX = CPUStatus[4];
1217
                                        REPINT = 1'b1;
1218
                                        NULLSEG = 1'b1;
1219
                                end
1220
                                ISIZE = IFETCH ? 1 : 0;
1221
                        end
1222
// --------------------------------  call/jmp direct near --------------------------------
1223
                        39: begin       // jump long
1224
                                WORD = 1'b1;
1225
                                ALUOP = 0;                       // ADD
1226
                                DISEL = 2'b10;          // ADDR
1227
                                ISIZE = FETCH[0][1] ? 2 : 3;
1228
                                RASEL = 3'b100; // write SP
1229
                                RSSEL = 2'b10;          // SS
1230
                                DOSEL = 2'b01;          // IP
1231
                                EAC = 4'b1000;          // SP - 2
1232
                                BBSEL = 2'b10;          // imm
1233
                                ISEL = 2'b00;
1234
                                DEXT = FETCH[0][1];
1235
                                MREQ = !FETCH[0][0];
1236
                                WR = MREQ;
1237
                                WE[1:0] = FETCH[0][0] ? 2'b00 : 2'b11;             // RASEL_HI/RASEL_LO
1238
                                IPWSEL = 1'b0;          // ALU
1239
                        end
1240
// --------------------------------  call/jmp far imm --------------------------------
1241
                        40: begin
1242
                                WORD = 1'b1;
1243
                                ALUOP = 31;                             // PASS B
1244
                                case({STAGE[1:0], FETCH[0][6]})
1245
                                        3'b000: begin   // stage1, push CS
1246
                                                RASEL = 3'b100;         // write SP
1247
                                                BBSEL = 2'b11;
1248
                                                RBSEL = 3'b001;                 // CS
1249
                                                RSSEL = 2'b10;                  // SS
1250
                                                EAC = 4'b1000;                  // SP - 2
1251
                                                DISEL = 2'b10;                  // ADDR
1252
                                                WR = 1'b1;
1253
                                                IFETCH = 1'b0;
1254
                                                WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1255
                                        end
1256
                                        3'b010, 3'b001: begin   // stage2, load CS
1257
                                                RASEL = 3'b001;         // CS
1258
                                                BBSEL = 2'b10;          // imm
1259
                                                WE[2] = 1'b1;           // RSSEL
1260
                                                ISEL = 2'b10;
1261
                                                MREQ = 1'b0;
1262
                                                IFETCH = 1'b0;
1263
                                        end
1264
                                        3'b100, 3'b011: begin   // stage3, push IP, load IP
1265
                                                RASEL = 3'b100;         // write SP
1266
                                                BBSEL = 2'b10;          // imm
1267
                                                RSSEL = 2'b10;          // SS
1268
                                                EAC = 4'b1000;          // SP - 2
1269
                                                DISEL = 2'b10;          // ADDR
1270
                                                DOSEL = 2'b01;          // IP    
1271
                                                ISEL = 2'b00;
1272
                                                MREQ = FETCH[0][4];
1273
                                                WR = MREQ;
1274
                                                WE[1:0] = {WR, WR};
1275
                                                IPWSEL = 1'b0;          // ALU
1276
                                                ISIZE = 5;
1277
                                        end
1278
                                endcase
1279
                        end
1280
// --------------------------------  ret near --------------------------------
1281
                        41: begin
1282
                                ISIZE = FETCH[0][0] ? 1 : 3;
1283
                                IFETCH = STAGE[0];
1284
                                ALUOP = 31;                     // PASS B
1285
                                if(!STAGE[0]) begin      // stage1, pop TMP16
1286
                                        RSSEL = 2'b10;                  // SS
1287
                                        WE[3] = 1'b1;                   // TMP16
1288
                                        ASEL = 1'b0;
1289
                                        AEXT = 1'b0;
1290
                                        DISP16 = 1'b1;
1291
                                        EAC = {1'b1, !FETCH[0][0], 2'b01};                        // SP + 2 (+ imm) 
1292
                                        DISEL = 2'b00;
1293
                                end else begin                  // stage2, TMP16 to IP
1294
                                        BBSEL = 2'b00;          // TMP16        
1295
                                        IPWSEL = 1'b0;          // ALU
1296
                                        MREQ = 1'b0;
1297
                                end
1298
                        end
1299
// --------------------------------  ret far --------------------------------
1300
                        42: begin
1301
                                ALUOP = 31;                     // PASS B
1302
                                RSSEL = 2'b10;                  // SS
1303
                                IFETCH = STAGE[1];
1304
                                DISEL = 2'b00;                  // DIN
1305
                                case(STAGE[1:0])
1306
                                        2'b00: begin    // stage1, pop IP in TMP16
1307
                                                WE[3] = 1'b1;                   // TMP16
1308
                                                EAC = 4'b1001;                  // SP + 2
1309
                                        end
1310
                                        2'b01: begin            // stage2, pop CS, TMP16 <- RA
1311
                                                RASEL = 3'b001; // CS
1312
                                                WE[2] = 1'b1;
1313
                                                EAC = {1'b1, !FETCH[0][0], 2'b01};
1314
                                                ASEL = 1'b0;
1315
                                                AEXT = 1'b0;
1316
                                                DISP16 = 1'b1;
1317
                                                BASEL = 1'b0;           // RA <- TMP16
1318
                                        end
1319
                                        2'b10: begin            // stage3, IP <- TMP16
1320
                                                BBSEL = 2'b00;          // TMP16
1321
                                                IPWSEL = 1'b0;          // ALU
1322
                                                MREQ = 1'b0;
1323
                                                ISIZE = FETCH[0][0] ? 1 : 3;
1324
                                        end
1325
                                endcase
1326
                        end
1327
// --------------------------------  iret --------------------------------
1328
                        43: begin
1329
                                ALUOP = 31;                     // PASS B
1330
                                RSSEL = 2'b10;                  // SS
1331
                                ISIZE = 1;
1332
                                IFETCH = &STAGE[1:0];
1333
                                case(STAGE[1:0])
1334
                                        2'b00: begin    // stage1, pop IP in FETCH
1335
                                                EAC = 4'b1001;                  // SP + 2
1336
                                                DOSEL = 2'b11;                  // write FETCH
1337
                                        end
1338
                                        2'b01: begin            // stage2, pop CS
1339
                                                RASEL = 3'b001; // CS
1340
                                                WE[2] = 1'b1;
1341
                                                EAC = {1'b1, !FETCH[0][0], 2'b01};
1342
                                                DISEL = 2'b00;
1343
                                                ASEL = 1'b0;
1344
                                                AEXT = 1'b0;
1345
                                                DISP16 = 1'b1;
1346
                                        end
1347
                                        2'b10: begin            // stage3, pop flags in TMP16
1348
                                                WE[3] = 1'b1;                   // TMP16
1349
                                                EAC = 4'b1001;                  // SP
1350
                                                DISEL = 2'b00;
1351
                                        end
1352
                                        2'b11: begin            // stage4, IP <- FETCH, FLAGS <- TM
1353
                                                BASEL = 1'b0;
1354
                                                BBSEL = 2'b10;          // imm
1355
                                                WE[4] = 1'b1;           // flags
1356
                                                ISEL = 2'b01;
1357
                                                DEXT = 1'b0;
1358
                                                IPWSEL = 1'b0;          // ALU
1359
                                                MREQ = 1'b0;
1360
                                        end
1361
                                endcase
1362
                        end
1363
// --------------------------------  cbw/cwd --------------------------------
1364
                        44: begin
1365
                                RASEL = FETCH[0][0] ? 3'b010 : 3'b100; // AH/DX
1366
                                RBSEL = 3'b000; // AX
1367
                                WE[1:0] = {1'b1, FETCH[0][0]};             // RASEL_HI, RASEL_LO
1368
                                ALUOP = {4'b1101, FETCH[0][0]};   // cbw/cwd
1369
                                MREQ = 1'b0;
1370
                                ISIZE = 1;
1371
                        end
1372
// --------------------------------  JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
1373
                        45: begin  // loop/loopz/loopnz/jcxz
1374
                                ALUOP = 0;                       // add
1375
                                ISIZE = 2;
1376
                                DOSEL = 2'b01;          // IP
1377
                                BBSEL = 2'b10;          // imm
1378
                                ISEL = 2'b00;
1379
                                DEXT = 1'b1;
1380
                                MREQ = 1'b0;
1381
                                IPWSEL = FETCH[0][7] ? LOOPC[FETCH[0][1:0]] : (JMPC[FETCH[0][3:1]] ~^ FETCH[0][0]);
1382
                                DECCX = FETCH[0][7] && (FETCH[0][1:0] != 2'b11);
1383
                        end
1384
// --------------------------------  CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
1385
                        46: begin
1386
                                WE[4] = 1'b1;           // flags
1387
                                ALUOP = 5'b11001;       // flag op
1388
                                ISIZE = 1;
1389
                                MREQ = 1'b0;
1390
                        end
1391
// --------------------------------  enter --------------------------------
1392
                        47: begin
1393
                                WORD = 1'b1;
1394
                                WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1395
                                case(STAGE[1:0])
1396
                                        2'b00: begin            // push BP
1397
                                                RASEL = 3'b100;         // write SP
1398
                                                RBSEL = 3'b101;                 // BP
1399
                                                RSSEL = 2'b10;                  // SS
1400
                                                EAC = 4'b1000;                  // SP - 2
1401
                                                DISEL = 2'b10;                  // ADDR
1402
                                                ALUOP = 31;                             // PASS B
1403
                                                WR = 1'b1;
1404
                                                IFETCH = 1'b0;
1405
                                        end
1406
                                        2'b01: begin            // mov BP, SP
1407
                                                RASEL = 3'b101; // BP
1408
                                                RBSEL = 3'b100; // SP
1409
                                                ALUOP = 31;                             // PASS B
1410
                                                MREQ = 1'b0;
1411
                                                IFETCH = 1'b0;
1412
                                        end
1413
                                        2'b10: begin            // sub SP, imm
1414
                                                BASEL = 1'b1;
1415
                                                RASEL = 3'b100; // SP
1416
                                                BBSEL = 2'b10;
1417
                                                ALUOP = 5'b00101;       // sub
1418
                                                ISEL = 2'b00;
1419
                                                MREQ = 1'b0;
1420
                                                ISIZE = 4;
1421
                                        end
1422
                                endcase
1423
                        end
1424
// --------------------------------  leave --------------------------------
1425
                        48: begin
1426
                                WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1427
                                if(!STAGE[0]) begin      // stage1, mov sp, bp
1428
                                        RASEL = 3'b100; // BP
1429
                                        RBSEL = 3'b101; // SP
1430
                                        ALUOP = 31;                             // PASS B
1431
                                        MREQ = 1'b0;
1432
                                        IFETCH = 1'b0;
1433
                                end else begin                  // stage2, pop bp
1434
                                        RASEL = 3'b101;         // BP
1435
                                        RSSEL = 2'b10;                  // SS
1436
                                        EAC = 4'b1001;                  // SP
1437
                                        DISEL = 2'b00;                  // DIN
1438
                                        ISIZE = 1;
1439
                                end
1440
                        end
1441
// --------------------------------  int, int 3, into --------------------------------
1442
                        49: begin
1443
                                MREQ = 1'b0;
1444
                                ISIZE = FETCH[0][1:0] == 2'b01 ? 2 : 1;
1445
                                IRQ = ~FETCH[0][1] | FLAGS[11];
1446
                                IRQL = FETCH[0][1] ? 3'b100 : {1'b0, ~FETCH[0][1:0]};      // 4, 2, 3
1447
                        end
1448
// --------------------------------  bound --------------------------------
1449
                        50: begin
1450
                                WORD = 1'b1;
1451
                                DOSEL = 2'b11;                  // load FETCH with DIN
1452
                                case(STAGE[1:0])
1453
                                        2'b00: begin // stage1,  read min in FETCH, ADDR16 in TMP16
1454
                                                RASEL = 3'b100;                 // SP   - write SP to SP for getting ADDR16 to TMP16
1455
                                                BBSEL = 2'b01;
1456
                                                RBSEL = 3'b100;                 // SP
1457
                                                ALUOP = 31;                             // PASS B
1458
                                                WE[3:0] = 4'b1011;                       // TMP16, RASEL_HI, RASEL_LO
1459
                                                ASEL = 1'b1;
1460
                                                IRQ = &MOD;             // illegal instruction
1461
                                                ISIZE = 0;
1462
                                                IFETCH = IRQ;
1463
                                        end
1464
                                        2'b01, 2'b10, 2'b11: begin      // stage2,3,4 load min/max in TMP16, compare reg with imm
1465
                                                BBSEL = 2'b10;                  // imm
1466
                                                ALUOP = 5'b00111;               // cmp
1467
                                                EAC = 4'b1011;                  // TMP16 + 2
1468
                                                ISEL = 2'b01;
1469
                                                IRQ = STAGE[1] & (STAGE[0] ? ~TLF & ~TZF : TLF);
1470
                                                MREQ = ~&STAGE[1:0];
1471
                                                IFETCH = IRQ | ~MREQ;
1472
                                                IRQL = 3'b101;
1473
                                                ISIZE = IRQ ? 0 : ISIZES;        // return address is BOUND
1474
                                        end
1475
                                endcase
1476
                        end
1477
// --------------------------------  hlt --------------------------------
1478
                        51: begin
1479
                                IFETCH = 1'b0;
1480
                                HALT = 1'b1;
1481
                                MREQ = 1'b0;
1482
                        end
1483
// --------------------------------  wait --------------------------------
1484
                        52: begin       // do nothing
1485
                                ISIZE = 1;
1486
                                MREQ = 1'b0;
1487
                        end
1488
// --------------------------------  aam --------------------------------
1489
                        53: begin
1490
                                MREQ = 1'b0;
1491
                                IRQL = 3'b000;  // divide overflow
1492
                                ISIZE = 2;
1493
                                case({DIVEND, STAGE[1:0]})
1494
                                        3'b000: begin   // stage1, clear AH
1495
                                                BASEL = 1'b0;    // TMP16
1496
                                                RASEL = 3'b100; // AH
1497
                                                BBSEL = 2'b00;   // TMP16
1498
                                                WE[1] = 1'b1;    // RASEL_HI
1499
                                                ALUOP = 5'b00101;       // sub
1500
                                                IFETCH = 1'b0;
1501
                                        end
1502
                                        3'b001, 3'b101: begin   // stage2, div
1503
                                                RASEL = 3'b100; // AH
1504
                                                BASEL = 1'b1;
1505
                                                BBSEL = 2'b10;   // imm
1506
                                                WE[1] = 1'b1;    // RASEL_HI
1507
                                                ALUOP = 5'b00101;       // sub
1508
                                                ISEL = 2'b00;
1509
                                                DIVSTAGE = ~DIVEND;
1510
                                                ALUSTAGE = ~DIVEND;
1511
                                                DIVOP = 1'b1;
1512
                                                IRQ = ~|STAGE[6:2] & DIVC;
1513
                                                IFETCH = IRQ;
1514
                                        end
1515
                                        3'b110: begin   // stage 3, AH <- AL, TMP16 <- AH
1516
                                                RASEL = 3'b100; // AH
1517
                                                BASEL = 1'b1;
1518
                                                RBSEL = 3'b000; // AL
1519
                                                WE[1] = 1'b1;   // RASEL_HI
1520
                                                ALUOP = 31;                     // PASS B
1521
                                                IFETCH = 1'b0;
1522
                                        end
1523
                                        3'b111: begin // stage4, AL <- TMP16 | TMP16, set flags
1524
                                                RASEL = 3'b000; // dest = AL
1525
                                                BASEL = 1'b0;    // TMP16
1526
                                                BBSEL = 2'b00;   // TMP16
1527
                                                WE = 5'b10001;   // FLAGS, RASEL_LO
1528
                                                ALUOP = 5'b00001;               // OR
1529
                                        end
1530
                                endcase
1531
                        end
1532
// --------------------------------  reset, irq, nmi, intr --------------------------------
1533
                        54:
1534
                                if(STAGE[3]) begin
1535
                                        if(FETCH[5][0]) begin    // reset
1536
                                                RASEL = {1'b0, STAGE[1:0]};      // ES, CS, SS, DS
1537
                                                WE = 5'b11100;          // FLAGS, TMP16, RSSEL
1538
                                                BASEL = 1'b0;           // TMP16
1539
                                                BBSEL = 2'b00;          // TMP16
1540
                                                ALUOP = STAGE[0] ? STAGE[1] ? 31 : 5'b01001 : 5'b00101;  // pass, dec, sub
1541
                                                MREQ = 1'b0;
1542
                                                IPWSEL = 1'b0;          // ALU16
1543
                                                IFETCH = &STAGE[1:0];
1544
                                        end else case({FETCH[5][1], STAGE[2:0]})
1545
                                                4'b1000: begin          // stage1 intr
1546
                                                        DOSEL = 2'b11;  // read FETCH[2]         
1547
                                                        MREQ = 1'b0;
1548
                                                        IFETCH = 1'b0;
1549
                                                        INTA = 1'b1;
1550
                                                end
1551
                                                4'b1001, 4'b0000: begin // stage1 irq, nmi, tf, stage2 intr - push flags, clear TF, IF
1552
                                                        RASEL = 3'b100;         // write SP
1553
                                                        RSSEL = 2'b10;                  // SS
1554
                                                        WE = 5'b10011;                  // flags, SP    
1555
                                                        ALUOP = 30;                             // pass flags
1556
                                                        EAC = 4'b1000;                  // SP - 2
1557
                                                        DISEL = 2'b10;                  // ADDR
1558
                                                        WR = 1'b1;
1559
                                                        IFETCH = 1'b0;
1560
                                                end
1561
                                                4'b1010, 4'b0001: begin // stage2 irq, nmi, tf, stage3 intr - push CS
1562
                                                        RASEL = 3'b100;         // write SP
1563
                                                        BBSEL = 2'b11;
1564
                                                        RBSEL = 3'b001;                 // CS
1565
                                                        RSSEL = 2'b10;                  // SS
1566
                                                        ALUOP = 31;                             // PASS B
1567
                                                        EAC = 4'b1000;                  // SP - 2
1568
                                                        DISEL = 2'b10;                  // ADDR
1569
                                                        WR = 1'b1;
1570
                                                        IFETCH = 1'b0;
1571
                                                        WE[1:0] = 2'b11;                 // RASEL_HI/RASEL_LO
1572
                                                end
1573
                                                4'b1011, 4'b0010: begin // stage3 irq, nmi, tf, stage4 intr - read offset in FETCH, ADDR16 in TMP16
1574
                                                        RASEL = 3'b100;                 // SP   - write SP to SP for getting ADDR16 to TMP16
1575
                                                        BBSEL = 2'b01;
1576
                                                        RBSEL = 3'b100;                 // SP
1577
                                                        ALUOP = 31;                             // PASS B
1578
                                                        EAC = 4'b1110;                  // int vector
1579
                                                        WE[3:0] = 4'b1011;       // TMP16, RASEL_HI, RASEL_LO
1580
                                                        ASEL = 1'b1;
1581
                                                        DISP16 = 1'b1;
1582
                                                        DOSEL = 2'b11;                  // load FETCH with DIN
1583
                                                        IFETCH = 1'b0;
1584
                                                        NULLSEG = 1'b1;
1585
                                                end
1586
                                                4'b1100, 4'b0011: begin // stage4 irq, nmi, tf, stage5 intr - read CS
1587
                                                        RASEL = 3'b001;                 // CS
1588
                                                        WE[2] = 1'b1;                   // RSSEL
1589
                                                        EAC = 4'b1011;                  // TMP16 + 2
1590
                                                        DISEL = 2'b00;                  // DIN
1591
                                                        IFETCH = 1'b0;
1592
                                                        NULLSEG = 1'b1;
1593
                                                end
1594
                                                4'b1101, 4'b0100: begin // stage5 irq, nmi, tf, stage6 intr - push IP, jump
1595
                                                        RASEL = 3'b100;         // write SP
1596
                                                        BBSEL = 2'b10;          // imm
1597
                                                        RSSEL = 2'b10;          // SS
1598
                                                        ALUOP = 31;                     // PASS B
1599
                                                        EAC = 4'b1000;          // SP - 2
1600
                                                        DISEL = 2'b10;          // ADDR
1601
                                                        DOSEL = 2'b01;          // IP    
1602
                                                        ISEL = 2'b01;
1603
                                                        WR = 1'b1;
1604
                                                        WE[1:0] = 2'b11;
1605
                                                        ISIZE = FETCH[5][2] ? 1 : 0;
1606
                                                        IPWSEL = 1'b0;          // ALU
1607
                                                end
1608
                                        endcase
1609
                                end else begin
1610
                                        MREQ = 1'b0;
1611
                                        ISIZE = 0;
1612
                                        IRQ = 1'b1;
1613
                                end
1614
 
1615
// --------------------------------  bad opcode/esc --------------------------------
1616
                        default: begin
1617
                                MREQ = 1'b0;
1618
                                ISIZE = 0;
1619
                                IRQ = 1'b1;
1620
                                if(FETCH[0][7:3] == 5'b11011) IRQL = 3'b111; // esc
1621
                        end
1622
                endcase
1623
         end
1624
 
1625
 
1626
 
1627
// instruction pre-decoder
1628
function [5:0]ICODE;
1629
        input [7:0]INSTR;
1630
        begin
1631
                case(INSTR[7:0])
1632
// --------------------------------  mov R/M to/from R/SR  --------------------------------
1633
                        8'b10001000, 8'b10001001, 8'b10001010, 8'b10001011,
1634
                        8'b10001110, 8'b10001100: ICODE = 0;
1635
// --------------------------------  mov IMM to R/M  --------------------------------
1636
                        8'b11000110, 8'b11000111: ICODE = 1;
1637
// --------------------------------  mov IMM to R --------------------------------
1638
                        8'b10110_000, 8'b10110_001, 8'b10110_010, 8'b10110_011, 8'b10110_100, 8'b10110_101, 8'b10110_110, 8'b10110_111,
1639
                        8'b10111_000, 8'b10111_001, 8'b10111_010, 8'b10111_011, 8'b10111_100, 8'b10111_101, 8'b10111_110, 8'b10111_111: ICODE = 2;
1640
// --------------------------------  mov mem to/from ACC --------------------------------
1641
                        8'b10100000, 8'b10100001,
1642
                        8'b10100010, 8'b10100011: ICODE = 3;
1643
// --------------------------------  segment override prefix --------------------------------
1644
                        8'b001_00_110, 8'b001_01_110, 8'b001_10_110, 8'b001_11_110: ICODE = 4;
1645
// --------------------------------  rep prefix --------------------------------
1646
                        8'b11110010, 8'b11110011: ICODE = 5;
1647
// --------------------------------  lock prefix --------------------------------
1648
                        8'b11110000: ICODE = 6;
1649
// --------------------------------  FF block --------------------------------
1650
                        8'b11111111, 8'b11111110:       ICODE = 7;
1651
// --------------------------------  push R/SR --------------------------------
1652
                        8'b01010_000, 8'b01010_001, 8'b01010_010, 8'b01010_011, 8'b01010_100, 8'b01010_101, 8'b01010_110, 8'b01010_111,
1653
                        8'b000_00_110, 8'b000_01_110, 8'b000_10_110, 8'b000_11_110: ICODE = 8;
1654
// --------------------------------  push Imm --------------------------------
1655
                        8'b01101000, 8'b01101010: ICODE = 9;
1656
// --------------------------------  pusha --------------------------------
1657
                        8'b01100000: ICODE = 10;
1658
// --------------------------------  pop R/M --------------------------------
1659
                        8'b10001111: ICODE = 11;
1660
// --------------------------------  pop R / SR --------------------------------
1661
                        8'b01011_000, 8'b01011_001, 8'b01011_010, 8'b01011_011, 8'b01011_100, 8'b01011_101, 8'b01011_110, 8'b01011_111,
1662
                        8'b000_00_111, 8'b000_10_111, 8'b000_11_111: ICODE = 12;
1663
// --------------------------------  popa --------------------------------
1664
                        8'b01100001: ICODE = 13;
1665
// --------------------------------  xchg R with R/M/Acc --------------------------------
1666
                        8'b10000110, 8'b10000111,
1667
                        8'b10010000, 8'b10010001, 8'b10010010, 8'b10010011, 8'b10010100, 8'b10010101, 8'b10010110, 8'b10010111: ICODE = 14;
1668
// --------------------------------  in --------------------------------
1669
                        8'b11100100, 8'b11100101,
1670
                        8'b11101100, 8'b11101101:       ICODE = 15;
1671
// --------------------------------  out --------------------------------
1672
                        8'b11100110, 8'b11100111,
1673
                        8'b11101110, 8'b11101111:       ICODE = 16;
1674
// --------------------------------  xlat --------------------------------
1675
                        8'b11010111: ICODE = 17;
1676
// --------------------------------  lea --------------------------------
1677
                        8'b10001101: ICODE = 18;
1678
// --------------------------------  lds, les --------------------------------
1679
                        8'b11000101, 8'b11000100: ICODE = 19;
1680
// --------------------------------  lahf, sahf --------------------------------
1681
                        8'b10011111, 8'b10011110: ICODE = 20;
1682
// --------------------------------  pushf --------------------------------
1683
                        8'b10011100: ICODE = 21;
1684
// --------------------------------  popf --------------------------------
1685
                        8'b10011101: ICODE = 22;
1686
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
1687
                        8'b00000000, 8'b00000001, 8'b00000010, 8'b00000011,             // add
1688
                        8'b00001000, 8'b00001001, 8'b00001010, 8'b00001011,             // or
1689
                        8'b00010000, 8'b00010001, 8'b00010010, 8'b00010011,             // adc
1690
                        8'b00011000, 8'b00011001, 8'b00011010, 8'b00011011,             // sbb
1691
                        8'b00100000, 8'b00100001, 8'b00100010, 8'b00100011,             // and
1692
                        8'b00101000, 8'b00101001, 8'b00101010, 8'b00101011,             // sub
1693
                        8'b00110000, 8'b00110001, 8'b00110010, 8'b00110011,             // xor
1694
                        8'b00111000, 8'b00111001, 8'b00111010, 8'b00111011,             // cmp
1695
                        8'b10000100, 8'b10000101: ICODE = 23;                                                                   // test 
1696
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
1697
                        8'b10000000, 8'b10000001, 8'b10000010, 8'b10000011: ICODE = 24;
1698
// --------------------------------  add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
1699
                        8'b00000100, 8'b00000101,               // add
1700
                        8'b00001100, 8'b00001101,               // or
1701
                        8'b00010100, 8'b00010101,               // adc
1702
                        8'b00011100, 8'b00011101,               // sbb
1703
                        8'b00100100, 8'b00100101,               // and
1704
                        8'b00101100, 8'b00101101,               // sub
1705
                        8'b00110100, 8'b00110101,               // xor
1706
                        8'b00111100, 8'b00111101,       // cmp
1707
                        8'b10101000, 8'b10101001: ICODE = 25; // test
1708
// --------------------------------  inc/dec R16 --------------------------------
1709
                        8'b01000000, 8'b01000001, 8'b01000010, 8'b01000011, 8'b01000100, 8'b01000101, 8'b01000110, 8'b01000111,
1710
                        8'b01001000, 8'b01001001, 8'b01001010, 8'b01001011, 8'b01001100, 8'b01001101, 8'b01001110, 8'b01001111: ICODE = 26;
1711
// --------------------------------  test/???/not/neg/mul/imul/div/idiv --------------------------------
1712
                        8'b11110110, 8'b11110111: ICODE = 27;
1713
// --------------------------------  imul imm --------------------------------
1714
                        8'b01101001, 8'b01101011: ICODE = 28;
1715
// --------------------------------  aad --------------------------------
1716
                        8'b11010101: ICODE = 29;
1717
// --------------------------------  daa, das, aaa, aas --------------------------------
1718
                        8'b00_100_111, 8'b00_101_111, 8'b00_110_111, 8'b00_111_111: ICODE = 30;
1719
// --------------------------------  shift/rot --------------------------------
1720
                        8'b11010000, 8'b11010001,                       // 1
1721
                        8'b11010010, 8'b11010011,                       // CL
1722
                        8'b11000000, 8'b11000001: ICODE = 31;   // imm
1723
// --------------------------------  (rep)movs --------------------------------
1724
                        8'b10100100, 8'b10100101: ICODE = 32;
1725
// --------------------------------  (rep)cmps --------------------------------
1726
                        8'b10100110, 8'b10100111: ICODE = 33;
1727
// --------------------------------  (rep)scas --------------------------------
1728
                        8'b10101110, 8'b10101111: ICODE = 34;
1729
// --------------------------------  (rep)lods --------------------------------
1730
                        8'b10101100, 8'b10101101: ICODE = 35;
1731
// --------------------------------  (rep)stos --------------------------------
1732
                        8'b10101010, 8'b10101011: ICODE = 36;  // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
1733
// --------------------------------  (rep)ins --------------------------------
1734
                        8'b01101100, 8'b01101101: ICODE = 37;
1735
// --------------------------------  (rep)outs --------------------------------
1736
                        8'b01101110, 8'b01101111: ICODE = 38;
1737
// --------------------------------  call/jmp direct near --------------------------------
1738
                        8'b11101000,                    // call long
1739
                        8'b11101011,                    // jump short
1740
                        8'b11101001: ICODE = 39;        // jump long
1741
// --------------------------------  call/jmp far imm --------------------------------
1742
                        8'b10011010, 8'b11101010: ICODE = 40;
1743
// --------------------------------  ret near --------------------------------
1744
                        8'b11000011, 8'b11000010: ICODE = 41;
1745
// --------------------------------  ret far --------------------------------
1746
                        8'b11001011, 8'b11001010: ICODE = 42;
1747
// --------------------------------  iret --------------------------------
1748
                        8'b11001111: ICODE = 43;
1749
// --------------------------------  cbw/cwd --------------------------------
1750
                        8'b10011000, 8'b10011001: ICODE = 44;
1751
// --------------------------------  JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
1752
                        8'b01110000, 8'b01110001,       // JO/JNO
1753
                        8'b01110010, 8'b01110011,       // JB/JNB
1754
                        8'b01110100, 8'b01110101,       // JE/JNE
1755
                        8'b01110110, 8'b01110111,       // JBE/JA
1756
                        8'b01111000, 8'b01111001,       // JS/JNS
1757
                        8'b01111010, 8'b01111011,       // JP/JNP
1758
                        8'b01111100, 8'b01111101,       // JL/JNL
1759
                        8'b01111110, 8'b01111111,       // JLE/JG
1760
                        8'b11100010, 8'b11100001, 8'b11100000, 8'b11100011: ICODE = 45;  // loop/loopz/loopnz/jcxz
1761
// --------------------------------  CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
1762
                        8'b11111000, 8'b11110101, 8'b11111001, 8'b11111100, 8'b11111101, 8'b11111010, 8'b11111011: ICODE = 46;
1763
// --------------------------------  enter --------------------------------
1764
                        8'b11001000: ICODE = 47;
1765
// --------------------------------  leave --------------------------------
1766
                        8'b11001001: ICODE = 48;
1767
// --------------------------------  int, int 3, into --------------------------------
1768
                        8'b11001101, 8'b11001100, 8'b11001110: ICODE = 49;
1769
// --------------------------------  bound --------------------------------
1770
                        8'b01100010: ICODE = 50;
1771
// --------------------------------  hlt --------------------------------
1772
                        8'b11110100: ICODE = 51;
1773
// --------------------------------  wait --------------------------------
1774
                        8'b10011011: ICODE = 52;        // do nothing
1775
// --------------------------------  aam --------------------------------
1776
                        8'b11010100: ICODE = 53;
1777
// --------------------------------  reset, irq, nmi, intr --------------------------------
1778
                        8'b00001111: ICODE = 54;
1779
// --------------------------------  bad opcode/esc --------------------------------
1780
                        default: ICODE = 55;
1781
                endcase
1782
        end
1783
endfunction
1784
 
1785
endmodule
1786
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.