OpenCores
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 +

powered by: WebSVN 2.1.0

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