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

Subversion Repositories rtf8088

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /rtf8088/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/rtl/verilog/REGFILE.v
0,0 → 1,126
//=============================================================================
// (C) 2009-2012 Robert Finch, Stratford
// robfinch<remove>@opencores.org
//
// Register file
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//=============================================================================
//
reg [15:0] rrro;
reg [15:0] rmo; // register output (controlled by mod r/m byte)
reg [15:0] rfso;
 
reg pf; // parity flag
reg af; // auxillary carry (half carry) flag
reg zf, cf, vf;
reg sf; // sign flag
reg df; // direction flag
reg ie; // interrupt enable flag
reg tf;
wire [15:0] flags = {1'b0,1'b0,2'b00,vf,df,ie,tf,sf,zf,1'b0,af,1'b0,pf,1'b0,cf};
 
reg [7:0] ir; // instruction register
reg [7:0] ir2; // extended instruction register
reg [15:0] ip; // instruction pointer
reg [15:0] ir_ip; // instruction pointer of ir
reg [15:0] ax;
reg [15:0] bx;
reg [15:0] cx;
reg [15:0] dx;
reg [15:0] si; // source index
reg [15:0] di; // destination index
reg [15:0] bp; // base pointer
reg [15:0] sp; // stack pointer
wire cxz = cx==16'h0000; // CX is zero
 
reg [15:0] cs; // code segment
reg [15:0] ds; // data segment
reg [15:0] es; // extra segment
reg [15:0] ss; // stack segment
 
// renamed byte registers for convenience
wire [7:0] al = ax[7:0];
wire [7:0] ah = ax[15:8];
wire [7:0] dl = dx[7:0];
wire [7:0] dh = dx[15:8];
wire [7:0] cl = cx[7:0];
wire [7:0] ch = cx[15:8];
wire [7:0] bl = bx[7:0];
wire [7:0] bh = bx[15:8];
 
wire [19:0] csip = {cs,4'd0} + ip;
wire [19:0] sssp = {ss,4'd0} + sp;
wire [19:0] dssi = {ds,4'd0} + si;
wire [19:0] esdi = {es,4'd0} + di;
 
// Read port
//
always @(w or rrr or ax or bx or cx or dx or sp or bp or si or di)
case({w,rrr})
4'd0: rrro <= {{8{ax[7]}},ax[7:0]};
4'd1: rrro <= {{8{cx[7]}},cx[7:0]};
4'd2: rrro <= {{8{dx[7]}},dx[7:0]};
4'd3: rrro <= {{8{bx[7]}},bx[7:0]};
4'd4: rrro <= {{8{ax[15]}},ax[15:8]};
4'd5: rrro <= {{8{cx[15]}},cx[15:8]};
4'd6: rrro <= {{8{dx[15]}},dx[15:8]};
4'd7: rrro <= {{8{bx[15]}},bx[15:8]};
4'd8: rrro <= ax;
4'd9: rrro <= cx;
4'd10: rrro <= dx;
4'd11: rrro <= bx;
4'd12: rrro <= sp;
4'd13: rrro <= bp;
4'd14: rrro <= si;
4'd15: rrro <= di;
endcase
 
 
// Second Read port
//
always @(w or rm or ax or bx or cx or dx or sp or bp or si or di)
case({w,rm})
4'd0: rmo <= {{8{ax[7]}},ax[7:0]};
4'd1: rmo <= {{8{cx[7]}},cx[7:0]};
4'd2: rmo <= {{8{dx[7]}},dx[7:0]};
4'd3: rmo <= {{8{bx[7]}},bx[7:0]};
4'd4: rmo <= {{8{ax[15]}},ax[15:8]};
4'd5: rmo <= {{8{cx[15]}},cx[15:8]};
4'd6: rmo <= {{8{dx[15]}},dx[15:8]};
4'd7: rmo <= {{8{bx[15]}},bx[15:8]};
4'd8: rmo <= ax;
4'd9: rmo <= cx;
4'd10: rmo <= dx;
4'd11: rmo <= bx;
4'd12: rmo <= sp;
4'd13: rmo <= bp;
4'd14: rmo <= si;
4'd15: rmo <= di;
endcase
 
 
// Read segment registers
//
always @(sreg3 or es or cs or ds or ss)
case(sreg3)
3'd0: rfso <= es;
3'd1: rfso <= cs;
3'd2: rfso <= ss;
3'd3: rfso <= ds;
default: rfso <= 16'h0000;
endcase
/rtl/verilog/FETCH_DISP16.v
0,0 → 1,103
// ============================================================================
// FETCH_DISP16
// - detch 16 bit displacement
//
//
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// Fetch 16 bit displacement
// ============================================================================
//
FETCH_DISP16:
begin
`INITIATE_CODE_READ;
state <= FETCH_DISP16_ACK;
end
 
FETCH_DISP16_ACK:
if (ack_i) begin
state <= FETCH_DISP16a;
`PAUSE_CODE_READ
disp16[7:0] <= dat_i;
end
 
FETCH_DISP16a:
begin
state <= FETCH_DISP16a_ACK;
`INITIATE_CODE_READ
end
 
FETCH_DISP16a_ACK:
if (ack_i) begin
state <= FETCH_DISP16b;
`TERMINATE_CODE_READ
disp16[15:8] <= dat_i;
end
 
FETCH_DISP16b:
casex(ir)
 
//-----------------------------------------------------------------
// Flow control operations
//-----------------------------------------------------------------
`CALL: state <= CALL;
`JMP: begin ip <= ip + disp16; state <= IFETCH; end
`JMPS: begin ip <= ip + disp16; state <= IFETCH; end
 
//-----------------------------------------------------------------
// Memory Operations
//-----------------------------------------------------------------
`MOV_AL2M,`MOV_AX2M:
begin
res <= ax;
ea <= {seg_reg,`SEG_SHIFT} + disp16;
state <= STORE_DATA;
end
`MOV_M2AL,`MOV_M2AX:
begin
d <= 1'b0;
rrr <= 3'd0;
ea <= {seg_reg,`SEG_SHIFT} + disp16;
state <= FETCH_DATA;
end
 
`MOV_MA:
case(substate)
FETCH_DATA:
if (hasFetchedData) begin
ir <= {4'b0,w,3'b0};
wrregs <= 1'b1;
res <= disp16;
state <= IFETCH;
end
endcase
 
`MOV_AM:
begin
w <= ir[0];
state <= STORE_DATA;
ea <= {ds,`SEG_SHIFT} + disp16;
res <= ir[0] ? {ah,al} : {al,al};
end
default: state <= IFETCH;
endcase
/rtl/verilog/PUSH.v
0,0 → 1,98
// ============================================================================
// PUSH register to stack
//
//
// (C) 2009-2012 Robert Finch, Stratford
// robfinch[remove]@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
PUSH:
begin
// Note SP is predecremented at the decode stage
cyc_type <= `CT_WRMEM;
lock_o <= 1'b1;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
state <= PUSH1;
case(ir)
`PUSH_AX: dat_o <= ah;
`PUSH_BX: dat_o <= bh;
`PUSH_CX: dat_o <= ch;
`PUSH_DX: dat_o <= dh;
`PUSH_SP: dat_o <= sp[15:8];
`PUSH_BP: dat_o <= bp[15:8];
`PUSH_SI: dat_o <= si[15:8];
`PUSH_DI: dat_o <= di[15:8];
`PUSH_CS: dat_o <= cs[15:8];
`PUSH_DS: dat_o <= ds[15:8];
`PUSH_SS: dat_o <= ss[15:8];
`PUSH_ES: dat_o <= es[15:8];
`PUSHF: dat_o <= flags[15:8];
8'hFF: dat_o <= a[15:8];
default: dat_o <= 8'hFF; // only gets here if there's a hardware error
endcase
end
PUSH1:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
sp <= sp_dec;
stb_o <= 1'b0;
we_o <= 1'b0;
state <= PUSH2;
end
PUSH2:
begin
cyc_type <= `CT_WRMEM;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
state <= PUSH3;
case(ir)
`PUSH_AX: dat_o <= al;
`PUSH_BX: dat_o <= bl;
`PUSH_CX: dat_o <= cl;
`PUSH_DX: dat_o <= dl;
`PUSH_SP: dat_o <= sp[7:0];
`PUSH_BP: dat_o <= bp[7:0];
`PUSH_SI: dat_o <= si[7:0];
`PUSH_DI: dat_o <= di[7:0];
`PUSH_CS: dat_o <= cs[7:0];
`PUSH_DS: dat_o <= ds[7:0];
`PUSH_SS: dat_o <= ss[7:0];
`PUSH_ES: dat_o <= es[7:0];
`PUSHF: dat_o <= flags[7:0];
8'hFF: dat_o <= a[7:0];
default: dat_o <= 8'hFF; // only get's here if there's a hardware error
endcase
end
 
// Note stack pointer is decrement already in DECODE
//
PUSH3:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
state <= IFETCH;
end
/rtl/verilog/RETFPOP.v
0,0 → 1,82
// ============================================================================
// RETFPOP: far return from subroutine and pop stack items
// Fetch ip from stack
//
//
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
RETFPOP:
begin
lock_o <= 1'b1;
`INITIATE_STACK_POP
state <= RETFPOP1;
end
RETFPOP1:
if (ack_i) begin
`PAUSE_STACK_POP
ip[7:0] <= dat_i;
state <= RETFPOP2;
end
RETFPOP2:
begin
`CONTINUE_STACK_POP
state <= RETFPOP3;
end
RETFPOP3:
if (ack_i) begin
`PAUSE_STACK_POP
ip[15:8] <= dat_i;
state <= RETFPOP4;
end
RETFPOP4:
begin
`CONTINUE_STACK_POP
state <= RETFPOP5;
end
RETFPOP5:
if (ack_i) begin
`PAUSE_STACK_POP
cs[7:0] <= dat_i;
state <= RETFPOP6;
end
RETFPOP6:
begin
`CONTINUE_STACK_POP
state <= RETFPOP7;
end
RETFPOP7:
if (ack_i) begin
lock_o <= 1'b0;
`COMPLETE_STACK_POP
cs[15:8] <= dat_i;
state <= RETFPOP8;
end
RETFPOP8:
begin
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd4;
res <= sp + data16;
state <= IFETCH;
end
 
/rtl/verilog/ALU.v
0,0 → 1,195
// ============================================================================
// ALU
// - perform datapath operations
//
//
// (C) 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// ============================================================================
//
function carry;
input op;
input a;
input b;
input s;
 
begin
carry = op ? (~a&b)|(s&~a)|(s&b) : (a&b)|(a&~s)|(b&~s);
end
 
endfunction
 
function overflow;
input op;
input a;
input b;
input s;
 
begin
overflow = (op ^ s ^ b) & (~op ^ a ^ b);
end
 
endfunction
 
reg [15:0] alu_o;
reg [15:0] a;
reg [15:0] b;
wire amsb = w ? a[15] : a[7];
wire bmsb = w ? b[15] : b[7];
wire [15:0] as = {!a[15],a[14:0]};
wire [15:0] bs = {!b[15],b[14:0]};
wire signed [15:0] sa = a;
wire signed [15:0] sb = b;
wire signed [7:0] als = a[7:0];
wire signed [7:0] bls = b[7:0];
wire signed [15:0] p = als * bls;
wire signed [31:0] wp = sa * sb;
 
// Compute AL/10
// - multiply by 1/10 = 26/256
wire [15:0] al26 = {al,4'b0} + {al,3'b0} + {al,1'b0}; // * 26
wire [7:0] aldv10 = al26[15:8]; // 256
 
wire [15:0] cmp_o = a - b;
wire eq = a == b;
wire ltu = a < b;
wire lt = as < bs;
 
always @(ir or ir2 or a or b or cf or af or al or ah or aldv10 or TTT)
begin
casex(ir)
`MOV_M2AL,`MOV_M2AX,`LDS,`LES:
alu_o <= a;
`MOV_MR,`MOV_R2S,
`MOV_RR8,`MOV_RR16,
`MOV_I8M,`MOV_I16M,
`MOV_I2AL,`MOV_I2DL,`MOV_I2CL,`MOV_I2BL,`MOV_I2AH,`MOV_I2DH,`MOV_I2CH,`MOV_I2BH,
`MOV_I2AX,`MOV_I2DX,`MOV_I2CX,`MOV_I2BX,`MOV_I2SP,`MOV_I2BP,`MOV_I2SI,`MOV_I2DI:
alu_o <= b;
`XCHG_MEM:
alu_o <= b;
`ADD,`ADD_ALI8,`ADD_AXI16: alu_o <= a + b;
`SUB,`SUB_ALI8,`SUB_AXI16: alu_o <= a - b;
`ADC,`ADC_ALI8,`ADC_AXI16: alu_o <= a + b + cf;
`SBB,`SBB_ALI8,`SBB_AXI16: alu_o <= a - b - cf;
`AND,`AND_ALI8,`AND_AXI16: alu_o <= a & b;
`OR, `OR_ALI8, `OR_AXI16: alu_o <= a | b;
`XOR,`XOR_ALI8,`XOR_AXI16: alu_o <= a ^ b;
`CMP,`CMP_ALI8,`CMP_AXI16: alu_o <= a - b;
`SCASB,`SCASW,`CMPSB,`CMPSW: alu_o <= a - b;
`INC_REG: alu_o <= a + 16'd1;
`DEC_REG: alu_o <= a - 16'd1;
`IMUL: alu_o <= w ? p : wp[15:0];
`ALU_I2R8:
case(TTT)
3'd0: alu_o <= a + b; // ADD
3'd1: alu_o <= a | b; // OR
3'd2: alu_o <= a + b + cf; // ADC
3'd3: alu_o <= a - b - cf; // SBB
3'd4: alu_o <= a & b; // AND
3'd5: alu_o <= a - b; // SUB
3'd6: alu_o <= a ^ b; // XOR
default: alu_o <= 16'h0000;
endcase
// ToDo: fix sign extension / extra immediate byte ?
`ALU_I2R16:
case(TTT)
3'd0: alu_o <= a + b; // ADD
3'd1: alu_o <= a | b; // OR
3'd2: alu_o <= a + b + cf; // ADC
3'd3: alu_o <= a - b - cf; // SBB
3'd4: alu_o <= a & b; // AND
3'd5: alu_o <= a - b; // SUB
3'd6: alu_o <= a ^ b; // XOR
default: alu_o <= 16'h0000;
endcase
`AAA:
if (al[3:0]>4'h9 || af) begin
alu_o[3:0] <= al[3:0] + 4'd6;
alu_o[7:4] <= 4'h0;
alu_o[15:8] <= ah + 8'd1;
end
else
alu_o <= ax;
`AAS:
if (al[3:0]>4'h9 || af) begin
alu_o[3:0] <= al[3:0] - 4'd6;
alu_o[7:4] <= 4'h0;
alu_o[15:8] <= ah - 8'd1;
end
else
alu_o <= ax;
// ToDo: fix +1 carry
`DAA:
begin
alu_o <= 16'h0000;
if (al[3:0]>4'h9 || af) begin
alu_o[3:0] <= al[3:0] + 4'd6;
end
if (al[7:4]>4'h9 || cf) begin
alu_o[7:4] <= al[7:4] + 4'd6;
end
end
// ToDo: fix +1 carry
`DAS:
begin
alu_o <= 16'h0000;
if (al[3:0]>4'h9 || af) begin
alu_o[3:0] <= al[3:0] - 4'd6;
end
if (al[7:4]>4'h9 || cf) begin
alu_o[7:4] <= al[7:4] - 4'd6;
end
end
 
`MORE1:
casex(ir2)
`AAM:
begin
alu_o[ 7:0] <= al - aldv10;
alu_o[15:8] <= aldv10;
end
default:
alu_o <= 16'h0000;
endcase
`MORE2:
casex(ir2)
`AAD:
begin
alu_o[ 7:0] <= {ah,3'b0} + {ah,1'b0} + al;
alu_o[15:8] <= 8'h00;
end
default:
alu_o <= 16'h0000;
endcase
default: alu_o <= 16'h0000;
endcase
end
 
assign pres = ~^alu_o[7:0];
assign reszw = alu_o==16'h0000;
assign reszb = alu_o[7:0]==8'h00;
assign resnb = alu_o[7];
assign resnw = alu_o[15];
 
assign resz = w ? reszw : reszb;
assign resn = w ? resnw : resnb;
 
/rtl/verilog/rtf8088sys.v
0,0 → 1,111
 
module rtf8088sys();
 
reg rst;
reg sys_clk;
wire cpu_mio;
wire cpu_cyc;
wire cpu_stb;
wire cpu_ack;
wire cpu_we;
wire [19:0] cpu_adr;
wire [7:0] cpu_dato;
reg [7:0] cpu_dati;
wire stkmem_ack;
wire [7:0] stkmem_o;
wire [7:0] bootromo;
wire br_acko;
wire mem_ack;
wire [7:0] memo;
 
initial begin
rst = 1'b0;
sys_clk = 1'b0;
#100 rst = 1'b1;
#100 rst = 1'b0;
end
 
always #10 sys_clk = ~sys_clk;
 
reg [7:0] mem [0:65535];
wire csmem = cpu_cyc && cpu_stb && cpu_adr[19:16]==4'h0;
always @(posedge sys_clk)
if (csmem & cpu_we) begin
$display("wrote mem[%h]=%h", cpu_adr,cpu_dato);
mem[cpu_adr[15:0]] <= cpu_dato;
end
assign mem_ack = csmem;
assign memo = csmem ? mem[cpu_adr[15:0]] : 8'h00;
 
bootrom u3
(
.cyc(cpu_cyc),
.stb(cpu_stb),
.adr(cpu_adr),
.o(bootromo),
.acko(br_acko)
);
 
stkmem u2
(
.clk_i(sys_clk),
.cyc_i(cpu_cyc),
.stb_i(cpu_stb),
.ack_o(stkmem_ack),
.we_i(cpu_we),
.adr_i(cpu_adr),
.dat_i(cpu_dato),
.dat_o(stkmem_o)
);
 
always @(stkmem_o or bootromo or memo)
cpu_dati = stkmem_o|bootromo|memo;
assign cpu_ack = stkmem_ack|br_acko|mem_ack;
 
rtf8088 u1
(
.rst_i(rst),
.clk_i(sys_clk),
.nmi_i(1'b0),
.irq_i(1'b0),
.busy_i(1'b0),
.inta_o(),
.lock_o(),
.mio_o(cpu_mio),
.cyc_o(cpu_cyc),
.stb_o(cpu_stb),
.ack_i(cpu_ack),
.we_o(cpu_we),
.adr_o(cpu_adr),
.dat_o(cpu_dato),
.dat_i(cpu_dati)
);
 
endmodule
 
 
module stkmem(clk_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i, dat_o);
input clk_i;
input cyc_i;
input stb_i;
output ack_o;
input we_i;
input [19:0] adr_i;
input [7:0] dat_i;
output [7:0] dat_o;
 
reg [10:0] rra;
reg [7:0] mem [2047:0];
wire cs = cyc_i && stb_i && adr_i[19:11]==9'h003;
assign ack_o = cs;
 
always @(negedge clk_i)
rra <= adr_i[10:0];
 
always @(negedge clk_i)
if (cs & we_i)
mem[adr_i[10:0]] <= dat_i;
 
assign dat_o = cs ? mem[rra] : 8'h00;
 
endmodule
/rtl/verilog/FETCH_DATA.v
0,0 → 1,95
//=============================================================================
// (C) 2009-2012 Robert Finch, Stratford
// robfinch<remove>@opencores.org
//
// FETCH_DATA
// Fetch data from memory.
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//=============================================================================
//
FETCH_DATA:
if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
lock_o <= bus_locked | w;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= ea;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= w;
stb_o <= 1'b0;
if (d) begin
a <= rrro;
b[ 7:0] <= dat_i;
b[15:8] <= {8{dat_i[7]}};
end
else begin
b <= rrro;
a[ 7:0] <= dat_i;
a[15:8] <= {8{dat_i[7]}};
end
if (w)
state <= FETCH_DATA1;
else begin
case(ir)
8'h80: state <= FETCH_IMM8;
8'h81: state <= FETCH_IMM16;
8'h83: state <= FETCH_IMM8;
8'hC0: state <= FETCH_IMM8;
8'hC1: state <= FETCH_IMM8;
8'hC6: state <= FETCH_IMM8;
8'hC7: state <= FETCH_IMM16;
8'hF6: state <= FETCH_IMM8;
8'hF7: state <= FETCH_IMM16;
default: state <= EXECUTE;
endcase
hasFetchedData <= 1'b1;
end
end
FETCH_DATA1:
if (!stb_o) begin
cyc_type <= `CT_RDMEM;
lock_o <= bus_locked | w;
stb_o <= 1'b1;
adr_o <= ea_inc;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= bus_locked;
cyc_o <= 1'b0;
stb_o <= 1'b0;
if (d)
b[15:8] <= dat_i;
else
a[15:8] <= dat_i;
case(ir)
8'h80: state <= FETCH_IMM8;
8'h81: state <= FETCH_IMM16;
8'h83: state <= FETCH_IMM8;
8'hC0: state <= FETCH_IMM8;
8'hC1: state <= FETCH_IMM8;
8'hC6: state <= FETCH_IMM8;
8'hC7: state <= FETCH_IMM16;
8'hF6: state <= FETCH_IMM8;
8'hF7: state <= FETCH_IMM16;
default: state <= EXECUTE;
endcase
hasFetchedData <= 1'b1;
end
/rtl/verilog/rtf8088.v
0,0 → 1,786
// ============================================================================
// 8088 Compatible CPU.
//
//
// (C) 2009,2010 Robert Finch, Stratford
// robfinch[remove]@opencores.org
//
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
// Webpack 9.2i xc3s1000 4-ft256
// 2550 slices / 4900 LUTs / 61 MHz
// 650 ff's / 2 MULTs
//
// Webpack 14.3 xc6slx45 3-csg324
// 701 ff's 4115 LUTs / 90.261 MHz
// ============================================================================
 
//`define BYTES_ONLY 1'b1
 
//`define BIG_SEGS
`ifdef BIG_SEGS
`define SEG_SHIFT 8'b0
`define AMSB 23
`define CS_RESET 16'hFF00
`else
`define SEG_SHIFT 4'b0
`define AMSB 19
`define CS_RESET 16'hF000
`endif
 
// Opcodes
//
`define MOV_RR 8'b1000100x
`define MOV_MR 8'b1000101x
`define MOV_IM 8'b1100011x
`define MOV_MA 8'b1010000x
`define MOV_AM 8'b0101001x
 
`define ADD 8'b000000xx
`define ADD_ALI8 8'h04
`define ADD_AXI16 8'h05
`define PUSH_ES 8'h06
`define POP_ES 8'h07
`define OR 8'b000010xx
`define AAD 8'h0A
`define AAM 8'h0A
`define OR_ALI8 8'h0C
`define OR_AXI16 8'h0D
`define PUSH_CS 8'h0E
`define EXTOP 8'h0F // extended opcode
 
`define ADC 8'b000100xx
`define ADC_ALI8 8'h14
`define ADC_AXI16 8'h15
`define PUSH_SS 8'h16
`define POP_SS 8'h17
`define SBB 8'b000110xx
`define SBB_ALI8 8'h1C
`define SBB_AXI16 8'h1D
`define PUSH_DS 8'h1E
`define POP_DS 8'h1F
 
`define AND 8'b001000xx
`define AND_ALI8 8'h24
`define AND_AXI16 8'h25
`define ES 8'h26
`define DAA 8'h27
`define SUB 8'b001010xx
`define SUB_ALI8 8'h2C
`define SUB_AXI16 8'h2D
`define CS 8'h2E
`define DAS 8'h2F
 
`define XOR 8'b001100xx
`define XOR_ALI8 8'h34
`define XOR_AXI16 8'h35
`define SS 8'h36
`define AAA 8'h37
`define CMP 8'b001110xx
`define CMP_ALI8 8'h3C
`define CMP_AXI16 8'h3D
`define DS 8'h3E
`define AAS 8'h3F
 
`define INC_REG 8'b01000xxx
`define INC_AX 8'h40
`define INC_CX 8'h41
`define INC_DX 8'h42
`define INC_BX 8'h43
`define INC_SP 8'h44
`define INC_BP 8'h45
`define INC_SI 8'h46
`define INC_DI 8'h47
`define DEC_REG 8'b01001xxx
`define DEC_AX 8'h48
`define DEC_CX 8'h49
`define DEC_DX 8'h4A
`define DEC_BX 8'h4B
`define DEC_SP 8'h4C
`define DEC_BP 8'h4D
`define DEC_SI 8'h4E
`define DEC_DI 8'h4F
 
`define PUSH_REG 8'b01010xxx
`define PUSH_AX 8'h50
`define PUSH_CX 8'h51
`define PUSH_DX 8'h52
`define PUSH_BX 8'h53
`define PUSH_SP 8'h54
`define PUSH_BP 8'h55
`define PUSH_SI 8'h56
`define PUSH_DI 8'h57
`define POP_REG 8'b01011xxx
`define POP_AX 8'h58
`define POP_CX 8'h59
`define POP_DX 8'h5A
`define POP_BX 8'h5B
`define POP_SP 8'h5C
`define POP_BP 8'h5D
`define POP_SI 8'h5E
`define POP_DI 8'h5F
 
`define PUSHA 8'h60
`define POPA 8'h61
`define BOUND 8'h62
`define ARPL 8'h63
`define FS 8'h64
`define GS 8'h65
`define INSB 8'h6C
`define INSW 8'h6D
`define OUTSB 8'h6E
`define OUTSW 8'h6F
 
`define Jcc 8'b0111xxxx
`define JO 8'h70
`define JNO 8'h71
`define JB 8'h72
`define JAE 8'h73
`define JE 8'h74
`define JNE 8'h75
`define JBE 8'h76
`define JA 8'h77
`define JS 8'h78
`define JNS 8'h79
`define JP 8'h7A
`define JNP 8'h7B
`define JL 8'h7C
`define JNL 8'h7D
`define JLE 8'h7E
`define JNLE 8'h7F
 
`define JNA 8'h76
`define JNAE 8'h72
`define JNB 8'h73
`define JNBE 8'h77
`define JC 8'h72
`define JNC 8'h73
`define JG 8'h7F
`define JNG 8'h7E
`define JGE 8'h7D
`define JNGE 8'h7C
`define JPE 8'h7A
`define JPO 8'h7B
 
`define ALU_I2R8 8'h80
`define ALU_I2R16 8'h81
`define TEST 8'b1000010x
`define XCHG_MEM 8'h86
`define MOV_RR8 8'h88
`define MOV_RR16 8'h89
`define MOV_MR8 8'h8A
`define MOV_MR16 8'h8B
`define MOV_S2R 8'h8C
`define LEA 8'h8D
`define MOV_R2S 8'h8E
`define POP_MEM 8'h8F
 
`define XCHG_AXR 8'b10010xxx
`define NOP 8'h90
`define CBW 8'h98
`define CWD 8'h99
`define CALLF 8'h9A
`define WAI 8'h9B
`define PUSHF 8'h9C
`define POPF 8'h9D
`define SAHF 8'h9E
`define LAHF 8'h9F
 
`define MOV_M2AL 8'hA0
`define MOV_M2AX 8'hA1
`define MOV_AL2M 8'hA2
`define MOV_AX2M 8'hA3
 
`define MOVSB 8'hA4
`define MOVSW 8'hA5
`define CMPSB 8'hA6
`define CMPSW 8'hA7
`define STOSB 8'hAA
`define STOSW 8'hAB
`define LODSB 8'hAC
`define LODSW 8'hAD
`define SCASB 8'hAE
`define SCASW 8'hAF
 
`define MOV_I2BYTREG 8'h1011_0xxx
`define MOV_I2AL 8'hB0
`define MOV_I2CL 8'hB1
`define MOV_I2DL 8'hB2
`define MOV_I2BL 8'hB3
`define MOV_I2AH 8'hB4
`define MOV_I2CH 8'hB5
`define MOV_I2DH 8'hB6
`define MOV_I2BH 8'hB7
`define MOV_I2AX 8'hB8
`define MOV_I2CX 8'hB9
`define MOV_I2DX 8'hBA
`define MOV_I2BX 8'hBB
`define MOV_I2SP 8'hBC
`define MOV_I2BP 8'hBD
`define MOV_I2SI 8'hBE
`define MOV_I2DI 8'hBF
 
`define RETPOP 8'hC2
`define RET 8'hC3
`define LES 8'hC4
`define LDS 8'hC5
`define MOV_I8M 8'hC6
`define MOV_I16M 8'hC7
`define LEAVE 8'hC9
`define RETFPOP 8'hCA
`define RETF 8'hCB
`define INT3 8'hCC
`define INT 8'hCD
`define INTO 8'hCE
`define IRET 8'hCF
 
`define RCL_81 8'hD0
`define RCL_161 8'hD1
`define MORE1 8'hD4
`define MORE2 8'hD5
`define XLAT 8'hD7
 
`define LOOPNZ 8'hE0
`define LOOPZ 8'hE1
`define LOOP 8'hE2
`define JCXZ 8'hE3
`define INB 8'hE4
`define INW 8'hE5
`define OUTB 8'hE6
`define OUTW 8'hE7
`define CALL 8'hE8
`define JMP 8'hE9
`define JMPF 8'hEA
`define JMPS 8'hEB
`define INB_DX 8'hEC
`define INW_DX 8'hED
`define OUTB_DX 8'hEE
`define OUTW_DX 8'hEF
 
`define LOCK 8'hF0
`define REPNZ 8'hF2
`define REPZ 8'hF3
`define HLT 8'hF4
`define CMC 8'hF5
`define IMUL 8'b1111011x
`define CLC 8'hF8
`define STC 8'hF9
`define CLI 8'hFA
`define STI 8'hFB
`define CLD 8'hFC
`define STD 8'hFD
`define GRPFF 8'b1111111x
 
// extended opcodes
// "OF"
`define LLDT 8'h00
`define LxDT 8'h01
`define LAR 8'h02
`define LSL 8'h03
`define CLTS 8'h06
 
`define LSS 8'hB2
`define LFS 8'hB4
`define LGS 8'hB5
 
`define INITIATE_CODE_READ cyc_type <= `CT_CODE; cyc_o <= 1'b1; stb_o <= 1'b1; we_o <= 1'b0; adr_o <= csip;
`define TERMINATE_CYCLE cyc_type <= `CT_PASSIVE; cyc_o <= 1'b0; stb_o <= 1'b0; we_o <= 1'b0;
`define TERMINATE_CODE_READ cyc_type <= `CT_PASSIVE; cyc_o <= 1'b0; stb_o <= 1'b0; we_o <= 1'b0; ip <= ip_inc;
`define PAUSE_CODE_READ cyc_type <= `CT_PASSIVE; stb_o <= 1'b0; ip <= ip_inc;
`define CONTINUE_CODE_READ cyc_type <= `CT_CODE; stb_o <= 1'b1; adr_o <= csip;
`define INITIATE_STACK_WRITE cyc_type <= `CT_WRMEM; cyc_o <= 1'b1; stb_o <= 1'b1; we_o <= 1'b1; adr_o <= sssp;
`define PAUSE_STACK_WRITE cyc_type <= `CT_PASSIVE; sp <= sp_dec; stb_o <= 1'b0; we_o <= 1'b0;
 
`define INITIATE_STACK_POP cyc_type <= `CT_RDMEM; lock_o <= 1'b1; cyc_o <= 1'b1; stb_o <= 1'b1; adr_o <= sssp;
`define COMPLETE_STACK_POP cyc_type <= `CT_PASSIVE; lock_o <= bus_locked; cyc_o <= 1'b0; stb_o <= 1'b0; sp <= sp_inc;
`define PAUSE_STACK_POP cyc_type <= `CT_PASSIVE; stb_o <= 1'b0; sp <= sp_inc;
`define CONTINUE_STACK_POP cyc_type <= `CT_RDMEM; stb_o <= 1'b1; adr_o <= sssp;
 
 
/*
Some modrm codes specify register-immediate or memory-immediate operations.
The operation to be performed is coded in the rrr field as only one register
spec (rm) is required.
 
80/81/83
rrr Operation
---------------
000 = ADD
001 = OR
010 = ADC
011 = SBB
100 = AND
101 = SUB
110 = XOR
111 = CMP
FE/FF
000 = INC
001 = DEC
010 = CALL
011 =
100 =
101 =
110 =
111 =
F6/F7:
000 = TEST
001 =
010 = NOT
011 = NEG
100 = MUL
101 =
110 =
111 =
*/
`define ADDRESS_INACTIVE 20'hFFFFF
`define DATA_INACTIVE 8'hFF
 
`include "cycle_types.v"
 
module rtf8088(rst_i, clk_i, nmi_i, irq_i, busy_i, inta_o, lock_o, mio_o, cyc_o, stb_o, ack_i, we_o, adr_o, dat_i, dat_o);
// States
parameter IFETCH=8'd1;
parameter IFETCH_ACK = 8'd2;
parameter XI_FETCH = 8'd3;
parameter XI_FETCH_ACK = 8'd4;
parameter DECODE = 8'd7;
parameter DECODER2 = 8'd8;
parameter DECODER3 = 8'd9;
 
parameter FETCH_VECTOR = 8'd10;
parameter FETCH_IMM8 = 8'd11;
parameter FETCH_IMM8_ACK = 8'd12;
parameter FETCH_IMM16 = 8'd13;
parameter FETCH_IMM16_ACK = 8'd14;
parameter FETCH_IMM16a = 8'd15;
parameter FETCH_IMM16a_ACK = 8'd16;
 
parameter MOV_I2BYTREG = 8'd17;
 
parameter FETCH_DISP8 = 8'd18;
parameter FETCH_DISP16 = 8'd19;
parameter FETCH_DISP16_ACK = 8'd20;
parameter FETCH_DISP16a = 8'd21;
parameter FETCH_DISP16a_ACK = 8'd22;
parameter FETCH_DISP16b = 8'd23;
 
parameter FETCH_OFFSET = 8'd24;
parameter FETCH_OFFSET1 = 8'd25;
parameter FETCH_OFFSET2 = 8'd26;
parameter FETCH_OFFSET3 = 8'd27;
parameter FETCH_SEGMENT = 8'd28;
parameter FETCH_SEGMENT1 = 8'd29;
parameter FETCH_SEGMENT2 = 8'd30;
parameter FETCH_SEGMENT3 = 8'd31;
parameter FETCH_STK_ADJ1 = 8'd32;
parameter FETCH_STK_ADJ1_ACK = 8'd33;
parameter FETCH_STK_ADJ2 = 8'd34;
parameter FETCH_STK_ADJ2_ACK = 8'd35;
parameter FETCH_DATA = 8'd36;
parameter FETCH_DATA1 = 8'd37;
 
parameter BRANCH1 = 8'd40;
parameter BRANCH2 = 8'd41;
parameter BRANCH3 = 8'd42;
 
parameter PUSHA = 8'd43;
parameter PUSHA1= 8'd44;
parameter POPA = 8'd45;
parameter POPA1 = 8'd46;
parameter RET = 8'd47;
parameter RETF = 8'd48;
parameter RETF1 = 8'd49;
parameter JMPF = 8'd50;
 
parameter CALLF = 8'd51;
parameter CALLF1 = 8'd52;
parameter CALLF2 = 8'd53;
parameter CALLF3 = 8'd54;
parameter CALLF4 = 8'd55;
parameter CALLF5 = 8'd56;
parameter CALLF6 = 8'd57;
parameter CALLF7 = 8'd58;
 
parameter CALL = 8'd59;
parameter CALL1 = 8'd60;
parameter CALL2 = 8'd61;
parameter CALL3 = 8'd62;
 
parameter PUSH = 8'd63;
parameter PUSH1 = 8'd64;
parameter PUSH2 = 8'd65;
parameter PUSH3 = 8'd66;
 
parameter IRET = 8'd70;
parameter IRET1 = 8'd71;
parameter IRET2 = 8'd72;
 
parameter POP = 8'd73;
parameter POP1 = 8'd74;
parameter POP2 = 8'd75;
parameter POP3 = 8'd76;
 
parameter CALL_IN = 8'd77;
parameter CALL_IN1 = 8'd78;
parameter CALL_IN2 = 8'd79;
parameter CALL_IN3 = 8'd80;
parameter CALL_IN4 = 8'd81;
 
parameter STOS = 8'd83;
parameter STOS1 = 8'd84;
parameter STOS2 = 8'd85;
parameter MOVS = 8'd86;
parameter MOVS1 = 8'd87;
parameter MOVS2 = 8'd88;
parameter MOVS3 = 8'd89;
parameter MOVS4 = 8'd90;
parameter MOVS5 = 8'd91;
 
parameter WRITE_REG = 8'd92;
 
parameter EACALC = 8'd93;
parameter EACALC1 = 8'd94;
parameter EACALC_DISP8 = 8'd95;
parameter EACALC_DISP8_ACK = 8'd96;
parameter EACALC_DISP16 = 8'd97;
parameter EACALC_DISP16_ACK = 8'd98;
parameter EACALC_DISP16a = 8'd99;
parameter EACALC_DISP16a_ACK = 8'd100;
parameter EXECUTE = 8'd101;
 
parameter INB = 8'd102;
parameter INB1 = 8'd103;
parameter INB2 = 8'd104;
parameter INB3 = 8'd105;
parameter INW = 8'd106;
parameter INW1 = 8'd107;
parameter INW2 = 8'd108;
parameter INW3 = 8'd109;
parameter INW4 = 8'd110;
parameter INW5 = 8'd111;
 
parameter OUTB = 8'd112;
parameter OUTB_NACK = 8'd113;
parameter OUTB1 = 8'd114;
parameter OUTB1_NACK = 8'd115;
parameter OUTW = 8'd116;
parameter OUTW_NACK = 8'd117;
parameter OUTW1 = 8'd118;
parameter OUTW1_NACK = 8'd119;
parameter OUTW2 = 8'd120;
parameter OUTW2_NACK = 8'd121;
parameter FETCH_PORTNUMBER = 8'd122;
 
parameter INVALID_OPCODE = 8'd123;
parameter IRQ1 = 8'd126;
 
parameter JUMP_VECTOR1 = 8'd127;
parameter JUMP_VECTOR2 = 8'd128;
parameter JUMP_VECTOR3 = 8'd129;
parameter JUMP_VECTOR4 = 8'd130;
parameter JUMP_VECTOR5 = 8'd131;
parameter JUMP_VECTOR6 = 8'd132;
parameter JUMP_VECTOR7 = 8'd133;
parameter JUMP_VECTOR8 = 8'd134;
parameter JUMP_VECTOR9 = 8'd135;
 
parameter STORE_DATA = 8'd136;
parameter STORE_DATA1 = 8'd137;
parameter STORE_DATA2 = 8'd138;
parameter STORE_DATA3 = 8'd139;
 
parameter INTO = 8'd140;
parameter FIRST = 8'd141;
 
parameter INTA0 = 8'd142;
parameter INTA1 = 8'd143;
parameter INTA2 = 8'd144;
parameter INTA3 = 8'd145;
 
parameter RETPOP = 8'd150;
parameter RETPOP_NACK = 8'd151;
parameter RETPOP1 = 8'd152;
parameter RETPOP1_NACK = 8'd153;
 
parameter RETFPOP = 8'd154;
parameter RETFPOP1 = 8'd155;
parameter RETFPOP2 = 8'd156;
parameter RETFPOP3 = 8'd157;
parameter RETFPOP4 = 8'd158;
parameter RETFPOP5 = 8'd159;
parameter RETFPOP6 = 8'd160;
parameter RETFPOP7 = 8'd161;
parameter RETFPOP8 = 8'd162;
 
parameter XLAT_ACK = 8'd166;
 
parameter FETCH_DESC = 8'd170;
parameter FETCH_DESC1 = 8'd171;
parameter FETCH_DESC2 = 8'd172;
parameter FETCH_DESC3 = 8'd173;
parameter FETCH_DESC4 = 8'd174;
parameter FETCH_DESC5 = 8'd175;
 
parameter INSB = 8'd180;
parameter INSB1 = 8'd181;
parameter OUTSB = 8'd182;
parameter OUTSB1 = 8'd183;
 
parameter SCASB = 8'd185;
parameter SCASB1 = 8'd186;
parameter SCASW = 8'd187;
parameter SCASW1 = 8'd188;
parameter SCASW2 = 8'd189;
 
parameter CMPSW = 8'd190;
parameter CMPSW1 = 8'd191;
parameter CMPSW2 = 8'd192;
parameter CMPSW3 = 8'd193;
parameter CMPSW4 = 8'd194;
parameter CMPSW5 = 8'd195;
 
parameter LODS = 8'd196;
parameter LODS_NACK = 8'd197;
parameter LODS1 = 8'd198;
parameter LODS1_NACK = 8'd199;
 
parameter INSW = 8'd200;
parameter INSW1 = 8'd201;
parameter INSW2 = 8'd202;
parameter INSW3 = 8'd203;
 
parameter OUTSW = 8'd205;
parameter OUTSW1 = 8'd206;
parameter OUTSW2 = 8'd207;
parameter OUTSW3 = 8'd208;
 
parameter CALL_FIN = 8'd210;
parameter CALL_FIN1 = 8'd211;
parameter CALL_FIN2 = 8'd212;
parameter CALL_FIN3 = 8'd213;
parameter CALL_FIN4 = 8'd214;
 
parameter INT = 8'd220;
parameter INT1 = 8'd221;
parameter INT2 = 8'd222;
parameter INT3 = 8'd223;
parameter INT4 = 8'd224;
parameter INT5 = 8'd225;
parameter INT6 = 8'd226;
parameter INT7 = 8'd227;
parameter INT8 = 8'd228;
parameter INT9 = 8'd229;
parameter INT10 = 8'd230;
parameter INT11 = 8'd231;
parameter INT12 = 8'd232;
parameter INT13 = 8'd233;
parameter INT14 = 8'd234;
 
parameter IRET3 = 8'd235;
parameter IRET4 = 8'd236;
parameter IRET5 = 8'd237;
parameter IRET6 = 8'd238;
parameter IRET7 = 8'd239;
parameter IRET8 = 8'd240;
parameter IRET9 = 8'd241;
parameter IRET10 = 8'd242;
parameter IRET11 = 8'd243;
parameter IRET12 = 8'd244;
 
parameter INSB2 = 8'd246;
parameter OUTSB2 = 8'd247;
parameter XCHG_MEM = 8'd248;
 
parameter CMPSB = 8'd250;
parameter CMPSB1 = 8'd251;
parameter CMPSB2 = 8'd252;
parameter CMPSB3 = 8'd253;
parameter CMPSB4 = 8'd254;
 
 
input rst_i;
input clk_i;
input nmi_i;
input irq_i;
input busy_i;
output inta_o;
output lock_o;
output mio_o;
output cyc_o;
output stb_o;
input ack_i;
output we_o;
output [`AMSB:0] adr_o;
input [ 7:0] dat_i;
output [ 7:0] dat_o;
 
reg inta_o;
reg lock_o;
reg cyc_o;
reg stb_o;
reg we_o;
reg [`AMSB:0] adr_o;
reg [ 7:0] dat_o;
 
reg mio_o;
wire busy_i;
 
reg [1:0] seg_sel; // segment selection 0=ES,1=SS,2=CS (or none), 3=DS
 
reg [7:0] state; // machine state
reg [7:0] substate;
reg hasFetchedModrm;
reg hasFetchedDisp8;
reg hasFetchedDisp16;
reg hasFetchedData;
reg hasStoredData;
reg hasFetchedVector;
 
reg [15:0] res; // result bus
wire pres; // parity result
wire reszw; // zero word
wire reszb; // zero byte
wire resnb; // negative byte
wire resnw; // negative word
wire resn;
wire resz;
 
reg [2:0] cyc_type; // type of bus sycle
reg w; // 0=8 bit, 1=16 bit
reg d;
reg [1:0] mod;
reg [2:0] rrr;
reg [2:0] rm;
reg sxi;
reg [2:0] sreg;
reg [1:0] sreg2;
reg [2:0] sreg3;
reg [2:0] TTT;
reg [7:0] lock_insn;
reg [7:0] prefix1;
reg [7:0] prefix2;
reg [7:0] int_num; // interrupt number to execute
reg [15:0] seg_reg; // segment register value for memory access
reg [15:0] data16; // caches data
reg [15:0] disp16; // caches displacement
reg [15:0] offset; // caches offset
reg [15:0] selector; // caches selector
reg [`AMSB:0] ea; // effective address
reg [39:0] desc; // buffer for sescriptor
reg [6:0] cnt; // counter
reg [1:0] S43;
reg wrregs;
reg wrsregs;
wire take_br;
 
reg nmi_armed;
reg rst_nmi; // reset the nmi flag
wire pe_nmi; // indicates positive edge on nmi signal
 
wire RESET = rst_i;
wire CLK = clk_i;
wire NMI = nmi_i;
 
`include "REGFILE.v"
`include "CONTROL_LOGIC.v"
`include "which_seg.v"
evaluate_branch u4 (ir,cx,zf,cf,sf,vf,pf,take_br);
`include "ALU.v"
nmi_detector u6 (RESET, CLK, NMI, rst_nmi, pe_nmi);
 
always @(posedge CLK)
if (RESET) begin
pf <= 1'b0;
cf <= 1'b0;
df <= 1'b0;
vf <= 1'b0;
zf <= 1'b0;
ie <= 1'b0;
hasFetchedModrm <= 1'b0;
cs <= `CS_RESET;
ip <= 16'hFFF0;
inta_o <= 1'b0;
mio_o <= 1'b1;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
cyc_type <= `CT_PASSIVE;
ir <= `NOP;
prefix1 <= 8'h00;
prefix2 <= 8'h00;
rst_nmi <= 1'b1;
wrregs <= 1'b0;
wrsregs <= 1'b0;
state <= IFETCH;
end
else begin
rst_nmi <= 1'b0;
wrregs <= 1'b0;
wrsregs <= 1'b0;
 
`include "WRITE_BACK.v"
 
case(state)
 
`include "IFETCH.v"
`include "DECODE.v"
`include "DECODER2.v"
`include "EACALC.v"
`include "CMPSB.v"
`include "CMPSW.v"
`include "MOVS.v"
`include "LODS.v"
`include "STOS.v"
`include "SCASB.v"
`include "SCASW.v"
`include "EXECUTE.v"
`include "FETCH_DATA.v"
`include "FETCH_DISP8.v"
`include "FETCH_DISP16.v"
`include "FETCH_IMMEDIATE.v"
`include "FETCH_OFFSET_AND_SEGMENT.v"
`include "MOV_I2BYTREG.v"
`include "STORE_DATA.v"
`include "BRANCH.v"
`include "CALL.v"
`include "CALLF.v"
`include "CALL_IN.v"
`include "INTA.v"
`include "INT.v"
`include "FETCH_STK_ADJ.v"
`include "RETPOP.v"
`include "RETFPOP.v"
`include "IRET.v"
`include "JUMP_VECTOR.v"
`include "PUSH.v"
`include "POP.v"
`include "INB.v"
`include "INW.v"
`include "OUTB.v"
`include "OUTW.v"
`include "INSB.v"
`include "OUTSB.v"
`include "XCHG_MEM.v"
 
default:
state <= IFETCH;
endcase
end
 
endmodule
/rtl/verilog/EVALUATE_BRANCH.v
0,0 → 1,114
// ============================================================================
// EVALUATE_BRANCH.v
// Evaluate branch condition
//
//
// (C) 2009,2010 Robert Finch
// Stratford
// robfinch[remove]@opencores.ca
//
//
// This source code is available for evaluation and validation purposes
// only. This copyright statement and disclaimer must remain present in
// the file.
//
// NO WARRANTY.
// THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER
// EXPRESS OR IMPLIED. The user must assume the entire risk of using the
// Work.
//
// IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
// INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO
// THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR.
//
// IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK
// IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN
// REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN
// LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU
// AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR
// LOSSES RELATING TO SUCH UNAUTHORIZED USE.
//
//
// Verilog
//
// ============================================================================
//
`ifndef JMPS
`define JMPS 8'hEB
`endif
 
`ifndef JO
`define JO 8'h70
`define JNO 8'h71
`define JB 8'h72
`define JAE 8'h73
`define JE 8'h74
`define JNE 8'h75
`define JBE 8'h76
`define JA 8'h77
`define JS 8'h78
`define JNS 8'h79
`define JP 8'h7A
`define JNP 8'h7B
`define JL 8'h7C
`define JNL 8'h7D
`define JLE 8'h7E
`define JNLE 8'h7F
 
`define JNA 8'h76
`define JNAE 8'h72
`define JNB 8'h73
`define JNBE 8'h77
`define JC 8'h72
`define JNC 8'h73
`define JG 8'h7F
`define JNG 8'h7E
`define JGE 8'h7D
`define JNGE 8'h7C
`define JPE 8'h7A
`define JPO 8'h7B
 
`define LOOPNZ 8'hE0
`define LOOPZ 8'hE1
`define LOOP 8'hE2
`define JCXZ 8'hE3
 
`endif
 
module evaluate_branch(ir,cx,zf,cf,sf,vf,pf,take_br);
input [7:0] ir;
input [15:0] cx;
input zf,cf,sf,vf,pf;
output take_br;
 
reg take_br;
wire cxo = cx==16'h0001; // CX is one
wire cxz = cx==16'h0000; // CX is zero
 
always @(ir or cx or cxz or cxo or zf or cf or sf or vf or pf)
case(ir)
`JMPS: take_br <= 1'b1;
`JP: take_br <= pf;
`JNP: take_br <= !pf;
`JO: take_br <= vf;
`JNO: take_br <= !vf;
`JE: take_br <= zf;
`JNE: take_br <= !zf;
`JAE: take_br <= !cf;
`JB: take_br <= cf;
`JS: take_br <= sf;
`JNS: take_br <= !sf;
`JBE: take_br <= cf | zf;
`JA: take_br <= !cf & !zf;
`JL: take_br <= sf ^ vf;
`JNL: take_br <= !(sf ^ vf);
`JLE: take_br <= (sf ^ vf) | zf;
`JNLE: take_br <= !((sf ^ vf) | zf);
`JCXZ: take_br <= cxz;
`LOOP: take_br <= !cxo;
`LOOPZ: take_br <= !cxo && zf;
`LOOPNZ: take_br <= !cxo && !zf;
default: take_br <= 1'b0;
endcase
 
endmodule
/rtl/verilog/cycle_types.v
0,0 → 1,33
// ============================================================================
// 2009-2012 Robert T Finch
// robfinch<remove>@opencores.org
//
// Bus cycle type definitions
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
 
`define CT_INTA 3'd0
`define CT_RDIO 3'd1
`define CT_WRIO 3'd2
`define CT_HALT 3'd3
`define CT_CODE 3'd4
`define CT_RDMEM 3'd5
`define CT_WRMEM 3'd6
`define CT_PASSIVE 3'd7
/rtl/verilog/MOVS.v
0,0 → 1,112
//=============================================================================
// MOVSB,MOVSW
// - moves a byte at a time to account for both bytes and words
//
//
// 2009-2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
//
MOVS:
`include "check_for_ints.v"
else if (w && (si==16'hFFFF)) begin
ir <= `NOP;
int_num <= 8'd13;
state <= INT1;
end
else if ((repz|repnz) & cxz)
state <= IFETCH;
else begin
if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
lock_o <= w;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= dssi;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
state <= w ? MOVS1 : MOVS3;
cyc_o <= 1'b0;
stb_o <= 1'b0;
a[7:0] <= dat_i;
si <= df ? si_dec : si_inc;
end
end
MOVS1:
if (!cyc_o) begin
cyc_type <= `CT_WRMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= esdi;
dat_o <= a[7:0];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
di <= df ? di_dec : di_inc;
state <= MOVS2;
end
MOVS2:
begin
cyc_type <= `CT_RDMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= dssi;
state <= MOVS3;
end
MOVS3:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
a[7:0] <= dat_i;
si <= df ? si_dec : si_inc;
state <= MOVS4;
end
MOVS4:
begin
cyc_type <= `CT_WRMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= esdi;
dat_o <= a[7:0];
state <= MOVS5;
end
MOVS5:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
di <= df ? di_dec : di_inc;
if (repz|repnz) begin
cx <= cx_dec;
state <= MOVS;
end
else
state <= IFETCH;
end
/rtl/verilog/STORE_DATA.v
0,0 → 1,70
// ============================================================================
// STORE_DATA
// - store data to memory.
//
//
// (C) 2009,2010,2012 Robert Finch
// robfinch[remove]@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// ============================================================================
//
STORE_DATA:
begin
cyc_type <= `CT_WRMEM;
lock_o <= bus_locked | w;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= ea;
dat_o <= res[7:0];
state <= STORE_DATA1;
end
STORE_DATA1:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
we_o <= 1'b0;
if (w) begin
state <= STORE_DATA2;
end
else begin
cyc_o <= 1'b0;
lock_o <= 1'b0;
state <= IFETCH;
end
end
STORE_DATA2:
begin
cyc_type <= `CT_WRMEM;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= ea_inc;
dat_o <= res[15:8];
state <= STORE_DATA3;
end
STORE_DATA3:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
state <= IFETCH;
end
/rtl/verilog/XCHG_MEM.v
0,0 → 1,5
XCHG_MEM:
begin
res <= b;
state <= STORE_DATA;
end
/rtl/verilog/FETCH_STK_ADJ.v
0,0 → 1,53
// ============================================================================
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
// FETCH_STK_ADJ
// - fetch stack adjustment word
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
// - fetch 16 bit stack adjustment
//
// ============================================================================
//
FETCH_STK_ADJ1:
begin
`INITIATE_CODE_READ
state <= FETCH_STK_ADJ1_ACK;
end
FETCH_STK_ADJ1_ACK:
if (ack_i) begin
`PAUSE_CODE_READ
data16[7:0] <= dat_i;
state <= FETCH_STK_ADJ2;
end
FETCH_STK_ADJ2:
begin
`CONTINUE_CODE_READ
state <= FETCH_STK_ADJ2_ACK;
end
FETCH_STK_ADJ2_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
if(ir==`RETPOP)
state <= RETPOP;
else
state <= RETFPOP;
data16[15:8] <= dat_i;
end
/rtl/verilog/INT.v
0,0 → 1,197
// ============================================================================
// INT.v
// - Interrupt handling
//
//
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// - bus is locked if immediate value is unaligned in memory
// - immediate values are the last operand to be fetched, hence
// the state machine can transition into the EXECUTE state.
// - we also know the immediate value can't be the target of an
// operation.
// ============================================================================
//
// Fetch interrupt number from instruction stream
//
INT:
begin
`INITIATE_CODE_READ
lock_o <= 1'b1;
sp <= sp_dec; // pre-decrement
state <= INT1;
end
INT1:
if (ack_i) begin
`PAUSE_CODE_READ
int_num <= dat_i;
state <= INT2;
end
INT2:
begin
cyc_type <= `CT_RDMEM;
lock_o <= 1'b1;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= {int_num,2'b00};
state <= INT3;
end
INT3:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
offset[7:0] <= dat_i;
state <= INT4;
end
INT4:
begin
cyc_type <= `CT_RDMEM;
stb_o <= 1'b1;
adr_o <= adr_o_inc;
state <= INT5;
end
INT5:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
offset[15:8] <= dat_i;
state <= INT6;
end
INT6:
if (!stb_o) begin
cyc_type <= `CT_RDMEM;
stb_o <= 1'b1;
adr_o <= adr_o_inc;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
state <= INT7;
selector[7:0] <= dat_i;
end
INT7:
if (!stb_o) begin
cyc_type <= `CT_RDMEM;
stb_o <= 1'b1;
adr_o <= adr_o_inc;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
state <= INT8;
selector[15:8] <= dat_i;
end
INT8:
if (!cyc_o) begin
`INITIATE_STACK_WRITE
lock_o <= 1'b1;
dat_o <= flags[15:8];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
sp <= sp_dec;
state <= INT9;
stb_o <= 1'b0;
we_o <= 1'b0;
end
INT9:
if (!stb_o) begin
cyc_type <= `CT_WRMEM;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
dat_o <= flags[7:0];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
sp <= sp_dec;
state <= INT10;
stb_o <= 1'b0;
we_o <= 1'b0;
ie <= 1'b0;
tf <= 1'b0;
end
INT10:
if (!stb_o) begin
cyc_type <= `CT_WRMEM;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
dat_o <= cs[15:8];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
sp <= sp_dec;
state <= INT11;
stb_o <= 1'b0;
we_o <= 1'b0;
end
INT11:
if (!stb_o) begin
cyc_type <= `CT_WRMEM;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
dat_o <= cs[7:0];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
sp <= sp_dec;
state <= INT12;
stb_o <= 1'b0;
we_o <= 1'b0;
end
INT12:
if (!stb_o) begin
cyc_type <= `CT_WRMEM;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
dat_o <= ir_ip[15:8];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
sp <= sp_dec;
state <= INT13;
stb_o <= 1'b0;
we_o <= 1'b0;
end
INT13:
if (!stb_o) begin
cyc_type <= `CT_WRMEM;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
dat_o <= ir_ip[7:0];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
state <= IFETCH;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
cs <= selector;
ip <= offset;
end
/rtl/verilog/INSB.v
0,0 → 1,51
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
INSB:
`include "check_for_ints.v"
else if (repdone)
state <= IFETCH;
else if (!cyc_o) begin
cyc_type <= `CT_RDIO;
cyc_o <= 1'b1;
stb_o <= 1'b1;
adr_o <= {`SEG_SHIFT,dx};
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
res[7:0] <= dat_i;
state <= INSB2;
end
INSB2:
if (!cyc_o) begin
cyc_type <= `CT_WRMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
adr_o <= esdi;
dat_o <= res[7:0];
we_o <= 1'b1;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
if (df)
di <= di - 16'd1;
else
di <= di + 16'd1;
if (repz|repnz) cx <= cx_dec;
state <= repz|repnz ? INSB : IFETCH;
end
/rtl/verilog/SCASB.v
0,0 → 1,68
// ============================================================================
// SCASB
//
//
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
SCASB:
`include "check_for_ints.v"
else if ((repz|repnz) & cxz)
state <= IFETCH;
else begin
if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
lock_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= esdi;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
state <= SCASB1;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
a <= al;
b <= dat_i;
if (df)
di <= di_dec;
else
di <= di_inc;
end
end
SCASB1:
begin
state <= IFETCH;
pf <= pres;
af <= carry (1'b0,a[3],b[3],alu_o[3]);
cf <= carry (1'b0,a[7],b[7],alu_o[7]);
vf <= overflow(1'b0,a[7],b[7],alu_o[7]);
sf <= alu_o[7];
zf <= reszb;
if (repz|repnz)
cx <= cx_dec;
if ((repz & reszb) | (repnz & !reszb))
state <= SCASB;
end
/rtl/verilog/INW.v
0,0 → 1,79
// ============================================================================
// INW.v
// - Fetch data from IO.
//
//
// 2009,2010,2012 Robert Finch
// robfinch@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//
// Verilog
//
// ============================================================================
//
INW:
begin
`INITIATE_CODE_READ
state <= INW1;
end
INW1:
if (ack_i) begin
`TERMINATE_CODE_READ
ea <= {12'h000,dat_i};
state <= INW2;
end
INW2:
begin
cyc_type <= `CT_RDIO;
mio_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= ea;
state <= INW3;
end
INW3:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
mio_o <= 1'b1;
stb_o <= 1'b0;
res[7:0] <= dat_i;
state <= INW4;
end
INW4:
begin
cyc_type <= `CT_RDIO;
mio_o <= 1'b0;
stb_o <= 1'b1;
adr_o <= ea_inc;
state <= INW5;
end
INW5:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
mio_o <= 1'b1;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd0;
res[15:8] <= dat_i;
state <= IFETCH;
end
/rtl/verilog/BRANCH.v
0,0 → 1,50
//============================================================================
// BRANCH.v
// Jcc disp8
// - conditional branches
// - fetch an 8 bit displacement and add into IP
//
//
// (C) 2009-2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//=============================================================================
//
// Fetch branch displacement if taking branch, otherwise skip
//
BRANCH1:
if (take_br) begin
`INITIATE_CODE_READ
state <= BRANCH2;
end
else begin
ip <= ip_inc;
state <= IFETCH;
end
BRANCH2:
if (ack_i) begin
`TERMINATE_CODE_READ
disp16 <= {{8{dat_i[7]}},dat_i};
state <= BRANCH3;
end
BRANCH3:
begin
ip <= ip + disp16;
state <= IFETCH;
end
/rtl/verilog/OUTW.v
0,0 → 1,75
//=============================================================================
// OUTW
// - output word data to IO.
//
//
// 2009,2010 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
//
OUTW: // Entry point for OUT port,AX
begin
`INITIATE_CODE_READ
state <= OUTW_NACK;
end
OUTW_NACK:
if (ack_i) begin
`TERMINATE_CODE_READ
ea <= {12'h000,dat_i};
state <= OUTW1;
end
OUTW1: // Entry point for OUT [DX],AX
begin
cyc_type <= `CT_WRIO;
lock_o <= 1'b1;
mio_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= ea;
dat_o <= al;
state <= OUTW1_NACK;
end
OUTW1_NACK:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
we_o <= 1'b0;
state <= OUTW2;
end
OUTW2:
begin
cyc_type <= `CT_WRIO;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= ea_inc;
dat_o <= ah;
state <= OUTW2_NACK;
end
OUTW2_NACK:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= 1'b0;
mio_o <= 1'b1;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
state <= IFETCH;
end
 
/rtl/verilog/FETCH_DISP8.v
0,0 → 1,39
// ============================================================================
// FETCH_DISP8
// - fetch 8 bit displacement
//
//
// 2009-2012 Robert Finch
// robfinch<remove>@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// - fetch 8 bit displacement
// ============================================================================
//
FETCH_DISP8:
if (!cyc_o) begin
`INITIATE_CODE_READ
end
else if (ack_i) begin
`TERMINATE_CODE_READ
state <= DECODE;
disp16 <= {{8{dat_i[7]}},dat_i};
hasFetchedDisp8 <= 1'b1;
end
/rtl/verilog/LODS.v
0,0 → 1,87
//=============================================================================
// LODS
// Fetch string data from memory.
//
//
// 2009,2010 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
//
LODS:
if (w && (si==16'hFFFF) && !df) begin
ir <= `NOP;
int_num <= 8'd13;
state <= INT1;
end
else begin
cyc_type <= `CT_RDMEM;
lock_o <= w;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= {seg_reg,`SEG_SHIFT} + si;
state <= LODS_NACK;
end
LODS_NACK:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= w;
cyc_o <= w;
stb_o <= 1'b0;
if (df) begin
si <= si_dec;
if (w)
b[15:8] <= dat_i;
else begin
b[ 7:0] <= dat_i;
b[15:8] <= {8{dat_i[7]}};
end
end
else begin
si <= si_inc;
b[ 7:0] <= dat_i;
b[15:8] <= {8{dat_i[7]}};
end
state <= w ? LODS1 : EXECUTE;
end
 
LODS1:
begin
cyc_type <= `CT_RDMEM;
stb_o <= 1'b1;
adr_o <= {seg_reg,`SEG_SHIFT} + si;
state <= LODS1_NACK;
end
LODS1_NACK:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
if (df) begin
si <= si_dec;
b[7:0] <= dat_i;
end
else begin
si <= si_inc;
b[15:8] <= dat_i;
end
state <= EXECUTE;
end
 
/rtl/verilog/EXECUTE.v
0,0 → 1,404
// ============================================================================
// (C) 2009,2010,2012 Robert Finch
// robfinch<remove>@opencores.org
//
// EXECUTE
// - execute instruction
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// ============================================================================
//
EXECUTE:
begin
casex(ir)
 
`EXTOP:
casex(ir2)
`LxDT: state <= FETCH_DESC;
endcase
 
`DAA:
begin
state <= IFETCH;
end
 
`ALU_I2R8,`ALU_I2R16,`ADD,`ADD_ALI8,`ADD_AXI16,`ADC,`ADC_ALI8,`ADC_AXI16:
begin
state <= IFETCH;
wrregs <= 1'b1;
res <= alu_o;
pf <= pres;
af <= carry (1'b0,a[3],b[3],alu_o[3]);
cf <= carry (1'b0,amsb,bmsb,resn);
vf <= overflow(1'b0,amsb,bmsb,resn);
sf <= resn;
zf <= resz;
end
 
`AND,`OR,`XOR,`AND_ALI8,`OR_ALI8,`XOR_ALI8,`AND_AXI16,`OR_AXI16,`XOR_AXI16:
begin
state <= IFETCH;
wrregs <= 1'b1;
res <= alu_o;
pf <= pres;
cf <= 1'b0;
vf <= 1'b0;
sf <= resn;
zf <= resz;
end
 
`TEST:
begin
state <= IFETCH;
res <= alu_o;
pf <= pres;
cf <= 1'b0;
vf <= 1'b0;
sf <= resn;
zf <= resz;
end
 
`CMP,`CMP_ALI8,`CMP_AXI16:
begin
state <= IFETCH;
pf <= pres;
af <= carry (1'b1,a[3],b[3],alu_o[3]);
cf <= carry (1'b1,amsb,bmsb,resn);
vf <= overflow(1'b1,amsb,bmsb,resn);
sf <= resn;
zf <= resz;
end
 
`SBB,`SUB,`SBB_ALI8,`SUB_ALI8,`SBB_AXI16,`SUB_AXI16:
begin
wrregs <= 1'b1;
state <= IFETCH;
res <= alu_o;
pf <= pres;
af <= carry (1'b1,a[3],b[3],alu_o[3]);
cf <= carry (1'b1,amsb,bmsb,resn);
vf <= overflow(1'b1,amsb,bmsb,resn);
sf <= resn;
zf <= resz;
end
 
8'hF6,8'hF7:
begin
wrregs <= 1'b1;
state <= IFETCH;
case(rrr)
3'd2: res <= ~b; // NOT
3'd3: res <= -b; // NEG
endcase
end
`INC_REG:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b1;
res <= alu_o;
pf <= pres;
af <= carry (1'b0,a[3],b[3],alu_o[3]);
vf <= overflow(1'b0,a[15],b[15],resnw);
sf <= resnw;
zf <= reszw;
end
`DEC_REG:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b1;
res <= alu_o;
pf <= pres;
af <= carry (1'b1,a[3],b[3],alu_o[3]);
vf <= overflow(1'b1,a[15],b[15],resnw);
sf <= resnw;
zf <= reszw;
end
`IMUL:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd0;
res <= alu_o;
if (w) begin
cf <= wp[31:16]!={16{resnw}};
vf <= wp[31:16]!={16{resnw}};
dx <= wp[31:16];
end
else begin
cf <= ah!={8{resnb}};
vf <= ah!={8{resnb}};
end
end
 
 
//-----------------------------------------------------------------
// Memory Operations
//-----------------------------------------------------------------
// registers not allowed on LEA
// invalid opcode
//
`LEA:
begin
w <= 1'b1;
res <= ea;
if (mod==2'b11) begin
int_num <= 8'h06;
state <= INT;
end
else begin
state <= IFETCH;
wrregs <= 1'b1;
end
end
`LDS:
begin
wrsregs <= 1'b1;
res <= alu_o;
rrr <= 3'd3;
state <= IFETCH;
end
`LES:
begin
wrsregs <= 1'b1;
res <= alu_o;
rrr <= 3'd0;
state <= IFETCH;
end
 
`MOV_RR8,`MOV_RR16,
`MOV_MR,
`MOV_M2AL,`MOV_M2AX,
`MOV_I2AL,`MOV_I2DL,`MOV_I2CL,`MOV_I2BL,`MOV_I2AH,`MOV_I2DH,`MOV_I2CH,`MOV_I2BH,
`MOV_I2AX,`MOV_I2DX,`MOV_I2CX,`MOV_I2BX,`MOV_I2SP,`MOV_I2BP,`MOV_I2SI,`MOV_I2DI:
begin
state <= IFETCH;
wrregs <= 1'b1;
res <= alu_o;
end
`XCHG_MEM:
begin
wrregs <= 1'b1;
if (mod==2'b11) rrr <= rm;
res <= alu_o;
b <= rrro;
state <= mod==2'b11 ? IFETCH : XCHG_MEM;
end
`MOV_I8M,`MOV_I16M:
begin
res <= alu_o;
state <= rrr==3'd0 ? STORE_DATA : INVALID_OPCODE;
end
 
`MOV_S2R:
begin
w <= 1'b1;
rrr <= rm;
res <= b;
if (mod==2'b11) begin
state <= IFETCH;
wrregs <= 1'b1;
end
else
state <= STORE_DATA;
end
`MOV_R2S:
begin
wrsregs <= 1'b1;
res <= alu_o;
state <= IFETCH;
end
 
`LODSB:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b0;
rrr <= 3'd0;
res <= a[7:0];
if ( df) si <= si_dec;
if (!df) si <= si_inc;
end
`LODSW:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd0;
res <= a;
if ( df) si <= si - 16'd2;
if (!df) si <= si + 16'd2;
end
 
8'hD0,8'hD1,8'hD2,8'hD3,8'hC0,8'hC1:
begin
state <= IFETCH;
wrregs <= 1'b1;
if (w)
case(rrr)
3'b000: // ROL
begin
res <= {b[14:0],b[15]};
cf <= bmsb;
vf <= bmsb^b[14];
end
3'b001: // ROR
begin
res <= {b[0],b[15:1]};
cf <= b[0];
vf <= cf^b[15];
end
3'b010: // RCL
begin
res <= {b[14:0],cf};
cf <= b[15];
vf <= b[15]^b[14];
end
3'b011: // RCR
begin
res <= {cf,b[15:1]};
cf <= b[0];
vf <= cf^b[15];
end
3'b100: // SHL
begin
res <= {b[14:0],1'b0};
cf <= b[15];
vf <= b[15]^b[14];
end
3'b101: // SHR
begin
res <= {1'b0,b[15:1]};
cf <= b[0];
vf <= b[15];
end
3'b111: // SAR
begin
res <= {b[15],b[15:1]};
cf <= b[0];
vf <= 1'b0;
end
endcase
else
case(rrr)
3'b000: // ROL
begin
res <= {b[6:0],b[7]};
cf <= b[7];
vf <= b[7]^b[6];
end
3'b001: // ROR
begin
res <= {b[0],b[7:1]};
cf <= b[0];
vf <= cf^b[7];
end
3'b010: // RCL
begin
res <= {b[6:0],cf};
cf <= b[7];
vf <= b[7]^b[6];
end
3'b011: // RCR
begin
res <= {cf,b[7:1]};
cf <= b[0];
vf <= cf^b[7];
end
3'b100: // SHL
begin
res <= {b[6:0],1'b0};
cf <= b[7];
vf <= b[7]^b[6];
end
3'b101: // SHR
begin
res <= {1'b0,b[7:1]};
cf <= b[0];
vf <= b[7];
end
3'b111: // SAR
begin
res <= {b[7],b[7:1]};
cf <= b[0];
vf <= 1'b0;
end
endcase
end
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
`GRPFF:
begin
case(rrr)
3'b000: // INC
begin
state <= IFETCH;
wrregs <= 1'b1;
af <= carry (1'b0,a[3],b[3],alu_o[3]);
vf <= overflow(1'b0,a[15],b[15],alu_o[15]);
w <= 1'b1;
res <= alu_o;
rrr <= rm;
pf <= pres;
sf <= resnw;
zf <= reszw;
end
3'b001: // DEC
begin
state <= IFETCH;
wrregs <= 1'b1;
af <= carry (1'b1,a[3],b[3],alu_o[3]);
vf <= overflow(1'b1,a[15],b[15],alu_o[15]);
w <= 1'b1;
res <= alu_o;
rrr <= rm;
pf <= pres;
sf <= resnw;
zf <= reszw;
end
3'b010: begin sp <= sp_dec; state <= CALL_IN; end
// These two should not be reachable here, as they would
// be trapped by the EACALC.
3'b011: state <= CALL_FIN; // CALL FAR indirect
3'b101: // JMP FAR indirect
begin
ip <= offset;
cs <= selector;
state <= IFETCH;
end
3'b110: begin sp <= sp_dec; state <= PUSH; end
default:
begin
af <= carry (1'b0,a[3],b[3],alu_o[3]);
vf <= overflow(1'b0,a[15],b[15],alu_o[15]);
end
endcase
end
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
default:
state <= IFETCH;
endcase
end
 
/rtl/verilog/FETCH_OFFSET_AND_SEGMENT.v
0,0 → 1,85
// ============================================================================
// FETCH_OFFSET_AND_SEGMENT.v
// - Fetch 16 bit offset
// - Fetch 16 bit segment
//
//
// 2009,2010,2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// ============================================================================
//
//
FETCH_OFFSET:
begin
lock_o <= 1'b1;
`INITIATE_CODE_READ
state <= FETCH_OFFSET1;
end
FETCH_OFFSET1:
if (ack_i) begin
`PAUSE_CODE_READ
offset[7:0] <= dat_i;
state <= FETCH_OFFSET2;
end
FETCH_OFFSET2:
begin
`CONTINUE_CODE_READ
state <= FETCH_OFFSET3;
end
FETCH_OFFSET3:
if (ack_i) begin
`TERMINATE_CODE_READ
offset[15:8] <= dat_i;
state <= FETCH_SEGMENT;
end
FETCH_SEGMENT:
begin
`INITIATE_CODE_READ
state <= FETCH_SEGMENT1;
end
FETCH_SEGMENT1:
if (ack_i) begin
`PAUSE_CODE_READ
state <= FETCH_SEGMENT2;
selector[7:0] <= dat_i;
end
FETCH_SEGMENT2:
begin
`CONTINUE_CODE_READ
state <= FETCH_SEGMENT3;
end
FETCH_SEGMENT3:
if (ack_i) begin
`TERMINATE_CODE_READ
selector[15:8] <= dat_i;
if (ir==`CALLF)
state <= CALLF;
else
state <= JMPF;
end
JMPF:
begin
cs <= selector;
ip <= offset;
state <= IFETCH;
end
 
/rtl/verilog/IRET.v
0,0 → 1,110
// ============================================================================
// IRET
// - return from interrupt
//
//
// 2009-2012 Robert Finch
// robfinch@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//
// Verilog
//
// IRET: return from interrupt
// Fetch cs:ip from stack
// pop ip
// pop cs
// pop flags
// ============================================================================
//
IRET1:
begin
`INITIATE_STACK_POP
state <= IRET2;
end
IRET2:
if (ack_i) begin
`PAUSE_STACK_POP
ip[7:0] <= dat_i;
state <= IRET3;
end
IRET3:
begin
`CONTINUE_STACK_POP
state <= IRET4;
end
IRET4:
if (ack_i) begin
`PAUSE_STACK_POP
ip[15:8] <= dat_i;
state <= IRET5;
end
IRET5:
begin
`CONTINUE_STACK_POP
state <= IRET6;
end
IRET6:
if (ack_i) begin
`PAUSE_STACK_POP
cs[7:0] <= dat_i;
state <= IRET7;
end
IRET7:
begin
`CONTINUE_STACK_POP
state <= IRET8;
end
IRET8:
if (ack_i) begin
`PAUSE_STACK_POP
cs[15:8] <= dat_i;
state <= IRET9;
end
IRET9:
begin
`CONTINUE_STACK_POP
state <= IRET10;
end
IRET10:
if (ack_i) begin
`PAUSE_STACK_POP
cf <= dat_i[0];
pf <= dat_i[2];
af <= dat_i[4];
zf <= dat_i[6];
sf <= dat_i[7];
state <= IRET11;
end
IRET11:
begin
`CONTINUE_STACK_POP
state <= IRET12;
end
IRET12:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
sp <= sp_inc;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
tf <= dat_i[0];
ie <= dat_i[1];
df <= dat_i[2];
vf <= dat_i[3];
state <= IFETCH;
end
/rtl/verilog/CMPSB.v
0,0 → 1,86
//=============================================================================
// CMPSB
//
//
// 2009-2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//=============================================================================
//
CMPSB:
`include "check_for_ints.v"
else begin
cyc_type <= `CT_RDMEM;
lock_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= {seg_reg,`SEG_SHIFT} + si;
state <= CMPSB1;
end
CMPSB1:
if (ack_i) begin
state <= CMPSB2;
`TERMINATE_CYCLE
lock_o <= 1'b0;
a[ 7:0] <= dat_i[7:0];
a[15:8] <= {8{dat_i[7]}};
end
CMPSB2:
begin
state <= CMPSB3;
cyc_type <= `CT_RDMEM;
lock_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= esdi;
end
CMPSB3:
if (ack_i) begin
state <= CMPSB4;
`TERMINATE_CYCLE
lock_o <= 1'b0;
b[ 7:0] <= dat_i[7:0];
b[15:8] <= {8{dat_i[7]}};
end
CMPSB4:
begin
pf <= pres;
zf <= reszb;
sf <= resnb;
af <= carry (1'b1,a[3],b[3],alu_o[3]);
cf <= carry (1'b1,a[7],b[7],alu_o[7]);
vf <= overflow(1'b1,a[7],b[7],alu_o[7]);
if (df) begin
si <= si_dec;
di <= di_dec;
end
else begin
si <= si_inc;
di <= di_inc;
end
if ((repz & !cxz & zf) | (repnz & !cxz & !zf)) begin
cx <= cx_dec;
state <= CMPSB;
end
else
state <= IFETCH;
end
 
/rtl/verilog/MOV_I2BYTREG.v
0,0 → 1,35
// ============================================================================
// MOV_I2BYTREG.v
//
//
// 2009,2010,2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
MOV_I2BYTREG:
if (ack_i) begin
`TERMINATE_CODE_READ
w <= 1'b0; // select byte size
rrr <= ir[2:0];
res <= {8'h00,dat_i};
wrregs <= 1'b1;
state <= IFETCH;
end
/rtl/verilog/inb.v
0,0 → 1,61
// ============================================================================
// INB.v
// - Fetch data from IO.
//
//
// 2009,2010,2012 Robert Finch
// robfinch<remove>@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
INB:
begin
`INITIATE_CODE_READ
state <= INB1;
end
INB1:
if (ack_i) begin
`TERMINATE_CODE_READ
ea <= {12'h00,dat_i};
state <= INB2;
end
INB2:
begin
cyc_type <= `CT_RDIO;
mio_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= ea;
state <= INB3;
end
INB3:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
mio_o <= 1'b1;
cyc_o <= 1'b0;
stb_o <= 1'b0;
res[7:0] <= dat_i;
w <= 1'b0;
rrr <= 3'd0;
wrregs <= 1'b1;
state <= IFETCH;
end
 
/rtl/verilog/RETPOP.v
0,0 → 1,66
// ============================================================================
// 2009-2012 Robert Finch
// Stratford
//
// RETPOP
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// RETPOP: near return from subroutine and pop stack items
// Fetch ip from stack
// ============================================================================
//
RETPOP:
begin
state <= RETPOP_NACK;
cyc_type <= `CT_RDMEM;
lock_o <= 1'b1;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= sssp;
end
RETPOP_NACK:
if (ack_i) begin
state <= RETPOP1;
cyc_type <= `CT_PASSIVE;
sp <= sp_inc;
stb_o <= 1'b0;
ip[7:0] <= dat_i;
end
RETPOP1:
begin
state <= RETPOP1_NACK;
cyc_type <= `CT_RDMEM;
stb_o <= 1'b1;
adr_o <= sssp;
end
RETPOP1_NACK:
if (ack_i) begin
state <= IFETCH;
cyc_type <= `CT_PASSIVE;
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd4;
res <= sp_inc + data16;
// sp <= sp_inc + data16;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
ip[15:8] <= dat_i;
end
/rtl/verilog/WRITE_BACK.v
0,0 → 1,54
//=============================================================================
// 2009,2010,2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
// WRITE_BACK state
// - update the register file
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
//
if (wrregs)
case({w,rrr})
4'b0000: ax[7:0] <= res[7:0];
4'b0001: cx[7:0] <= res[7:0];
4'b0010: dx[7:0] <= res[7:0];
4'b0011: bx[7:0] <= res[7:0];
4'b0100: ax[15:8] <= res[7:0];
4'b0101: cx[15:8] <= res[7:0];
4'b0110: dx[15:8] <= res[7:0];
4'b0111: bx[15:8] <= res[7:0];
4'b1000: ax <= res;
4'b1001: cx <= res;
4'b1010: dx <= res;
4'b1011: bx <= res;
4'b1100: sp <= res;
4'b1101: bp <= res;
4'b1110: si <= res;
4'b1111: di <= res;
endcase
 
// Write to segment register
//
if (wrsregs)
case(rrr)
3'd0: es <= res;
3'd1: cs <= res;
3'd2: ss <= res;
3'd3: ds <= res;
default: ;
endcase
/rtl/verilog/CALL.v
0,0 → 1,50
//=============================================================================
// CALL NEAR
//
//
// 2009-2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//=============================================================================
//
CALL:
begin
`INITIATE_STACK_WRITE
lock_o <= 1'b1;
dat_o <= ip[15:8];
state <= CALL1;
end
CALL1:
if (ack_i) begin
state <= CALL2;
`PAUSE_STACK_WRITE
end
CALL2:
begin
state <= CALL3;
`INITIATE_STACK_WRITE
dat_o <= ip[7:0];
end
CALL3:
if (ack_i) begin
`TERMINATE_CYCLE
lock_o <= 1'b0;
ip <= ip + disp16;
state <= IFETCH;
end
/rtl/verilog/NMI_DETECTOR.v
0,0 → 1,58
// ============================================================================
// 2009,2010 Robert Finch
// rplaskitti[remove]@birdcomputer.ca
// Stratford
//
//
// Detect an edge on nmi.
//
//
// This source code is available for evaluation and validation purposes
// only. This copyright statement and disclaimer must remain present in
// the file.
//
// NO WARRANTY.
// THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER
// EXPRESS OR IMPLIED. The user must assume the entire risk of using the
// Work.
//
// IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
// INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO
// THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR.
//
// IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK
// IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN
// REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN
// LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU
// AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR
// LOSSES RELATING TO SUCH UNAUTHORIZED USE.
//
//
// Verilog
//
// ============================================================================
//
module nmi_detector(RESET, CLK, nmi_i, rst_nmi, pe_nmi);
input RESET;
input CLK;
input nmi_i;
input rst_nmi; // reset the nmi flag
output pe_nmi;
reg pe_nmi;
 
reg prev_nmi; // records previous nmi state
 
always @(posedge CLK)
if (RESET) begin
prev_nmi <= 1'b0;
pe_nmi <= 1'b0;
end
else begin
prev_nmi <= nmi_i;
if (nmi_i & !prev_nmi)
pe_nmi <= 1'b1;
else if (rst_nmi)
pe_nmi <= 1'b0;
end
 
endmodule
/rtl/verilog/WB8088_BRIDGE.v
0,0 → 1,167
// ============================================================================
// 8088 to WISHBONE bus bridge
//
//
// 2009 Robert T Finch
// robfinch<remove>@opencores.org
//
//
// This source code is available for evaluation and validation purposes
// only. This copyright statement and disclaimer must remain present in
// the file.
//
// NO WARRANTY.
// THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER
// EXPRESS OR IMPLIED. The user must assume the entire risk of using the
// Work.
//
// IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
// INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO
// THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR.
//
// IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK
// IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN
// REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN
// LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU
// AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR
// LOSSES RELATING TO SUCH UNAUTHORIZED USE.
//
//
// Verilog
//
// Connects an internal WISHBONE bus to the regular 8088 bus.
// If there is a hold acknowledge, a number of line have to be tri-stated.
//
// Slice 16 / LUTs 30 / FF's 5 / 307.977 MHz
// ============================================================================
//
`ifndef CT_INTA
`include "cycle_types.v"
`endif
 
module wb8088_bridge(
rst_i, clk_i,
nmi_i, irq_i, busy_i, inta_o,
stb_o, ack_i, we_o, adr_o, dat_i, dat_o,
ie, cyc_type, S43,
RESET, CLK, NMI, INTR, INTA_n, ALE, DEN_n, DT_R, IO_M, RD_n, WR_n, READY, A, AD, SSO,
TEST_n, HOLD, HLDA
);
parameter T0 = 3'd0;
parameter T1 = 3'd1;
parameter T2 = 3'd2;
parameter T3 = 3'd3;
parameter T4 = 3'd4;
 
output rst_i;
output clk_i;
output nmi_i;
output irq_i;
output busy_i;
input inta_o;
input stb_o;
output ack_i;
input we_o;
input [19:0] adr_o;
input [7:0] dat_o;
output [7:0] dat_i;
 
input ie;
input [2:0] cyc_type;
input [1:0] S43;
 
input RESET;
input CLK;
input NMI;
input INTR;
output INTA_n;
output ALE;
output DEN_n;
output DT_R;
output IO_M;
output RD_n;
output WR_n;
input READY;
output [19:8] A;
tri [19:8] A;
inout [7:0] AD;
tri [7:0] AD;
output SSO;
input TEST_n;
input HOLD;
output HLDA;
 
reg HLDA;
reg [2:0] Tcyc; // "T" cycle
wire IsT1 = Tcyc==T1;
wire IsT2 = Tcyc==T2;
wire IsT3 = Tcyc==T3;
wire IsT4 = Tcyc==T4;
wire IsT23 = (Tcyc==T2) || (Tcyc==T3);
 
assign rst_i = RESET;
assign clk_i = CLK;
assign irq_i = INTR;
assign nmi_i = NMI;
assign busy_i = TEST_n;
// Will not get to T4 unless READY is active
assign ack_i = IsT3 & READY;
assign ALE = IsT1 && !CLK; // high pulse during clock low
assign RD_n = HLDA ? 1'bz : !(stb_o && !we_o && IsT23);
assign WR_n = HLDA ? 1'bz : !(stb_o && we_o && IsT23);
assign INTA_n = !(inta_o & IsT23);
assign dat_i = AD[7:0];
 
assign AD[7:0] = HLDA ? 8'bz : IsT1 ? (inta_o ? 8'bz : adr_o[7:0]) : // address cycle
(we_o ? dat_o : 8'bz); // data cycle
assign A[15:8] = (HLDA | inta_o) ? 8'bz : adr_o[15:8];
assign A[19:16] = HLDA ? 4'bz : IsT1 ? adr_o[19:16] : {1'b0,ie,S43};
 
assign DEN_n = HLDA ? 1'bz : !(we_o ? IsT23 || (IsT4 && !CLK) :
(CLK && IsT2) || IsT3 || (IsT4 && !CLK));
assign DT_R = HLDA ? 1'bz : we_o;
assign IO_M = cyc_type==`CT_RDIO || cyc_type==`CT_WRIO || cyc_type==`CT_HALT || cyc_type==`CT_INTA;
assign SSO = cyc_type==`CT_RDIO || cyc_type==`CT_HALT || cyc_type==`CT_RDMEM || cyc_type==`CT_PASSIVE;
 
// T State generator
// Tcyc:
// - bus cycle state machine
// The machine sits in state T0 until a bus request is present, then transitions to state T1.
// The machine sits in state T1 if there is a HOLD present
// State T2 always moves to state T3
// The machine sits in state T3 until the bus transfer is acknowledged
// State T4 waits for the WISHBONE bus to acknowledge bus cycle completion.
 
always @(negedge CLK)
if (RESET)
Tcyc <= T4;
else begin
case(Tcyc)
T0: if (stb_o) Tcyc <= T1; // If there is a request for a bus cycle
T1: Tcyc <= HOLD ? T1 : T2; // HOLD in the T1 state
T2: Tcyc <= T3; // always move to next
T3: if (READY) Tcyc <= T4; // wait for READY signal
T4: if (!stb_o) Tcyc <= T0; // wait for end of bus cycle
default: Tcyc <= T4;
endcase
end
 
// HOLD generator
// - drive HLDA low as soon as HOLD goes low
// - drive HLDA active if there is a HOLD during T1 or T4
//
always @(negedge CLK)
if (RESET)
HLDA <= 1'b0;
else begin
if (HOLD) begin
if (Tcyc==T1) HLDA <= 1'b1;
if (Tcyc==T4) HLDA <= 1'b1;
end
else
HLDA <= 1'b0;
end
 
endmodule
 
/rtl/verilog/check_for_ints.v
0,0 → 1,25
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Check for interrupts during string instructions.
//
if (pe_nmi & checkForInts) begin
rst_nmi <= 1'b1;
int_num <= 8'h02;
ir <= `NOP;
state <= INT2;
end
else if (irq_i & ie & checkForInts) begin
ir <= `NOP;
state <= INTA0;
end
/rtl/verilog/SCASW.v
0,0 → 1,97
// ============================================================================
// SCASW
//
//
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
SCASW:
`include "check_for_ints.v"
else if (w && (di==16'hFFFF) && !df) begin
ir <= `NOP;
int_num <= 8'd13;
state <= INT1;
end
else if ((repz|repnz) & cxz)
state <= IFETCH;
else begin
if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
lock_o <= 1'b1;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= esdi;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
state <= SCASW1;
stb_o <= 1'b0;
a <= ax;
if (df) begin
b[15:8] <= dat_i;
di <= di_dec;
end
else begin
b[7:0] <= dat_i;
di <= di_inc;
end
end
end
SCASW1:
if (!stb_o) begin
cyc_type <= `CT_RDMEM;
stb_o <= 1'b1;
adr_o <= esdi;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
state <= SCASW2;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
a <= ax;
if (df) begin
b <= dat_i;
di <= di_dec;
end
else begin
b[15:8] <= dat_i;
di <= di_inc;
end
end
SCASW2:
begin
pf <= pres;
af <= carry (1'b0,a[3],b[3],alu_o[3]);
cf <= carry (1'b0,a[15],b[15],alu_o[15]);
vf <= overflow(1'b0,a[15],b[15],alu_o[15]);
sf <= resnw;
zf <= reszw;
if (repz|repnz)
cx <= cx_dec;
if ((repz & reszw) | (repnz & !reszw))
state <= SCASW;
else
state <= IFETCH;
end
/rtl/verilog/bootrom.v
0,0 → 1,229
module bootrom(cyc, stb, adr, o, acko);
input cyc;
input stb;
input [19:0] adr;
output [7:0] o;
reg [7:0] o;
output acko;
 
wire cs = cyc && stb && adr[19:12]==8'hFF;
assign acko = cs;
 
reg [7:0] mem [256:2047];
integer i;
 
initial begin
$readmemh("c:\\emu8086\\MyBuild\\test1.hex", mem);
for (i = 256; i < 264; i = i + 1)
$display("%h:%h ", i, mem[i]);
 
// mem[0] = 8'hb8; // MOV AX,0
// mem[1] = 8'h00;
// mem[2] = 8'h00;
//
// // Move to segment register
// mem[3] = 8'h8e; // MOV DS,AX
// mem[4] = 8'hd8;
// mem[5] = 8'h8e; // MOV SS,AX
// mem[6] = 8'hd0;
//
// // Move immediate to register
// mem[7] = 8'hbb; // MOV BX,128
// mem[8] = 8'h80;
// mem[9] = 8'h00;
// mem[10] = 8'hbe; // MOV SI,1
// mem[11] = 8'h01;
// mem[12] = 8'h00;
// mem[13] = 8'hbf; // MOV DI,2
// mem[14] = 8'h02;
// mem[15] = 8'h00;
// mem[16] = 8'hbd; // MOV BP,768
// mem[17] = 8'h00;
// mem[18] = 8'h03;
//
// // Displacement is zero
// mem[19] = 8'hc6; // MOV [BX+SI],1
// mem[20] = 8'h00;
// mem[21] = 8'h01;
// mem[22] = 8'hc6; // MOV [BX+DI],2
// mem[23] = 8'h01;
// mem[24] = 8'h02;
// mem[25] = 8'hc6; // MOV [BP+SI],3
// mem[26] = 8'h02;
// mem[27] = 8'h03;
// mem[28] = 8'hc6; // MOV [BP+DI],4
// mem[29] = 8'h03;
// mem[30] = 8'h04;
// mem[31] = 8'hc6; // MOV [SI],5
// mem[32] = 8'h04;
// mem[33] = 8'h05;
// mem[34] = 8'hc6; // MOV [DI],6
// mem[35] = 8'h05;
// mem[36] = 8'h06;
// mem[37] = 8'hc6; // MOV 0400,7
// mem[38] = 8'h06;
// mem[39] = 8'h07;
// mem[40] = 8'h00;
// mem[41] = 8'h04;
// mem[42] = 8'hc6; // MOV [BX],8
// mem[43] = 8'h07;
// mem[44] = 8'h08;
//
// // Displacement is a single byte
// mem[45] = 8'hc6; // MOV [BX+SI+10],1
// mem[46] = 8'h40;
// mem[47] = 8'h0A;
// mem[48] = 8'h01;
// mem[49] = 8'hc6; // MOV [BX+DI+10],2
// mem[50] = 8'h41;
// mem[51] = 8'h0A;
// mem[52] = 8'h02;
// mem[53] = 8'hc6; // MOV [BP+SI+10],3
// mem[54] = 8'h42;
// mem[55] = 8'h0A;
// mem[56] = 8'h03;
// mem[57] = 8'hc6; // MOV [BP+DI+10],4
// mem[58] = 8'h43;
// mem[59] = 8'h0A;
// mem[60] = 8'h04;
// mem[61] = 8'hc6; // MOV [SI+10],5
// mem[62] = 8'h44;
// mem[63] = 8'h0A;
// mem[64] = 8'h05;
// mem[65] = 8'hc6; // MOV [DI+10],6
// mem[66] = 8'h45;
// mem[67] = 8'h0A;
// mem[68] = 8'h06;
// mem[69] = 8'hc6; // MOV [BP+10],7
// mem[70] = 8'h46;
// mem[71] = 8'h0A;
// mem[72] = 8'h07;
// mem[73] = 8'hc6; // MOV [BX+10],8
// mem[74] = 8'h47;
// mem[75] = 8'h0A;
// mem[76] = 8'h08;
//
// // Displacement is a two bytes
// mem[77] = 8'hc6; // MOV [BX+SI+1034],1
// mem[78] = 8'h80;
// mem[79] = 8'h0A;
// mem[80] = 8'h04;
// mem[81] = 8'h01;
// mem[82] = 8'hc6; // MOV [BX+DI+1034],2
// mem[83] = 8'h81;
// mem[84] = 8'h0A;
// mem[85] = 8'h04;
// mem[86] = 8'h02;
// mem[87] = 8'hc6; // MOV [BP+SI+1034],3
// mem[88] = 8'h82;
// mem[89] = 8'h0A;
// mem[90] = 8'h04;
// mem[91] = 8'h03;
// mem[92] = 8'hc6; // MOV [BP+DI+1034],4
// mem[93] = 8'h83;
// mem[94] = 8'h0A;
// mem[95] = 8'h04;
// mem[96] = 8'h04;
// mem[97] = 8'hc6; // MOV [SI+1034],5
// mem[98] = 8'h84;
// mem[99] = 8'h0A;
// mem[100] = 8'h04;
// mem[101] = 8'h05;
// mem[102] = 8'hc6; // MOV [DI+1034],6
// mem[103] = 8'h85;
// mem[104] = 8'h0A;
// mem[105] = 8'h04;
// mem[106] = 8'h06;
// mem[107] = 8'hc6; // MOV [BP+1034],7
// mem[108] = 8'h86;
// mem[109] = 8'h0A;
// mem[110] = 8'h04;
// mem[111] = 8'h07;
// mem[112] = 8'hc6; // MOV [BX+1034],8
// mem[113] = 8'h87;
// mem[114] = 8'h0A;
// mem[115] = 8'h04;
// mem[116] = 8'h08;
//
// mem[117] = 8'h90; // NOP
// mem[118] = 8'h90;
// mem[119] = 8'h90;
//
// mem[120] = 8'hb8; // MOV AX,1
// mem[121] = 8'h01;
// mem[122] = 8'h00;
// mem[123] = 8'hbb; // MOV BX,2
// mem[124] = 8'h02;
// mem[125] = 8'h00;
// mem[126] = 8'hb9; // MOV CX,3
// mem[127] = 8'h03;
// mem[128] = 8'h00;
// mem[129] = 8'hba; // MOV DX,4
// mem[130] = 8'h04;
// mem[131] = 8'h00;
// mem[132] = 8'hbc; // MOV SP,128
// mem[133] = 8'h80;
// mem[134] = 8'h00;
// mem[135] = 8'hbd; // MOV BP,6
// mem[136] = 8'h06;
// mem[137] = 8'h00;
// mem[138] = 8'hbe; // MOV SI,7
// mem[139] = 8'h07;
// mem[140] = 8'h00;
// mem[141] = 8'hbf; // MOV DI,8
// mem[142] = 8'h08;
// mem[143] = 8'h00;
// mem[144] = 8'h50; // PUSH AX
// mem[145] = 8'h51; // PUSH CX
// mem[146] = 8'h52; // PUSH DX
// mem[147] = 8'h53; // PUSH BX
// mem[148] = 8'h54; // PUSH SP
// mem[149] = 8'h55; // PUSH BP
// mem[150] = 8'h56; // PUSH SI
// mem[151] = 8'h57; // PUSH DI
// mem[152] = 8'h06; // PUSH ES
// mem[153] = 8'h0e; // PUSH CS
// mem[154] = 8'h16; // PUSH SS
// mem[155] = 8'h1e; // PUSH DS
// mem[156] = 8'h9c; // PUSHF
// mem[157] = 8'h90;
// mem[158] = 8'h90;
// mem[159] = 8'h90;
// mem[160] = 8'hFF; // PUSH 040B
// mem[161] = 8'h36;
// mem[162] = 8'h0B;
// mem[163] = 8'h04;
// mem[164] = 8'h90; // NOP
// mem[165] = 8'h8F; // POP 040B
// mem[166] = 8'h06;
// mem[167] = 8'h0B;
// mem[168] = 8'h04;
// mem[169] = 8'h9D; // POPF
// mem[170] = 8'h1F; // POP DS
// mem[171] = 8'h17; // POP SS
// mem[172] = 8'h0F; // POP CS
// mem[173] = 8'h07; // POP ES
// mem[174] = 8'h5f; // POP DI
// mem[175] = 8'h5e; // POP SI
// mem[176] = 8'h5d; // POP BP
// mem[177] = 8'h5d; // POP BP
// mem[178] = 8'h5b; // POP BX
// mem[179] = 8'h5a; // POP DX
// mem[180] = 8'h59; // POP CX
// mem[181] = 8'h58; // POP AX
//
mem[2032] = 8'hea; // JMP FAR FF00:0100
mem[2033] = 8'h00;
mem[2034] = 8'h01;
mem[2035] = 8'h00;
mem[2036] = 8'hFF;
end
 
always @(adr or cs)
if (cs)
o <= mem[adr[10:0]];
else
o <= 8'h00;
 
endmodule
 
/rtl/verilog/CALLF.v
0,0 → 1,76
//=============================================================================
// CALL FAR and CALL FAR indirect
//
//
// 2009-2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//=============================================================================
//
CALLF:
begin
`INITIATE_STACK_WRITE
lock_o <= 1'b1;
dat_o <= cs[15:8];
state <= CALLF1;
end
CALLF1:
if (ack_i) begin
`PAUSE_STACK_WRITE
state <= CALLF2;
end
CALLF2:
begin
`INITIATE_STACK_WRITE
dat_o <= cs[7:0];
state <= CALLF3;
end
CALLF3:
if (ack_i) begin
`PAUSE_STACK_WRITE
state <= CALLF4;
end
CALLF4:
begin
`INITIATE_STACK_WRITE
dat_o <= ip[15:8];
state <= CALLF5;
end
CALLF5:
if (ack_i) begin
`PAUSE_STACK_WRITE
state <= CALLF6;
end
CALLF6:
begin
`INITIATE_STACK_WRITE
dat_o <= ip[7:0];
state <= CALLF7;
end
CALLF7:
if (ack_i) begin
`TERMINATE_CYCLE
if (ir==8'hFF && rrr==3'b011) // CALL FAR indirect
state <= JUMP_VECTOR1;
else begin
cs <= selector;
ip <= offset;
state <= IFETCH;
end
end
/rtl/verilog/DECODE.v
0,0 → 1,291
// ============================================================================
// DECODE
// - decode / dispatch instruction
//
//
// (C) 2009-2012 Robert Finch
// Stratford
// robfinch[remove]@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// Decode / dispatch instruction
// ============================================================================
//
DECODE:
casex(ir)
`MORE1: state <= XI_FETCH;
`MORE2: state <= XI_FETCH;
`EXTOP: state <= XI_FETCH;
 
`DEC_REG,`INC_REG:
begin
w <= 1'b1;
rrr <= ir[2:0];
state <= EXECUTE;
end
 
`LEA: state <= EXECUTE;
 
//-----------------------------------------------------------------
// Immediate Loads
//-----------------------------------------------------------------
`MOV_I2AL,`MOV_I2DL,`MOV_I2CL,`MOV_I2BL,`MOV_I2AH,`MOV_I2DH,`MOV_I2CH,`MOV_I2BH:
begin
`INITIATE_CODE_READ
state <= MOV_I2BYTREG;
end
 
`MOV_I2AX,`MOV_I2DX,`MOV_I2CX,`MOV_I2BX,`MOV_I2SP,`MOV_I2BP,`MOV_I2SI,`MOV_I2DI:
begin
w <= 1'b1;
rrr <= ir[2:0];
if (ip==16'hFFFF) begin
int_num <= 8'h0d;
state <= INT2;
end
else
state <= FETCH_IMM16;
end
`XLAT:
if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
adr_o <= {seg_reg,`SEG_SHIFT} + bx + al;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
res <= dat_i;
wrregs <= 1'b1;
w <= 1'b0;
rrr <= 3'd0;
state <= IFETCH;
end
 
//-----------------------------------------------------------------
// Arithmetic Operations
//-----------------------------------------------------------------
`AAA,`AAS:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd0;
res <= alu_o;
af <= (al[3:0]>4'h9 || af);
cf <= (al[3:0]>4'h9 || af);
end
`ADD_ALI8,`ADC_ALI8,`SUB_ALI8,`SBB_ALI8,`AND_ALI8,`OR_ALI8,`XOR_ALI8,`CMP_ALI8:
begin
w <= 1'b0;
a <= {{8{al[7]}},al};
rrr <= 3'd0;
state <= FETCH_IMM8;
end
`ADD_AXI16,`ADC_AXI16,`SUB_AXI16,`SBB_AXI16,`AND_AXI16,`OR_AXI16,`XOR_AXI16,`CMP_AXI16:
begin
w <= 1'b1;
a <= ax;
rrr <= 3'd0;
if (ip==16'hFFFF) begin
int_num <= 8'h0d;
state <= INT2;
end
else
state <= FETCH_IMM16;
end
`ALU_I2R8:
begin
state <= FETCH_IMM8;
a <= rrro;
end
`ALU_I2R16:
begin
state <= FETCH_IMM16;
a <= rrro;
end
`XCHG_AXR:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b1;
rrr <= ir[2:0];
res <= ax;
case(ir[2:0])
3'd0: ax <= ax;
3'd1: ax <= cx;
3'd2: ax <= dx;
3'd3: ax <= bx;
3'd4: ax <= sp;
3'd5: ax <= bp;
3'd6: ax <= si;
3'd7: ax <= di;
endcase
end
`CBW: begin ax[15:8] <= {8{ax[7]}}; state <= IFETCH; end
`CWD:
begin
state <= IFETCH;
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd2;
res <= {16{ax[15]}};
end
 
//-----------------------------------------------------------------
// String Operations
//-----------------------------------------------------------------
`LODSB: state <= LODS;
`LODSW: state <= LODS;
`STOSB: state <= STOS;
`STOSW: state <= STOS;
`MOVSB: state <= MOVS;
`MOVSW: state <= MOVS;
`CMPSB: state <= CMPSB;
`CMPSW: state <= CMPSW;
`SCASB: state <= SCASB;
`SCASW: state <= SCASW;
 
//-----------------------------------------------------------------
// Stack Operations
//-----------------------------------------------------------------
`PUSH_REG: begin sp <= sp_dec; state <= PUSH; end
`PUSH_DS: begin sp <= sp_dec; state <= PUSH; end
`PUSH_ES: begin sp <= sp_dec; state <= PUSH; end
`PUSH_SS: begin sp <= sp_dec; state <= PUSH; end
`PUSH_CS: begin sp <= sp_dec; state <= PUSH; end
`PUSHF: begin sp <= sp_dec; state <= PUSH; end
`POP_REG: state <= POP;
`POP_DS: state <= POP;
`POP_ES: state <= POP;
`POP_SS: state <= POP;
`POPF: state <= POP;
 
//-----------------------------------------------------------------
// Flow controls
//-----------------------------------------------------------------
`NOP: state <= IFETCH;
`HLT: if (pe_nmi | (irq_i & ie)) state <= IFETCH;
`WAI: if (!busy_i) state <= IFETCH;
`LOOP: begin cx <= cx_dec; state <= BRANCH1; end
`LOOPZ: begin cx <= cx_dec; state <= BRANCH1; end
`LOOPNZ: begin cx <= cx_dec; state <= BRANCH1; end
`Jcc: state <= BRANCH1;
`JCXZ: state <= BRANCH1;
`JMPS: state <= BRANCH1;
`JMPF: state <= FETCH_OFFSET;
`CALL: begin sp <= sp_dec; state <= FETCH_DISP16; end
`CALLF: begin sp <= sp_dec; state <= FETCH_OFFSET; end
`RET: state <= RETPOP; // data16 is zero
`RETPOP: state <= FETCH_STK_ADJ1;
`RETF: state <= RETFPOP; // data16 is zero
`RETFPOP: state <= FETCH_STK_ADJ1;
`IRET: state <= IRET1;
`INT: state <= INT;
`INT3: begin int_num <= 8'd3; state <= INT2; end
`INTO:
if (vf) begin
int_num <= 8'd4;
state <= INT2;
end
else
state <= IFETCH;
 
//-----------------------------------------------------------------
// Flag register operations
//-----------------------------------------------------------------
`STI: begin ie <= 1'b1; state <= IFETCH; end
`CLI: begin ie <= 1'b0; state <= IFETCH; end
`STD: begin df <= 1'b1; state <= IFETCH; end
`CLD: begin df <= 1'b0; state <= IFETCH; end
`STC: begin cf <= 1'b1; state <= IFETCH; end
`CLC: begin cf <= 1'b0; state <= IFETCH; end
`CMC: begin cf <= !cf; state <= IFETCH; end
`LAHF:
begin
ax[15] <= sf;
ax[14] <= zf;
ax[12] <= af;
ax[10] <= pf;
ax[8] <= cf;
state <= IFETCH;
end
`SAHF:
begin
sf <= ah[7];
zf <= ah[6];
af <= ah[4];
pf <= ah[2];
cf <= ah[0];
state <= IFETCH;
end
 
//-----------------------------------------------------------------
// IO instructions
// - fetch port number, then vector
//-----------------------------------------------------------------
`INB: state <= INB;
`INW: state <= INW;
`OUTB: state <= OUTB;
`OUTW: state <= OUTW;
`INB_DX: begin ea <= {`SEG_SHIFT,dx}; state <= INB1; end
`INW_DX: begin ea <= {`SEG_SHIFT,dx}; state <= INW1; end
`OUTB_DX: begin ea <= {`SEG_SHIFT,dx}; state <= OUTB1; end
`OUTW_DX: begin ea <= {`SEG_SHIFT,dx}; state <= OUTW1; end
`INSB: state <= INSB;
`OUTSB: state <= OUTSB;
`OUTSW: state <= OUTSW;
 
//-----------------------------------------------------------------
// Control Prefix
//-----------------------------------------------------------------
`LOCK: begin lock_insn <= ir; state <= IFETCH; end
`REPZ,`REPNZ,`CS,`DS,`ES,`SS: state <= IFETCH;
 
//-----------------------------------------------------------------
// disp16 instructions
//-----------------------------------------------------------------
`MOV_M2AL,`MOV_M2AX,`MOV_AL2M,`MOV_AX2M,`CALL,`JMP:
begin
`INITIATE_CODE_READ
state <= FETCH_DISP16_ACK;
end
 
default:
begin
//-----------------------------------------------------------------
// MOD/RM instructions
//-----------------------------------------------------------------
$display("Fetching mod/rm");
if (ir==`MOV_R2S || ir==`MOV_S2R)
w <= 1'b1;
if (ir==`LDS || ir==`LES)
w <= 1'b1;
if (fetch_modrm) begin
`INITIATE_CODE_READ
state <= EACALC;
end
else
state <= IFETCH;
end
endcase
/rtl/verilog/DECODER2.v
0,0 → 1,75
// ============================================================================
// DECODER2.v
// - Extended opcode decoder
//
//
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// ============================================================================
//
//
DECODER2:
begin
state <= IFETCH;
case(ir)
`MORE1:
casex(ir2)
`AAM:
begin
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd0;
res <= alu_o;
sf <= 1'b0;
zf <= reszb;
pf <= pres;
end
default: ;
endcase
`MORE2:
casex(ir2)
`AAD:
begin
wrregs <= 1'b1;
w <= 1'b1;
rrr <= 3'd0;
res <= alu_o;
sf <= 1'b0;
zf <= reszw;
pf <= pres;
end
default: ;
endcase
`EXTOP:
casex(ir2)
`LxDT:
begin
w <= 1'b1;
`INITIATE_CODE_READ
state <= EACALC; // override state transition
end
default: ;
endcase
default: ;
endcase
end
 
/rtl/verilog/STOS.v
0,0 → 1,88
//=============================================================================
// STOSB,STOSW
// Store string data to memory.
//
//
// 2009-2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
//
STOS:
`include "check_for_ints.v"
else if (w && (di==16'hFFFF)) begin
ir <= `NOP;
int_num <= 8'd13;
state <= INT1;
end
else if (repdone)
state <= IFETCH;
else begin
if (!cyc_o) begin
cyc_type <= `CT_WRMEM;
lock_o <= w;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= esdi;
dat_o <= (w & df) ? ah : al;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
if (repz|repnz) begin
state <= w ? STOS1 : STOS;
cx <= cx_dec;
end
else
state <= w ? STOS1 : IFETCH;
lock_o <= w;
cyc_o <= w;
stb_o <= 1'b0;
we_o <= 1'b0;
if (df)
di <= di_dec;
else
di <= di_inc;
end
end
STOS1:
begin
cyc_type <= `CT_WRMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= esdi;
dat_o <= df ? al : ah;
state <= STOS2;
end
STOS2:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
if (repz|repnz)
state <= STOS;
else
state <= IFETCH;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
if (df)
di <= di_dec;
else
di <= di_inc;
end
/rtl/verilog/WRITE_SEG.v
0,0 → 1,40
//=============================================================================
// 2009,2010 Robert Finch
// Stratford
// eq<remove>@birdcomputer.ca
//
// WRITE_SEG state
// - update the segment register
//
//
// NO WARRANTY.
// THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER
// EXPRESS OR IMPLIED. The user must assume the entire risk of using the
// Work.
//
// IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
// INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO
// THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR.
//
// IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK
// IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN
// REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN
// LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU
// AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR
// LOSSES RELATING TO SUCH UNAUTHORIZED USE.
//
//=============================================================================
//
// Write to segment register
//
WRITE_SEG:
begin
state <= IFETCH;
case(rrr)
3'd0: es <= res;
3'd1: cs <= res;
3'd2: ss <= res;
3'd3: ds <= res;
default: ;
endcase
end
/rtl/verilog/CMPSW.v
0,0 → 1,131
//=============================================================================
// CMPSW
//
//
// 2009,2010 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
//=============================================================================
//
CMPSW:
`include "check_for_ints.v"
else begin
cyc_type <= `CT_RDMEM;
lock_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= {seg_reg,4'b0} + si;
state <= CMPSW1;
end
CMPSW1:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
if (df) begin
si <= si_dec;
a[15:8] <= dat_i;
end
else begin
si <= si_inc;
a[ 7:0] <= dat_i;
end
state <= CMPSW2;
end
CMPSW2:
if (!stb_o) begin
cyc_type <= `CT_RDMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= {seg_reg,4'b0} + si;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
if (df) begin
si <= si_dec;
a[7:0] <= dat_i;
end
else begin
si <= si_inc;
a[15:8] <= dat_i;
end
state <= CMPSW3;
end
CMPSW3:
if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
adr_o <= esdi;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
if (df) begin
di <= di_dec;
b[15:8] <= dat_i;
end
else begin
di <= di_inc;
b[ 7:0] <= dat_i;
end
state <= CMPSW4;
end
CMPSW4:
if (!stb_o) begin
cyc_type <= `CT_RDMEM;
lock_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= esdi;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
if (df) begin
di <= di_dec;
b[7:0] <= dat_i;
end
else begin
di <= di_inc;
b[15:8] <= dat_i;
end
state <= CMPSW5;
end
CMPSW5:
begin
pf <= pres;
zf <= reszw;
sf <= resnw;
af <= carry (1'b1,a[3],b[3],alu_o[3]);
cf <= carry (1'b1,a[15],b[15],alu_o[15]);
vf <= overflow(1'b1,a[15],b[15],alu_o[15]);
if ((repz & !cxz & zf) | (repnz & !cxz & !zf)) begin
cx <= cx_dec;
state <= CMPSW;
end
else
state <= IFETCH;
end
 
/rtl/verilog/INTA.v
0,0 → 1,63
//=============================================================================
// INTA: acknowledge interrupt
//
//
// 2009,2010,2012 Robert Finch
// Stratford
// robfinch<remove>opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// - issue two interrupt acknowledge cycles
// - one the second cycle load the interrupt number
//=============================================================================
//
INTA0:
begin
cyc_type <= `CT_INTA;
inta_o <= 1'b1;
mio_o <= 1'b0;
lock_o <= 1'b1;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
state <= INTA1;
end
INTA1:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
mio_o <= 1'b1;
stb_o <= 1'b0;
state <= INTA2;
end
INTA2:
begin
cyc_type <= `CT_INTA;
mio_o <= 1'b0;
stb_o <= 1'b1;
state <= INTA3;
end
INTA3:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
inta_o <= 1'b0;
mio_o <= 1'b1;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
int_num <= dat_i;
state <= INT1;
end
/rtl/verilog/OUTSB.v
0,0 → 1,51
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
OUTSB:
`include "check_for_ints.v"
else if (repdone)
state <= IFETCH;
else if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
adr_o <= dssi;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
res[7:0] <= dat_i;
state <= OUTSB2;
end
OUTSB2:
if (!cyc_o) begin
cyc_type <= `CT_WRIO;
cyc_o <= 1'b1;
stb_o <= 1'b1;
adr_o <= {`SEG_SHIFT,dx};
dat_o <= res[7:0];
we_o <= 1'b1;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
if (df)
si <= si - 16'd1;
else
si <= si + 16'd1;
if (repz|repnz) cx <= cx_dec;
state <= repz|repnz ? OUTSB : IFETCH;
end
/rtl/verilog/JUMP_VECTOR.v
0,0 → 1,88
// ============================================================================
// JUMP_VECTOR
// - fetch 32 bit vector into selector:offset and jump to it
//
//
// 2009,2010,2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Verilog
//
// ============================================================================
//
JUMP_VECTOR1:
begin
lock_o <= 1'b1;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= ea; // ea set by EACALC
state <= JUMP_VECTOR2;
end
JUMP_VECTOR2:
if (ack_i) begin
ea <= ea_inc;
offset[7:0] <= dat_i;
stb_o <= 1'b0;
state <= JUMP_VECTOR3;
end
JUMP_VECTOR3:
begin
stb_o <= 1'b1;
adr_o <= ea;
state <= JUMP_VECTOR4;
end
JUMP_VECTOR4:
if (ack_i) begin
ea <= ea_inc;
stb_o <= 1'b0;
offset[15:8] <= dat_i;
state <= JUMP_VECTOR5;
end
JUMP_VECTOR5:
begin
stb_o <= 1'b1;
adr_o <= ea;
state <= JUMP_VECTOR6;
end
JUMP_VECTOR6:
if (ack_i) begin
ea <= ea_inc;
selector[7:0] <= dat_i;
stb_o <= 1'b0;
state <= JUMP_VECTOR7;
end
JUMP_VECTOR7:
begin
stb_o <= 1'b1;
adr_o <= ea;
state <= JUMP_VECTOR8;
end
JUMP_VECTOR8:
if (ack_i) begin
cyc_o <= 1'b0;
stb_o <= 1'b0;
selector[15:8] <= dat_i;
state <= JUMP_VECTOR9;
end
JUMP_VECTOR9:
begin
ip <= offset;
cs <= selector;
state <= IFETCH;
end
/rtl/verilog/CONTROL_LOGIC.v
0,0 → 1,211
// ============================================================================
// CONTROL_LOGIC
// - assorted control logic
//
//
// (C) 2009,2010 Robert Finch
// robfinch[remove]@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// ============================================================================
//
wire [15:0] sp_dec = sp - 16'd1;
wire [15:0] sp_inc = sp + 16'd1;
wire [15:0] ip_inc = ip + 16'd1;
wire [15:0] ip_dec = ip - 16'd1;
wire [15:0] cx_dec = cx - 16'd1;
wire [15:0] si_dec = si - 16'd1;
wire [15:0] di_dec = di - 16'd1;
wire [15:0] si_inc = si + 16'd1;
wire [15:0] di_inc = di + 16'd1;
wire [15:0] sp_dec2 = sp - 16'd2;
wire [15:0] sp_inc2 = sp + 16'd2;
wire [15:0] ip_inc2 = ip + 16'd2;
wire [15:0] ip_dec2 = ip - 16'd2;
wire [19:0] ea_inc = ea + 20'd1;
wire [19:0] ea_inc2 = ea + 20'd2;
wire [19:0] adr_o_inc = adr_o + 20'd1;
wire [4:0] modrm = {mod,rm};
wire [15:0] offsdisp = offset + disp16;
 
wire checkForInts = (prefix1==8'h00) && (prefix2==8'h00);
wire doCmp = ir==8'h38 || ir==8'h39 || ir==8'h3A || ir==8'h3B || ir==8'h3C || ir==8'h3D;
 
 
// Detect when to fetch the mod-r/m byte
//
wire fetch_modrm =
ir==8'h00 || ir==8'h01 || ir==8'h02 || ir==8'h03 || // ADD
ir==8'h08 || ir==8'h09 || ir==8'h0A || ir==8'h0B || // OR
ir==8'h10 || ir==8'h11 || ir==8'h12 || ir==8'h13 || // ADC
ir==8'h18 || ir==8'h19 || ir==8'h1A || ir==8'h1B || // SBB
ir==8'h20 || ir==8'h21 || ir==8'h22 || ir==8'h23 || // AND
ir==8'h28 || ir==8'h29 || ir==8'h2A || ir==8'h2B || // SUB
ir==8'h30 || ir==8'h31 || ir==8'h32 || ir==8'h33 || // XOR
ir==8'h38 || ir==8'h39 || ir==8'h3A || ir==8'h3B || // CMP
ir==8'h3C || ir==8'h3D || // CMP
ir==8'h62 || // BOUND
ir==8'h63 || // ARPL
ir==8'h69 || ir==8'h6B || // IMUL
ir[7:4]==4'h8 ||
(ir[7]==1'b0 && ir[6]==1'b0 && ir[2]==1'b0) || // arithmetic
(ir==8'h0F && ir2[7:4]==4'hA && ir2[2:1]==2'b10) ||
ir==8'hC4 || ir==8'hC5 || // LES / LDS
ir==8'hC6 || ir==8'hC7 || // MOV I
ir==8'hC0 || ir==8'hC1 || // shift / rotate
ir==8'hD0 || ir==8'hD1 || ir==8'hD2 || ir==8'hD3 || // shift / rotate
ir==8'hF6 || ir==8'hF7 || // NOT / NEG / TEST / MUL / IMUL / DIV / IDIV
ir==8'hFE || ir==8'hFF // INC / DEC / CALL
;
 
// Detect when to fetch the mod-r/m byte during a two byte opcode
//
wire fetch_modrm2 =
ir2==8'h00 || // LLDT / LTR / STR / VERR / VERW
ir2==8'h01 || // INVLPG / LGDT / LIDT / LMSW / SGDT /
ir2==8'h02 || // LAR
ir2==8'h03 || // LSL
ir2[7:4]==4'h9 ||
ir2==8'hA4 || ir2==8'hAC || ir2==8'hA5 || ir2==8'hAD || // SHRD / SHLD
ir2==8'hAF || // IMUL
ir2==8'hB0 || ir2==8'hB1 || // CMPXCHG
ir2==8'hB2 || ir2==8'hB4 || ir2==8'hB5 || // LSS / LFS / LGS
ir2==8'hB6 || ir2==8'hB7 || ir2==8'hFE || ir2==8'hFF ||
ir2==8'hA3 || ir2==8'hBA || ir2==8'hBB || ir2==8'hBC || ir2==8'hBD ||
ir2==8'hC0 || ir2==8'hC1 // XADD
;
 
wire fetch_data =
ir==8'h8A || ir==8'h8B || // memory to register
ir==8'hA0 || ir==8'hA1 || // memory to accumulator
ir==8'h8E || // memory to segmenr register
(ir==8'h0f && (ir2==8'hB6 || ir2==8'hB7 || ir2==8'hBE || ir2==8'hBf)) || // memory to register - needs more resolving.
ir==`POP_AX ||
ir==`POP_DX ||
ir==`POP_CX ||
ir==`POP_BX ||
ir==`POP_SP ||
ir==`POP_BP ||
ir==`POP_SI ||
ir==`POP_DI ||
ir==8'h86 || ir==8'h87 || // exchange register with memory
ir==`LDS ||
ir==`LES ||
(ir==`EXTOP && (ir2==`LFS || ir2==`LGS || ir2==`LSS)) ||
ir==`POPF ||
 
fetch_modrm;
 
wire store_data =
(ir==8'h0F && ir2==8'h00 && rrr==3'd0 && mod!=2'b11) || // SLDT
(ir==8'h0F && ir2==8'h00 && rrr==3'd1 && mod!=2'b11) || // STR
(ir==8'h0F && ir2==8'h01 && rrr==3'd0 && mod!=2'b11) || // SGDT
(ir==8'h0F && ir2==8'h01 && rrr==3'd1 && mod!=2'b11) || // SIDT
(ir==8'h0F && ir2==8'h01 && rrr==3'd4 && mod!=2'b11) || // SMSW
(ir==8'h00 && mod!=2'b11) || // ADD b
(ir==8'h01 && mod!=2'b11) || // ADD w
(ir==8'h08 && mod!=2'b11) || // OR b
(ir==8'h09 && mod!=2'b11) || // OR w
(ir==8'h10 && mod!=2'b11) || // ADC b
(ir==8'h11 && mod!=2'b11) || // ADC w
(ir==8'h18 && mod!=2'b11) || // SBB b
(ir==8'h19 && mod!=2'b11) || // SBB w
(ir==8'h20 && mod!=2'b11) || // AND b
(ir==8'h21 && mod!=2'b11) || // AND w
(ir==8'h28 && mod!=2'b11) || // SUB b
(ir==8'h29 && mod!=2'b11) || // SUB w
(ir==8'h30 && mod!=2'b11) || // XOR b
(ir==8'h31 && mod!=2'b11) || // XOR w
(ir==8'h63 && mod!=2'b11) || // ARPL
(ir==8'hD0 && mod!=2'b11) || // byte shifts #1
(ir==8'hD1 && mod!=2'b11) || // word shifts #1
(ir==8'hD2 && mod!=2'b11) || // byte shifts CL
(ir==8'hD3 && mod!=2'b11) || // word shifts CL
(ir==8'hC0 && mod!=2'b11) || // byte shifts #n8
(ir==8'hC1 && mod!=2'b11) || // word shifts #n8
(hasFetchedModrm && (d==1'b0) && (mod!=2'b11)) ||
ir==8'hA2 || // MOV mem8,AL
ir==8'hA3 || // MOV mem16,AL
((ir==8'h86 || ir==8'h87) && (mod!=2'b11)) || // XCHG
((ir==8'h88 || ir==8'h89) && (mod!=2'b11)) || // MOV
((ir==8'h6B || ir==8'h69) && (mod!=2'b11)) || // IMUL
((ir==8'hC6 || ir==8'hC7) && rrr==3'd0 && (mod!=2'b11)) || // MOV mem,imm
( ir==8'h8C && rrr[2]==1'b0 && (mod!=2'b11)) || // MOV mem16,seg_reg
((ir==8'hF6 || ir==8'hF7) && rrr==3'd2 && (mod!=2'b11)) || // NOT
((ir==8'hF6 || ir==8'hF7) && rrr==3'd3 && (mod!=2'b11)) || // NEG
((ir==8'hF6 || ir==8'hF7) && rrr==3'd4 && (mod!=2'b11)) || // MUL
((ir==8'hF6 || ir==8'hF7) && rrr==3'd5 && (mod!=2'b11)) || // IMUL
((ir==8'hF6 || ir==8'hF7) && rrr==3'd6 && (mod!=2'b11)) || // DIV
((ir==8'hF6 || ir==8'hF7) && rrr==3'd7 && (mod!=2'b11)) || // IDIV
((ir==8'hFE || ir==8'hFF) && rrr==3'd0 && (mod!=2'b11)) || // INC
((ir==8'hFE || ir==8'hFF) && rrr==3'd1 && (mod!=2'b11)) || // DEC
((ir==8'h80 || ir==8'h81 || ir==8'h83) && (rrr!=3'b111) && (mod!=2'b11)) // compare excluded
;
 
wire bus_locked = prefix1==`LOCK || prefix2==`LOCK ||
((ir==8'h86||ir==8'h87) && mod!=2'b11)
;
 
wire is_prefix =
ir==`REPZ ||
ir==`REPNZ ||
ir==`LOCK ||
ir==`CS ||
ir==`DS ||
ir==`ES ||
ir==`SS
;
 
wire tgt_reg8 =
ir==8'h10 ||
ir==8'h12
;
 
/*
if (ir==8'h80 && mod==2'b11) tgt <= RM8; src <= IMM8;
if (ir==8'h81 && mod==2'b11) tgt <= RM16; src <= IMM16;
if (ir==8'h83 && mod==2'b11) tgt <= RM16; src <= IMM8;
if (ir==8'h80 && mod!=2'b11) tgt <= MEM8; src <= IMM8;
if (ir==8'h81 && mod!=2'b11) tgt <= MEM16; src <= IMM16;
if (ir==8'h83 && mod!=2'b11) tgt <= MEM16; src <= IMM8;
case(rrr)
3'b000: op <= `ADD;
3'b010: op <= `ADC;
3'b100: op <= `AND;
3'b111: op <= `CMP;
endcase
*/
 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wire lea = ir==`LEA;
 
wire hasPrefix = prefix1!=8'h00;
wire hasDoublePrefix = hasPrefix && prefix2!=8'h00;
wire repz = prefix1==`REPZ || prefix2==`REPZ;
wire repnz = prefix1==`REPNZ || prefix2==`REPNZ;
 
wire repdone =
((repz | repnz) & cxz) ||
(repz & !zf) ||
(repnz & zf)
;
 
/rtl/verilog/POP.v
0,0 → 1,92
// ============================================================================
// POP register from stack
//
//
// (C) 2009,2010 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// ============================================================================
//
POP:
begin
cyc_type <= `CT_RDMEM;
lock_o <= 1'b1;
cyc_o <= 1'b1;
stb_o <= 1'b1;
adr_o <= sssp;
w <= 1'b1;
rrr <= ir[2:0];
state <= POP1;
end
POP1:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
sp <= sp_inc;
res[7:0] <= dat_i;
case(ir)
`POP_SS: begin rrr <= 3'd2; end
`POP_ES: begin rrr <= 3'd0; end
`POP_DS: begin rrr <= 3'd3; end
`POPF:
begin
cf <= dat_i[0];
pf <= dat_i[2];
af <= dat_i[4];
zf <= dat_i[6];
sf <= dat_i[7];
end
default: ;
endcase
state <= POP2;
end
POP2:
begin
`CONTINUE_STACK_POP
state <= POP3;
end
POP3:
if (ack_i) begin
state <= IFETCH;
cyc_type <= `CT_PASSIVE;
lock_o <= 1'b0;
cyc_o <= 1'b0;
stb_o <= 1'b0;
sp <= sp_inc;
res[15:8] <= dat_i;
case(ir)
`POP_AX,`POP_CX,`POP_BX,`POP_DX,
`POP_SI,`POP_DI,`POP_BP,`POP_SP:
wrregs <= 1'b1;
`POP_SS,`POP_ES,`POP_DS:
wrsregs <= 1'b1;
`POPF:
begin
tf <= dat_i[0];
ie <= dat_i[1];
df <= dat_i[2];
vf <= dat_i[3];
end
`POP_MEM:
state <= STORE_DATA;
default: ;
endcase
end
/rtl/verilog/which_seg.v
0,0 → 1,150
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Determine segment register for memory access.
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
always @(modrm or prefix1 or prefix2 or cs or ds or es or ss or ir)
case(ir)
`SCASB: seg_reg <= es;
`SCASW: seg_reg <= es;
default:
case(prefix1)
`CS: seg_reg <= cs;
`DS: seg_reg <= ds;
`ES: seg_reg <= es;
`SS: seg_reg <= ss;
default:
case(prefix2)
`CS: seg_reg <= cs;
`DS: seg_reg <= ds;
`ES: seg_reg <= es;
`SS: seg_reg <= ss;
default:
casex(ir)
`CMPSB: seg_reg <= ds;
`CMPSW: seg_reg <= ds;
`LODSB: seg_reg <= ds;
`LODSW: seg_reg <= ds;
`MOVSB: seg_reg <= ds;
`MOVSW: seg_reg <= ds;
`STOSB: seg_reg <= ds;
`STOSW: seg_reg <= ds;
`MOV_AL2M: seg_reg <= ds;
`MOV_AX2M: seg_reg <= ds;
default:
case(modrm)
5'b00_000: seg_reg <= ds;
5'b00_001: seg_reg <= ds;
5'b00_010: seg_reg <= ss;
5'b00_011: seg_reg <= ss;
5'b00_100: seg_reg <= ds;
5'b00_101: seg_reg <= ds;
5'b00_110: seg_reg <= ds;
5'b00_111: seg_reg <= ds;
5'b01_000: seg_reg <= ds;
5'b01_001: seg_reg <= ds;
5'b01_010: seg_reg <= ss;
5'b01_011: seg_reg <= ss;
5'b01_100: seg_reg <= ds;
5'b01_101: seg_reg <= ds;
5'b01_110: seg_reg <= ss;
5'b01_111: seg_reg <= ds;
5'b10_000: seg_reg <= ds;
5'b10_001: seg_reg <= ds;
5'b10_010: seg_reg <= ss;
5'b10_011: seg_reg <= ss;
5'b10_100: seg_reg <= ds;
5'b10_101: seg_reg <= ds;
5'b10_110: seg_reg <= ss;
5'b10_111: seg_reg <= ds;
default: seg_reg <= ds;
endcase
endcase
endcase
endcase
endcase
always @(state or modrm or prefix1 or prefix2 or ir)
case(state)
IFETCH,XI_FETCH,DECODE,FETCH_IMM8,FETCH_IMM16,FETCH_DISP8:
S43 <= 2'b10; // code segment
PUSH,PUSH1,POP,POP1,
IRET,IRET1,IRET2,IRET3,IRET4,IRET5,
RETFPOP,RETFPOP1,RETFPOP2,RETFPOP3,
RETPOP,RETPOP1:
S43 <= 2'b01; // stack
default:
case(prefix1)
`CS: S43 <= 2'b10;
`DS: S43 <= 2'b11;
`ES: S43 <= 2'b00;
`SS: S43 <= 2'b01;
default:
case(prefix2)
`CS: S43 <= 2'b10;
`DS: S43 <= 2'b11;
`ES: S43 <= 2'b00;
`SS: S43 <= 2'b01;
default:
casex(ir)
`CMPSB: S43 <= 2'b11;
`CMPSW: S43 <= 2'b11;
`LODSB: S43 <= 2'b11;
`LODSW: S43 <= 2'b11;
`MOVSB: S43 <= 2'b11;
`MOVSW: S43 <= 2'b11;
`STOSB: S43 <= 2'b11;
`STOSW: S43 <= 2'b11;
`MOV_AL2M: S43 <= 2'b11;
`MOV_AX2M: S43 <= 2'b11;
default:
case(modrm)
5'b00_000: S43 <= 2'b11;
5'b00_001: S43 <= 2'b11;
5'b00_010: S43 <= 2'b01;
5'b00_011: S43 <= 2'b01;
5'b00_100: S43 <= 2'b11;
5'b00_101: S43 <= 2'b11;
5'b00_110: S43 <= 2'b11;
5'b00_111: S43 <= 2'b11;
5'b01_000: S43 <= 2'b11;
5'b01_001: S43 <= 2'b11;
5'b01_010: S43 <= 2'b01;
5'b01_011: S43 <= 2'b01;
5'b01_100: S43 <= 2'b11;
5'b01_101: S43 <= 2'b11;
5'b01_110: S43 <= 2'b01;
5'b01_111: S43 <= 2'b11;
5'b10_000: S43 <= 2'b11;
5'b10_001: S43 <= 2'b11;
5'b10_010: S43 <= 2'b01;
5'b10_011: S43 <= 2'b01;
5'b10_100: S43 <= 2'b11;
5'b10_101: S43 <= 2'b11;
5'b10_110: S43 <= 2'b01;
5'b10_111: S43 <= 2'b11;
default: S43 <= 2'b11;
endcase // modrm
endcase // ir
endcase // prefix2
endcase // prefix1
endcase // state
 
/rtl/verilog/CALL_IN.v
0,0 → 1,92
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// CALL NEAR Indirect
//
// 2009-2012 Robert Finch
// robfinch<remove>@opencores.org
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
CALL_IN:
if (!cyc_o) begin
cyc_type <= `CT_WRMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
dat_o <= ip[15:8];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
state <= CALL_IN1;
sp <= sp_dec;
stb_o <= 1'b0;
we_o <= 1'b0;
end
CALL_IN1:
if (!stb_o) begin
cyc_type <= `CT_WRMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= sssp;
dat_o <= ip[7:0];
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
ea <= {cs,`SEG_SHIFT}+b;
if (mod==2'b11) begin
ip <= b;
state <= IFETCH;
end
else
state <= CALL_IN2;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
end
CALL_IN2:
if (!cyc_o) begin
cyc_type <= `CT_RDMEM;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b0;
adr_o <= ea;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
stb_o <= 1'b0;
state <= CALL_IN3;
b[7:0] <= dat_i;
end
CALL_IN3:
if (!stb_o) begin
cyc_type <= `CT_RDMEM;
stb_o <= 1'b1;
adr_o <= ea_inc;
end
else if (ack_i) begin
cyc_type <= `CT_PASSIVE;
state <= CALL_IN4;
cyc_o <= 1'b0;
stb_o <= 1'b0;
b[15:8] <= dat_i;
end
CALL_IN4:
begin
state <= IFETCH;
ip <= b;
end
 
/rtl/verilog/IFETCH.v
0,0 → 1,117
//=============================================================================
// Fetch instruction
//
//
// (C) 2009,2010,2012 Robert Finch, Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// - All of the state control flags are reset.
//
// - If the current instruction is a prefix then we want to shift it
// into the prefix buffer before fetching the instruction. Also
// interrupts are blocked if the previous instruction is a prefix.
//
// - two bytes are fetched at once if the instruction is aligned on
// an even address. This saves a bus cycle most of the time.
//
// ToDo:
// - add an exception if more than two prefixes are present.
//
//=============================================================================
//
IFETCH:
begin
// Reset all instruction processing flags at instruction fetch
cyc_type <= `CT_PASSIVE;
mod <= 2'd0;
rrr <= 3'd0;
rm <= 3'd0;
sxi <= 1'b0;
hasFetchedModrm <= 1'b0;
hasFetchedDisp8 <= 1'b0;
hasFetchedDisp16 <= 1'b0;
hasFetchedVector <= 1'b0;
hasStoredData <= 1'b0;
hasFetchedData <= 1'b0;
data16 <= 16'h0000;
cnt <= 7'd0;
// if (prefix1!=8'h00 && prefix2 !=8'h00 && is_prefix)
// state <= TRIPLE_PREFIX;
if (is_prefix) begin
prefix1 <= ir;
prefix2 <= prefix1;
end
else begin
prefix1 <= 8'h00;
prefix2 <= 8'h00;
end
 
if (pe_nmi & checkForInts) begin
state <= INT2;
rst_nmi <= 1'b1;
int_num <= 8'h02;
ir <= `NOP;
end
else if (irq_i & ie & checkForInts) begin
state <= INTA0;
ir <= `NOP;
end
else if (ir==`HLT) begin
state <= IFETCH;
cyc_type <= `CT_HALT;
end
else begin
state <= IFETCH_ACK;
`INITIATE_CODE_READ
inta_o <= 1'b0;
mio_o <= 1'b1;
lock_o <= bus_locked;
end
end
 
IFETCH_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
ir <= dat_i;
$display("IR: %h",dat_i);
if (!hasPrefix)
ir_ip <= ip;
// ir_ip <= dat_i;
w <= dat_i[0];
d <= dat_i[1];
sxi <= dat_i[1];
sreg2 <= dat_i[4:3];
sreg3 <= {1'b0,dat_i[4:3]};
ir2 <= 8'h00;
state <= DECODE;
end
 
// Fetch extended opcode
//
XI_FETCH:
begin
`INITIATE_CODE_READ
state <= XI_FETCH_ACK;
end
 
XI_FETCH_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
ir2 <= dat_i;
state <= DECODER2;
end
/rtl/verilog/FETCH_IMMEDIATE.v
0,0 → 1,74
// ============================================================================
// FETCH_IMM16
// - fetch 16 bit immediate from instruction stream as operand 'B'
// FETCH_IMM8
// - Fetch 8 bit immediate as operand 'B'
//
//
// 2009-2012 Robert Finch
// robfinch[remove]@opencores.org
// Stratford
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// - bus is locked if immediate value is unaligned in memory
// - immediate values are the last operand to be fetched, hence
// the state machine can transition into the EXECUTE state.
// - we also know the immediate value can't be the target of an
// operation.
// ============================================================================
//
FETCH_IMM8:
begin
`INITIATE_CODE_READ
state <= FETCH_IMM8_ACK;
end
 
FETCH_IMM8_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
lock_o <= bus_locked;
b <= {{8{dat_i[7]}},dat_i};
state <= EXECUTE;
end
 
FETCH_IMM16:
begin
lock_o <= 1'b1;
`INITIATE_CODE_READ
state <= FETCH_IMM16_ACK;
end
FETCH_IMM16_ACK:
if (ack_i) begin
`PAUSE_CODE_READ
state <= FETCH_IMM16a;
b[ 7:0] <= dat_i;
end
FETCH_IMM16a:
begin
`CONTINUE_CODE_READ
state <= FETCH_IMM16a_ACK;
end
FETCH_IMM16a_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
lock_o <= bus_locked;
b[15:8] <= dat_i;
$display("Fetched #%h", {dat_i,b[7:0]});
state <= EXECUTE;
end
 
/rtl/verilog/EACALC.v
0,0 → 1,285
// ============================================================================
// EACALC
// - calculation of effective address
//
//
// (C) 2009-2012 Robert Finch, Stratford
// robfinch[remove]@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// Verilog
//
// - the effective address calculation may need to fetch an additional
// eight or sixteen bit displacement value in order to calculate the
// effective address.
// - the EA calc only needs to be done once as there is only ever a
// single memory operand address. Once the EA is calculated it is
// used for both the fetch and the store when memory is the target.
// ============================================================================
//
EACALC:
// Terminate an outstanding MODRM fetch cycle
if (cyc_o) begin
if (ack_i) begin
`TERMINATE_CODE_READ
mod <= dat_i[7:6];
rrr <= dat_i[5:3];
sreg3 <= dat_i[5:3];
TTT <= dat_i[5:3];
rm <= dat_i[2:0];
$display("Mod/RM=%b_%b_%b", dat_i[7:6],dat_i[5:3],dat_i[2:0]);
end
end
else begin
 
disp16 <= 16'h0000;
 
case(mod)
 
2'b00:
begin
state <= EACALC1;
// ToDo: error on stack state
case(rm)
3'd0: offset <= bx + si;
3'd1: offset <= bx + di;
3'd2: offset <= bp + si;
3'd3: offset <= bp + di;
3'd4: offset <= si;
3'd5: offset <= di;
3'd6: begin
state <= EACALC_DISP16;
offset <= 16'h0000;
end
3'd7: offset <= bx;
endcase
end
 
2'b01:
begin
state <= EACALC_DISP8;
case(rm)
3'd0: offset <= bx + si;
3'd1: offset <= bx + di;
3'd2: offset <= bp + si;
3'd3: offset <= bp + di;
3'd4: offset <= si;
3'd5: offset <= di;
3'd6: offset <= bp;
3'd7: offset <= bx;
endcase
end
 
2'b10:
begin
state <= EACALC_DISP16;
case(rm)
3'd0: offset <= bx + si;
3'd1: offset <= bx + di;
3'd2: offset <= bp + si;
3'd3: offset <= bp + di;
3'd4: offset <= si;
3'd5: offset <= di;
3'd6: offset <= bp;
3'd7: offset <= bx;
endcase
end
 
2'b11:
begin
state <= EXECUTE;
case(ir)
`MOV_I8M:
begin
rrr <= rm;
if (rrr==3'd0) state <= FETCH_IMM8;
end
`MOV_I16M:
begin
rrr <= rm;
if (rrr==3'd0) state <= FETCH_IMM16;
end
`MOV_S2R:
begin
a <= rfso;
b <= rfso;
end
`MOV_R2S:
begin
a <= rmo;
b <= rmo;
end
`POP_MEM:
begin
ir <= 8'h58|rm;
state <= POP;
end
`XCHG_MEM:
begin
wrregs <= 1'b1;
res <= rmo;
b <= rrro;
end
default:
begin
if (d) begin
a <= rmo;
b <= rrro;
end
else begin
a <= rrro;
b <= rmo;
end
end
endcase
hasFetchedData <= 1'b1;
end
endcase
end
 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Fetch 16 bit displacement
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
EACALC_DISP16:
begin
lock_o <= 1'b1;
`INITIATE_CODE_READ
state <= EACALC_DISP16_ACK;
end
EACALC_DISP16_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
disp16[7:0] <= dat_i;
state <= EACALC_DISP16a;
end
EACALC_DISP16a:
begin
`INITIATE_CODE_READ
state <= EACALC_DISP16a_ACK;
end
EACALC_DISP16a_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
lock_o <= bus_locked;
disp16[15:8] <= dat_i;
state <= EACALC1;
end
 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Fetch 8 bit displacement
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
EACALC_DISP8:
begin
`INITIATE_CODE_READ
state <= EACALC_DISP8_ACK;
end
EACALC_DISP8_ACK:
if (ack_i) begin
`TERMINATE_CODE_READ
disp16 <= {{8{dat_i[7]}},dat_i};
state <= EACALC1;
end
 
 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Add the displacement into the effective address
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
EACALC1:
begin
casex(ir)
`EXTOP:
casex(ir2)
8'h00:
begin
case(rrr)
3'b010: state <= FETCH_DESC; // LLDT
3'b011: state <= FETCH_DATA; // LTR
default: state <= FETCH_DATA;
endcase
if (w && (offsdisp==16'hFFFF)) begin
int_num <= 8'h0d;
state <= INT;
end
end
8'h01:
begin
case(rrr)
3'b010: state <= FETCH_DESC;
3'b011: state <= FETCH_DESC;
default: state <= FETCH_DATA;
endcase
if (w && (offsdisp==16'hFFFF)) begin
int_num <= 8'h0d;
state <= INT;
end
end
8'h03:
if (w && (offsdisp==16'hFFFF)) begin
int_num <= 8'h0d;
state <= INT;
end
else
state <= FETCH_DATA;
default:
if (w && (offsdisp==16'hFFFF)) begin
int_num <= 8'h0d;
state <= INT;
end
else
state <= FETCH_DATA;
endcase
`MOV_I8M: state <= FETCH_IMM8;
`MOV_I16M:
if (ip==16'hFFFF) begin
int_num <= 8'h0d;
state <= INT;
end
else
state <= FETCH_IMM16;
`POP_MEM:
begin
state <= POP;
end
`XCHG_MEM:
begin
// bus_locked <= 1'b1;
state <= FETCH_DATA;
end
default:
begin
if (w && (offsdisp==16'hFFFF)) begin
int_num <= 8'h0d;
state <= INT;
end
else
state <= FETCH_DATA;
if (ir==8'hff) begin
case(rrr)
3'b011: state <= CALLF; // CAll FAR indirect
3'b101: state <= JUMP_VECTOR1; // JMP FAR indirect
3'b110: begin d <= 1'b0; state <= FETCH_DATA; end// for a push
default: ;
endcase
end
end
endcase
// ea <= ea + disp16;
ea <= {seg_reg,`SEG_SHIFT} + offsdisp; // offsdisp = offset + disp16
end
/rtl/verilog/OUTB.v
0,0 → 1,56
//=============================================================================
// OUTB
// - output byte data to IO.
//
//
// 2009-2012 Robert Finch
// Stratford
// robfinch<remove>@opencores.org
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
//
OUTB: // Entry point for OUTB port,AL
begin
`INITIATE_CODE_READ
state <= OUTB_NACK;
end
OUTB_NACK:
if (ack_i) begin
`TERMINATE_CODE_READ
ea <= {12'h000,dat_i};
state <= OUTB1;
end
OUTB1: // Entry point for OUTB [DX],AL
begin
cyc_type <= `CT_WRIO;
mio_o <= 1'b0;
cyc_o <= 1'b1;
stb_o <= 1'b1;
we_o <= 1'b1;
adr_o <= ea;
dat_o <= al;
state <= OUTB1_NACK;
end
OUTB1_NACK:
if (ack_i) begin
cyc_type <= `CT_PASSIVE;
mio_o <= 1'b1;
cyc_o <= 1'b0;
stb_o <= 1'b0;
we_o <= 1'b0;
state <= IFETCH;
end

powered by: WebSVN 2.1.0

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