⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a86_idecoder.v

📁 使用CPLD仿真8088核,内有源程序和说明
💻 V
字号:
// http://gforge.openchip.org/projects/a86
//
//
//

`include "timescale.v"
`include "a86_defines.v"

module a86_idecoder(
  clk,empty,
  i0,i1,i2,i3,i4,i5,
  opcode,addrmode,
  data16,data16_hi,
  icode
);

input clk;
output empty;

input [7:0] i0;
input [7:0] i1;
input [7:0] i2;
input [7:0] i3;
input [7:0] i4;
input [7:0] i5;

output [7:0] opcode;
output [7:0] addrmode;
output [15:0] data16;
output [15:0] data16_hi;

 
output [`a86_icode_width-1:0] icode;
reg [`a86_icode_width-1:0] icode;


reg [7:0] opcode;
reg [7:0] addrmode;

reg [15:0] data16;
reg [15:0] data16_hi;


// route/mux opcode bytes

// opcode is 1st
always @ (i1) opcode = i1;
// addrmode is 2nd
always @ (i2) addrmode = i2;

// if 16:16 data is present hi word is {4,5} always
always @ (i4,i5) data16_hi  = {i5, i4};

// if 16 bit data is present it is 2,3 or 3,4 mux it here!
always @ (i1,i2,i3,i4)
  case (i1[1])
    1'b0: data16 = {i2,i3}; 
    default data16 = {i3,i4};
  endcase

// duplicate instruction over icode bus in case some module needs it directly!
always @ (i1,i2,i3,i4,i5) begin
  icode[`a86_icode_i_start+7:`a86_icode_i_start] = i1;
  icode[`a86_icode_i_start+15:`a86_icode_i_start+8] = i2;
  icode[`a86_icode_i_start+23:`a86_icode_i_start+16] = i3;
  icode[`a86_icode_i_start+31:`a86_icode_i_start+24] = i4;
  icode[`a86_icode_i_start+39:`a86_icode_i_start+32] = i5;
end


// (Micro) Instruction Decoder



// Magic is required here!
reg i0valid; 
always @ (i0) i0valid = 1; // dummmy goaway

reg i1valid; 
always @ (i1) i1valid = 1; // dummmy goaway


// single bit to hold LOCK prefix i(-1)
reg lock; 


reg x40;
reg x70;

reg B0;
reg E0;
reg F0;

always @ (i1) 
  if (i1[7:4] == 4'b0100) x40 = #1 1;
  else x40 = #1 0;

always @ (i1) 
  if (i1[7:4] == 4'b1011) B0 = #1 1;
  else B0 = #1 0;

always @ (i1) 
  if (i1[7:4] == 4'b1110) E0 = #1 1;
  else E0 = #1 0;

always @ (i1) 
  if (i1[7:4] == 4'b1111) F0 = #1 1;
  else F0 = #1 0;



// Decode Prefix if i0 is valid (i.e. Prefix present)
// if LOCK prefix, we should only store on bit "LOCK" and empty i0
//
always @ (i0,i0valid) begin

  // Segment override ?
  // CS 0010 1110
  // DS 0011 1110
  // ES 0010 0110
  // SS 0011 0110
  // xx 001X X110
  case ( {i0[7:5],i0[2:0]} )
    6'b001110: icode[`icode_seg_override] = i0valid;
    default icode[`icode_seg_override] = 0;
  endcase

  // REP
  // .. 1111 0010
  // .. 1111 0011
  // xx 1111 001X  
  case ( i0[7:1] )
    7'b1111001: icode[`icode_rep_prefix] = i0valid;
    default icode[`icode_rep_prefix] = 0;
  endcase

  
end

// Lock Prefix?
always @ (posedge clk) 
  if (i0 == 8'b11110000) lock <= i0valid;
  else lock <= 0;  

// rout it out
always @ (lock) 
  icode[`icode_lock_prefix] = lock;  
  





// Decode Instruction (done here partially?)

// 0111 xxxx Jcc
// 1110 00xx LOOP, JCXZ
// 1110 10xx JMP
// 1110 1011 JMP disp8
// 1110 1001 JMP disp16
// 1110 1010 JMP ptr16:16
// 1110 1000 CALL disp16


reg i_jr;

// Relative jumps and LOOP things
always @ (i1, E0) begin
  if ( (i1[7:4]==4'b0111)         // Jcc
     | (E0 & (i1[3:2]==2'b00))    // LOOP, JCXZ
     | (E0 & (i1[3:0]==4'b1011))  // JMP rel8
  ) i_jr = 1;
  else i_jr = 0;
end

always @ (i1,i_jr,i1valid) begin

  icode[`a86_icode_jr] = i_jr; 

  // ADSU

  // ADC 0001 00xx
  // ADC 1000 00xx xx01 0xxx
  // ADD 0000 00xx
  // ADD 1000 00xx xx00 0xxx
  // SBB 0001 10xx
  // SBB 1000 00xx xx01 1xxx
  // SUB 0010 10xx
  // SUB 1000 00xx xx10 1xxx
  // INC 0100 0xxx
  // INC 1111 111x xx00 0xxx
  // DEC 0100 1xxx
  // DEC 1111 111x xx00 10xxx
end


always @ (E0,i1,i_jr) begin
  if (E0 & (i1[3:2]==2'b00) & (i1[1:0] != 2'b11)) icode[`a86_icode_dec_cx] = 1;
  else icode[`a86_icode_dec_cx] = 0;
end

// INC DEC reg
always @ (x40)
  if ( x40 == 1) icode[`a86_icode_incdec] = 1;
  else icode[`a86_icode_incdec] = 0;


// direct write to PC
// EA
always @ (i1) begin
   // Load PC from immediate word!
   if ((i1[7:1] == 7'b1110101) ) icode[`a86_icode_ip_wr] = #1 1;
   else icode[`a86_icode_ip_wr] = #1 0;
end


// In or Out
//
// 1110 010w in im
// 1110 110w in r
// 1110 011w out im
// 1110 111w out r


always @ (i1, E0)
  if ( E0 & i1[2] ) icode[`a86_icode_inout] = #1 1;
  else icode[`a86_icode_inout] = #1 0;

always @ (i1, E0)
  if ( E0 & i1[2] & (i1[1]==0) ) icode[`a86_icode_in] = #1 1;
  else icode[`a86_icode_in] = #1 0;

always @ (i1, E0)
  if ( E0 & i1[2] & i1[1] ) icode[`a86_icode_out] = #1 1;
  else icode[`a86_icode_out] = #1 0;


reg i_aaa;
reg i_aad;
reg i_aam;
reg i_aas;
reg i_cbw;
reg i_cwd;
reg i_daa;
reg i_das;

reg i_1_byte;
reg i_2_byte;
reg i_3_byte;
reg i_4_byte;
reg i_5_byte;


reg alub_immed;
reg alub_immed_3b;

always @(i1) 
  if (i1[7:2] == 6'b100000) alub_immed = 1;
  else alub_immed = 0;

always @(alub_immed) 
  icode[`a86_icode_alub_immed] = alub_immed;


always @(i1,B0) 
  if (B0 | ((i1[7:6] == 2'b00) & (i1[2:1] == 2'b10)) ) alub_immed_3b = 1;
  else alub_immed_3b = 0;

always @(alub_immed_3b) 
  icode[`a86_icode_alub_immed_3b] = alub_immed_3b;


// one byte instruction ?
always @ (i_aaa,i_aas,i_cbw,i_cwd,i_daa,i_das,i1,icode)
  i_1_byte = i_aaa | i_aas | i_cbw | i_cwd | i_daa | i_das 
    | (icode[`a86_icode_inout] & i1[3]) 
    ;
always @(i_1_byte) #0 icode[`a86_icode_1_byte_instr] = i_1_byte;

always @(i_daa,i_das,i1,icode) begin
   i_2_byte = icode[`a86_icode_jr] 
     | ( i1[7:2] == 6'b111001 );
end
always @(i_2_byte) #0 icode[`a86_icode_2_byte_instr] = i_2_byte;

always @(alub_immed_3b) begin
   i_3_byte = alub_immed_3b;
end
always @(i_3_byte) #0 icode[`a86_icode_3_byte_instr] = i_3_byte;


always @(alub_immed) begin
   i_4_byte = alub_immed;
end
always @(i_4_byte) #0 icode[`a86_icode_4_byte_instr] = i_4_byte;


// Calc Instruction size!
reg [2:0] i_size;
always @(i_1_byte,i_2_byte,i_3_byte,i_4_byte) begin

  if (i_2_byte) i_size = #1 3'b010;
  else if (i_3_byte) i_size = #1 3'b011;
        else if (i_4_byte) i_size = #1 3'b100;
             else if (i_5_byte) i_size = #1 3'b101;
                  else i_size = #1 3'b001;

end

always @(i_size) 
  icode[`a86_icode_instr_size+2:`a86_icode_instr_size] = i_size[2:0];

// Write to REGs (AX, BX, CX, DX) 
/*

*/
reg wr_AX_BX_CX_BX;

always @(icode) begin
  // IN instruction! 
  // INC DEC register ?
//  wr_AX_BX_CX_BX = icode[`a86_icode_in] | icode[`a86_icode_incdec]; 

  icode[`a86_icode_iobus_we] = icode[`a86_icode_out] ;

  // for OUT commands pass register to IO
  icode[`a86_icode_alu_sela] = icode[`a86_icode_out];

  // for IN commands pass IO to register
  // also for MOV reg, immed!
  icode[`a86_icode_alu_selb] = icode[`a86_icode_in] | B0;

end

//always @(wr_AX_BX_CX_BX) icode[`a86_icode_wr_ax_bx_cx_dx] = wr_AX_BX_CX_BX;


reg [2:0] reg_sel2_i1_bits;   // select bits in i1
reg [2:0] reg_sel2_aux_bits;  // select bits in aux field
reg [2:0] reg_sel2_rm_bits;  // select bits in rm field
reg [2:0] reg_sel2_bits;

reg aux_in_use; // aux field is in use


// reg selector is in i1 (2:0) INC, DEC
always @(x40,B0, i1)
  if (x40 | B0) reg_sel2_i1_bits = i1[2:0];
  else reg_sel2_i1_bits = 3'b000;

// aux field?
always @(aux_in_use,i2)  
  if (aux_in_use) reg_sel2_aux_bits = 3'b000;
  else reg_sel2_aux_bits = 3'b000;

// immed 4 byte
always @(alub_immed,i2)  
  if (alub_immed) reg_sel2_rm_bits = i2[2:0];
  else reg_sel2_rm_bits = 3'b000;


always @(reg_sel2_i1_bits, reg_sel2_aux_bits,reg_sel2_rm_bits)  
  reg_sel2_bits = reg_sel2_i1_bits | reg_sel2_aux_bits | reg_sel2_rm_bits;

// sec operand select register
reg sel2_AX;
reg sel2_BX;
reg sel2_CX;
reg sel2_DX;
// sec operand write register
reg wr2_AX;
reg wr2_BX;
reg wr2_CX;
reg wr2_DX;

reg wr2reg;
always @(x40,alub_immed,alub_immed_3b)
  wr2reg = x40 | alub_immed | alub_immed_3b;

always @(reg_sel2_bits)
  if (reg_sel2_bits == 3'b000) sel2_AX = 1;
  else sel2_AX = 0;
always @(reg_sel2_bits)
  if (reg_sel2_bits == 3'b011) sel2_BX = 1;
  else sel2_BX = 0;
always @(reg_sel2_bits)
  if (reg_sel2_bits == 3'b001) sel2_CX = 1;
  else sel2_CX = 0;
always @(reg_sel2_bits)
  if (reg_sel2_bits == 3'b010) sel2_DX = 1;
  else sel2_DX = 0;

always @(wr2reg,sel2_AX)
  if (wr2reg == 1) wr2_AX = sel2_AX;
  else wr2_AX = 0;

always @(wr2reg,sel2_BX)
  if (wr2reg == 1) wr2_BX = sel2_BX;
  else wr2_BX = 0;

always @(wr2reg,sel2_CX,icode)
  if (wr2reg == 1) wr2_CX = sel2_CX;
  else wr2_CX = icode[`a86_icode_dec_cx];

always @(wr2reg,sel2_DX)
  if (wr2reg == 1) wr2_DX = sel2_DX;
  else wr2_DX = 0;



always @(sel2_AX,icode) 
  icode[`a86_icode_sel_ax] = sel2_AX | icode[`a86_icode_out];
always @(sel2_BX) 
  icode[`a86_icode_sel_bx] = sel2_BX;
always @(sel2_CX) 
  icode[`a86_icode_sel_cx] = sel2_CX;
always @(sel2_DX) 
  icode[`a86_icode_sel_dx] = sel2_DX;

always @(wr2_AX,icode) 
  icode[`a86_icode_wr_ax] = wr2_AX | icode[`a86_icode_in];
always @(wr2_BX) 
  icode[`a86_icode_wr_bx] = wr2_BX;
always @(wr2_CX) 
  icode[`a86_icode_wr_cx] = wr2_CX;
always @(wr2_DX) 
  icode[`a86_icode_wr_dx] = wr2_DX;

// Select ALU Op
reg [2:0] alu_sel_immed;
reg [2:0] alu_sel_norm;
reg [2:0] alu_sel;

always @(alub_immed,i1,i2)
  if (alub_immed) alu_sel_immed = i2[5:3]; // ALU op is in aux!
  else alu_sel_immed = 3'b000; 

always @(i1,i2)
  if ( i1[7:6] == 2'b00) alu_sel_norm = i1[5:3]; // ALU op is in aux!
  else alu_sel_norm = 3'b000; 

always @(alu_sel_immed,alu_sel_norm)
  alu_sel = alu_sel_immed | alu_sel_norm;


// select lines for ALU

always @(alu_sel)
  if (alu_sel == 3'b100) icode[`a86_icode_alu_and] = 1;
  else icode[`a86_icode_alu_and] = 0;

always @(alu_sel)
  if (alu_sel == 3'b001) icode[`a86_icode_alu_or] = 1;
  else icode[`a86_icode_alu_or] = 0;

always @(alu_sel)
  if (alu_sel == 3'b110) icode[`a86_icode_alu_xor] = 1;
  else icode[`a86_icode_alu_xor] = 0;



// immed operand as second?
/*
ALU OP

1000 00sw  mm AAA rrr data16 (4 byte)
00AA A0dw  mm reg r/m
00AA A10w  ax,data16 (3 byte)

010 ADC
000 ADD
111 CMP
101 SUB
011 SBB
100 AND
001 OR
110 XOR

*/






/*
`define	a86_icode_alu_adsu  33         // 
`define	a86_icode_alu_adsu_add  34     // 
`define	a86_icode_incdec  35           // 

`define	a86_icode_alu_and  37             // 
`define	a86_icode_alu_or  38              // 
`define	a86_icode_alu_xor  39             // 

`define	a86_icode_alu_sela 40             // 
`define	a86_icode_alu_selb 41             // 
*/




endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -