URL
https://opencores.org/ocsvn/next186/next186/trunk
Subversion Repositories next186
Compare Revisions
- This comparison shows the changes necessary to convert path
/next186/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/Next186_BIU_2T_delayread.v
0,0 → 1,210
////////////////////////////////////////////////////////////////////////////////// |
// |
// This file is part of the Next186 project |
// http://opencores.org/project,next186 |
// |
// Filename: Next186_BIU_2T_delayread.v |
// Description: Part of the Next186 CPU project, bus interface unit |
// Version 1.0 |
// Creation date: 20Jan2012 - 10Mar2012 |
// |
// Author: Nicolae Dumitrache |
// e-mail: ndumitrache@opencores.org |
// |
///////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2011 Nicolae Dumitrache |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, download it |
// from http://www.opencores.org/lgpl.shtml |
// |
/////////////////////////////////////////////////////////////////////////////////// |
// Additional Comments: |
// |
// Description: Next186 Bus Interface Unit, 32bit width SRAM, double CPU frequency (2T), delayed read (1T) |
// |
// The CPU is able to execute (up to) one instrusction/clock with sepparate data and instruction buses. |
// This particular bus interface links the CPU with a 32bit width memory bus and it is able to address up to 1MB. |
// It have a 16byte instruction queue, and works at up to 80Mhz, allowing the CPU to execute an instruction at 2T. It is possible |
// to implement a BIU with sepparate data/instruction buses, which will run at the same frequency as the CPU, but it requires more resources. |
// |
// The 32bit data bus width and the double BIU clock allows the instruction queue to be almost always full, avoiding the CPU starving. |
// The data un-alignement penalties are required only when data words crosses the 4byte boundaries. |
////////////////////////////////////////////////////////////////////////////////// |
// How to compute each instruction duration, in clock cycles (please note that it is specific to this particular BIU implementation): |
// |
// 1 - From the Next186_features.doc see for each instruction how many T states are required (you will notice they are always |
// less or equal than 486 and much less than the original 80186 |
// 2 - multiply this number by 2 - the BIU works at double ALU frequency because it needs to multiplex the data and instructions, |
// in order to keep the ALU permanently feed with instructions. The 16bit queue acts like a flexible instruction buffer. |
// 3 - add penalties, as follows: |
// +1T for each memory read - because of the synchronous SRAM which need this extra cycle to deliver the data |
// +2T for each jump - required to flush and re-fill the instruction queue |
// +1T for each 16bit(word) read/write which overlaps the 4byte boundary - specific to 32bit bus width |
// +1T if the jump is made at an address with the latest 2bits 11 - specific to 32bit bus width |
// +1T when the instruction queue empties - this case appears very rare, when a lot of 5-6 bytes memory write |
// instructions are executed one after the other |
// Some examples: |
// - the instruction "inc word ptr [1]" will require 5T (2x2T inc M + 1T read) |
// - the instruction "inc word ptr [3]" will require 7T (2x2T inc M + 1T read + 1T unaligned read + 1T unaligned write) |
// - the instruction "imul ax,bx,234" will require 4T (2x2T imul) |
// - the instruction "loop <address = 1>" will require 4T (2x1T loop + 2T flush) |
// - the instruction "loop <address = 3>" will require 5T (2x1T loop + 2T flush + 1T unaligned jump) |
// - the instruction "call <address = 0>" will require 4T (2x1T call near + 2T flush |
// - the instruction "ret <address = 0>" will require 5T (2x2T ret + 1T read penalty) |
////////////////////////////////////////////////////////////////////////////////// |
|
`timescale 1ns / 1ps |
|
|
module BIU186_32bSync_2T_DelayRead( |
input CLK, |
output [47:0]INSTR, |
input [2:0]ISIZE, |
input IFETCH, |
input FLUSH, |
input MREQ, |
input WR, |
input WORD, |
input [19:0]ADDR, |
input [19:0]IADDR, |
output reg CE186, // CPU clock enable |
input [31:0]RAM_DIN, |
output [31:0]RAM_DOUT, |
output [17:0]RAM_ADDR, |
output RAM_MREQ, |
output wire[3:0]RAM_WMASK, |
output reg [15:0]DOUT, |
input [15:0]DIN, |
input CE // BIU clock enable |
); |
|
reg [31:0]queue[3:0]; |
reg [1:0]STATE = 0; |
reg OLDSTATE = 1; |
reg [3:0]qpos = 0; |
reg [4:0]qsize = 0; |
reg [1:0]rpos = 0; |
reg [17:0]piaddr = 0; |
reg [7:0]exdata = 0; |
reg rdi = 0; |
reg data_bound; |
|
reg [1:0]NEXTSTATE; |
reg RAM_RD; |
reg RAM_WR; |
reg sflush; |
wire [4:0]newqsize = sflush ? -IADDR[1:0] : CE186 && IFETCH && ~FLUSH ? qsize - ISIZE : qsize; |
wire qnofull = qsize < 13; |
reg iread;// = (qnofull && !RAM_RD && !RAM_WR) || sflush; |
wire [3:0]nqpos = (FLUSH && IFETCH) ? {2'b00, IADDR[1:0]} : (qpos + ISIZE); |
wire [17:0]MIADDR = sflush ? IADDR[19:2] : piaddr; |
wire split = (&ADDR[1:0]) && WORD; // data between dwords |
wire [15:0]DSWAP = ADDR[0] ? {DIN[7:0], DIN[15:8]} : DIN; |
wire [1:0]a1 = nqpos[3:2] + 1; |
wire [1:0]a2 = nqpos[3:2] + 2; |
wire [31:0]q1 = rdi && (a1 == rpos) ? RAM_DIN : queue[a1]; |
wire [7:0]q2 = rdi && (a2 == rpos) ? RAM_DIN[7:0] : queue[a2][7:0]; |
|
assign INSTR = {q2, q1, queue[nqpos[3:2]]} >> {nqpos[1:0], 3'b000}; |
// assign DOUT = split ? {RAM_DIN[7:0], exdata} : (RAM_DIN >> {ADDR[1:0], 3'b000}); |
assign RAM_DOUT = {DSWAP, DSWAP}; |
assign RAM_MREQ = iread || RAM_RD || RAM_WR; |
assign RAM_ADDR = iread ? MIADDR : ADDR[19:2] + data_bound; |
assign RAM_WMASK = data_bound ? {3'b000, RAM_WR} : {2'b00, WORD & RAM_WR, RAM_WR} << ADDR[1:0]; |
|
always @(*) begin |
RAM_RD = 0; |
RAM_WR = 0; |
CE186 = 0; |
sflush = 0; |
data_bound = 0; |
iread = 0; |
|
case(ADDR[1:0]) |
2'b00: DOUT = RAM_DIN[15:0]; |
2'b01: DOUT = RAM_DIN[23:8]; |
2'b10: DOUT = RAM_DIN[31:16]; |
2'b11: DOUT = {RAM_DIN[7:0], WORD ? exdata : RAM_DIN[31:24]}; |
endcase |
|
case(STATE) |
0: begin // no cpu activity on first state |
iread = qnofull; |
NEXTSTATE = 1; |
end |
1: begin |
NEXTSTATE = 1; |
if(FLUSH && IFETCH && !OLDSTATE) begin |
sflush = 1; |
iread = 1; |
end else if((FLUSH && IFETCH && (qsize > 5)) || (qsize > 11)) begin |
NEXTSTATE = 0; |
if(MREQ) begin |
if(WR) begin // write |
RAM_WR = 1; |
if(split) NEXTSTATE = 3; |
else CE186 = 1; |
end else begin |
RAM_RD = 1; |
NEXTSTATE = split ? 2 : 3; |
end |
end else begin |
iread = qnofull; |
CE186 = 1; |
end |
end else iread = 1; // else nextstate = 1 |
end |
2: begin |
RAM_RD = 1; |
data_bound = 1; // split memory access |
NEXTSTATE = 3; |
end |
3: begin |
RAM_WR = WR && MREQ; |
iread = !(WR && MREQ) && qnofull; |
data_bound = split; |
CE186 = 1; |
NEXTSTATE = 0; |
end |
endcase |
end |
|
always @ (posedge CLK) if(CE) begin |
rdi <= iread; |
if(rdi) queue[rpos] <= RAM_DIN; |
if(iread) begin |
qsize <= {newqsize[4:2] + 1, newqsize[1:0]}; |
piaddr <= MIADDR + 1; |
end else begin |
qsize <= newqsize; |
piaddr <= MIADDR; |
end |
if(CE186 && IFETCH) qpos <= nqpos; |
if(sflush) rpos <= 0; |
else if(rdi) rpos <= rpos + 1; |
OLDSTATE <= STATE[0]; |
STATE <= NEXTSTATE; |
if(data_bound) exdata <= RAM_DIN[31:24]; |
end |
|
endmodule |
|
/Next186_features.doc
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Next186_features.doc
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: sample/boot.asm
===================================================================
--- sample/boot.asm (nonexistent)
+++ sample/boot.asm (revision 2)
@@ -0,0 +1,57 @@
+; this is the bootstrap code contained in SRAM.coe initialization file
+
+.186
+.model tiny
+.code
+ org 0
+start:
+ mov ax,0ff80h
+ mov ss,ax
+ mov ds,ax
+ mov es,ax
+ mov sp,100h
+
+ mov si,com
+ call srecb
+ mov bh,ah
+ call srecb
+ mov bl,ah
+
+sloop:
+ call srecb
+ mov [si],ah
+ inc si
+ dec bx
+ jnz sloop
+ jmp exec
+
+; ---------------- serial receive byte 115200 bps --------------
+srecb:
+ mov ah,80h
+ mov cx,56h
+srstb:
+ in al,0
+ and al,1
+ jnz srstb
+ nop
+l1:
+ loop l1
+
+rnxtb:
+ mov cl,adh
+l2:
+ loop l2
+ test al,80h
+ jnz return
+ in al,0
+ ror ax,1
+ jmp rnxtb
+return:
+ ret
+exec: jmp com
+
+ org 100h
+com:
+
+
+end start
\ No newline at end of file
Index: sample/SRAM.coe
===================================================================
--- sample/SRAM.coe (nonexistent)
+++ sample/SRAM.coe (revision 2)
@@ -0,0 +1,5 @@
+memory_initialization_radix = 16;
+memory_initialization_vector =
+8eff80b8, 8ed88ed0, 0100bcc0, e80100be, e7880012, 88000de8, 0008e8e3, 4b462488, 1debf775, 48b980b4, 2400e400, 90fa7501, 90b1fee2, 80a8fee2, 00e40675, f2ebc8d1, 00bce9c3, 00000000, 00000000, 00000000, 00000000, 00000000, 00000000, 00000000, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 79, FE, 09, 28, 35, FE, 02, C0, 2A, 03, 00, 7B, FE, 20, 30, 1C, FE, 0A, C0, 21, 50, 78, 11, 00, 78, 01, 30, 07, ED, B0, 62, 6B, 13, 01, 4F, 00, 36, 20, E5, ED, B0, E1, 18, 0A, 77, 23, 3E, 7F, BC, 20, 03, BD, 28, DD, 22, 03, 00, C9, 1A, 13, FE, 24, C8, D5, 5F, CD, 50, 00, D1, 18, F3, 31, 00, 00, 21, 30, 7F, 22, 03, 00, 3E, 1C, D3, 02, 0E, 09, 11, C0, 00, CD, 48, 00, DD, 21, 00, 01, CD, E0, 00, 61, CD, E0, 00, 69, CD, E0, 00, DD, 71, 00, DD, 23, 2B, 7C, B5, 20, F3, C3, 00, 01, 0A, 57, 61, 69, 74, 69, 6E, 67, 20, 6F, 6E, 20, 52, 53, 32, 33, 32, 20, 31, 31, 35, 32, 30, 30, 62, 70, 73, 2E, 2E, 2E, 0A, 24, 01, 80, 45, DB, 01, E6, 10, 20, FA, 10, FE, 06, 8a, 10, FE, D8, DB, 01, E6, 10, C6, F0, CB, 19, 18, F1, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 800000ea, 000000ff, 00, 00,
+
+8eff80b8, 8ed88ed0, 0100bcc0, e80100be, e7880012, 88000de8, 0008e8e3, 4b462488, 1debf775, 56b980b4, 2400e400, 90fa7501, adb1fee2, 80a8fee2, 00e40675, f2ebc8d1, 00bce9c3, 00000000, 00000000, 00000000, 00000000, 00000000, 00000000, 00000000, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 79, FE, 09, 28, 35, FE, 02, C0, 2A, 03, 00, 7B, FE, 20, 30, 1C, FE, 0A, C0, 21, 50, 78, 11, 00, 78, 01, 30, 07, ED, B0, 62, 6B, 13, 01, 4F, 00, 36, 20, E5, ED, B0, E1, 18, 0A, 77, 23, 3E, 7F, BC, 20, 03, BD, 28, DD, 22, 03, 00, C9, 1A, 13, FE, 24, C8, D5, 5F, CD, 50, 00, D1, 18, F3, 31, 00, 00, 21, 30, 7F, 22, 03, 00, 3E, 1C, D3, 02, 0E, 09, 11, C0, 00, CD, 48, 00, DD, 21, 00, 01, CD, E0, 00, 61, CD, E0, 00, 69, CD, E0, 00, DD, 71, 00, DD, 23, 2B, 7C, B5, 20, F3, C3, 00, 01, 0A, 57, 61, 69, 74, 69, 6E, 67, 20, 6F, 6E, 20, 52, 53, 32, 33, 32, 20, 31, 31, 35, 32, 30, 30, 62, 70, 73, 2E, 2E, 2E, 0A, 24, 01, 80, 45, DB, 01, E6, 10, 20, FA, 10, FE, 06, 8a, 10, FE, D8, DB, 01, E6, 10, C6, F0, CB, 19, 18, F1, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 800000ea, 000000ff, 00, 00
\ No newline at end of file
Index: sample/system.v
===================================================================
--- sample/system.v (nonexistent)
+++ sample/system.v (revision 2)
@@ -0,0 +1,186 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// This file is part of the Next186 project
+// http://opencores.org/project,next186
+//
+// Filename: system.v
+// Description: Next80186 example system with 4K SRAM, working at 80MHZ
+// Version 1.0
+// Creation date: 20Jan2012 - 10Mar2012
+//
+// Author: Nicolae Dumitrache
+// e-mail: ndumitrache@opencores.org
+//
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011 Nicolae Dumitrache
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, download it
+// from http://www.opencores.org/lgpl.shtml
+//
+///////////////////////////////////////////////////////////////////////////////////
+//
+// Comments:
+// This project was developed and tested on a XILINX Spartan3AN board.
+//
+// This is a demonstration system containing:
+// - Next80186 CPU
+// - Next80186 BIU - 32bit bus, 80Mhz
+// - 4KB SRAM (2KB at address 00000h - interrupt table zone, 2KB at address FF800h - ROM zone)
+// - 1DCM with 50Mhz input and 80Mhz output
+// The system is connected to RS232, to 9 LEDs on board and to a RESET button.
+//
+///////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module system(
+// output [17:0]RAM_ADDR,
+// output CE,
+// output [3:0]RAM_WMASK,
+// output RAM_MREQ,
+// output RAM_WR,
+// output [31:0]RAM_DIN,
+// output [31:0]RAM_DOUT,
+// output [47:0]INSTR,
+// output IFETCH,
+// output FLUSH,
+// output MREQ,
+// output WR,
+// output WORD,
+// output [19:0]ADDR,
+// output [19:0]IADDR,
+// output [15:0]DIN,
+// output [15:0]DOUT,
+// output [2:0]ISIZE,
+// output HALT,
+// output IORQ,
+
+ input CLK_50MHZ,
+ input BTN_SOUTH,
+ output reg[7:0]LED,
+ output FPGA_AWAKE, // HALT
+ input RS232_DCE_RXD,
+ output reg RS232_DCE_TXD
+ );
+
+
+ wire [19:0]ADDR;
+ wire [19:0]IADDR;
+ wire [15:0]DIN;
+ wire [15:0]DOUT;
+ wire [47:0]INSTR;
+ wire [2:0]ISIZE;
+ wire [31:0]RAM_DIN;
+ wire [31:0]RAM_DOUT;
+ wire [17:0]RAM_ADDR;
+ wire [3:0] RAM_WMASK;
+ wire RAM_MREQ;
+ wire CE;
+ wire MREQ;
+ wire WR;
+ wire WORD;
+ wire IFETCH;
+ wire FLUSH;
+ wire HALT;
+ wire IORQ;
+
+ reg s_RS232_DCE_RXD;
+ wire CLK;
+ reg [4:0]rstcount = 0;
+
+ Next186_CPU CPU186
+ (
+ .ADDR(ADDR),
+ .DIN({DIN[15:1], IORQ ? s_RS232_DCE_RXD : DIN[0]}),
+ .DOUT(DOUT),
+ .CLK(CLK),
+ .CE(CE),
+ .INTR(1'b0),
+ .NMI(1'b0),
+ .RST(BTN_SOUTH || !rstcount[4]),
+ .MREQ(MREQ),
+ .IORQ(IORQ),
+// .INTA(INTA),
+ .WR(WR),
+ .WORD(WORD),
+// .LOCK(LOCK),
+ .IADDR(IADDR),
+ .INSTR(INSTR),
+ .IFETCH(IFETCH),
+ .FLUSH(FLUSH),
+ .ISIZE(ISIZE),
+ .HALT(FPGA_AWAKE)
+ );
+
+ BIU186_32bSync_2T_DelayRead BIU186
+ (
+ .CLK(CLK),
+ .INSTR(INSTR),
+ .ISIZE(ISIZE),
+ .IFETCH(IFETCH),
+ .FLUSH(FLUSH),
+ .MREQ(MREQ),
+ .WR(WR),
+ .WORD(WORD),
+ .ADDR(ADDR),
+ .IADDR(IADDR),
+ .CE186(CE),
+ .RAM_DIN(RAM_DIN),
+ .RAM_DOUT(RAM_DOUT),
+ .RAM_ADDR(RAM_ADDR),
+ .RAM_MREQ(RAM_MREQ),
+ .RAM_WMASK(RAM_WMASK),
+ .DOUT(DIN),
+ .DIN(DOUT),
+ .CE(1'b1)
+ );
+
+ wire block0 = RAM_ADDR[17:9] == 9'b000000000;
+ wire block1 = RAM_ADDR[17:9] == 9'b111111111;
+
+ sram SRAM_
+ (
+ .clka(CLK), // input clka
+ .ena(RAM_MREQ && (block0 || block1)), // input ena
+ .wea(RAM_WMASK), // input [3 : 0] wea
+ .addra(RAM_ADDR[9:0]), // input [9 : 0] addra
+ .dina(RAM_DOUT), // input [31 : 0] dina
+ .douta(RAM_DIN) // output [31 : 0] douta
+ );
+
+ dcm system_clock
+ (
+ .CLKIN_IN(CLK_50MHZ),
+ .CLKFX_OUT(CLK)
+// .CLKIN_IBUFG_OUT(CLKIN_IBUFG_OUT),
+// .CLK0_OUT(CLK0_OUT)
+ );
+
+
+ always @ (posedge CLK) begin
+ if(CE && IORQ && WR) begin
+ if(ADDR[0]) RS232_DCE_TXD <= DOUT[0];
+ else LED <= DOUT[7:0];
+ end
+ s_RS232_DCE_RXD <= RS232_DCE_RXD;
+ if(CE && ~rstcount[4]) rstcount <= rstcount + 1;
+ end
+endmodule
Index: sample/mon/a.asm
===================================================================
--- sample/mon/a.asm (nonexistent)
+++ sample/mon/a.asm (revision 2)
@@ -0,0 +1,156 @@
+.186
+.model tiny
+.code
+zero:
+ org 24h
+srecv label near
+ org 100h
+start:
+ xor ax,ax
+ mov es,ax
+ mov word ptr es:[10h*4], offset int10
+ mov es:[10h*4+2], cs
+ mov word ptr es:[11h*4], offset int11
+ mov es:[11h*4+2], cs
+ mov ax,1
+ mov ax,cs
+ mov es,ax
+
+newline:
+ mov di, offset buf
+ mov cx, 15
+newchar:
+ int 10h
+ mov al,ah
+ stosb
+ int 11h
+ cmp al,8
+ jne nobs
+ sub di,2
+ cmp di,offset buf
+ jae nobs
+ mov di,offset buf
+nobs:
+ cmp al,13
+ jz nc1
+ loop newchar
+ mov al,13
+ stosb
+ int 11h
+nc1:
+ mov byte ptr [di-1], 0
+ mov si,offset buf
+ cmp byte ptr [si],'d'
+ jne nodump
+
+ mov cx,8
+ xor si,si
+ dl1:
+ mov dx,16
+ push cx
+ call dumpline
+ mov al,13
+ int 11h
+ pop cx
+ loop dl1
+
+ jmp cr
+nodump:
+ call prtstr
+ mov al, '?'
+ int 11h
+cr:
+ mov al,13
+ int 11h
+ jmp newline
+
+buf db 16 dup(0)
+
+;--------------------------------- receive char INT10 -----------------------------------
+int10: ; get RS232 char in ah
+ push cx
+ call srecv
+ pop cx
+ iret
+
+;--------------------------------- send char INT11 -----------------------------------
+int11: ; write RS232 char from al
+ push ax
+ push cx
+ out 0,al
+ mov ah,1
+ add ax,ax
+int111:
+ out 1,al
+ mov cx,0adh;8bh;90h
+even
+ loop $
+ shr ax,1
+ jnz int111
+ pop cx
+ pop ax
+ iret
+
+;--------------------------------- print string at SI -----------------------------------
+prtstr:
+ lodsb
+ test al,al
+ jz prtstr1
+ int 11h
+ jmp prtstr
+prtstr1:
+ ret
+
+;--------------------------------- print 4 digit hex number in ax -------------------------------
+prthex4:
+ xchg ah,al
+ call prthex2
+ mov al,ah
+;--------------------------------- print 2 digit hex number in al -------------------------------
+prthex2:
+ mov bx, offset hexdigit
+ push ax
+ shr al,4
+ xlat
+ int 11h
+ pop ax
+ and al,15
+ xlat
+ int 11h
+ ret
+hexdigit db "0123456789ABCDEF"
+
+;-------------------------------- dump DX bytes memory at DS:SI -------------------------------
+dumpline:
+ mov ax,ds
+ call prthex4
+ mov al, ':'
+ int 11h
+ mov ax,si
+ call prthex4
+ mov cx,dx
+ mov al,' '
+ int 11h
+dump1:
+ mov al, ' '
+ int 11h
+ lodsb
+ call prthex2
+ loop dump1
+ mov cx,dx
+ sub si,dx
+ mov al,' '
+ int 11h
+ int 11h
+dump2:
+ lodsb
+ sub al,32
+ cmp al,128-32
+ jb dump3
+ mov al,'.'-32
+dump3: add al,32
+ int 11h
+ loop dump2
+ ret
+
+end start
Index: sample/mon/a.lst
===================================================================
--- sample/mon/a.lst (nonexistent)
+++ sample/mon/a.lst (revision 2)
@@ -0,0 +1,220 @@
+Microsoft (R) Macro Assembler Version 6.14.8444 03/12/12 12:53:08
+a.asm Page 1 - 1
+
+
+ .186
+ .model tiny
+ 0000 .code
+ 0000 zero:
+ org 24h
+ 0024 srecv label near
+ org 100h
+ 0100 start:
+ 0100 33 C0 xor ax,ax
+ 0102 8E C0 mov es,ax
+ 0104 26: C7 06 0040 mov word ptr es:[10h*4], offset int10
+ 0189 R
+ 010B 26: 8C 0E 0042 mov es:[10h*4+2], cs
+ 0110 26: C7 06 0044 mov word ptr es:[11h*4], offset int11
+ 018F R
+ 0117 26: 8C 0E 0046 mov es:[11h*4+2], cs
+ 011C B8 0001 mov ax,1
+ 011F 8C C8 mov ax,cs
+ 0121 8E C0 mov es,ax
+
+ 0123 newline:
+ 0123 BF 0179 R mov di, offset buf
+ 0126 B9 000F mov cx, 15
+ 0129 newchar:
+ 0129 CD 10 int 10h
+ 012B 8A C4 mov al,ah
+ 012D AA stosb
+ 012E CD 11 int 11h
+ 0130 3C 08 cmp al,8
+ 0132 75 0C jne nobs
+ 0134 83 EF 02 sub di,2
+ 0137 81 FF 0179 R cmp di,offset buf
+ 013B 73 03 jae nobs
+ 013D BF 0179 R mov di,offset buf
+ 0140 nobs:
+ 0140 3C 0D cmp al,13
+ 0142 74 07 jz nc1
+ 0144 E2 E3 loop newchar
+ 0146 B0 0D mov al,13
+ 0148 AA stosb
+ 0149 CD 11 int 11h
+ 014B nc1:
+ 014B C6 45 FF 00 mov byte ptr [di-1], 0
+ 014F BE 0179 R mov si,offset buf
+ 0152 80 3C 64 cmp byte ptr [si],'d'
+ 0155 75 15 jne nodump
+
+ 0157 B9 0008 mov cx,8
+ 015A 33 F6 xor si,si
+ 015C dl1:
+ 015C BA 0010 mov dx,16
+ 015F 51 push cx
+ 0160 E8 0074 call dumpline
+ 0163 B0 0D mov al,13
+ 0165 CD 11 int 11h
+ 0167 59 pop cx
+ 0168 E2 F2 loop dl1
+
+ 016A EB 07 jmp cr
+ 016C nodump:
+ 016C E8 0036 call prtstr
+ 016F B0 3F mov al, '?'
+ 0171 CD 11 int 11h
+ 0173 cr:
+ 0173 B0 0D mov al,13
+ 0175 CD 11 int 11h
+ 0177 EB AA jmp newline
+
+ 0179 0010 [ buf db 16 dup(0)
+ 00
+ ]
+
+ ;--------------------------------- receive char INT10 -----------------------------------
+ 0189 int10: ; get RS232 char in ah
+ 0189 51 push cx
+ 018A E8 FE97 call srecv
+ 018D 59 pop cx
+ 018E CF iret
+
+ ;--------------------------------- send char INT11 -----------------------------------
+ 018F int11: ; write RS232 char from al
+ 018F 50 push ax
+ 0190 51 push cx
+ 0191 E6 00 out 0,al
+ 0193 B4 01 mov ah,1
+ 0195 03 C0 add ax,ax
+ 0197 int111:
+ 0197 E6 01 out 1,al
+ 0199 B9 00AD mov cx,0adh;8bh;90h
+ 019C even
+ 019C E2 FE loop $
+ 019E D1 E8 shr ax,1
+ 01A0 75 F5 jnz int111
+ 01A2 59 pop cx
+ 01A3 58 pop ax
+ 01A4 CF iret
+
+ ;--------------------------------- print string at SI -----------------------------------
+ 01A5 prtstr:
+ 01A5 AC lodsb
+ 01A6 84 C0 test al,al
+ 01A8 74 04 jz prtstr1
+ 01AA CD 11 int 11h
+ 01AC EB F7 jmp prtstr
+ 01AE prtstr1:
+ 01AE C3 ret
+
+ ;--------------------------------- print 4 digit hex number in ax -------------------------------
+ 01AF prthex4:
+ 01AF 86 E0 xchg ah,al
+ 01B1 E8 0002 call prthex2
+ 01B4 8A C4 mov al,ah
+ ;--------------------------------- print 2 digit hex number in al -------------------------------
+ 01B6 prthex2:
+ 01B6 BB 01C7 R mov bx, offset hexdigit
+ 01B9 50 push ax
+ 01BA C0 E8 04 shr al,4
+ 01BD D7 xlat
+ 01BE CD 11 int 11h
+ 01C0 58 pop ax
+ 01C1 24 0F and al,15
+ 01C3 D7 xlat
+ 01C4 CD 11 int 11h
+ 01C6 C3 ret
+ 01C7 30 31 32 33 34 35 hexdigit db "0123456789ABCDEF"
+ 36 37 38 39 41 42
+ 43 44 45 46
+
+ ;-------------------------------- dump DX bytes memory at DS:SI -------------------------------
+ 01D7 dumpline:
+ 01D7 8C D8 mov ax,ds
+ 01D9 E8 FFD3 call prthex4
+ 01DC B0 3A mov al, ':'
+ 01DE CD 11 int 11h
+ 01E0 8B C6 mov ax,si
+ 01E2 E8 FFCA call prthex4
+ 01E5 8B CA mov cx,dx
+ 01E7 B0 20 mov al,' '
+ 01E9 CD 11 int 11h
+ 01EB dump1:
+ 01EB B0 20 mov al, ' '
+ 01ED CD 11 int 11h
+ 01EF AC lodsb
+ 01F0 E8 FFC3 call prthex2
+ 01F3 E2 F6 loop dump1
+ 01F5 8B CA mov cx,dx
+ 01F7 2B F2 sub si,dx
+ 01F9 B0 20 mov al,' '
+ 01FB CD 11 int 11h
+ 01FD CD 11 int 11h
+ 01FF dump2:
+ 01FF AC lodsb
+ 0200 2C 20 sub al,32
+ 0202 3C 60 cmp al,128-32
+ 0204 72 02 jb dump3
+ 0206 B0 0E mov al,'.'-32
+ 0208 04 20 dump3: add al,32
+ 020A CD 11 int 11h
+ 020C E2 F1 loop dump2
+ 020E C3 ret
+
+ end start
+Microsoft (R) Macro Assembler Version 6.14.8444 03/12/12 12:53:08
+a.asm Symbols 2 - 1
+
+
+
+
+Segments and Groups:
+
+ N a m e Size Length Align Combine Class
+
+DGROUP . . . . . . . . . . . . . GROUP
+_TEXT . . . . . . . . . . . . . 16 Bit 020F Word Public 'CODE'
+_DATA . . . . . . . . . . . . . 16 Bit 0000 Word Public 'DATA'
+
+
+Symbols:
+
+ N a m e Type Value Attr
+
+@CodeSize . . . . . . . . . . . Number 0000h
+@DataSize . . . . . . . . . . . Number 0000h
+@Interface . . . . . . . . . . . Number 0000h
+@Model . . . . . . . . . . . . . Number 0001h
+@code . . . . . . . . . . . . . Text DGROUP
+@data . . . . . . . . . . . . . Text DGROUP
+@fardata? . . . . . . . . . . . Text FAR_BSS
+@fardata . . . . . . . . . . . . Text FAR_DATA
+@stack . . . . . . . . . . . . . Text DGROUP
+buf . . . . . . . . . . . . . . Byte 0179 _TEXT
+cr . . . . . . . . . . . . . . . L Near 0173 _TEXT
+dl1 . . . . . . . . . . . . . . L Near 015C _TEXT
+dump1 . . . . . . . . . . . . . L Near 01EB _TEXT
+dump2 . . . . . . . . . . . . . L Near 01FF _TEXT
+dump3 . . . . . . . . . . . . . L Near 0208 _TEXT
+dumpline . . . . . . . . . . . . L Near 01D7 _TEXT
+hexdigit . . . . . . . . . . . . Byte 01C7 _TEXT
+int10 . . . . . . . . . . . . . L Near 0189 _TEXT
+int111 . . . . . . . . . . . . . L Near 0197 _TEXT
+int11 . . . . . . . . . . . . . L Near 018F _TEXT
+nc1 . . . . . . . . . . . . . . L Near 014B _TEXT
+newchar . . . . . . . . . . . . L Near 0129 _TEXT
+newline . . . . . . . . . . . . L Near 0123 _TEXT
+nobs . . . . . . . . . . . . . . L Near 0140 _TEXT
+nodump . . . . . . . . . . . . . L Near 016C _TEXT
+prthex2 . . . . . . . . . . . . L Near 01B6 _TEXT
+prthex4 . . . . . . . . . . . . L Near 01AF _TEXT
+prtstr1 . . . . . . . . . . . . L Near 01AE _TEXT
+prtstr . . . . . . . . . . . . . L Near 01A5 _TEXT
+srecv . . . . . . . . . . . . . L Near 0024 _TEXT
+start . . . . . . . . . . . . . L Near 0100 _TEXT
+zero . . . . . . . . . . . . . . L Near 0000 _TEXT
+
+ 0 Warnings
+ 0 Errors
Index: sample/mon/a.com
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: sample/mon/a.com
===================================================================
--- sample/mon/a.com (nonexistent)
+++ sample/mon/a.com (revision 2)
sample/mon/a.com
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: sample/readme.txt.txt
===================================================================
--- sample/readme.txt.txt (nonexistent)
+++ sample/readme.txt.txt (revision 2)
@@ -0,0 +1,2 @@
+The provided SRAM initialization .COE file contains a RS232 bootstrap program which can load code at address FF80:0100 with help of provided SerialComm.exe application.
+A sample .ASM application is provided (a simple RS232 feedback loop, with a minimemory dump feature) - see "mon" folder.
Index: sample/SerialComm.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: sample/SerialComm.exe
===================================================================
--- sample/SerialComm.exe (nonexistent)
+++ sample/SerialComm.exe (revision 2)
sample/SerialComm.exe
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: Next186_Regs.v
===================================================================
--- Next186_Regs.v (nonexistent)
+++ Next186_Regs.v (revision 2)
@@ -0,0 +1,184 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// This file is part of the Next186 project
+// http://opencores.org/project,next186
+//
+// Filename: Next186_Regs.v
+// Description: Part of the Next186 CPU project, registers module
+// Version 1.0
+// Creation date: 11Apr2011 - 07Jun2011
+//
+// Author: Nicolae Dumitrache
+// e-mail: ndumitrache@opencores.org
+//
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011 Nicolae Dumitrache
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, download it
+// from http://www.opencores.org/lgpl.shtml
+//
+///////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
+
+module Next186_Regs(
+ input [2:0]RASEL,
+ input [2:0]RBSEL,
+ input BASEL,
+ input [1:0]BBSEL,
+ input [1:0]RSSEL,
+ input [15:0]DIN,
+ input [15:0]ALUOUT,
+ input [15:0]ADDR16,
+ input [15:0]DIMM,
+ input [4:0]WE, // 4=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
+ input IFETCH,
+ input [15:0]FIN,
+ input [1:0]DISEL,
+ input [15:0]IPIN,
+ input WORD,
+ input INCSP,
+ input DECCX,
+ input DIVOP,
+ input DIVEND,
+ input DIVC,
+ input DIVSGN,
+ output [1:0]CXZ,
+ output [15:0]FOUT,
+ output [15:0]RA,
+ output [15:0]RB,
+ output reg [15:0]TMP16,
+ output reg [15:0]SP,
+ output reg [15:0]IP,
+ output reg [15:0]AX,
+ output reg [15:0]BX,
+ output reg [15:0]BP,
+ output reg [15:0]SI,
+ output reg [15:0]DI,
+ output [15:0]RS,
+ output [15:0]CS,
+ output reg [15:0]DX,
+ output DIVEXC,
+ input CLK,
+ input CLKEN
+ );
+
+ reg [15:0]CX;
+ reg [15:0]SREG[3:0];
+ reg [8:0]FLG;
+ reg [15:0]REG_ASEL;
+ reg [15:0]REG_BSEL;
+ wire [15:0]RW = DISEL[0] ? ALUOUT : ADDR16; // x1=ALU, 10=ADDR, 00=DIN
+ wire [2:0]ASEL = {WORD & RASEL[2], RASEL[1:0]};
+ wire [2:0]BSEL = {WORD & RBSEL[2], RBSEL[1:0]};
+ wire [7:0]RWHI = WORD || &WE[1:0] ? RW[15:8] : RW[7:0];
+ wire [8:0]RWDL = {DIVOP && ~DIVC ? DX[7:0] : RW[7:0], AX[15]};
+ wire [8:0]RWDH = {DIVOP && ~DIVC ? DX[15:7] : {RWHI, RW[7]}};
+ wire [8:0]RWAH = {DIVOP && ~DIVC ? AX[15:8] : RWHI, AX[7]};
+ assign DIVEXC = WORD ? RWDH[8] : RWAH[8];
+
+ wire FASTDIN = ~|DISEL;
+ wire [15:0]FDRW = FASTDIN ? DIN : RW;
+ wire [7:0]FASTDINH = WORD || &WE[1:0] ? DIN[15:8] : DIN[7:0]; // fast data path for AH/DH (tweak for speed)
+ wire [15:0]CXM1 = CX + 16'hffff;
+
+ assign FOUT = {4'b0000, FLG[8:3], 1'b0, FLG[2], 1'b0, FLG[1], 1'b1, FLG[0]};
+ assign CS = SREG[1];
+ assign CXZ = {|CX[15:1], CX[0]};
+
+ wire [15:0]RA1 = {REG_ASEL[15:8], WORD | !RASEL[2] ? REG_ASEL[7:0] : REG_ASEL[15:8]};
+ assign RA = BASEL ? RA1 : TMP16;
+ assign RB = BBSEL[1] ? BBSEL[0] ? SREG[BSEL[1:0]] : DIMM : BBSEL[0] ? {REG_BSEL[15:8], WORD | !RBSEL[2] ? REG_BSEL[7:0] : REG_BSEL[15:8]} : TMP16;
+ assign RS = SREG[RSSEL];
+
+ always @* begin
+ case(ASEL)
+ 0: REG_ASEL = AX;
+ 1: REG_ASEL = CX;
+ 2: REG_ASEL = DX;
+ 3: REG_ASEL = BX;
+ 4: REG_ASEL = SP;
+ 5: REG_ASEL = BP;
+ 6: REG_ASEL = SI;
+ 7: REG_ASEL = DI;
+ endcase
+ case(BSEL)
+ 0: REG_BSEL = AX;
+ 1: REG_BSEL = CX;
+ 2: REG_BSEL = DX;
+ 3: REG_BSEL = BX;
+ 4: REG_BSEL = SP;
+ 5: REG_BSEL = BP;
+ 6: REG_BSEL = SI;
+ 7: REG_BSEL = DI;
+ endcase
+ end
+/*
+ BUFG BUFG_inst (
+ .O(CLKD), // Clock buffer output
+ .I(CLK) // Clock buffer input
+ );
+*/
+ always @(posedge CLK)
+ if(CLKEN) begin
+ if(WE[0] && ASEL == 0) AX[7:0] <= FDRW[7:0];
+ else if(DIVOP) AX[7:0] <= {AX[6:0], DIVC ^ DIVSGN};
+
+ if(WE[1] && ASEL == 0) AX[15:8] <= FASTDIN ? FASTDINH : (DIVOP && ~DIVEND ? RWAH[7:0] : RWAH[8:1]);
+ else if(DIVOP) AX[15:8] <= AX[14:7];
+
+ if(WE[0] && ASEL == 1) CX[7:0] <= FDRW[7:0];
+ else if(DECCX) CX[7:0] <= CXM1[7:0];
+
+ if(WE[1] && ASEL == 1) CX[15:8] <= FASTDIN ? FASTDINH : RWHI;
+ else if(DECCX) CX[15:8] <= CXM1[15:8];
+
+ if(WE[0] && ASEL == 2) DX[7:0] <= FASTDIN ? DIN[7:0] : (DIVOP && ~DIVEND ? RWDL[7:0] : RWDL[8:1]);
+ if(WE[1] && ASEL == 2) DX[15:8] <= FASTDIN ? FASTDINH : (DIVOP && ~DIVEND ? RWDH[7:0] : RWDH[8:1]);
+
+ if(WE[0] && ASEL == 3) BX[7:0] <= FDRW[7:0];
+ if(WE[1] && ASEL == 3) BX[15:8] <= FASTDIN ? FASTDINH : RWHI;
+
+ if(WE[0] && ASEL == 4) SP <= FDRW;
+ else if(INCSP) SP <= ADDR16;
+
+ if(WE[0] && ASEL == 5) BP <= FDRW;
+ if(WE[0] && ASEL == 6) SI <= FDRW;
+ if(WE[0] && ASEL == 7) DI <= FDRW;
+
+ if(WE[2])
+ case(RASEL[1:0])
+ 0: SREG[0] <= FDRW;
+ 1: SREG[1] <= FDRW;
+ 2: SREG[2] <= FDRW;
+ 3: SREG[3] <= FDRW;
+ endcase
+
+ if(WE[3]) TMP16 <= |WE[1:0] ? (&DISEL[1:0] ? DIN : ADDR16) : FDRW; // TMP16
+ else TMP16 <= RA; // XCHG, MUL
+
+ if(WE[4]) FLG <= {FIN[11:6], FIN[4], FIN[2], FIN[0]}; // FLAGS
+
+ if(IFETCH) IP <= IPIN; // IP
+ end
+
+endmodule
Index: Next186_ALU.v
===================================================================
--- Next186_ALU.v (nonexistent)
+++ Next186_ALU.v (revision 2)
@@ -0,0 +1,338 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// This file is part of the Next186 project
+// http://opencores.org/project,next186
+//
+// Filename: Next186_ALU.v
+// Description: Part of the Next186 CPU project, arithmetic-logic unit and effective address unit implementation
+// Version 1.0
+// Creation date: 11Apr2011 - 07Jun2011
+//
+// Author: Nicolae Dumitrache
+// e-mail: ndumitrache@opencores.org
+//
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011 Nicolae Dumitrache
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, download it
+// from http://www.opencores.org/lgpl.shtml
+//
+///////////////////////////////////////////////////////////////////////////////////
+// Additional Comments:
+//
+// ADD 00_000
+// OR 00_001
+// ADC 00_010
+// SBB 00_011
+// AND 00_100
+// SUB 00_101
+// XOR 00_110
+// CMP 00_111
+//
+// INC 01_000
+// DEC 01_001
+// NOT 01_010
+// NEG 01_011
+// DAA 01_100 // +0066h
+// DAS 01_101 // -0066h
+// AAA 01_110 // +0106h
+// AAS 01_111 // -0106h
+//
+// MUL 10_000
+// IMUL 10_001
+//
+// FLAGOP 11_001
+// CBW 11_010
+// CWD 11_011
+// SHF/ROT 1 11_100
+// SHF/ROT n 11_101
+// PASS FLAGS 11_110 // ALUOP <- FLAGS, clear TF, IF
+// PASS RB 11_111 // ALUOP <- RB, FLAGS <- RA
+//
+//
+// FLAGS: X X X X OF DF IF TF | SF ZF X AF X PF X CF
+//
+//////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module Next186_ALU(
+ input [15:0] RA,
+ input [15:0] RB,
+ input [15:0] TMP16,
+ input [15:0] FETCH23,
+ input [15:0]FIN,
+ input [4:0]ALUOP,
+ input [2:0]EXOP,
+ input [3:0]FLAGOP,
+ input WORD,
+ input INC2,
+ output reg [15:0]FOUT,
+ output reg [15:0]ALUOUT,
+ output reg ALUCONT,
+ output NULLSHIFT,
+ output COUT,
+ output SOUT,
+ input [2:0]STAGE,
+ input CLK
+ );
+
+ reg CPLOP2;
+ wire [15:0]SUMOP1 = ALUOP[3:1] == 3'b101 ? 16'h0000 : RA; // NEG, NOT
+ reg [15:0]SUMOP21;
+ wire [15:0]SUMOP2 = CPLOP2 ? ~SUMOP21 : SUMOP21;
+ wire SCIN1 = ALUOP[3:1] == 3'b001 ? FIN[0] : ALUOP[3:0] == 4'b1010 ? 1'b1 : 1'b0; //ADD/ADC, NOT
+ wire SCIN = CPLOP2 ? ~SCIN1 : SCIN1; // carry in
+ wire SC16OUT;
+ wire SC8OUT;
+ wire AF;
+ wire [15:0]SUMOUT;
+ wire parity = ~^ALUOUT[7:0];
+ wire zero8 = ~|ALUOUT[7:0];
+ wire zero = ~|ALUOUT[15:0];
+ wire overflow8 = (SUMOP1[7] & SUMOP2[7] & !SUMOUT[7]) | (!SUMOP1[7] & !SUMOP2[7] & SUMOUT[7]);
+ wire overflow = (SUMOP1[15] & SUMOP2[15] & !SUMOUT[15]) | (!SUMOP1[15] & !SUMOP2[15] & SUMOUT[15]);
+ wire LO9 = RA[3:0] > 9;
+ wire LONIBBLE = LO9 | FIN[4];
+ wire HINIBBLE = (RA[7:4] > 8 && LO9) | FIN[0];
+
+// ADDER
+ assign {AF, SUMOUT[3:0]} = SUMOP1[3:0] + SUMOP2[3:0] + SCIN;
+ assign {SC8OUT, SUMOUT[7:4]} = SUMOP1[7:4] + SUMOP2[7:4] + AF;
+ assign {SC16OUT, SUMOUT[15:8]} = SUMOP1[15:8] + SUMOP2[15:8] + SC8OUT;
+ assign COUT = (WORD ? SC16OUT : SC8OUT) ^ CPLOP2;
+ assign SOUT = WORD ? SUMOUT[15] : SUMOUT[7];
+
+// SHIFTER
+ reg [4:0]SHNOPT; // optimized shift
+ wire [4:0]SHN = {STAGE[2:1] ^ SHNOPT[4:3], SHNOPT[2:0]};
+ assign NULLSHIFT = ~|SHNOPT;
+ wire [2:0]COUNT = |SHN[4:3] ? 0 : SHN[2:0];
+ wire [2:0]SCOUNT = (EXOP[0] ? COUNT[2:0] : 3'b000) - (EXOP[0] ? 3'b001 : COUNT[2:0]);
+ reg [7:0]SHEX;
+ wire [17:0]SHBAR = (EXOP[0] ? {1'bx, SHEX, WORD ? RA[15:8]: SHEX, RA[7:0]} : {RA, SHEX, 1'bx}) >> SCOUNT;
+
+// MULTIPLIER
+ wire signed [16:0]MULOP1 = WORD ? {ALUOP[0] & TMP16[15], TMP16} : {ALUOP[0] ? {9{TMP16[7]}} : 9'b000000000, TMP16[7:0]};
+ wire signed [16:0]MULOP2 = WORD ? {ALUOP[0] & FETCH23[15], FETCH23} : {ALUOP[0] ? {9{FETCH23[7]}} : 9'b000000000, FETCH23[7:0]};
+ wire signed [31:0]MUL = MULOP1 * MULOP2;
+
+ always @* begin
+ FOUT[15:8] = {4'bxxxx, WORD ? overflow : overflow8, FIN[10:8]};
+ FOUT[7] = WORD ? ALUOUT[15] : ALUOUT[7];
+ FOUT[6] = WORD ? zero : zero8;
+ FOUT[5] = 1'bx;
+ FOUT[4] = AF ^ CPLOP2;
+ FOUT[3] = 1'bx;
+ FOUT[2] = parity;
+ FOUT[1] = 1'bx;
+ FOUT[0] = COUT;
+ ALUOUT = 16'hxxxx;
+ ALUCONT = 1'bx;
+
+ case(ALUOP[3:0]) // complement second operand
+ 4'b0000, 4'b0010, 4'b1000, 4'b1100, 4'b1110: CPLOP2 = 1'b0; // ADD, ADC, INC, DEC, DAA, AAA
+ default: CPLOP2 = 1'b1;
+ endcase
+
+ case(ALUOP[3:0])
+ 4'b1000, 4'b1001: SUMOP21 = INC2 && WORD ? 2 : 1; // INC/DEC
+ 4'b1100, 4'b1101: SUMOP21 = {9'b000000000, HINIBBLE, HINIBBLE, 2'b00, LONIBBLE, LONIBBLE, 1'b0};
+ 4'b1110, 4'b1111: SUMOP21 = {7'b0000000, LONIBBLE, 5'b00000, LONIBBLE, LONIBBLE, 1'b0};
+ default: SUMOP21 = RB;
+ endcase
+
+ if(ALUOP[0])
+ case({WORD, EXOP[2:1]})
+ 3'b000: SHNOPT = {2'b00, RB[2:0]};
+ 3'b001, 3'b101: SHNOPT = RB[4:0];
+ 3'b010, 3'b011: SHNOPT = |RB[4:3] ? 5'b01000 : RB[4:0];
+ 3'b100: SHNOPT = {1'b0, RB[3:0]};
+ 3'b110, 3'b111: SHNOPT = RB[4] ? 5'b10000 : RB[4:0];
+ endcase
+ else SHNOPT = 5'b00001;
+
+ case({WORD, EXOP})
+ 4'b1000: SHEX = RA[15:8]; // ROL16
+ 4'b0010: SHEX = {FIN[0], RA[7:1]}; // RCL8
+ 4'b0011, 4'b1011: SHEX = {RA[6:0], FIN[0]}; // RCR8, RCR16
+ 4'b0111: SHEX = {8{RA[7]}}; // SAR8
+ 4'b0000, 4'b0001, 4'b1001: SHEX = RA[7:0]; // ROL8, ROR8, ROR16
+ 4'b1010: SHEX = {FIN[0], RA[15:9]}; // RCL16
+ 4'b1111: SHEX = {8{RA[15]}}; // SAR16
+ default: SHEX = 8'h00; // SHL16, SHR16, SHL8, SHR8
+ endcase
+
+ case(ALUOP)
+ 5'b00000, 5'b00010, 5'b00011, 5'b00101, 5'b00111, 5'b01010, 5'b01011: ALUOUT = SUMOUT; // ADD, ADC, SBB, SUB, CMP, NOT, NEG
+ 5'b00001: begin // OR
+ ALUOUT = RA | RB;
+ FOUT[0] = 1'b0;
+ FOUT[11] = 1'b0;
+ FOUT[4] = FIN[4];
+ end
+ 5'b00100: begin // AND
+ ALUOUT = RA & RB;
+ FOUT[0] = 1'b0;
+ FOUT[11] = 1'b0;
+ FOUT[4] = FIN[4];
+ end
+ 5'b00110: begin // XOR
+ ALUOUT = RA ^ RB;
+ FOUT[0] = 1'b0;
+ FOUT[11] = 1'b0;
+ FOUT[4] = FIN[4];
+ end
+ 5'b01000, 5'b01001: begin // INC, DEC
+ ALUOUT = SUMOUT;
+ FOUT[0] = FIN[0];
+ end
+ 5'b01100, 5'b01101: begin // DAA, DAS
+ ALUOUT = SUMOUT;
+ FOUT[0] = HINIBBLE ? 1'b1 : FIN[0];
+ FOUT[4] = LONIBBLE ? 1'b1 : FIN[4];
+ end
+ 5'b01110, 5'b01111: begin // AAA, AAS
+ ALUOUT = {SUMOUT[15:8], 4'b0000, SUMOUT[3:0]};
+ FOUT[0] = LONIBBLE;
+ FOUT[4] = LONIBBLE;
+ end
+ 5'b10000, 5'b10001 : begin // MUL, IMUL
+ ALUOUT = STAGE[1] ? MUL[31:16] : MUL[15:0];
+ FOUT[0] = WORD ? !zero : |MUL[15:8];
+ FOUT[11] = FOUT[0];
+ end
+ 5'b11001: begin // flag op
+ FOUT[11:8] = FIN[11:8];
+ FOUT[7] = FIN[7];
+ FOUT[6] = FIN[6];
+ FOUT[4] = FIN[4];
+ FOUT[2] = FIN[2];
+ FOUT[0] = FIN[0];
+ case(FLAGOP)
+ 4'b1000: FOUT[0] = 1'b0; // CLC
+ 4'b0101: FOUT[0] = !FIN[0]; // CMC
+ 4'b1001: FOUT[0] = 1'b1; // STC
+ 4'b1100: FOUT[10] = 1'b0; // CLD
+ 4'b1101: FOUT[10] = 1'b1; // STD
+ 4'b1010: FOUT[9] = 1'b0; // CLI
+ default: FOUT[9] = 1'b1; // STI
+ endcase
+ end
+ 5'b11010: ALUOUT[7:0] = {8{RB[7]}};
+ 5'b11011: ALUOUT[15:0] = {16{RB[15]}};
+ 5'b11100, 5'b11101: begin // ROT/SHF
+ ALUOUT = SHBAR[16:1];
+ FOUT[0] = EXOP[0] ? SHBAR[0] : WORD ? SHBAR[17] : SHBAR[9];
+ FOUT[11] = WORD ? RA[15] ^ ALUOUT[15] : RA[7] ^ ALUOUT[7]; // OF is defined only for 1bit rotate/shift
+ if(!EXOP[2]) begin // ROT
+ FOUT[7] = FIN[7];
+ FOUT[6] = FIN[6];
+ FOUT[4] = FIN[4];
+ FOUT[2] = FIN[2];
+ end
+ case({SHN[4:3], STAGE[2:1]})
+ 4'b0100, 4'b1101, 4'b0110: ALUCONT = |SHN[2:0];
+ 4'b1000, 4'b1100, 4'b1001: ALUCONT = 1'b1;
+ default: ALUCONT = 1'b0;
+ endcase
+ end
+
+ 5'b11110: begin
+ ALUOUT = FIN;
+ FOUT[11] = FIN[11];
+ FOUT[9] = 1'b0; // IF
+ FOUT[8] = 1'b0; // TF
+ FOUT[7] = FIN[7];
+ FOUT[6] = FIN[6];
+ FOUT[4] = FIN[4];
+ FOUT[2] = FIN[2];
+ FOUT[0] = FIN[0];
+ end
+ 5'b11111: begin
+ ALUOUT = RB;
+ FOUT = {WORD ? RA[15:8] : FIN[15:8], RA[7:0]};
+ end
+ endcase
+ end
+
+endmodule
+
+// 0000 - BX+SI+DISP
+// 0001 - BX+DI+DISP
+// 0010 - BP+SI+DISP
+// 0011 - BP+DI+DISP
+// 0100 - SI+DISP
+// 0101 - DI+DISP
+// 0110 - BP+DISP
+// 0111 - BX+DISP
+// 1000 - SP-2
+// 1001 - SP+2
+// 1010 - BX+AL
+// 1011 - TMP16+2
+// 1100 -
+// 1101 - SP+2+DISP
+// 1110 - DISP[7:0]<<2
+// 1111 - PIO
+module Next186_EA(
+ input [15:0] SP,
+ input [15:0] BX,
+ input [15:0] BP,
+ input [15:0] SI,
+ input [15:0] DI,
+ input [15:0] PIO,
+ input [15:0] TMP16,
+ input [7:0] AL,
+ input [15:0] AIMM,
+ input [3:0]EAC,
+ output [15:0] ADDR16
+ );
+
+ reg [15:0]OP1;
+ reg [15:0]OP2;
+ reg [15:0]OP3;
+
+ always @* begin
+ case(EAC)
+ 4'b0000, 4'b0001, 4'b0111, 4'b1010: OP1 = BX;
+ 4'b0010, 4'b0011, 4'b0110: OP1 = BP;
+ 4'b1000, 4'b1001, 4'b1101: OP1 = SP;
+ 4'b1011: OP1 = TMP16;
+ default: OP1 = 16'h0000;
+ endcase
+ case(EAC)
+ 4'b0000, 4'b0010, 4'b0100: OP2 = SI;
+ 4'b0001, 4'b0011, 4'b0101: OP2 = DI;
+ 4'b1001, 4'b1011, 4'b1101: OP2 = 16'h0002; // SP/TMP16 + 2
+ default: OP2 = 16'h0000;
+ endcase
+ case(EAC)
+ 4'b1000: OP3 = 16'hfffe; // SP - 2
+ 4'b1010: OP3 = {8'b00000000, AL}; // XLAT
+ 4'b1001, 4'b1011: OP3 = 16'h0000; // SP/TMP16 + 2
+ 4'b1110: OP3 = {6'b000000, AIMM[7:0], 2'b00}; // int
+ 4'b1111: OP3 = PIO; // in,out
+ default: OP3 = AIMM;
+ endcase
+ end
+
+ assign ADDR16 = OP1 + OP2 + OP3;
+endmodule
Index: Next186_CPU.v
===================================================================
--- Next186_CPU.v (nonexistent)
+++ Next186_CPU.v (revision 2)
@@ -0,0 +1,1786 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// This file is part of the Next186 project
+// http://opencores.org/project,next186
+//
+// Filename: Next186_CPU.v
+// Description: Implementation of 80186 instruction compatible CPU
+// Version 1.0
+// Creation date: 24Mar2011 - 07Jun2011
+//
+// Author: Nicolae Dumitrache
+// e-mail: ndumitrache@opencores.org
+//
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011 Nicolae Dumitrache
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, download it
+// from http://www.opencores.org/lgpl.shtml
+//
+///////////////////////////////////////////////////////////////////////////////////
+//
+// Comments:
+// This project was developed and tested on a XILINX Spartan3AN board.
+//
+// Next186 processor features:
+// All 80186 intstructions are implemented according with the 80186 specifications
+// Designed with 2 buses: 16bit/20bit data/data_address and 48bit/20bit instruction/instruction_address.
+// This allows most instructions to be executed in one clock cycle.
+// In order to couple the CPU unit with a single bus, these sepparate data/instruction buses must be multiplexed by
+// a dedicated bus interface unit (BIU).
+// It is able to execute up to 40Mips on Spartan XC3S700AN speed grade -4, performances comparable with a 486 CPU.
+// Small size, the CPU + BIU requires ~25% or 1500 slices - on Spartan XC3S700AN
+//
+///////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module Next186_CPU(
+ output [19:0] ADDR,
+ input [15:0] DIN,
+ output [15:0] DOUT,
+ input CLK,
+ input CE,
+ input INTR,
+ input NMI,
+ input RST,
+ output reg MREQ,
+ output wire IORQ,
+ output reg INTA,
+ output reg WR,
+ output reg WORD,
+ output LOCK,
+ output [19:0]IADDR,
+ input [47:0]INSTR,
+ output reg IFETCH,
+ output FLUSH,
+ output reg [2:0]ISIZE,
+ output reg HALT
+ );
+
+// connections
+ wire [15:0]RA;
+ wire [15:0]RB;
+ wire [15:0]TMP16;
+ wire [15:0]SP;
+ wire [15:0]IP;
+ wire [15:0]AX;
+ wire [15:0]BX;
+ wire [15:0]BP;
+ wire [15:0]SI;
+ wire [15:0]DI;
+ wire [15:0]DX;
+ wire [15:0]FLAGS;
+ wire [15:0]FIN;
+ wire [15:0]ALUOUT;
+ wire [15:0]AIMM1;
+ reg [15:0]DIMM1;
+ wire [15:0]RS;
+ wire [15:0]ADDR16;
+ wire [15:0]CS;
+ wire ALUCONT;
+ wire NULLSHIFT;
+ wire [1:0]CXZ;
+ wire COUT; // adder carry out
+ wire DIVEXC; // exit carry for unsigned DIV
+ wire SOUT; // adder sign out
+
+// Registers
+ reg [7:0]FETCH[5:0];
+ reg [6:0]STAGE = 0;
+ reg [5:0]CPUStatus = 0; //1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=LOCK
+ reg TZF = 0, TLF = 0;
+ reg SRST = 0;
+ reg SNMI = 0, FNMI = 0;
+ reg SINTR = 0;
+ reg [15:0]CRTIP; // current instruction ptr (used by interrupts)
+ reg DIVQSGN;
+ reg RDIVEXC;
+
+// control
+ reg [2:0]RASEL;
+ reg [2:0]RBSEL;
+ reg BASEL;
+ reg [1:0]BBSEL;
+ reg [1:0]RSSEL;
+ reg [4:0]WE; // 4=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
+ reg [4:0]ALUOP;
+ reg [3:0]EAC;
+ reg [1:0]DISEL;
+ reg [1:0]ISEL;
+ reg ASEL;
+ reg AEXT;
+ reg DEXT;
+ reg [1:0]DOSEL;
+ reg IPWSEL;
+ reg [5:0]status; //1:0=SR override, 2=override ON/OFF, 3=Z(REP), 4=REP ON/OFF, 5=lock
+ reg NOBP;
+ reg ALUSTAGE; // inc STAGE with 2
+ reg DIVSTAGE; // inc STAGE with 4
+ reg DISP16;
+ reg DECCX;
+ reg IRQ;
+ reg [2:0]IRQL;
+ reg REPINT;
+ reg [5:0]ICODE1 = 23;
+ reg NULLSEG;
+ reg DIVOP;
+
+// signals
+ assign IORQ = &EAC;
+ assign LOCK = CPUStatus[5];
+ assign FLUSH = ~IPWSEL || (ISIZE == 3'b000);
+ wire [15:0]IPADD = ISIZE == 3'b000 ? CRTIP : IP + ISIZE;
+ wire [15:0]IPIN = IPWSEL ? IPADD : ALUOUT;
+ wire [1:0]MOD = FETCH[1][7:6];
+ wire [2:0]REG = FETCH[1][5:3];
+ wire [2:0]RM = FETCH[1][2:0];
+ wire USEBP = RM[1] && ~&RM;
+ wire POP = {EAC[3], EAC[1:0]} == 3'b101;
+ wire [15:0]ADDR16_SP = POP ? SP : ADDR16;
+ wire [1:0]WBIT = {WORD | RASEL[2], WORD | !RASEL[2]};
+ wire [1:0]ISELS = {DISP16 | AEXT, DISP16 | ~AEXT};
+ wire [2:0]ISIZES = DISP16 ? 4 : AEXT ? 3 : 2;
+ reg [2:0]ISIZEW;
+ reg [2:0]ISIZEI; // ise imm
+ wire [1:0]WRBIT = WR ? 2'b00 : WBIT;
+ wire RCXZ = CPUStatus[4] && ~|CXZ;
+ wire NRORCXLE1 = ~CPUStatus[4] || ~CXZ[1];
+ 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]};
+ wire [3:0]LOOPC = {CXZ != 2'b00, CXZ == 2'b01, CXZ == 2'b01 || !FLAGS[6], CXZ == 2'b01 || FLAGS[6]};
+ wire IDIV = FETCH[0][1] & FETCH[1][3];
+ wire DIVRSGN = (WORD ? FETCH[3][7] : FETCH[2][7]) & IDIV;
+ wire DIVSGN = DIVQSGN ^ DIVRSGN;
+ wire DIVEND = FETCH[0][0] ? STAGE[6] : STAGE[5];
+ wire DIVC = ((COUT & ~RDIVEXC) ^ ~DIVRSGN);
+ wire QSGN = (WORD ? DX[15] : AX[15]) & IDIV;
+// interrupts
+ wire SAMPLEINT = ~(WE[2] & RASEL[1:0] == 2'b10) & ~status[2] & ~status[4] & ~status[5]; // not load SS, no prefix
+ wire NMIACK = SNMI & ~FNMI; // NMI acknowledged
+ wire INTRACK = FLAGS[9] & (~WE[4] | FIN[9]) & SINTR; // INTR acknowledged (IF and not CLI in progress)
+ wire IACK = IRQ | (SAMPLEINT & (NMIACK | INTRACK)) | (~WE[2] & ~HALT & FLAGS[8]); // interrupt acknowledged
+
+ Next186_Regs REGS (
+ .RASEL(RASEL),
+ .RBSEL(RBSEL),
+ .BASEL(BASEL),
+ .BBSEL(BBSEL),
+ .RSSEL(RSSEL),
+ .DIN(DIN),
+ .ALUOUT(ALUOUT),
+ .ADDR16(ADDR16),
+ .DIMM(DEXT ? {{8{DIMM1[7]}}, DIMM1[7:0]} : DIMM1),
+ .WE(WE),
+ .IFETCH(IFETCH),
+ .RA(RA),
+ .RB(RB),
+ .TMP16(TMP16),
+ .SP(SP),
+ .IP(IP),
+ .AX(AX),
+ .BX(BX),
+ .BP(BP),
+ .SI(SI),
+ .DI(DI),
+ .DX(DX),
+ .RS(RS),
+ .FIN(FIN),
+ .FOUT(FLAGS),
+ .DISEL(DISEL),
+ .WORD(WORD | &DISEL),
+ .IPIN(IPIN),
+ .CLK(CLK),
+ .CLKEN(CE),
+ .CS(CS),
+ .INCSP(POP),
+ .CXZ(CXZ),
+ .DECCX(DECCX),
+ .DIVOP(DIVOP),
+ .DIVEND(DIVEND),
+ .DIVSGN(DIVSGN),
+ .DIVC(DIVC),
+ .DIVEXC(DIVEXC)
+ );
+
+ Next186_ALU ALU16 (
+ .RA(DOSEL == 2'b01 ? IPADD : RA),
+ .RB(RB),
+ .TMP16(TMP16),
+ .FETCH23({FETCH[3], FETCH[2]}),
+ .FIN(FLAGS),
+ .FOUT(FIN),
+ .ALUOP(ALUOP),
+ .EXOP(FETCH[1][5:3]),
+ .FLAGOP(FETCH[0][3:0]),
+ .ALUOUT(ALUOUT),
+ .WORD(WORD),
+ .ALUCONT(ALUCONT),
+ .NULLSHIFT(NULLSHIFT),
+ .STAGE(STAGE[2:0]),
+ .INC2(&DISEL), // when DISEL == 2'b11, inc/dec value is 2 if WORD and 1 if ~WORD
+ .COUT(COUT),
+ .SOUT(SOUT),
+ .CLK(CLK)
+ );
+
+ Next186_EA EA (
+ .SP(SP),
+ .BX(BX),
+ .BP(NOBP ? 16'h0000 : BP),
+ .SI(SI),
+ .DI(DI),
+ .PIO(FETCH[0][3] ? DX : {8'h00, FETCH[1]}),
+ .TMP16(TMP16),
+ .AL(AX[7:0]),
+ .AIMM(AEXT ? {{8{AIMM1[7]}}, AIMM1[7:0]} : (DISP16 ? AIMM1 : 16'h0000)),
+ .ADDR16(ADDR16),
+ .EAC(EAC)
+ );
+
+ assign DOUT = DOSEL[1] ? DOSEL[0] ? AX : TMP16 : DOSEL[0] ? IPADD : ALUOUT;
+ assign ADDR = {{NULLSEG ? 16'h0000 : RS} + {4'b0000, ADDR16_SP[15:4]}, ADDR16_SP[3:0]};
+ assign IADDR = {CS + {4'b0000, IPIN[15:4]}, IPIN[3:0]};
+ assign AIMM1 = ASEL ? {FETCH[3], FETCH[2]} : {FETCH[2], FETCH[1]};
+
+ always @(posedge CLK)
+ if(CE) begin
+ if(SRST) begin // reset
+// FETCH[0] <= 8'h0f;
+ FETCH[0][0] <= 1'b1; // for word=1
+ ICODE1 <= 54;
+ FETCH[5][1:0] <= 2'b01; // RESET
+ STAGE <= 4'b1000;
+ end else begin
+ if(IACK & (IFETCH | HALT | REPINT)) begin // interrupt sampled and acknowledged
+ FETCH[0][1:0] <= 2'b11;
+ ICODE1 <= 54;
+ STAGE <= 4'b1000;
+ FETCH[5][2:0] <= {HALT, 2'b00};
+ if(IRQ) FETCH[2] <= IRQL != 3'b010 ? {5'b00000, IRQL} : FETCH[1];
+ else if(NMIACK) begin
+ FETCH[2] <= 8'h02;
+ FNMI <= 1'b1;
+ end else if(INTRACK) FETCH[5][1:0] <= 2'b10;
+ else FETCH[2] <= 8'h01; // trap
+ end else if(IFETCH) begin // no interrupt, fetch
+ FETCH[5] <= INSTR[47:40];
+ FETCH[4] <= INSTR[39:32];
+ FETCH[3] <= INSTR[31:24];
+ FETCH[2] <= INSTR[23:16];
+ FETCH[1] <= INSTR[15:8];
+ FETCH[0] <= INSTR[7:0];
+ STAGE <= 0;
+ CPUStatus[5:0] <= status[5:0];
+ TZF <= status[3];
+ ICODE1 <= ICODE(INSTR[7:0]);
+ end else begin // no interrupt, no fetch
+ STAGE <= STAGE + {DIVSTAGE, ALUSTAGE} + 1;
+ if(&DOSEL) {FETCH[3], FETCH[2]} <= |DISEL ? DIN : RB;
+ TZF <= FIN[6]; // zero flag for REP
+ TLF <= FIN[7] != FIN[11]; // less flag for BOUND
+ end
+ end
+ if(IFETCH & ~status[2] & ~status[4] & ~status[5]) CRTIP <= IPIN; // no prefix
+ SRST <= RST; // level detection RST
+ SINTR <= INTR; // level detection INTR
+ if(NMI) SNMI <= 1'b1; // edge detection NMI
+ else if(FNMI) begin
+ SNMI <= 1'b0;
+ FNMI <= 1'b0;
+ end
+ if(~|STAGE[1:0]) DIVQSGN <= QSGN;
+ RDIVEXC <= DIVOP & DIVEXC & ~IDIV; // bit 8/16 for unsigned DIV
+ end
+
+ always @(ISEL, FETCH[0], FETCH[1], FETCH[2], FETCH[3], FETCH[4], FETCH[5])
+ case(ISEL)
+ 2'b00: DIMM1 = {FETCH[2], FETCH[1]};
+ 2'b01: DIMM1 = {FETCH[3], FETCH[2]};
+ 2'b10: DIMM1 = {FETCH[4], FETCH[3]};
+ 2'b11: DIMM1 = {FETCH[5], FETCH[4]};
+ endcase
+
+ always @(FETCH[0], WORD, DISP16, AEXT) begin
+ case({WORD, DISP16, AEXT})
+ 3'b000: ISIZEW = 3;
+ 3'b001, 3'b100: ISIZEW = 4;
+ 3'b010, 3'b101: ISIZEW = 5;
+ default: ISIZEW = 6;
+ endcase
+ case({FETCH[0][1:0] == 2'b01, DISP16, AEXT})
+ 3'b000: ISIZEI = 3;
+ 3'b001, 3'b100: ISIZEI = 4;
+ 3'b110: ISIZEI = 6;
+ default: ISIZEI = 5;
+ endcase
+ end
+
+ 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,
+ WBIT, ISIZES, ISELS, WRBIT, ISIZEW, STAGE, NULLSHIFT, ALUCONT, FLAGS, CXZ, RCXZ, NRORCXLE1, TZF, JMPC, LOOPC, ICODE1, DIVQSGN, DIVSGN, DIVRSGN, SOUT) begin
+ WORD = FETCH[0][0];
+ BASEL = FETCH[0][1] | &MOD;
+ RASEL = FETCH[0][1] ? REG : RM; // destination
+ BBSEL = {1'b0, !FETCH[0][1] | &MOD};
+ RBSEL = FETCH[0][1] ? RM : REG; // source
+ RSSEL = CPUStatus[2] ? CPUStatus[1:0] : (USEBP && !NOBP ? 2'b10 : 2'b11);
+ WE = 5'b00000; // 5=flags, 3=TMP16, 2=RSSEL, 1=RASEL_HI, 0=RASEL_LO
+ ALUOP = 5'bxxxxx;
+ EAC = {1'b0, RM};
+ DISEL = 2'b01; // ALU
+ ISEL = 2'bxx;
+ ASEL = 1'bx;
+ AEXT = MOD == 2'b01;
+ DEXT = 1'b0;
+ DOSEL = 2'b00; // ALU
+ MREQ = 1'b1;
+ WR = 1'b0;
+ ISIZE = 3'bxxx;
+ IPWSEL = 1'b1; // IP + ISIZE
+ IFETCH = 1'b1;
+ status = 6'b00x0xx;
+
+ DISP16 = MOD == 2'b10 || NOBP;
+ NOBP = {MOD, RM} == 5'b00110;
+ HALT = 1'b0;
+ INTA = 1'b0;
+ ALUSTAGE = 1'b0;
+ DIVSTAGE = 1'b0;
+ DECCX = 1'b0;
+ IRQ = 1'b0;
+ IRQL = 3'b110; // unused opcode
+ REPINT = 1'b0;
+ NULLSEG = 1'b0;
+ DIVOP = 1'b0;
+
+ case(ICODE1) // one hot synthesis
+// -------------------------------- mov R/M to/from R/SR --------------------------------
+ 0: begin
+ if(FETCH[0][2]) WORD = 1'b1;
+ if(FETCH[0][2:1] == 2'b10) BBSEL = 2'b11; // RB = SR
+ ALUOP = 31; // PASS B
+ DISEL = {1'b0, &MOD};
+ ASEL = 1'b1;
+ MREQ = ~&MOD;
+ WR = MREQ & !FETCH[0][1];
+ 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
+ ISIZE = ISIZES;
+ end
+// -------------------------------- mov IMM to R/M --------------------------------
+ 1: begin
+ RASEL = RM; // destination
+ BBSEL = 2'b10;
+ ALUOP = 31; // PASS B
+ ISEL = ISELS;
+ ASEL = 1'b1;
+ MREQ = ~&MOD;
+ WR = MREQ;
+ WE[1:0] = WRBIT; // RASEL_HI/RASEL_LO
+ ISIZE = ISIZEW;
+ end
+// -------------------------------- mov IMM to R --------------------------------
+ 2: begin
+ WORD = FETCH[0][3];
+ RASEL = FETCH[0][2:0]; // destination
+ BBSEL = 2'b10; // imm
+ WE[1:0] = WBIT; // RASEL_HI/RASEL_LO
+ ALUOP = 31; // PASS B
+ ISEL = 2'b00;
+ MREQ = 1'b0;
+ ISIZE = WORD ? 3 : 2;
+ end
+// -------------------------------- mov mem to/from ACC --------------------------------
+ 3: begin
+ RASEL = 0; // ACC
+ BBSEL = 2'b01; // reg
+ RBSEL = 0; // ACC
+ ALUOP = 31; // PASS B
+ EAC = 4'b0110;
+ DISEL = 2'b00;
+ ASEL = 1'b0;
+ AEXT = 1'b0;
+ MREQ = 1'b1;
+ WR = FETCH[0][1];
+ WE[1:0] = WRBIT; // IP, RASEL_HI/RASEL_LO
+ ISIZE = 3;
+ NOBP = 1'b1;
+ end
+// -------------------------------- segment override prefix --------------------------------
+ 4: begin
+ status = {CPUStatus[5:3], 1'b1, FETCH[0][4:3]};
+ MREQ = 1'b0;
+ ISIZE = 1;
+ end
+// -------------------------------- rep prefix --------------------------------
+ 5: begin
+ status = {CPUStatus[5], 1'b1, FETCH[0][0], CPUStatus[2:0]};
+ MREQ = 1'b0;
+ ISIZE = 1;
+ end
+// -------------------------------- lock prefix --------------------------------
+ 6: begin
+ status = {1'b1, CPUStatus[4:0]};
+ MREQ = 1'b0;
+ ISIZE = 1;
+ end
+// -------------------------------- FF block --------------------------------
+ 7: begin
+ ISIZE = ISIZES;
+ case({FETCH[0][0], REG})
+ // -------------------------------- push R/M --------------------------------
+ 4'b1110:
+ if(!(&MOD || STAGE[0])) begin // stage1, read data in TMP16
+ WE[3] = 1'b1; // TMP16
+ DISEL = 2'b00;
+ ASEL = 1'b1;
+ IFETCH = 1'b0;
+ end else begin // stage2, push R/TMP16
+ RASEL = 3'b100; // write SP
+ RSSEL = 2'b10; // SS
+ ALUOP = 31; // PASS B
+ WE[1:0] = 2'b11; // RASEL_HI/RASEL_LO
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ WR = 1'b1;
+ end
+ // -------------------------------- inc/dec R/M --------------------------------
+ 4'b0000, 4'b1000, 4'b0001, 4'b1001: begin
+ ASEL = 1'b1;
+ if(!(&MOD || STAGE[0])) begin // stage1, load op from memory in TMP16
+ WE[3] = 1'b1; // TMP16
+ DISEL = 2'b00; // DIN
+ IFETCH = 1'b0;
+ end else begin // stage2, execute and write
+ BASEL = &MOD;
+ RASEL = RM; // destination
+ ALUOP = {2'b01, FETCH[1][5:3]};
+ MREQ = ~BASEL;
+ WR = MREQ;
+ WE = {3'b100, WRBIT}; // flags, IP, RASEL_HI, RASEL_LO
+ end
+ end
+ // -------------------------------- call/jmp near R/M --------------------------------
+ 4'b1010, 4'b1100: begin
+ if(!STAGE[0] && ~&MOD) begin // stage1, load op in TMP16
+ ASEL = 1'b1;
+ WE[3] = 1'b1; // TMP16
+ DISEL = 2'b00; // DIN
+ IFETCH = 1'b0;
+ end else begin // stage2, push IP, jump
+ RASEL = 3'b100; // write SP
+ RSSEL = 2'b10; // SS
+ ALUOP = 31; // PASS B
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ DOSEL = 2'b01; // IP
+ MREQ = REG[1];
+ WR = MREQ;
+ WE[1:0] = {WR, WR};
+ IPWSEL = 1'b0; // ALU
+ end
+ end
+ // -------------------------------- call/jmp far R/M --------------------------------
+ 4'b1011, 4'b1101: begin
+ ALUOP = 31; // PASS B
+ IRQ = &MOD;
+ case({STAGE[1:0], REG[1]})
+ 3'b001: begin // stage1, push CS
+ RASEL = 3'b100; // write SP
+ BBSEL = 2'b11;
+ RBSEL = 3'b001; // CS
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ MREQ = ~IRQ;
+ WR = MREQ;
+ IFETCH = IRQ;
+ WE[1:0] = IRQ ? 2'b00 : 2'b11; // RASEL_HI/RASEL_LO
+ ISIZE = 0;
+ end
+ 3'b011, 3'b000: begin // stage2, read offset in FETCH, ADDR16 in TMP16
+ RASEL = 3'b100; // SP - write SP to SP for getting ADDR16 to TMP16
+ BBSEL = 2'b01;
+ RBSEL = 3'b100; // SP
+ WE[3:0] = IRQ ? 4'b0000 : 4'b1011; // TMP16, RASEL_HI, RASEL_LO
+ ASEL = 1'b1;
+ DOSEL = 2'b11; // load FETCH with DIN
+ IFETCH = IRQ;
+ MREQ = ~IRQ;
+ ISIZE = 0;
+ end
+ 3'b101, 3'b010: begin // stage3, read CS
+ RASEL = 3'b001; // CS
+ WE[2] = 1'b1; // RSSEL
+ EAC = 4'b1011; // TMP16 + 2
+ DISEL = 2'b00; // DIN
+ IFETCH = 1'b0;
+ end
+ 3'b111, 3'b100: begin // stage4, push IP, jump
+ RASEL = 3'b100; // write SP
+ BBSEL = 2'b10; // imm
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ DOSEL = 2'b01; // IP
+ ISEL = 2'b01;
+ MREQ = REG[1];
+ WR = MREQ;
+ WE[1:0] = {WR, WR};
+ IPWSEL = 1'b0; // ALU
+ end
+ endcase
+ end
+ // -------------------------------- bad opcode --------------------------------
+ default: begin
+ MREQ = 1'b0;
+ IRQ = 1'b1;
+ ISIZE = 0;
+ end
+ endcase
+ end
+// -------------------------------- push R/SR --------------------------------
+ 8: begin
+ WORD = 1'b1;
+ RASEL = 3'b100; // write SP
+ BBSEL = {~FETCH[0][6], 1'b1};
+ RBSEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // source
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ WE[1:0] = 2'b11; // RASEL_HI/RASEL_LO
+ ALUOP = 31; // PASS B
+ WR = 1'b1;
+ ISIZE = 1;
+ end
+// -------------------------------- push Imm --------------------------------
+ 9: begin
+ WORD = 1'b1;
+ RASEL = 3'b100; // write SP
+ BBSEL = 2'b10; // imm
+ RSSEL = 2'b10; // SS
+ WE[1:0] = 2'b11; // RASEL_HI/RASEL_LO
+ ALUOP = 31; // PASS B
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ ISEL = 2'b00;
+ DEXT = FETCH[0][1];
+ WR = 1'b1;
+ ISIZE = FETCH[0][1] ? 2 : 3;
+ end
+// -------------------------------- pusha --------------------------------
+ 10: begin
+ WORD = 1'b1;
+ RASEL = 3'b100; // write SP
+ RBSEL = STAGE[2:0]; // source
+ RSSEL = 2'b10; // SS
+ ALUOP = 31; // PASS B
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ WR = 1'b1;
+ ISIZE = 1;
+ IFETCH = &STAGE[2:0];
+ WE[1:0] = 2'b11; // RASEL_HI, RASEL_LO
+ end
+// -------------------------------- pop R/M --------------------------------
+ 11:
+ case(REG)
+ 3'b000: begin
+ ISIZE = ISIZES;
+ if(!STAGE[0]) begin // pop TMP16/REG
+ RASEL = RM; // destination
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1001; // SP
+ DISEL = 2'b00; // DIN
+ IFETCH = &MOD;
+ WE[3:0] = IFETCH ? 4'b0011 : 4'b1000; // TMP16, RASEL_HI, RASEL_LO
+ end else begin // R/M <- TMP16
+ RASEL = RM; // destination
+ BBSEL = 2'b00; // TMP
+ ALUOP = 31; // PASS B
+ ASEL = 1'b1;
+ MREQ = ~&MOD;
+ WR = MREQ;
+ WE[1:0] = WR ? 2'b00 : 2'b11; // RASEL_HI, RASEL_LO
+ end
+ end
+ default: begin // bad opcode
+ MREQ = 1'b0;
+ ISIZE = 0;
+ IRQ = 1'b1;
+ end
+ endcase
+// -------------------------------- pop R / SR --------------------------------
+ 12: begin
+ WORD = 1'b1;
+ RASEL = FETCH[0][6] ? FETCH[0][2:0] : {1'b0, FETCH[0][4:3]}; // destination
+ RSSEL = 2'b10; // SS
+ WE[2:0] = FETCH[0][6] ? 3'b011 : 3'b100; // RSSEL, RASEL_HI, RASEL_LO
+ EAC = 4'b1001; // SP
+ DISEL = 2'b00; // DIN
+ ISIZE = 1;
+ end
+// -------------------------------- popa --------------------------------
+ 13: begin
+ RASEL = ~STAGE[2:0]; // destination
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1001; // SP
+ DISEL = 2'b00; // DIN
+ ISIZE = 1;
+ IFETCH = &STAGE[2:0];
+ WE[1:0] = {STAGE[2:0] == 3'b011 ? 2'b00 : 2'b11}; // IP, RASEL_HI, RASEL_LO (skip SP)
+ end
+// -------------------------------- xchg R with R/M/Acc --------------------------------
+ 14: begin
+ WORD = FETCH[0][0] | FETCH[0][4];
+ ASEL = 1'b1;
+ MREQ = ~&MOD && !FETCH[0][4];
+ ALUOP = 31; // PASS B
+ ISIZE = FETCH[0][4] ? 1 : ISIZES;
+ if(!STAGE[0]) begin // stage1, R/M/Acc -> REG -> TMP16
+ BASEL = 1'b1;
+ RASEL = FETCH[0][4] ? FETCH[0][2:0] : REG; // destination
+ BBSEL = 2'b01; // reg
+ RBSEL = FETCH[0][4] ? 3'b000 : RM; // source
+ DISEL = {1'b0, !MREQ};
+ WE[1:0] = WBIT; // RASEL_HI, RASEL_LO
+ IFETCH = ~|FETCH[0][2:0]; // nop
+ end else begin // stage2, TMP16 -> R/M/Acc
+ RASEL = FETCH[0][4] ? 3'b000 : RM; // destination
+ BBSEL = 2'b00; // TMP16
+ WR = MREQ;
+ WE[1:0] = WRBIT; // RASEL_HI, RASEL_LO
+ end
+ end
+// -------------------------------- in --------------------------------
+ 15: begin
+ RASEL = 3'b000; // AX/AL
+ WE[1:0] = {WORD, 1'b1}; // RASEL_HI, RASEL_LO
+ DISEL = 2'b00; //DIN
+ MREQ = 1'b0;
+ ISIZE = FETCH[0][3] ? 1 : 2;
+ EAC = 4'b1111;
+ NULLSEG = 1'b1;
+ end
+// -------------------------------- out --------------------------------
+ 16: begin
+ DOSEL = 2'b11; // AX
+ MREQ = 1'b0;
+ WR = 1'b1;
+ ISIZE = FETCH[0][3] ? 1 : 2;
+ EAC = 4'b1111;
+ NULLSEG = 1'b1;
+ end
+// -------------------------------- xlat --------------------------------
+ 17: begin
+ WORD = 1'b0;
+ RASEL = 3'b000; // AL
+ WE[0] = 1'b1; // RASEL_LO
+ EAC = 4'b1010; // XLAT
+ DISEL = 2'b00; // DIN
+ ISIZE = 1;
+ NOBP = 1'b1; // for RSSEL
+ end
+// -------------------------------- lea --------------------------------
+ 18: begin
+ RASEL = REG; // destination
+ WE[1:0] = {&MOD ? 2'b00 : 2'b11}; // RASEL_HI, RASEL_LO
+ DISEL = 2'b10; // EA
+ ASEL = 1'b1;
+ MREQ = 1'b0;
+ ISIZE = ISIZES;
+ end
+// -------------------------------- lds, les --------------------------------
+ 19: begin
+ WORD = 1'b1;
+ DISEL = 2'b00; // DIN
+ ASEL = 1'b1;
+ if(!STAGE[0]) begin // stage1, load offset
+ RASEL = REG; // destination
+ IFETCH = &MOD; // bad opcode
+ IRQ = IFETCH;
+ ISIZE = 0;
+ WE[3:0] = {2'b10, IFETCH ? 2'b00 : 2'b11}; // TMP16, RASEL_HI, RASEL_LO
+ end else begin // stage2, load segment
+ RASEL = FETCH[0][0] ? 3'b011 : 3'b000; // ds/es
+ WE[2] = 1'b1; // RSSEL
+ EAC = 4'b1011; // TMP16 + 2
+ ISIZE = ISIZES;
+ end
+ end
+// -------------------------------- lahf, sahf --------------------------------
+ 20: begin
+ WORD = 1'b0;
+ RASEL = 3'b100; // AH
+ WE = {!FETCH[0][0], 2'b00, FETCH[0][0], 1'b0}; // FLAGS, IP, RASEL_HI
+ ALUOP = FETCH[0][0] ? 30 : 31; // PASS/STORE FLAGS
+ MREQ = 1'b0;
+ ISIZE = 1;
+ end
+// -------------------------------- pushf --------------------------------
+ 21: begin
+ WORD = 1'b1;
+ RASEL = 3'b100; // write SP
+ RSSEL = 2'b10; // SS
+ WE[1:0] = 2'b11;
+ ALUOP = 30; // pass flags
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ WR = 1'b1;
+ ISIZE = 1;
+ end
+// -------------------------------- popf --------------------------------
+ 22: begin
+ ISIZE = 1;
+ IFETCH = STAGE[0];
+ if(!STAGE[0]) begin // stage1, pop TMP16
+ RSSEL = 2'b10; // SS
+ WE[3] = 1'b1; // TMP16
+ EAC = 4'b1001; // SP
+ DISEL = 2'b00;
+ end else begin // stage2, TMP16 to FLAGS
+ BASEL = 1'b0;
+ WE[4] = 1'b1; // flags
+ ALUOP = 31; // store flags
+ MREQ = 1'b0;
+ end
+ end
+// -------------------------------- add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
+ 23: begin
+ ASEL = 1'b1;
+ if(!(&MOD || STAGE[0])) begin // stage1, load op from memory in TMP16
+ WE[3] = 1'b1; // TMP16
+ DISEL = 2'b00; // DIN
+ IFETCH = 1'b0;
+ end else begin // stage2, execute and write
+ ALUOP = {2'b00, FETCH[0][2] ? 3'b100 : FETCH[0][5:3]}; // test = and
+ MREQ = ~&MOD & ~|FETCH[0][2:1] & ~&FETCH[0][5:3]; // no cmp or test
+ WR = MREQ;
+ WE = {3'b100, WR | &FETCH[0][5:3] | FETCH[0][2] ? 2'b00 : WBIT}; // flags, RASEL_HI, RASEL_LO
+ ISIZE = ISIZES;
+ end
+ end
+// -------------------------------- add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
+ 24: begin
+ ASEL = 1'b1;
+ if(!(&MOD || STAGE[0])) begin // stage1, load op from memory in TMP16
+ WE[3] = 1'b1; // TMP16
+ DISEL = 2'b00; // DIN
+ IFETCH = 1'b0;
+ end else begin // stage2, execute and write
+ BASEL = &MOD;
+ RASEL = RM;
+ BBSEL = 2'b10; // imm
+ ALUOP = {2'b00, FETCH[1][5:3]};
+ ISEL = ISELS;
+ DEXT = FETCH[0][1];
+ MREQ = ~BASEL & ~&FETCH[1][5:3];
+ WR = MREQ;
+ WE = {3'b100, WR | &FETCH[1][5:3]? 2'b00 : WBIT}; // flags, RASEL_HI, RASEL_LO
+ ISIZE = ISIZEI;
+ end
+ end
+// -------------------------------- add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
+ 25: begin // test
+ BASEL = 1'b1;
+ RASEL = 3'b000; // acc
+ BBSEL = 2'b10; // imm
+ WE = {3'b100, &FETCH[0][5:3] | FETCH[0][7] ? 2'b00 : WBIT}; // flags, RASEL_HI, RASEL_LO
+ ALUOP = {2'b00, FETCH[0][7] ? 3'b100 : FETCH[0][5:3]};
+ ISEL = 2'b00;
+ MREQ = 1'b0;
+ ISIZE = WORD ? 3 : 2;
+ end
+// -------------------------------- inc/dec R16 --------------------------------
+ 26: begin
+ WORD = 1'b1;
+ BASEL = 1'b1;
+ RASEL = FETCH[0][2:0]; // destination
+ WE = 5'b10011; // flags, RASEL_HI, RASEL_LO
+ ALUOP = {2'b01, FETCH[0][5:3]};
+ MREQ = 1'b0;
+ ISIZE = 1;
+ end
+// -------------------------------- test/???/not/neg/mul/imul/div/idiv --------------------------------
+ 27: begin
+ ASEL = 1'b1;
+ case(REG)
+ 3'b000: begin // TEST R/M with Imm
+ if(!(&MOD || |STAGE[1:0])) begin // stage1, load op from memory in TMP16
+ DISEL = 2'b00;
+ WE[3] = 1'b1; // mem in TMP16
+ IFETCH = 1'b0;
+ end else begin
+ BASEL = &MOD;
+ RASEL = RM; // destination
+ BBSEL = 2'b10; // imm
+ ALUOP = 5'b00100; // AND
+ ISEL = ISELS;
+ MREQ = 1'b0;
+ WE[4] = 1'b1; // flags
+ ISIZE = ISIZEW;
+ end
+ end
+ 3'b010, 3'b011: begin // NOT/NEG R/M
+ if(!(&MOD || |STAGE[1:0])) begin // stage1, load op from memory in TMP16
+ DISEL = 2'b00;
+ WE[3] = 1'b1; // mem in TMP16
+ IFETCH = 1'b0;
+ end else begin
+ BASEL = &MOD;
+ RASEL = RM; // destination
+ ALUOP = {2'b01, REG};
+ MREQ = ~&MOD;
+ WR = MREQ;
+ WE = {REG[0], 2'b00, WRBIT}; // flags, RASEL_HI, RASEL_LO
+ ISIZE = ISIZES;
+ end
+ end
+ 3'b100, 3'b101: begin // MUL, IMUL
+ ISIZE = ISIZES;
+ ALUOP = {4'b1000, REG[0]}; // BASEL = FETCH[0][1] = 1
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, RA -> TMP16, RB (mem) -> FETCH
+ MREQ = ~&MOD;
+ DISEL = {1'b0, MREQ};
+ RASEL = 3'b000; // AX
+ DOSEL = 2'b11;
+ IFETCH = 1'b0;
+ end
+ 2'b01: begin // stage2, write AX
+ WE[1:0] = 2'b11;
+ RASEL = 3'b000; // AX
+ MREQ = 1'b0;
+ IFETCH = ~FETCH[0][0];
+ end
+ 2'b10: begin // stage 2, write DX
+ WE = 5'b10011;
+ RASEL = 3'b010; // DX
+ MREQ = 1'b0;
+ end
+ endcase
+ end
+ 3'b110, 3'b111: begin // div, idiv
+ ISIZE = ISIZES;
+ IRQL = 3'b000; // divide overflow
+ MREQ = 1'b0;
+ case({DIVEND, STAGE[1:0]})
+ 3'b000: begin // stage1, RB (mem) -> FETCH
+ MREQ = ~&MOD;
+ DISEL = {1'b0, MREQ};
+ DOSEL = 2'b11;
+ IFETCH = 1'b0;
+ DIVSTAGE = ~QSGN;
+ end
+ 3'b001: begin // stage2, pre dec AX
+// WORD = 1'b1;
+ RASEL = 3'b000; // AX
+ WE[1:0] = 2'b11; // RASEL_HI, RASEL_LO
+ ALUOP = 5'b01001; // DEC
+ IFETCH = 1'b0;
+ ALUSTAGE = ~(DIVQSGN && FETCH[0][0] && COUT);
+ end
+ 3'b010: begin // stage3, pre dec DX
+ RASEL = 3'b010; // DX
+ WE[1:0] = 2'b11; // RASEL_HI, RASEL_LO
+ ALUOP = 5'b01001; // DEC
+ IFETCH = 1'b0;
+ end
+ 3'b011, 3'b111: begin // stage4, div loop
+ RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
+ BBSEL = 2'b10; // imm
+ WE[1:0] = {1'b1, WORD}; // RASEL_HI, RASEL_LO
+ ALUOP = {2'b00, DIVSGN ? 3'b000 : 3'b101}; // add/sub
+ ISEL = 2'b01;
+ DIVSTAGE = ~DIVEND;
+ ALUSTAGE = ~DIVEND | ~DIVQSGN;
+ DIVOP = 1'b1;
+ IRQ = ~|STAGE[6:3] & DIVC & ~(STAGE[2] & DIVSGN); // early overflow for positive quotient
+ IFETCH = (DIVEND && ~DIVQSGN && ~DIVRSGN) || IRQ;
+ end
+ 3'b100: begin // stage5, post inc R
+ RASEL = WORD ? 3'b010 : 3'b100; // DX/AH
+ WE[1:0] = {1'b1, WORD}; // RASEL_HI, RASEL_LO
+ ALUOP = 5'b01000; // inc
+ IFETCH = ~DIVSGN;
+ end
+ default: begin // stage6, post inc Q
+ RASEL = 3'b000; // AX/AL
+ WE[1:0] = {WORD, 1'b1}; // RASEL_HI, RASEL_LO
+ ALUOP = 5'b01000; // inc
+ IRQ = SOUT ^ DIVSGN; // overflow for negative quotient
+ end
+ endcase
+ end
+ default: begin // bad opcode
+ MREQ = 1'b0;
+ ISIZE = 0;
+ IRQ = 1'b1;
+ end
+ endcase
+ end
+// -------------------------------- imul imm --------------------------------
+ 28: begin
+ ASEL = 1'b1;
+ if(!STAGE[0]) begin // stage1, load op from memory (or RA) in TMP16
+ RASEL = RM;
+ DISEL = 2'b00; // DIN
+ DOSEL = 2'b11;
+ ISEL = ISELS;
+ DEXT = FETCH[0][1];
+ BBSEL = 2'b10; // imm
+ MREQ = ~&MOD;
+ WE[3] = MREQ; // TMP16
+ IFETCH = 1'b0;
+ end else begin // stage2, execute and write
+ RASEL = REG;
+ ALUOP = 5'b10001; // imul
+ MREQ = 1'b0;
+ WE = 5'b10011; // flags, RASEL_HI, RASEL_LO
+ ISIZE = ISIZEI;
+ end
+ end
+// -------------------------------- aad --------------------------------
+ 29: begin
+ MREQ = 1'b0;
+ WORD = 1'b0;
+ BASEL = 1'b1;
+ IFETCH = &STAGE[1:0];
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, load AH in TMP16, move imm in FETCH
+ RASEL = 3'b100; // AH
+ DISEL = 2'b00; // DIN
+ DOSEL = 2'b11; // write FETCH
+ ISEL = 2'b00; // RB -> FETCH
+ BBSEL = 2'b10; // imm
+ end
+ 2'b01: begin // stage2, TMP16 <- TMP16 * 10
+ ALUOP = 5'b10000; // mul
+ WE[3] = 1'b1; // TMP16
+ end
+ 2'b10: begin // stage3, AL <- TMP16 + AL
+ RASEL = 3'b000; // AL
+ BBSEL = 2'b00; // TMP16
+ WE = 5'b10001; // flags, RASEL_LO
+ ALUOP = 5'b00000; // ADD
+ end
+ 2'b11: begin // stage4, AH <- 0
+ RASEL = 3'b100; // AH
+ RBSEL = 3'b100; // AH
+ WE[1] = 1'b1; // RASEL_HI
+ ALUOP = 5'b00101; // SUB
+ ISIZE = 2;
+ end
+ endcase
+ end
+// -------------------------------- daa, das, aaa, aas --------------------------------
+ 30: begin
+ WORD = FETCH[0][4];
+ RASEL = 3'b000; // AX,AL
+ WE = {3'b100, FETCH[0][4], 1'b1}; // flags, RASEL_HI, RASEL_LO
+ ALUOP = {2'b01, FETCH[0][5:3]};
+ MREQ = 1'b0;
+ ISIZE = 1;
+ end
+// -------------------------------- shift/rot --------------------------------
+ 31: begin // imm
+ ALUOP = {4'b1110, FETCH[0][4:1] != 4'b1000};
+ ASEL = 1'b1;
+ if(!(&MOD || STAGE[0])) begin // stage1, load op from memory in TMP16
+ WE[3] = 1'b1; // TMP16
+ DISEL = 2'b00; // DIN
+ IFETCH = 1'b0;
+ end else begin // stage2, execute and write
+ BASEL = &MOD && ~|STAGE[2:1];
+ RASEL = RM;
+ BBSEL = FETCH[0][1] ? 2'b01 : 2'b10; // imm/reg
+ RBSEL = 3'b001; // CL
+ ISEL = ISELS;
+ IRQ = REG == 3'b110;
+ MREQ = ~&MOD && ~NULLSHIFT && ~ALUCONT && ~IRQ;
+ WR = MREQ;
+ WE = NULLSHIFT || IRQ ? 5'b00000 : ALUCONT ? 5'b11000 : {3'b100, WRBIT}; // flags, TMP16, RASEL_HI, RASEL_LO
+ IFETCH = ~ALUCONT || IRQ;
+ ALUSTAGE = 1'b1;
+ if(IRQ) ISIZE = 0;
+ else case({|FETCH[0][4:1], DISP16, AEXT})
+ 3'b100: ISIZE = 2;
+ 3'b000, 3'b101: ISIZE = 3;
+ 3'b001, 3'b110: ISIZE = 4;
+ default: ISIZE = 5;
+ endcase
+ end
+ end
+// -------------------------------- (rep)movs --------------------------------
+ 32: begin
+ BASEL = 1'b1;
+ AEXT = 1'b0;
+ DISP16 = 1'b0;
+ NOBP = 1'b1; // for RSSEL
+ if(!STAGE[0]) begin // stage1, read DS:[SI] in TMP16, inc/dec SI
+ RASEL = 3'b110; // SI
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0100; // SI+DISP
+ DISEL = 2'b11; // ALU 16bit
+ IFETCH = RCXZ; // REP & CX==0
+ MREQ = ~RCXZ;
+ WE = IFETCH ? 5'b00000 : 5'b01011; // TMP16, RASEL_HI, RASEL_LO
+ end else begin // stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
+ RASEL = 3'b111; // DI
+ RSSEL = 2'b00; // ES
+ WE[1:0] = 2'b11; // RASEL_HI, RASEL_LO
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0101; // DI + DISP
+ DISEL = 2'b11; // ALU 16bit
+ DOSEL = 2'b10; // TMP16
+ WR = 1'b1;
+ IFETCH = NRORCXLE1; // not REP or CX<=1
+ DECCX = CPUStatus[4];
+ REPINT = 1'b1;
+ end
+ ISIZE = IFETCH ? 1 : 0;
+ end
+// -------------------------------- (rep)cmps --------------------------------
+ 33: begin
+ DISP16 = 1'b0;
+ AEXT = 1'b0;
+ NOBP = 1'b1; // for RSSEL
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, read ES:[DI] in FETCH[2:1], inc/dec DI
+ RASEL = 3'b111; // SI
+ RSSEL = 2'b00; // ES
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0101; // DI+DISP
+ DISEL = 2'b11; // ALU 16bit
+ DOSEL = 2'b11; // read data to FETCH
+ IFETCH = CPUStatus[4] && (~|CXZ || (CPUStatus[3] ^ TZF)); // REP & CX==0
+ MREQ = ~IFETCH;
+ WE[1:0] = IFETCH ? 2'b00 : 2'b11; // RASEL_HI, RASEL_LO
+ end
+ 2'b01: begin // stage2, read DS:[SI] in TMP16, inc/dec SI
+ RASEL = 3'b110; // DI
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0100; // SI+DISP
+ DISEL = 2'b11; // ALU 16bit
+ IFETCH = 1'b0;
+ WE[3:0] = 4'b1011; // RASEL_HI, RASEL_LO
+ end
+ 2'b10: begin // stage3, compare TMP16 wit imm, set flags, dec CX
+ BASEL = 1'b0; // TMP16
+ BBSEL = 2'b10; // imm
+ ISEL = 2'b01;
+ WE[4] = 1'b1; // flags
+ ALUOP = 5'b00111; // cmp
+ MREQ = 1'b0;
+ IFETCH = ~CPUStatus[4];
+ DECCX = CPUStatus[4];
+ ALUSTAGE = 1'b1;
+ REPINT = 1'b1;
+ end
+ endcase
+ ISIZE = IFETCH ? 1 : 0;
+ end
+// -------------------------------- (rep)scas --------------------------------
+ 34: begin
+ DISP16 = 1'b0;
+ AEXT = 1'b0;
+ NOBP = 1'b1; // for RSSEL (not really necesary, but with it the synthesis generates better speed)
+ if(!STAGE[0]) begin // stage1, read ES:[DI] in TMP16, inc/dec DI
+ RASEL = 3'b111; // DI
+ RSSEL = 2'b00; // ES
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0101; // DI+DISP
+ DISEL = 2'b11; // ALU 16bit
+ IFETCH = CPUStatus[4] && (~|CXZ || (CPUStatus[3] ^ TZF)); // REP & CX==0
+ MREQ = ~IFETCH;
+ WE[3:0] = IFETCH ? 4'b0000 : 4'b1011; // TMP16, RASEL_HI, RASEL_LO
+ end else begin //stage2, compare AL/AX with TMP16, set flags, dec CX
+ RASEL = 3'b000; // AL/AX
+ BBSEL = 2'b00; // TMP16
+ WE[4] = 1'b1; // flags
+ ALUOP = 5'b00111; // cmp
+ MREQ = 1'b0;
+ IFETCH = ~CPUStatus[4];
+ DECCX = CPUStatus[4];
+ REPINT = 1'b1;
+ end
+ ISIZE = IFETCH ? 1 : 0;
+ end
+// -------------------------------- (rep)lods --------------------------------
+ 35: begin
+ BASEL = 1'b1;
+ DISP16 = 1'b0;
+ AEXT = 1'b0;
+ NOBP = 1'b1; // for RSSEL
+ if(!STAGE[0]) begin // stage1, read DS:[SI] in AL/AX
+ RASEL = 3'b000; // AX
+ EAC = 4'b0100; // SI+DISP
+ DISEL = 2'b00; // DIN
+ IFETCH = RCXZ; // REP & CX==0
+ MREQ = ~RCXZ;
+ WE[1:0] = IFETCH ? 2'b00 : {WORD, 1'b1}; // RASEL_HI, RASEL_LO
+ end else begin // stage2, inc/dec SI, dec CX
+ RASEL = 3'b110; // SI
+ ALUOP = {4'b0100, FLAGS[10]};
+ DISEL = 2'b11; // ALU 16bit
+ IFETCH = NRORCXLE1; // nor REP or CX<=1
+ MREQ = 1'b0;
+ WE[1:0] = 2'b11; // RASEL_HI, RASEL_LO
+ DECCX = CPUStatus[4];
+ REPINT = 1'b1;
+ end
+ ISIZE = IFETCH ? 1 : 0;
+ end
+// -------------------------------- (rep)stos --------------------------------
+ 36: begin // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
+ BASEL = 1'b1;
+ DISP16 = 1'b0;
+ AEXT = 1'b0;
+ RASEL = 3'b111; // DI
+ RSSEL = 2'b00; // ES
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0101; // DI + DISP
+ DISEL = 2'b11; // ALU 16bit
+ DOSEL = 2'b11; // AX
+ IFETCH = NRORCXLE1; // not REP or CX<=1
+ MREQ = ~RCXZ;
+ WR = ~RCXZ;
+ WE[1:0] = {MREQ, MREQ}; // RASEL_HI, RASEL_LO
+ DECCX = CPUStatus[4] && |CXZ;
+ REPINT = 1'b1;
+ ISIZE = IFETCH ? 1 : 0;
+ end
+// -------------------------------- (rep)ins --------------------------------
+ 37: begin
+ BASEL = 1'b1;
+ DISP16 = 1'b0;
+ AEXT = 1'b0;
+ if(!STAGE[0]) begin // stage1, input in TMP16
+ WE[3] = 1'b1; // TMP16
+ DISEL = 2'b00; //DIN
+ IFETCH = RCXZ; // REP & CX==0
+ MREQ = 1'b0;
+ EAC = {~RCXZ, 3'b111};
+ NULLSEG = 1'b1;
+ end else begin // stage2, write TMP16 in ES:[DI], inc/dec DI, dec CX
+ RASEL = 3'b111; // DI
+ RSSEL = 2'b00; // ES
+ WE[1:0] = 2'b11; // RASEL_HI, RASEL_LO
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0101; // DI + DISP
+ DISEL = 2'b11; // ALU 16bit
+ DOSEL = 2'b10; // TMP16
+ WR = 1'b1;
+ IFETCH = NRORCXLE1; // not REP or CX<=1
+ DECCX = CPUStatus[4];
+ REPINT = 1'b1;
+ end
+ ISIZE = IFETCH ? 1 : 0;
+ end
+// -------------------------------- (rep)outs --------------------------------
+ 38: begin
+ BASEL = 1'b1;
+ DISP16 = 1'b0;
+ NOBP = 1'b1; // for RSSEL
+ if(!STAGE[0]) begin // stage1, read DS:[SI] in TMP16, inc/dec SI
+ AEXT = 1'b0; // tweak for speed (can be moved outside )
+ RASEL = 3'b110; // SI
+ ALUOP = {4'b0100, FLAGS[10]};
+ EAC = 4'b0100; // SI+DISP
+ DISEL = 2'b11; // ALU 16bit
+ IFETCH = RCXZ; // REP & CX==0
+ MREQ = ~RCXZ;
+ WE[3:0] = IFETCH ? 4'b0000 : 4'b1011; // TMP16, RASEL_HI, RASEL_LO
+ end else begin // stage2, out TMP16 at port DX, dec CX
+ DOSEL = 2'b10; // TMP16
+ MREQ = 1'b0;
+ EAC = 4'b1111;
+ WR = 1'b1;
+ IFETCH = NRORCXLE1; // not REP or CX<=1
+ DECCX = CPUStatus[4];
+ REPINT = 1'b1;
+ NULLSEG = 1'b1;
+ end
+ ISIZE = IFETCH ? 1 : 0;
+ end
+// -------------------------------- call/jmp direct near --------------------------------
+ 39: begin // jump long
+ WORD = 1'b1;
+ ALUOP = 0; // ADD
+ DISEL = 2'b10; // ADDR
+ ISIZE = FETCH[0][1] ? 2 : 3;
+ RASEL = 3'b100; // write SP
+ RSSEL = 2'b10; // SS
+ DOSEL = 2'b01; // IP
+ EAC = 4'b1000; // SP - 2
+ BBSEL = 2'b10; // imm
+ ISEL = 2'b00;
+ DEXT = FETCH[0][1];
+ MREQ = !FETCH[0][0];
+ WR = MREQ;
+ WE[1:0] = FETCH[0][0] ? 2'b00 : 2'b11; // RASEL_HI/RASEL_LO
+ IPWSEL = 1'b0; // ALU
+ end
+// -------------------------------- call/jmp far imm --------------------------------
+ 40: begin
+ WORD = 1'b1;
+ ALUOP = 31; // PASS B
+ case({STAGE[1:0], FETCH[0][6]})
+ 3'b000: begin // stage1, push CS
+ RASEL = 3'b100; // write SP
+ BBSEL = 2'b11;
+ RBSEL = 3'b001; // CS
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ WR = 1'b1;
+ IFETCH = 1'b0;
+ WE[1:0] = 2'b11; // RASEL_HI/RASEL_LO
+ end
+ 3'b010, 3'b001: begin // stage2, load CS
+ RASEL = 3'b001; // CS
+ BBSEL = 2'b10; // imm
+ WE[2] = 1'b1; // RSSEL
+ ISEL = 2'b10;
+ MREQ = 1'b0;
+ IFETCH = 1'b0;
+ end
+ 3'b100, 3'b011: begin // stage3, push IP, load IP
+ RASEL = 3'b100; // write SP
+ BBSEL = 2'b10; // imm
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ DOSEL = 2'b01; // IP
+ ISEL = 2'b00;
+ MREQ = FETCH[0][4];
+ WR = MREQ;
+ WE[1:0] = {WR, WR};
+ IPWSEL = 1'b0; // ALU
+ ISIZE = 5;
+ end
+ endcase
+ end
+// -------------------------------- ret near --------------------------------
+ 41: begin
+ ISIZE = FETCH[0][0] ? 1 : 3;
+ IFETCH = STAGE[0];
+ ALUOP = 31; // PASS B
+ if(!STAGE[0]) begin // stage1, pop TMP16
+ RSSEL = 2'b10; // SS
+ WE[3] = 1'b1; // TMP16
+ ASEL = 1'b0;
+ AEXT = 1'b0;
+ DISP16 = 1'b1;
+ EAC = {1'b1, !FETCH[0][0], 2'b01}; // SP + 2 (+ imm)
+ DISEL = 2'b00;
+ end else begin // stage2, TMP16 to IP
+ BBSEL = 2'b00; // TMP16
+ IPWSEL = 1'b0; // ALU
+ MREQ = 1'b0;
+ end
+ end
+// -------------------------------- ret far --------------------------------
+ 42: begin
+ ALUOP = 31; // PASS B
+ RSSEL = 2'b10; // SS
+ IFETCH = STAGE[1];
+ DISEL = 2'b00; // DIN
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, pop IP in TMP16
+ WE[3] = 1'b1; // TMP16
+ EAC = 4'b1001; // SP + 2
+ end
+ 2'b01: begin // stage2, pop CS, TMP16 <- RA
+ RASEL = 3'b001; // CS
+ WE[2] = 1'b1;
+ EAC = {1'b1, !FETCH[0][0], 2'b01};
+ ASEL = 1'b0;
+ AEXT = 1'b0;
+ DISP16 = 1'b1;
+ BASEL = 1'b0; // RA <- TMP16
+ end
+ 2'b10: begin // stage3, IP <- TMP16
+ BBSEL = 2'b00; // TMP16
+ IPWSEL = 1'b0; // ALU
+ MREQ = 1'b0;
+ ISIZE = FETCH[0][0] ? 1 : 3;
+ end
+ endcase
+ end
+// -------------------------------- iret --------------------------------
+ 43: begin
+ ALUOP = 31; // PASS B
+ RSSEL = 2'b10; // SS
+ ISIZE = 1;
+ IFETCH = &STAGE[1:0];
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, pop IP in FETCH
+ EAC = 4'b1001; // SP + 2
+ DOSEL = 2'b11; // write FETCH
+ end
+ 2'b01: begin // stage2, pop CS
+ RASEL = 3'b001; // CS
+ WE[2] = 1'b1;
+ EAC = {1'b1, !FETCH[0][0], 2'b01};
+ DISEL = 2'b00;
+ ASEL = 1'b0;
+ AEXT = 1'b0;
+ DISP16 = 1'b1;
+ end
+ 2'b10: begin // stage3, pop flags in TMP16
+ WE[3] = 1'b1; // TMP16
+ EAC = 4'b1001; // SP
+ DISEL = 2'b00;
+ end
+ 2'b11: begin // stage4, IP <- FETCH, FLAGS <- TM
+ BASEL = 1'b0;
+ BBSEL = 2'b10; // imm
+ WE[4] = 1'b1; // flags
+ ISEL = 2'b01;
+ DEXT = 1'b0;
+ IPWSEL = 1'b0; // ALU
+ MREQ = 1'b0;
+ end
+ endcase
+ end
+// -------------------------------- cbw/cwd --------------------------------
+ 44: begin
+ RASEL = FETCH[0][0] ? 3'b010 : 3'b100; // AH/DX
+ RBSEL = 3'b000; // AX
+ WE[1:0] = {1'b1, FETCH[0][0]}; // RASEL_HI, RASEL_LO
+ ALUOP = {4'b1101, FETCH[0][0]}; // cbw/cwd
+ MREQ = 1'b0;
+ ISIZE = 1;
+ end
+// -------------------------------- JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
+ 45: begin // loop/loopz/loopnz/jcxz
+ ALUOP = 0; // add
+ ISIZE = 2;
+ DOSEL = 2'b01; // IP
+ BBSEL = 2'b10; // imm
+ ISEL = 2'b00;
+ DEXT = 1'b1;
+ MREQ = 1'b0;
+ IPWSEL = FETCH[0][7] ? LOOPC[FETCH[0][1:0]] : (JMPC[FETCH[0][3:1]] ~^ FETCH[0][0]);
+ DECCX = FETCH[0][7] && (FETCH[0][1:0] != 2'b11);
+ end
+// -------------------------------- CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
+ 46: begin
+ WE[4] = 1'b1; // flags
+ ALUOP = 5'b11001; // flag op
+ ISIZE = 1;
+ MREQ = 1'b0;
+ end
+// -------------------------------- enter --------------------------------
+ 47: begin
+ WORD = 1'b1;
+ WE[1:0] = 2'b11; // RASEL_HI/RASEL_LO
+ case(STAGE[1:0])
+ 2'b00: begin // push BP
+ RASEL = 3'b100; // write SP
+ RBSEL = 3'b101; // BP
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ ALUOP = 31; // PASS B
+ WR = 1'b1;
+ IFETCH = 1'b0;
+ end
+ 2'b01: begin // mov BP, SP
+ RASEL = 3'b101; // BP
+ RBSEL = 3'b100; // SP
+ ALUOP = 31; // PASS B
+ MREQ = 1'b0;
+ IFETCH = 1'b0;
+ end
+ 2'b10: begin // sub SP, imm
+ BASEL = 1'b1;
+ RASEL = 3'b100; // SP
+ BBSEL = 2'b10;
+ ALUOP = 5'b00101; // sub
+ ISEL = 2'b00;
+ MREQ = 1'b0;
+ ISIZE = 4;
+ end
+ endcase
+ end
+// -------------------------------- leave --------------------------------
+ 48: begin
+ WE[1:0] = 2'b11; // RASEL_HI/RASEL_LO
+ if(!STAGE[0]) begin // stage1, mov sp, bp
+ RASEL = 3'b100; // BP
+ RBSEL = 3'b101; // SP
+ ALUOP = 31; // PASS B
+ MREQ = 1'b0;
+ IFETCH = 1'b0;
+ end else begin // stage2, pop bp
+ RASEL = 3'b101; // BP
+ RSSEL = 2'b10; // SS
+ EAC = 4'b1001; // SP
+ DISEL = 2'b00; // DIN
+ ISIZE = 1;
+ end
+ end
+// -------------------------------- int, int 3, into --------------------------------
+ 49: begin
+ MREQ = 1'b0;
+ ISIZE = FETCH[0][1:0] == 2'b01 ? 2 : 1;
+ IRQ = ~FETCH[0][1] | FLAGS[11];
+ IRQL = FETCH[0][1] ? 3'b100 : {1'b0, ~FETCH[0][1:0]}; // 4, 2, 3
+ end
+// -------------------------------- bound --------------------------------
+ 50: begin
+ WORD = 1'b1;
+ DOSEL = 2'b11; // load FETCH with DIN
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, read min in FETCH, ADDR16 in TMP16
+ RASEL = 3'b100; // SP - write SP to SP for getting ADDR16 to TMP16
+ BBSEL = 2'b01;
+ RBSEL = 3'b100; // SP
+ ALUOP = 31; // PASS B
+ WE[3:0] = 4'b1011; // TMP16, RASEL_HI, RASEL_LO
+ ASEL = 1'b1;
+ IRQ = &MOD; // illegal instruction
+ ISIZE = 0;
+ IFETCH = IRQ;
+ end
+ 2'b01, 2'b10, 2'b11: begin // stage2,3,4 load min/max in TMP16, compare reg with imm
+ BBSEL = 2'b10; // imm
+ ALUOP = 5'b00111; // cmp
+ EAC = 4'b1011; // TMP16 + 2
+ ISEL = 2'b01;
+ IRQ = STAGE[1] & (STAGE[0] ? ~TLF & ~TZF : TLF);
+ MREQ = ~&STAGE[1:0];
+ IFETCH = IRQ | ~MREQ;
+ IRQL = 3'b101;
+ ISIZE = IRQ ? 0 : ISIZES; // return address is BOUND
+ end
+ endcase
+ end
+// -------------------------------- hlt --------------------------------
+ 51: begin
+ IFETCH = 1'b0;
+ HALT = 1'b1;
+ MREQ = 1'b0;
+ end
+// -------------------------------- wait --------------------------------
+ 52: begin // do nothing
+ ISIZE = 1;
+ MREQ = 1'b0;
+ end
+// -------------------------------- aam --------------------------------
+ 53: begin
+ MREQ = 1'b0;
+ IRQL = 3'b000; // divide overflow
+ ISIZE = 2;
+ case({DIVEND, STAGE[1:0]})
+ 3'b000: begin // stage1, clear AH
+ BASEL = 1'b0; // TMP16
+ RASEL = 3'b100; // AH
+ BBSEL = 2'b00; // TMP16
+ WE[1] = 1'b1; // RASEL_HI
+ ALUOP = 5'b00101; // sub
+ IFETCH = 1'b0;
+ end
+ 3'b001, 3'b101: begin // stage2, div
+ RASEL = 3'b100; // AH
+ BASEL = 1'b1;
+ BBSEL = 2'b10; // imm
+ WE[1] = 1'b1; // RASEL_HI
+ ALUOP = 5'b00101; // sub
+ ISEL = 2'b00;
+ DIVSTAGE = ~DIVEND;
+ ALUSTAGE = ~DIVEND;
+ DIVOP = 1'b1;
+ IRQ = ~|STAGE[6:2] & DIVC;
+ IFETCH = IRQ;
+ end
+ 3'b110: begin // stage 3, AH <- AL, TMP16 <- AH
+ RASEL = 3'b100; // AH
+ BASEL = 1'b1;
+ RBSEL = 3'b000; // AL
+ WE[1] = 1'b1; // RASEL_HI
+ ALUOP = 31; // PASS B
+ IFETCH = 1'b0;
+ end
+ 3'b111: begin // stage4, AL <- TMP16 | TMP16, set flags
+ RASEL = 3'b000; // dest = AL
+ BASEL = 1'b0; // TMP16
+ BBSEL = 2'b00; // TMP16
+ WE = 5'b10001; // FLAGS, RASEL_LO
+ ALUOP = 5'b00001; // OR
+ end
+ endcase
+ end
+// -------------------------------- reset, irq, nmi, intr --------------------------------
+ 54:
+ if(STAGE[3]) begin
+ if(FETCH[5][0]) begin // reset
+ RASEL = {1'b0, STAGE[1:0]}; // ES, CS, SS, DS
+ WE = 5'b11100; // FLAGS, TMP16, RSSEL
+ BASEL = 1'b0; // TMP16
+ BBSEL = 2'b00; // TMP16
+ ALUOP = STAGE[0] ? STAGE[1] ? 31 : 5'b01001 : 5'b00101; // pass, dec, sub
+ MREQ = 1'b0;
+ IPWSEL = 1'b0; // ALU16
+ IFETCH = &STAGE[1:0];
+ end else case({FETCH[5][1], STAGE[2:0]})
+ 4'b1000: begin // stage1 intr
+ DOSEL = 2'b11; // read FETCH[2]
+ MREQ = 1'b0;
+ IFETCH = 1'b0;
+ INTA = 1'b1;
+ end
+ 4'b1001, 4'b0000: begin // stage1 irq, nmi, tf, stage2 intr - push flags, clear TF, IF
+ RASEL = 3'b100; // write SP
+ RSSEL = 2'b10; // SS
+ WE = 5'b10011; // flags, SP
+ ALUOP = 30; // pass flags
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ WR = 1'b1;
+ IFETCH = 1'b0;
+ end
+ 4'b1010, 4'b0001: begin // stage2 irq, nmi, tf, stage3 intr - push CS
+ RASEL = 3'b100; // write SP
+ BBSEL = 2'b11;
+ RBSEL = 3'b001; // CS
+ RSSEL = 2'b10; // SS
+ ALUOP = 31; // PASS B
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ WR = 1'b1;
+ IFETCH = 1'b0;
+ WE[1:0] = 2'b11; // RASEL_HI/RASEL_LO
+ end
+ 4'b1011, 4'b0010: begin // stage3 irq, nmi, tf, stage4 intr - read offset in FETCH, ADDR16 in TMP16
+ RASEL = 3'b100; // SP - write SP to SP for getting ADDR16 to TMP16
+ BBSEL = 2'b01;
+ RBSEL = 3'b100; // SP
+ ALUOP = 31; // PASS B
+ EAC = 4'b1110; // int vector
+ WE[3:0] = 4'b1011; // TMP16, RASEL_HI, RASEL_LO
+ ASEL = 1'b1;
+ DISP16 = 1'b1;
+ DOSEL = 2'b11; // load FETCH with DIN
+ IFETCH = 1'b0;
+ NULLSEG = 1'b1;
+ end
+ 4'b1100, 4'b0011: begin // stage4 irq, nmi, tf, stage5 intr - read CS
+ RASEL = 3'b001; // CS
+ WE[2] = 1'b1; // RSSEL
+ EAC = 4'b1011; // TMP16 + 2
+ DISEL = 2'b00; // DIN
+ IFETCH = 1'b0;
+ NULLSEG = 1'b1;
+ end
+ 4'b1101, 4'b0100: begin // stage5 irq, nmi, tf, stage6 intr - push IP, jump
+ RASEL = 3'b100; // write SP
+ BBSEL = 2'b10; // imm
+ RSSEL = 2'b10; // SS
+ ALUOP = 31; // PASS B
+ EAC = 4'b1000; // SP - 2
+ DISEL = 2'b10; // ADDR
+ DOSEL = 2'b01; // IP
+ ISEL = 2'b01;
+ WR = 1'b1;
+ WE[1:0] = 2'b11;
+ ISIZE = FETCH[5][2] ? 1 : 0;
+ IPWSEL = 1'b0; // ALU
+ end
+ endcase
+ end else begin
+ MREQ = 1'b0;
+ ISIZE = 0;
+ IRQ = 1'b1;
+ end
+
+// -------------------------------- bad opcode/esc --------------------------------
+ default: begin
+ MREQ = 1'b0;
+ ISIZE = 0;
+ IRQ = 1'b1;
+ if(FETCH[0][7:3] == 5'b11011) IRQL = 3'b111; // esc
+ end
+ endcase
+ end
+
+
+
+// instruction pre-decoder
+function [5:0]ICODE;
+ input [7:0]INSTR;
+ begin
+ case(INSTR[7:0])
+// -------------------------------- mov R/M to/from R/SR --------------------------------
+ 8'b10001000, 8'b10001001, 8'b10001010, 8'b10001011,
+ 8'b10001110, 8'b10001100: ICODE = 0;
+// -------------------------------- mov IMM to R/M --------------------------------
+ 8'b11000110, 8'b11000111: ICODE = 1;
+// -------------------------------- mov IMM to R --------------------------------
+ 8'b10110_000, 8'b10110_001, 8'b10110_010, 8'b10110_011, 8'b10110_100, 8'b10110_101, 8'b10110_110, 8'b10110_111,
+ 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;
+// -------------------------------- mov mem to/from ACC --------------------------------
+ 8'b10100000, 8'b10100001,
+ 8'b10100010, 8'b10100011: ICODE = 3;
+// -------------------------------- segment override prefix --------------------------------
+ 8'b001_00_110, 8'b001_01_110, 8'b001_10_110, 8'b001_11_110: ICODE = 4;
+// -------------------------------- rep prefix --------------------------------
+ 8'b11110010, 8'b11110011: ICODE = 5;
+// -------------------------------- lock prefix --------------------------------
+ 8'b11110000: ICODE = 6;
+// -------------------------------- FF block --------------------------------
+ 8'b11111111, 8'b11111110: ICODE = 7;
+// -------------------------------- push R/SR --------------------------------
+ 8'b01010_000, 8'b01010_001, 8'b01010_010, 8'b01010_011, 8'b01010_100, 8'b01010_101, 8'b01010_110, 8'b01010_111,
+ 8'b000_00_110, 8'b000_01_110, 8'b000_10_110, 8'b000_11_110: ICODE = 8;
+// -------------------------------- push Imm --------------------------------
+ 8'b01101000, 8'b01101010: ICODE = 9;
+// -------------------------------- pusha --------------------------------
+ 8'b01100000: ICODE = 10;
+// -------------------------------- pop R/M --------------------------------
+ 8'b10001111: ICODE = 11;
+// -------------------------------- pop R / SR --------------------------------
+ 8'b01011_000, 8'b01011_001, 8'b01011_010, 8'b01011_011, 8'b01011_100, 8'b01011_101, 8'b01011_110, 8'b01011_111,
+ 8'b000_00_111, 8'b000_10_111, 8'b000_11_111: ICODE = 12;
+// -------------------------------- popa --------------------------------
+ 8'b01100001: ICODE = 13;
+// -------------------------------- xchg R with R/M/Acc --------------------------------
+ 8'b10000110, 8'b10000111,
+ 8'b10010000, 8'b10010001, 8'b10010010, 8'b10010011, 8'b10010100, 8'b10010101, 8'b10010110, 8'b10010111: ICODE = 14;
+// -------------------------------- in --------------------------------
+ 8'b11100100, 8'b11100101,
+ 8'b11101100, 8'b11101101: ICODE = 15;
+// -------------------------------- out --------------------------------
+ 8'b11100110, 8'b11100111,
+ 8'b11101110, 8'b11101111: ICODE = 16;
+// -------------------------------- xlat --------------------------------
+ 8'b11010111: ICODE = 17;
+// -------------------------------- lea --------------------------------
+ 8'b10001101: ICODE = 18;
+// -------------------------------- lds, les --------------------------------
+ 8'b11000101, 8'b11000100: ICODE = 19;
+// -------------------------------- lahf, sahf --------------------------------
+ 8'b10011111, 8'b10011110: ICODE = 20;
+// -------------------------------- pushf --------------------------------
+ 8'b10011100: ICODE = 21;
+// -------------------------------- popf --------------------------------
+ 8'b10011101: ICODE = 22;
+// -------------------------------- add, or, adc, sbb, and, sub, xor, cmp, test R/M with R --------------------------------
+ 8'b00000000, 8'b00000001, 8'b00000010, 8'b00000011, // add
+ 8'b00001000, 8'b00001001, 8'b00001010, 8'b00001011, // or
+ 8'b00010000, 8'b00010001, 8'b00010010, 8'b00010011, // adc
+ 8'b00011000, 8'b00011001, 8'b00011010, 8'b00011011, // sbb
+ 8'b00100000, 8'b00100001, 8'b00100010, 8'b00100011, // and
+ 8'b00101000, 8'b00101001, 8'b00101010, 8'b00101011, // sub
+ 8'b00110000, 8'b00110001, 8'b00110010, 8'b00110011, // xor
+ 8'b00111000, 8'b00111001, 8'b00111010, 8'b00111011, // cmp
+ 8'b10000100, 8'b10000101: ICODE = 23; // test
+// -------------------------------- add, or, adc, sbb, and, sub, xor, cmp R/M with Imm --------------------------------
+ 8'b10000000, 8'b10000001, 8'b10000010, 8'b10000011: ICODE = 24;
+// -------------------------------- add, or, adc, sbb, and, sub, xor, cmp, test Acc with Imm --------------------------------
+ 8'b00000100, 8'b00000101, // add
+ 8'b00001100, 8'b00001101, // or
+ 8'b00010100, 8'b00010101, // adc
+ 8'b00011100, 8'b00011101, // sbb
+ 8'b00100100, 8'b00100101, // and
+ 8'b00101100, 8'b00101101, // sub
+ 8'b00110100, 8'b00110101, // xor
+ 8'b00111100, 8'b00111101, // cmp
+ 8'b10101000, 8'b10101001: ICODE = 25; // test
+// -------------------------------- inc/dec R16 --------------------------------
+ 8'b01000000, 8'b01000001, 8'b01000010, 8'b01000011, 8'b01000100, 8'b01000101, 8'b01000110, 8'b01000111,
+ 8'b01001000, 8'b01001001, 8'b01001010, 8'b01001011, 8'b01001100, 8'b01001101, 8'b01001110, 8'b01001111: ICODE = 26;
+// -------------------------------- test/???/not/neg/mul/imul/div/idiv --------------------------------
+ 8'b11110110, 8'b11110111: ICODE = 27;
+// -------------------------------- imul imm --------------------------------
+ 8'b01101001, 8'b01101011: ICODE = 28;
+// -------------------------------- aad --------------------------------
+ 8'b11010101: ICODE = 29;
+// -------------------------------- daa, das, aaa, aas --------------------------------
+ 8'b00_100_111, 8'b00_101_111, 8'b00_110_111, 8'b00_111_111: ICODE = 30;
+// -------------------------------- shift/rot --------------------------------
+ 8'b11010000, 8'b11010001, // 1
+ 8'b11010010, 8'b11010011, // CL
+ 8'b11000000, 8'b11000001: ICODE = 31; // imm
+// -------------------------------- (rep)movs --------------------------------
+ 8'b10100100, 8'b10100101: ICODE = 32;
+// -------------------------------- (rep)cmps --------------------------------
+ 8'b10100110, 8'b10100111: ICODE = 33;
+// -------------------------------- (rep)scas --------------------------------
+ 8'b10101110, 8'b10101111: ICODE = 34;
+// -------------------------------- (rep)lods --------------------------------
+ 8'b10101100, 8'b10101101: ICODE = 35;
+// -------------------------------- (rep)stos --------------------------------
+ 8'b10101010, 8'b10101011: ICODE = 36; // stage1, write AL/AX in ES:[DI], inc/dec DI, dec CX
+// -------------------------------- (rep)ins --------------------------------
+ 8'b01101100, 8'b01101101: ICODE = 37;
+// -------------------------------- (rep)outs --------------------------------
+ 8'b01101110, 8'b01101111: ICODE = 38;
+// -------------------------------- call/jmp direct near --------------------------------
+ 8'b11101000, // call long
+ 8'b11101011, // jump short
+ 8'b11101001: ICODE = 39; // jump long
+// -------------------------------- call/jmp far imm --------------------------------
+ 8'b10011010, 8'b11101010: ICODE = 40;
+// -------------------------------- ret near --------------------------------
+ 8'b11000011, 8'b11000010: ICODE = 41;
+// -------------------------------- ret far --------------------------------
+ 8'b11001011, 8'b11001010: ICODE = 42;
+// -------------------------------- iret --------------------------------
+ 8'b11001111: ICODE = 43;
+// -------------------------------- cbw/cwd --------------------------------
+ 8'b10011000, 8'b10011001: ICODE = 44;
+// -------------------------------- JMP cond, LOOP, LOOPZ, LOOPNZ, JCXZ --------------------------------
+ 8'b01110000, 8'b01110001, // JO/JNO
+ 8'b01110010, 8'b01110011, // JB/JNB
+ 8'b01110100, 8'b01110101, // JE/JNE
+ 8'b01110110, 8'b01110111, // JBE/JA
+ 8'b01111000, 8'b01111001, // JS/JNS
+ 8'b01111010, 8'b01111011, // JP/JNP
+ 8'b01111100, 8'b01111101, // JL/JNL
+ 8'b01111110, 8'b01111111, // JLE/JG
+ 8'b11100010, 8'b11100001, 8'b11100000, 8'b11100011: ICODE = 45; // loop/loopz/loopnz/jcxz
+// -------------------------------- CLC, CMC, STC, CLD, STD, CLI, STI --------------------------------
+ 8'b11111000, 8'b11110101, 8'b11111001, 8'b11111100, 8'b11111101, 8'b11111010, 8'b11111011: ICODE = 46;
+// -------------------------------- enter --------------------------------
+ 8'b11001000: ICODE = 47;
+// -------------------------------- leave --------------------------------
+ 8'b11001001: ICODE = 48;
+// -------------------------------- int, int 3, into --------------------------------
+ 8'b11001101, 8'b11001100, 8'b11001110: ICODE = 49;
+// -------------------------------- bound --------------------------------
+ 8'b01100010: ICODE = 50;
+// -------------------------------- hlt --------------------------------
+ 8'b11110100: ICODE = 51;
+// -------------------------------- wait --------------------------------
+ 8'b10011011: ICODE = 52; // do nothing
+// -------------------------------- aam --------------------------------
+ 8'b11010100: ICODE = 53;
+// -------------------------------- reset, irq, nmi, intr --------------------------------
+ 8'b00001111: ICODE = 54;
+// -------------------------------- bad opcode/esc --------------------------------
+ default: ICODE = 55;
+ endcase
+ end
+endfunction
+
+endmodule
+