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 |