Compare commits
2 Commits
b00cd988cf
...
ba52ff89e6
Author | SHA1 | Date | |
---|---|---|---|
ba52ff89e6 | |||
59ec1b7a15 |
14
system/alu.v
14
system/alu.v
@ -26,7 +26,7 @@ wire signed [7:0]SIGNED_8B;
|
|||||||
assign SIGNED_B=B;
|
assign SIGNED_B=B;
|
||||||
assign SIGNED_8B=B[7:0];
|
assign SIGNED_8B=B[7:0];
|
||||||
|
|
||||||
assign FLAGS={(Wbit==1)?OUT[15:15]:OUT[7:7],(Wbit==1) ? (OUT[15:0]=='h0000) : (OUT[7:0]=='h00),5'b00000,C_FLAG};
|
assign FLAGS={(Wbit==1)?OUT[15:15]:OUT[7:7],(Wbit==1) ? (OUT[15:0]=='h0000) : (OUT[7:0]=='h00),5'b0,C_FLAG};
|
||||||
|
|
||||||
always @ ( * ) begin
|
always @ ( * ) begin
|
||||||
if(Wbit==1)begin
|
if(Wbit==1)begin
|
||||||
@ -35,9 +35,9 @@ always @ ( * ) begin
|
|||||||
`ALU_OP_ADD_SIGNED_B: {C_FLAG,OUT}=A+SIGNED_B;
|
`ALU_OP_ADD_SIGNED_B: {C_FLAG,OUT}=A+SIGNED_B;
|
||||||
`ALU_OP_SUB: {C_FLAG,OUT}=A-B;
|
`ALU_OP_SUB: {C_FLAG,OUT}=A-B;
|
||||||
`ALU_OP_SUB_REVERSE: {C_FLAG,OUT}=B-A;
|
`ALU_OP_SUB_REVERSE: {C_FLAG,OUT}=B-A;
|
||||||
`ALU_OP_AND: OUT=A&B;
|
`ALU_OP_AND: begin C_FLAG=0;OUT=A&B; end
|
||||||
`ALU_OP_OR: OUT=A|B;
|
`ALU_OP_OR: begin C_FLAG=0;OUT=A|B; end
|
||||||
`ALU_OP_XOR: OUT=A^B;
|
`ALU_OP_XOR: begin C_FLAG=0;OUT=A^B; end
|
||||||
default:begin
|
default:begin
|
||||||
OUT=0;
|
OUT=0;
|
||||||
C_FLAG=0;
|
C_FLAG=0;
|
||||||
@ -49,9 +49,9 @@ always @ ( * ) begin
|
|||||||
`ALU_OP_ADD_SIGNED_B: {C_FLAG,OUT[7:0]}=A[7:0]+SIGNED_8B;
|
`ALU_OP_ADD_SIGNED_B: {C_FLAG,OUT[7:0]}=A[7:0]+SIGNED_8B;
|
||||||
`ALU_OP_SUB: {C_FLAG,OUT[7:0]}=A[7:0]-B[7:0];
|
`ALU_OP_SUB: {C_FLAG,OUT[7:0]}=A[7:0]-B[7:0];
|
||||||
`ALU_OP_SUB_REVERSE: {C_FLAG,OUT[7:0]}=B[7:0]-A[7:0];
|
`ALU_OP_SUB_REVERSE: {C_FLAG,OUT[7:0]}=B[7:0]-A[7:0];
|
||||||
`ALU_OP_AND: OUT=A&B;
|
`ALU_OP_AND: begin C_FLAG=0;OUT=A&B; end
|
||||||
`ALU_OP_OR: OUT=A|B;
|
`ALU_OP_OR: begin C_FLAG=0;OUT=A|B; end
|
||||||
`ALU_OP_XOR: OUT=A^B;
|
`ALU_OP_XOR: begin C_FLAG=0;OUT=A^B; end
|
||||||
default:begin
|
default:begin
|
||||||
OUT=0;
|
OUT=0;
|
||||||
C_FLAG=0;
|
C_FLAG=0;
|
||||||
|
182
system/decoder.v
182
system/decoder.v
@ -29,21 +29,22 @@ module microcode(
|
|||||||
initial begin
|
initial begin
|
||||||
string ucode_path;
|
string ucode_path;
|
||||||
if($value$plusargs("MICROCODE=%s",ucode_path))begin
|
if($value$plusargs("MICROCODE=%s",ucode_path))begin
|
||||||
$readmemb(ucode_path,ucode,0,`UCODE_SIZE-1);
|
$readmemb(ucode_path,ucode_rom,0,`UCODE_SIZE-1);
|
||||||
end else begin
|
end else begin
|
||||||
$display("Please supply microcode rom file as a runtime vvp argument +MICROCODE=<path>");
|
$display("Please supply microcode rom file as a runtime vvp argument +MICROCODE=<path>");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [`UCODE_DATA_BITS-1:0] ucode [ 0:`UCODE_SIZE-1 ];
|
reg [`UCODE_DATA_BITS-1:0] ucode_rom [ 0:`UCODE_SIZE-1 ];
|
||||||
|
|
||||||
assign DATA=ucode[ADDR];
|
assign DATA=ucode_rom[ADDR];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// verilator lint_off UNUSEDSIGNAL
|
||||||
module decoder(
|
module decoder(
|
||||||
input wire [15:0] CIR,input wire [15:0] FLAGS, output wire [3:0] INSTRUCTION_INFO, output wire [1:0]DECODER_SIGNALS,output reg [`PROC_STATE_BITS-1:0]next_state
|
input wire [15:0] CIR,input wire [15:0] FLAGS, output wire [2:0] INSTRUCTION_INFO, output wire [1:0]DECODER_SIGNALS,output reg [`PROC_STATE_BITS-1:0]next_state
|
||||||
,output reg [2:0]IN_MOD, output reg [2:0]RM, output reg [15:0] PARAM1,output reg [15:0] PARAM2
|
,output reg [2:0]IN_MOD, output reg [2:0]RM, output reg [15:0] PARAM1,output reg [15:0] PARAM2
|
||||||
,output reg [1:0]in_alu1_sel1,output reg [1:0]in_alu1_sel2,output reg [2:0]OUT_MOD
|
,output reg [1:0]in_alu1_sel1,output reg [1:0]in_alu1_sel2,output reg [2:0]OUT_MOD
|
||||||
,output wire [11:0]REGISTER_FILE_CONTROL
|
,output wire [11:0]REGISTER_FILE_CONTROL
|
||||||
@ -51,6 +52,7 @@ module decoder(
|
|||||||
,output reg [`UCODE_ADDR_BITS-1:0] seq_addr_entry, input wire SIMPLE_MICRO, input wire [`UCODE_ADDR_BITS-1:0] seq_addr_input
|
,output reg [`UCODE_ADDR_BITS-1:0] seq_addr_entry, input wire SIMPLE_MICRO, input wire [`UCODE_ADDR_BITS-1:0] seq_addr_input
|
||||||
,output reg [2:0]instruction_size
|
,output reg [2:0]instruction_size
|
||||||
);
|
);
|
||||||
|
// verilator lint_on UNUSEDSIGNAL
|
||||||
|
|
||||||
reg [3:0]reg_read_port1_addr;
|
reg [3:0]reg_read_port1_addr;
|
||||||
reg [3:0]reg_read_port2_addr;
|
reg [3:0]reg_read_port2_addr;
|
||||||
@ -58,45 +60,49 @@ reg [3:0]reg_write_addr;
|
|||||||
assign REGISTER_FILE_CONTROL={reg_write_addr,reg_read_port1_addr,reg_read_port2_addr};
|
assign REGISTER_FILE_CONTROL={reg_write_addr,reg_read_port1_addr,reg_read_port2_addr};
|
||||||
|
|
||||||
/* For correct fetching of instructions and global options for the alu */
|
/* For correct fetching of instructions and global options for the alu */
|
||||||
reg Wbit,Sbit,unaligning,opcode_size;
|
reg Wbit,Sbit,opcode_size;
|
||||||
assign INSTRUCTION_INFO={Wbit,Sbit,unaligning,opcode_size};
|
assign INSTRUCTION_INFO={Wbit,Sbit,opcode_size};
|
||||||
|
|
||||||
reg ERROR, HALT;
|
reg ERROR, HALT;
|
||||||
assign DECODER_SIGNALS={ERROR,HALT};
|
assign DECODER_SIGNALS={ERROR,HALT};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// verilator lint_off UNUSEDSIGNAL
|
||||||
wire [`UCODE_DATA_BITS-1:0] ucode_data;
|
wire [`UCODE_DATA_BITS-1:0] ucode_data;
|
||||||
reg [`UCODE_ADDR_BITS-1:0] UCODE_ADDR;
|
// verilator lint_on UNUSEDSIGNAL
|
||||||
|
|
||||||
microcode ucode(seq_addr_input,ucode_data);
|
microcode ucode(seq_addr_input,ucode_data);
|
||||||
|
|
||||||
/* 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */
|
/* 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */
|
||||||
|
|
||||||
`define invalid_instruction next_state=`PROC_IF_STATE_ENTRY;ERROR=1;IN_MOD=2'b11;
|
`define invalid_instruction next_state=`PROC_IF_STATE_ENTRY;ERROR<=1;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||||
`define start_aligning_instruction unaligning=0;
|
|
||||||
`define start_unaligning_instruction unaligning=1;
|
|
||||||
|
|
||||||
//TODO: A possible optimisation for instruction with 8bit parameter and
|
//TODO: A possible optimisation for instruction with 8bit parameter and
|
||||||
//opcode_size=0 would be to set PARAM1 here instead of sending execution over
|
//opcode_size=0 would be to set PARAM1 here instead of sending execution over
|
||||||
//to PROC_DE_LOAD_8_PARAM
|
//to PROC_DE_LOAD_8_PARAM
|
||||||
|
|
||||||
|
`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=0;HALT<=0;
|
||||||
|
|
||||||
|
// I use blocking for basically putting names on the different fields of CIR and
|
||||||
|
// then branching off of that instead of the raw bits. otherwise the code
|
||||||
|
// would be identical
|
||||||
|
// verilator lint_off BLKSEQ
|
||||||
always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||||
if (SIMPLE_MICRO==0)begin
|
if (SIMPLE_MICRO==0)begin
|
||||||
ERROR=0;HALT=0;seq_addr_entry=`UCODE_NO_INSTRUCTION;
|
casez({CIR[15:8],CIR[5:3]})
|
||||||
casex({CIR[15:8],CIR[5:3]})
|
11'b0000_010?_??? : begin
|
||||||
11'b0000_010x_xxx : begin
|
|
||||||
/* ADD - Add Immediate word/byte to accumulator */
|
/* ADD - Add Immediate word/byte to accumulator */
|
||||||
/* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/
|
/* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=CIR[8:8];
|
Wbit=CIR[8:8];
|
||||||
if(Wbit)begin
|
if(Wbit)begin
|
||||||
`start_unaligning_instruction
|
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
end else begin
|
end else begin
|
||||||
`start_aligning_instruction
|
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
end
|
end
|
||||||
IN_MOD=2'b11;
|
IN_MOD=3'b011;
|
||||||
in_alu1_sel1=2'b00;
|
in_alu1_sel1=2'b00;
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
@ -107,9 +113,10 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
next_state=`PROC_DE_LOAD_16_PARAM;
|
next_state=`PROC_DE_LOAD_16_PARAM;
|
||||||
else
|
else
|
||||||
next_state=`PROC_DE_LOAD_8_PARAM;
|
next_state=`PROC_DE_LOAD_8_PARAM;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1000_00xx_101, /* SUB */
|
11'b1000_00??_101, /* SUB */
|
||||||
11'b1000_00xx_000 : /* ADD */ begin
|
11'b1000_00??_000 : /* ADD */ begin
|
||||||
/* ADD - Add Immediate word/byte to register/memory */
|
/* ADD - Add Immediate word/byte to register/memory */
|
||||||
/* 1 0 0 0 0 0 S W | MOD 0 0 0 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */
|
/* 1 0 0 0 0 0 S W | MOD 0 0 0 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */
|
||||||
/* SUB - Subtract immediate word/byte from register/memory */
|
/* SUB - Subtract immediate word/byte from register/memory */
|
||||||
@ -117,25 +124,23 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
opcode_size=1;
|
opcode_size=1;
|
||||||
Wbit=CIR[8:8];
|
Wbit=CIR[8:8];
|
||||||
Sbit=CIR[9:9];
|
Sbit=CIR[9:9];
|
||||||
IN_MOD=CIR[7:6];
|
IN_MOD={1'b0,CIR[7:6]};
|
||||||
RM=CIR[2:0];
|
RM=CIR[2:0];
|
||||||
in_alu1_sel1=2'b00;
|
in_alu1_sel1=2'b00;
|
||||||
if(IN_MOD==2'b11)begin
|
if(IN_MOD==3'b011)begin
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr={Wbit,RM};
|
||||||
reg_write_addr={Wbit,RM};
|
reg_write_addr={Wbit,RM};
|
||||||
end else begin
|
end else begin
|
||||||
in_alu1_sel2=2'b00;
|
in_alu1_sel2=2'b00;
|
||||||
end
|
end
|
||||||
OUT_MOD={1'b0,IN_MOD};
|
OUT_MOD=IN_MOD;
|
||||||
case({Sbit,Wbit})
|
case({Sbit,Wbit})
|
||||||
2'b00,2'b11:begin
|
2'b00,2'b11:begin
|
||||||
`start_unaligning_instruction
|
|
||||||
next_state=`PROC_DE_LOAD_8_PARAM;
|
next_state=`PROC_DE_LOAD_8_PARAM;
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
end
|
end
|
||||||
2'b01:begin
|
2'b01:begin
|
||||||
`start_aligning_instruction
|
|
||||||
next_state=`PROC_DE_LOAD_16_PARAM;
|
next_state=`PROC_DE_LOAD_16_PARAM;
|
||||||
instruction_size=4;
|
instruction_size=4;
|
||||||
end
|
end
|
||||||
@ -151,23 +156,22 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
`invalid_instruction
|
`invalid_instruction
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1000_00xx_111 : begin
|
11'b1000_00??_111 : begin
|
||||||
/* CMP - compare Immediate with register / memory */
|
/* CMP - compare Immediate with register / memory */
|
||||||
/* 1 0 0 0 0 0 S W | MOD 1 1 1 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */
|
/* 1 0 0 0 0 0 S W | MOD 1 1 1 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */
|
||||||
opcode_size=1;
|
opcode_size=1;
|
||||||
Wbit=CIR[8:8];
|
Wbit=CIR[8:8];
|
||||||
Sbit=CIR[9:9];
|
Sbit=CIR[9:9];
|
||||||
IN_MOD=CIR[7:6];
|
IN_MOD={1'b0,CIR[7:6]};
|
||||||
RM=CIR[2:0];
|
RM=CIR[2:0];
|
||||||
case({Sbit,Wbit})
|
case({Sbit,Wbit})
|
||||||
2'b00,2'b11:begin
|
2'b00,2'b11:begin
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
`start_unaligning_instruction
|
|
||||||
end
|
end
|
||||||
2'b01:begin
|
2'b01:begin
|
||||||
instruction_size=4;
|
instruction_size=4;
|
||||||
`start_aligning_instruction
|
|
||||||
end
|
end
|
||||||
2'b10:begin
|
2'b10:begin
|
||||||
`invalid_instruction
|
`invalid_instruction
|
||||||
@ -176,7 +180,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu1_sel1=2'b00;
|
in_alu1_sel1=2'b00;
|
||||||
OUT_MOD=3'b100;
|
OUT_MOD=3'b100;
|
||||||
ALU_1OP=`ALU_OP_SUB;
|
ALU_1OP=`ALU_OP_SUB;
|
||||||
if(IN_MOD==2'b11)begin
|
if(IN_MOD==3'b011)begin
|
||||||
/*compare register with param*/
|
/*compare register with param*/
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr={Wbit,RM};
|
||||||
@ -187,15 +191,15 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu1_sel2=2'b00;
|
in_alu1_sel2=2'b00;
|
||||||
next_state=`PROC_DE_LOAD_16_PARAM; /*will the call MEMIO_READ*/
|
next_state=`PROC_DE_LOAD_16_PARAM; /*will the call MEMIO_READ*/
|
||||||
end
|
end
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1011_0xxx_xxx : begin
|
11'b1011_0???_??? : begin
|
||||||
/* MOV - Move Immediate byte to register */
|
/* MOV - Move Immediate byte to register */
|
||||||
/* 1 0 1 1 W REG | DATA | DATA if W |*/
|
/* 1 0 1 1 W REG | DATA | DATA if W |*/
|
||||||
`start_aligning_instruction
|
|
||||||
Wbit=CIR[11:11]; /* IS 0 */
|
Wbit=CIR[11:11]; /* IS 0 */
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
IN_MOD=2'b11;
|
IN_MOD=3'b011;
|
||||||
in_alu1_sel1=2'b00;
|
in_alu1_sel1=2'b00;
|
||||||
in_alu1_sel2=2'b00;
|
in_alu1_sel2=2'b00;
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
@ -204,14 +208,14 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
PARAM2=0;
|
PARAM2=0;
|
||||||
ALU_1OP=`ALU_OP_ADD;
|
ALU_1OP=`ALU_OP_ADD;
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1011_1xxx_xxx : begin
|
11'b1011_1???_??? : begin
|
||||||
/*MOV - Move Immediate word to register*/
|
/*MOV - Move Immediate word to register*/
|
||||||
`start_unaligning_instruction
|
|
||||||
Wbit=CIR[11:11]; /*IS 1 */
|
Wbit=CIR[11:11]; /*IS 1 */
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
IN_MOD=2'b11;
|
IN_MOD=3'b011;
|
||||||
in_alu1_sel1=2'b00;
|
in_alu1_sel1=2'b00;
|
||||||
in_alu1_sel2=2'b00;
|
in_alu1_sel2=2'b00;
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
@ -219,12 +223,11 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
ALU_1OP=`ALU_OP_ADD;
|
ALU_1OP=`ALU_OP_ADD;
|
||||||
PARAM2=0;
|
PARAM2=0;
|
||||||
next_state=`PROC_DE_LOAD_16_PARAM;
|
next_state=`PROC_DE_LOAD_16_PARAM;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
|
11'b1000_10??_??? : begin
|
||||||
11'b1000_10xx_xxx : begin
|
|
||||||
/* MOV - Reg/Mem to/from register */
|
/* MOV - Reg/Mem to/from register */
|
||||||
/* 1 0 0 0 1 0 D W | MOD REG RM | < DISP LO > | < DISP HI > |*/
|
/* 1 0 0 0 1 0 D W | MOD REG RM | < DISP LO > | < DISP HI > |*/
|
||||||
`start_aligning_instruction
|
|
||||||
opcode_size=1;
|
opcode_size=1;
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
RM=CIR[2:0];
|
RM=CIR[2:0];
|
||||||
@ -234,7 +237,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
if(CIR[9:9] == 1)begin
|
if(CIR[9:9] == 1)begin
|
||||||
/* Mem/Reg to reg */
|
/* Mem/Reg to reg */
|
||||||
IN_MOD={1'b0,CIR[7:6]};
|
IN_MOD={1'b0,CIR[7:6]};
|
||||||
if(IN_MOD==2'b11)begin
|
if(IN_MOD==3'b011)begin
|
||||||
/*Reg to Reg*/
|
/*Reg to Reg*/
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr={Wbit,RM};
|
||||||
@ -250,7 +253,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
/* Reg to Mem/Reg */
|
/* Reg to Mem/Reg */
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
OUT_MOD={1'b0,CIR[7:6]};
|
OUT_MOD={1'b0,CIR[7:6]};
|
||||||
if(IN_MOD==2'b11)begin
|
if(IN_MOD==3'b011)begin
|
||||||
/*Reg to Reg*/
|
/*Reg to Reg*/
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
reg_write_addr={Wbit,RM};
|
reg_write_addr={Wbit,RM};
|
||||||
@ -262,22 +265,22 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
reg_read_port2_addr={Wbit,CIR[5:3]};
|
reg_read_port2_addr={Wbit,CIR[5:3]};
|
||||||
end
|
end
|
||||||
|
|
||||||
ALU_1OP=`ALU_OP_ADD;
|
ALU_1OP=`ALU_OP_ADD;
|
||||||
|
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b0100_xxxx_xxx:begin//DEC
|
11'b0100_????_???:begin//DEC
|
||||||
/* DEC - Decrement Register */
|
/* DEC - Decrement Register */
|
||||||
/* | 0 1 0 0 1 REG | */
|
/* | 0 1 0 0 1 REG | */
|
||||||
/* INC - Increment Register */
|
/* INC - Increment Register */
|
||||||
/* | 0 1 0 0 0 REG | */
|
/* | 0 1 0 0 0 REG | */
|
||||||
instruction_size=1;
|
instruction_size=1;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
`start_unaligning_instruction
|
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
in_alu1_sel1=2'b01;
|
in_alu1_sel1=2'b01;
|
||||||
in_alu1_sel2=2'b00;
|
in_alu1_sel2=2'b00;
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
IN_MOD=2'b11;
|
IN_MOD=3'b011;
|
||||||
PARAM2=1;
|
PARAM2=1;
|
||||||
reg_read_port1_addr={1'b1,CIR[10:8]};
|
reg_read_port1_addr={1'b1,CIR[10:8]};
|
||||||
reg_write_addr={1'b1,CIR[10:8]};
|
reg_write_addr={1'b1,CIR[10:8]};
|
||||||
@ -286,44 +289,47 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
else
|
else
|
||||||
ALU_1OP=`ALU_OP_SUB;
|
ALU_1OP=`ALU_OP_SUB;
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1111_111x_00x : begin
|
11'b1111_111?_00? : begin
|
||||||
/* INC - Register/Memory */
|
/* INC - Register/Memory */
|
||||||
/* 1 1 1 1 1 1 1 W | MOD 0 0 0 R/M | < DISP LO> | < DISP HI> */
|
/* 1 1 1 1 1 1 1 W | MOD 0 0 0 R/M | < DISP LO> | < DISP HI> */
|
||||||
/* DEC - Register/Memory */
|
/* DEC - Register/Memory */
|
||||||
/* 1 1 1 1 1 1 1 W | MOD 0 0 1 R/M | < DISP LO> | < DISP HI> */
|
/* 1 1 1 1 1 1 1 W | MOD 0 0 1 R/M | < DISP LO> | < DISP HI> */
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
opcode_size=1;
|
opcode_size=1;
|
||||||
`start_aligning_instruction
|
|
||||||
Wbit=CIR[8:8];
|
Wbit=CIR[8:8];
|
||||||
IN_MOD=CIR[7:6];
|
IN_MOD={1'b0,CIR[7:6]};
|
||||||
RM=CIR[2:0];
|
RM=CIR[2:0];
|
||||||
in_alu1_sel2=(IN_MOD==2'b11)? 2'b01 : 2'b00;
|
in_alu1_sel2=(IN_MOD==3'b011)? 2'b01 : 2'b00;
|
||||||
in_alu1_sel1=2'b00;/* number 1 */
|
in_alu1_sel1=2'b00;/* number 1 */
|
||||||
PARAM1=1;
|
PARAM1=1;
|
||||||
OUT_MOD={1'b0,IN_MOD};
|
OUT_MOD=IN_MOD;
|
||||||
|
|
||||||
/*in case IN_MOD=11 */
|
/*in case IN_MOD=011 */
|
||||||
reg_read_port2_addr={1'b0,RM};
|
reg_read_port2_addr={1'b0,RM};
|
||||||
reg_write_addr={1'b0,RM};
|
reg_write_addr={1'b0,RM};
|
||||||
|
|
||||||
ALU_1OP=(CIR[3:3]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
ALU_1OP=(CIR[3:3]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
||||||
if ( IN_MOD == 2'b11 )
|
if ( IN_MOD == 3'b011 )
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
next_state=`PROC_MEMIO_READ;
|
next_state=`PROC_MEMIO_READ;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1111_0100_xxx : begin
|
11'b1111_0100_??? : begin
|
||||||
/* HLT - Halt */
|
/* HLT - Halt */
|
||||||
/* 1 1 1 1 0 1 0 0 | */
|
/* 1 1 1 1 0 1 0 0 | */
|
||||||
instruction_size=1;
|
instruction_size=1;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
`start_unaligning_instruction
|
IN_MOD=3'b011;
|
||||||
IN_MOD=2'b11;
|
HALT<=1;
|
||||||
HALT=1;
|
ERROR<=0;
|
||||||
|
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||||
next_state=`PROC_HALT_STATE;
|
next_state=`PROC_HALT_STATE;
|
||||||
|
|
||||||
end
|
end
|
||||||
11'b0011_110x_xxx : begin
|
11'b0011_110?_??? : begin
|
||||||
/* CMP - Compare Immediate with accumulator */
|
/* CMP - Compare Immediate with accumulator */
|
||||||
/* 0 0 1 1 1 1 0 W | DATA | DATA if W |*/
|
/* 0 0 1 1 1 1 0 W | DATA | DATA if W |*/
|
||||||
/* */
|
/* */
|
||||||
@ -333,12 +339,10 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
if(Wbit)begin
|
if(Wbit)begin
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
`start_unaligning_instruction
|
|
||||||
end else begin
|
end else begin
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
`start_aligning_instruction
|
|
||||||
end
|
end
|
||||||
IN_MOD=2'b11;
|
IN_MOD=3'b011;
|
||||||
in_alu1_sel1=2'b00;
|
in_alu1_sel1=2'b00;
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,3'b000};
|
reg_read_port2_addr={Wbit,3'b000};
|
||||||
@ -350,8 +354,9 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
PARAM1[7:0]=CIR[7:0];
|
PARAM1[7:0]=CIR[7:0];
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b0111_xxxx_xxx:begin
|
11'b0111_????_???:begin
|
||||||
/* Conditional relative jumps */
|
/* Conditional relative jumps */
|
||||||
/* JE/JZ - Jump on Zero */
|
/* JE/JZ - Jump on Zero */
|
||||||
/* 0 1 1 1 0 1 0 0 | IP-INC8 |*/
|
/* 0 1 1 1 0 1 0 0 | IP-INC8 |*/
|
||||||
@ -361,7 +366,6 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
/* 0 1 1 1 1 0 0 1 | IP-INC8 |*/
|
/* 0 1 1 1 1 0 0 1 | IP-INC8 |*/
|
||||||
/* .... */
|
/* .... */
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
`start_aligning_instruction
|
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
in_alu1_sel1=2'b10;
|
in_alu1_sel1=2'b10;
|
||||||
@ -403,11 +407,11 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
`invalid_instruction; /*We don't support that condition*/
|
`invalid_instruction; /*We don't support that condition*/
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1110_1011_xxx:begin
|
11'b1110_1011_???:begin
|
||||||
/* JMP - Unconditional jump direct within segment (short) */
|
/* JMP - Unconditional jump direct within segment (short) */
|
||||||
/* | 1 1 1 0 1 0 1 1 | IP-INC-LO | */
|
/* | 1 1 1 0 1 0 1 1 | IP-INC-LO | */
|
||||||
`start_aligning_instruction
|
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
@ -417,70 +421,67 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
ALU_1OP=`ALU_OP_ADD_SIGNED_B;
|
ALU_1OP=`ALU_OP_ADD_SIGNED_B;
|
||||||
OUT_MOD=3'b101;
|
OUT_MOD=3'b101;
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1100_1101_xxx:begin
|
11'b1100_1101_???:begin
|
||||||
/* INT - execute interrupt handler */
|
/* INT - execute interrupt handler */
|
||||||
/* 1 1 0 0 1 1 0 1 | DATA |*/
|
/* 1 1 0 0 1 1 0 1 | DATA |*/
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
`start_aligning_instruction
|
|
||||||
/* Emulate MS-DOS print routines */
|
/* Emulate MS-DOS print routines */
|
||||||
if(CIR[7:0]==8'h21 && register_file.registers[0][15:8]==8'h02)begin
|
if(CIR[7:0]==8'h21 && register_file.registers[0][15:8]==8'h02)begin
|
||||||
$write("%s" ,register_file.registers[2][7:0]); /*TODO:Could trigger erroneously while CIR is not final*/
|
$write("%s" ,register_file.registers[2][7:0]); /*TODO:Could trigger erroneously while CIR is not final*/
|
||||||
end
|
end
|
||||||
next_state=`PROC_IF_STATE_ENTRY;
|
next_state=`PROC_IF_STATE_ENTRY;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1110_1000_xxx:begin
|
11'b1110_1000_???:begin
|
||||||
/* CALL - Direct call within segment */
|
/* CALL - Direct call within segment */
|
||||||
/* 1 1 1 0 1 0 0 0 | IP-INC-LO | IP-INC-HI |*/
|
/* 1 1 1 0 1 0 0 0 | IP-INC-LO | IP-INC-HI |*/
|
||||||
|
|
||||||
// Microcode instruction
|
// Microcode instruction
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
`start_unaligning_instruction
|
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=1;
|
Sbit=1;
|
||||||
PARAM2=2; //subtract from sp
|
PARAM2=2; //subtract from sp
|
||||||
seq_addr_entry=`UCODE_CALL_ENTRY;
|
seq_addr_entry<=`UCODE_CALL_ENTRY;
|
||||||
end
|
end
|
||||||
11'b1100_0011_xxx:begin
|
11'b1100_0011_???:begin
|
||||||
/* RET - Return from call within segment */
|
/* RET - Return from call within segment */
|
||||||
/* | 1 1 0 0 0 0 1 1 | */
|
/* | 1 1 0 0 0 0 1 1 | */
|
||||||
|
|
||||||
// Microcode instruction
|
// Microcode instruction
|
||||||
`start_unaligning_instruction
|
|
||||||
instruction_size=1;
|
instruction_size=1;
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM1=2;
|
PARAM1=2;
|
||||||
seq_addr_entry=`UCODE_RET_ENTRY;
|
seq_addr_entry<=`UCODE_RET_ENTRY;
|
||||||
end
|
end
|
||||||
11'b1010_101x_xxx:begin
|
11'b1010_101?_???:begin
|
||||||
/* STOS - Write byte/word to [DI] and increment accordingly */
|
/* STOS - Write byte/word to [DI] and increment accordingly */
|
||||||
/* | 1 0 1 0 1 0 1 W | */
|
/* | 1 0 1 0 1 0 1 W | */
|
||||||
`start_unaligning_instruction
|
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
instruction_size=1;
|
instruction_size=1;
|
||||||
Wbit=CIR[8:8];
|
Wbit=CIR[8:8];
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
RM=101;
|
RM=3'b101;
|
||||||
seq_addr_entry=`UCODE_STOS_ENTRY;
|
seq_addr_entry<=`UCODE_STOS_ENTRY;
|
||||||
PARAM2=(Wbit==1)?2:1;
|
PARAM2=(Wbit==1)?2:1;
|
||||||
end
|
end
|
||||||
11'b0101_0xxx_xxx:begin
|
11'b0101_0???_???:begin
|
||||||
/* PUSH - SP-=2; [SP]=REG */
|
/* PUSH - SP-=2; [SP]=REG */
|
||||||
/* | 0 1 0 1 0 REG | */
|
/* | 0 1 0 1 0 REG | */
|
||||||
`start_unaligning_instruction
|
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
instruction_size=1;
|
instruction_size=1;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM2=2;
|
PARAM2=2;
|
||||||
reg_read_port2_addr={1'b1,CIR[10:8]};
|
reg_read_port2_addr={1'b1,CIR[10:8]};
|
||||||
seq_addr_entry=`UCODE_PUSH_ENTRY;
|
seq_addr_entry<=`UCODE_PUSH_ENTRY;
|
||||||
end
|
end
|
||||||
11'b1111_011x_000:begin
|
11'b1111_011?_000:begin
|
||||||
/* TEST - Bitwise AND affecting only flags */
|
/* TEST - Bitwise AND affecting only flags */
|
||||||
/* 1 1 1 1 0 1 1 W | MOD 0 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
|
/* 1 1 1 1 0 1 1 W | MOD 0 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
|
||||||
opcode_size=1;
|
opcode_size=1;
|
||||||
@ -488,18 +489,16 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
IN_MOD={1'b0,CIR[7:6]};
|
IN_MOD={1'b0,CIR[7:6]};
|
||||||
RM={CIR[2:0]};
|
RM={CIR[2:0]};
|
||||||
if(Wbit==1)begin
|
if(Wbit==1)begin
|
||||||
`start_aligning_instruction
|
|
||||||
instruction_size=4;
|
instruction_size=4;
|
||||||
next_state=`PROC_DE_LOAD_16_PARAM;
|
next_state=`PROC_DE_LOAD_16_PARAM;
|
||||||
end else begin
|
end else begin
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
`start_unaligning_instruction
|
|
||||||
next_state=`PROC_DE_LOAD_8_PARAM;
|
next_state=`PROC_DE_LOAD_8_PARAM;
|
||||||
end
|
end
|
||||||
in_alu1_sel1=2'b00; /* PARAM1 */
|
in_alu1_sel1=2'b00; /* PARAM1 */
|
||||||
ALU_1OP=`ALU_OP_AND;
|
ALU_1OP=`ALU_OP_AND;
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
2'b11:begin
|
3'b011:begin
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr={Wbit,RM};
|
||||||
end
|
end
|
||||||
@ -508,30 +507,29 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
OUT_MOD=3'b100;/*NULL*/
|
OUT_MOD=3'b100;/*NULL*/
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b0101_1xxx_xxx:begin
|
11'b0101_1???_???:begin
|
||||||
/* POP - REG=[SP]; SP+=2 */
|
/* POP - REG=[SP]; SP+=2 */
|
||||||
/* | 0 1 0 1 1 REG | */
|
/* | 0 1 0 1 1 REG | */
|
||||||
`start_unaligning_instruction
|
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
instruction_size=1;
|
instruction_size=1;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM1=2;
|
PARAM1=2;
|
||||||
reg_write_addr={1'b1,CIR[10:8]};
|
reg_write_addr={1'b1,CIR[10:8]};
|
||||||
seq_addr_entry=`UCODE_POP_ENTRY;
|
seq_addr_entry<=`UCODE_POP_ENTRY;
|
||||||
end
|
end
|
||||||
11'b1111_1111_100:begin
|
11'b1111_1111_100:begin
|
||||||
/* JMP - Unconditional indirect within segment jump */
|
/* JMP - Unconditional indirect within segment jump */
|
||||||
/* 1 1 1 1 1 1 1 1 | MOD 1 0 0 R/M | < DISP-LO > | < DISP-HI > */
|
/* 1 1 1 1 1 1 1 1 | MOD 1 0 0 R/M | < DISP-LO > | < DISP-HI > */
|
||||||
`start_aligning_instruction
|
|
||||||
opcode_size=1;
|
opcode_size=1;
|
||||||
instruction_size=2;
|
instruction_size=2;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
IN_MOD={1'b0,CIR[7:6]};
|
IN_MOD={1'b0,CIR[7:6]};
|
||||||
RM=CIR[2:0];
|
RM=CIR[2:0];
|
||||||
in_alu1_sel1=2'b11;
|
in_alu1_sel1=2'b11;
|
||||||
if (IN_MOD==2'b11)begin
|
if (IN_MOD==3'b011)begin
|
||||||
in_alu1_sel2=2'b01;
|
in_alu1_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr={Wbit,RM};
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
@ -541,8 +539,9 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
ALU_1OP=`ALU_OP_ADD;
|
ALU_1OP=`ALU_OP_ADD;
|
||||||
OUT_MOD=3'b101;
|
OUT_MOD=3'b101;
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
11'b1100_011x_000:begin
|
11'b1100_011?_000:begin
|
||||||
/* MOV - Move immediate to register/memory */
|
/* MOV - Move immediate to register/memory */
|
||||||
/* 1 1 0 0 0 1 1 W | MOD 0 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
|
/* 1 1 0 0 0 1 1 W | MOD 0 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
|
||||||
Wbit=CIR[8:8];
|
Wbit=CIR[8:8];
|
||||||
@ -551,18 +550,16 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu1_sel2=2'b11;
|
in_alu1_sel2=2'b11;
|
||||||
if(Wbit==1)begin
|
if(Wbit==1)begin
|
||||||
instruction_size=4;
|
instruction_size=4;
|
||||||
`start_aligning_instruction;
|
|
||||||
next_state=`PROC_DE_LOAD_16_PARAM;
|
next_state=`PROC_DE_LOAD_16_PARAM;
|
||||||
end else begin
|
end else begin
|
||||||
instruction_size=3;
|
instruction_size=3;
|
||||||
`start_unaligning_instruction;
|
|
||||||
next_state=`PROC_DE_LOAD_8_PARAM;
|
next_state=`PROC_DE_LOAD_8_PARAM;
|
||||||
end
|
end
|
||||||
|
|
||||||
OUT_MOD={1'b0,CIR[7:6]};
|
OUT_MOD={1'b0,CIR[7:6]};
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
RM=CIR[2:0];
|
RM=CIR[2:0];
|
||||||
|
`normal_instruction;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`invalid_instruction
|
`invalid_instruction
|
||||||
@ -572,7 +569,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
/*Microcode output*/
|
/*Microcode output*/
|
||||||
//Sbit, Wbit, opcode_size and the others are still latched
|
//Sbit, Wbit, opcode_size and the others are still latched
|
||||||
//from when we ordered the switch to microcode
|
//from when we ordered the switch to microcode
|
||||||
seq_addr_entry=ucode_data[5:0];
|
seq_addr_entry <= ucode_data[`UCODE_ADDR_BITS-1:0];
|
||||||
case(ucode_data[7:6])
|
case(ucode_data[7:6])
|
||||||
2'b00: next_state=`PROC_EX_STATE_ENTRY;
|
2'b00: next_state=`PROC_EX_STATE_ENTRY;
|
||||||
2'b01: next_state=`PROC_DE_LOAD_16_PARAM;
|
2'b01: next_state=`PROC_DE_LOAD_16_PARAM;
|
||||||
@ -594,6 +591,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
3'b100: ALU_1OP=`ALU_OP_XOR;
|
3'b100: ALU_1OP=`ALU_OP_XOR;
|
||||||
3'b101: ALU_1OP=`ALU_OP_ADD_SIGNED_B;
|
3'b101: ALU_1OP=`ALU_OP_ADD_SIGNED_B;
|
||||||
3'b110: ALU_1OP=`ALU_OP_SUB_REVERSE;
|
3'b110: ALU_1OP=`ALU_OP_SUB_REVERSE;
|
||||||
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
if(ucode_data[33:33]==0)
|
if(ucode_data[33:33]==0)
|
||||||
reg_read_port1_addr=ucode_data[25:22];
|
reg_read_port1_addr=ucode_data[25:22];
|
||||||
@ -604,5 +602,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Wbit=ucode_data[36:36];
|
Wbit=ucode_data[36:36];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
`undef invalid_instruction
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
// verilator lint_on BLKSEQ
|
||||||
|
@ -60,3 +60,5 @@
|
|||||||
`define PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2 6'b110010
|
`define PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2 6'b110010
|
||||||
|
|
||||||
`define PROC_NEXT_MICROCODE 6'b111000
|
`define PROC_NEXT_MICROCODE 6'b111000
|
||||||
|
|
||||||
|
`define PROC_RESET 6'b111100
|
||||||
|
@ -40,7 +40,7 @@ assign external_data_bus=read?data_bus_output_register:16'hz;
|
|||||||
reg [`PROC_STATE_BITS-1:0] state;
|
reg [`PROC_STATE_BITS-1:0] state;
|
||||||
|
|
||||||
/*############ Decoder ########################################################## */
|
/*############ Decoder ########################################################## */
|
||||||
wire Wbit, Sbit, unaligning_instruction,opcode_size;
|
wire Wbit, Sbit, opcode_size;
|
||||||
wire [`PROC_STATE_BITS-1:0] next_state;
|
wire [`PROC_STATE_BITS-1:0] next_state;
|
||||||
wire [2:0]RM;
|
wire [2:0]RM;
|
||||||
wire [15:0]DE_PARAM1;// Input param1 form decoder to alu
|
wire [15:0]DE_PARAM1;// Input param1 form decoder to alu
|
||||||
@ -48,7 +48,7 @@ wire [15:0]DE_PARAM2;
|
|||||||
wire DE_ERROR,DE_HALT;
|
wire DE_ERROR,DE_HALT;
|
||||||
wire [3:0]DE_reg_read_port1_addr,DE_reg_write_addr,DE_reg_read_port2_addr;
|
wire [3:0]DE_reg_read_port1_addr,DE_reg_write_addr,DE_reg_read_port2_addr;
|
||||||
wire [11:0]DE_REGISTER_CONTROL;
|
wire [11:0]DE_REGISTER_CONTROL;
|
||||||
wire [3:0]INSTRUCTION_INFO;
|
wire [2:0]INSTRUCTION_INFO;
|
||||||
wire [1:0]DECODER_SIGNALS;
|
wire [1:0]DECODER_SIGNALS;
|
||||||
wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry;
|
wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry;
|
||||||
|
|
||||||
@ -79,9 +79,8 @@ decoder decoder(
|
|||||||
.instruction_size(DE_instruction_size)
|
.instruction_size(DE_instruction_size)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign Wbit=INSTRUCTION_INFO[3:3];
|
assign Wbit=INSTRUCTION_INFO[2:2];
|
||||||
assign Sbit=INSTRUCTION_INFO[2:2];
|
assign Sbit=INSTRUCTION_INFO[1:1];
|
||||||
assign unaligning_instruction=INSTRUCTION_INFO[1:1];
|
|
||||||
assign opcode_size=INSTRUCTION_INFO[0:0];
|
assign opcode_size=INSTRUCTION_INFO[0:0];
|
||||||
|
|
||||||
assign DE_reg_write_addr=DE_REGISTER_CONTROL[11:8];
|
assign DE_reg_write_addr=DE_REGISTER_CONTROL[11:8];
|
||||||
@ -99,9 +98,9 @@ reg [15:0] CIR;
|
|||||||
reg [15:0] PARAM1;
|
reg [15:0] PARAM1;
|
||||||
reg [15:0] PARAM2;
|
reg [15:0] PARAM2;
|
||||||
|
|
||||||
reg [15:0]FLAGS;
|
// verilator lint_off UNDRIVEN
|
||||||
|
reg [15:0] FLAGS;
|
||||||
reg [15:0] BYTE_WRITE_TEMP_REG;//we read 16bits here if we want to change just 8 and leave the rest
|
// verilator lint_on UNDRIVEN
|
||||||
|
|
||||||
//Architectural Register file
|
//Architectural Register file
|
||||||
reg [3:0] reg_write_addr;
|
reg [3:0] reg_write_addr;
|
||||||
@ -130,10 +129,13 @@ register_file register_file(
|
|||||||
);
|
);
|
||||||
|
|
||||||
reg [15:0] ProgCount;
|
reg [15:0] ProgCount;
|
||||||
wire ProgCount_next_opcode;
|
|
||||||
wire ProgCount_arg;
|
// verilator lint_off UNUSEDSIGNAL
|
||||||
assign ProgCount_next_opcode=ProgCount+instruction_size;
|
wire [15:0] ProgCount_next_opcode;
|
||||||
assign ProgCount_arg=ProgCount+opcode_size+1;
|
wire [15:0] ProgCount_arg;
|
||||||
|
assign ProgCount_next_opcode=ProgCount+{13'b0,instruction_size};
|
||||||
|
assign ProgCount_arg=ProgCount+{15'b0,opcode_size}+16'd1;
|
||||||
|
// verilator lint_on UNUSEDSIGNAL
|
||||||
|
|
||||||
/*############ ALU / Execution units ########################################################## */
|
/*############ ALU / Execution units ########################################################## */
|
||||||
// ALU 1
|
// ALU 1
|
||||||
@ -147,7 +149,7 @@ mux4 #(.WIDTH(16)) MUX16_1A(
|
|||||||
/*0*/ PARAM1,
|
/*0*/ PARAM1,
|
||||||
/*1*/ reg_read_port1_data,
|
/*1*/ reg_read_port1_data,
|
||||||
/*2*/ ProgCount[15:0],
|
/*2*/ ProgCount[15:0],
|
||||||
/*3*/ 16'b0000000000000000, /*0 Constant*/
|
/*3*/ 16'd0, /*0 Constant*/
|
||||||
in_alu1_sel1,
|
in_alu1_sel1,
|
||||||
ALU_1A);
|
ALU_1A);
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ mux4 #(.WIDTH(16)) MUX16_1B(
|
|||||||
/*0*/ PARAM2,
|
/*0*/ PARAM2,
|
||||||
/*1*/ reg_read_port2_data,
|
/*1*/ reg_read_port2_data,
|
||||||
/*2*/ ProgCount[15:0],
|
/*2*/ ProgCount[15:0],
|
||||||
/*3*/ 16'b0000000000000000, /*0 Constant*/
|
/*3*/ 16'd0, /*0 Constant*/
|
||||||
in_alu1_sel2,
|
in_alu1_sel2,
|
||||||
ALU_1B);
|
ALU_1B);
|
||||||
|
|
||||||
@ -176,29 +178,31 @@ ALU ALU1(
|
|||||||
/*############ Processor state machine ########################################################## */
|
/*############ Processor state machine ########################################################## */
|
||||||
|
|
||||||
/*** RESET LOGIC ***/
|
/*** RESET LOGIC ***/
|
||||||
|
/* verilator lint_off MULTIDRIVEN */
|
||||||
always @(negedge reset) begin
|
always @(negedge reset) begin
|
||||||
if (reset==0) begin
|
state <= `PROC_HALT_STATE; //TODO: race condition ??
|
||||||
@(posedge clock);
|
|
||||||
state=`PROC_HALT_STATE;
|
|
||||||
ucode_seq_addr=`UCODE_NO_INSTRUCTION;
|
|
||||||
ProgCount=0;//TODO: Reset Vector
|
|
||||||
HALT=0;
|
|
||||||
reg_write_we=1;
|
|
||||||
IOMEM=0;
|
|
||||||
@(posedge reset)
|
|
||||||
@(negedge clock);
|
|
||||||
state=`PROC_IF_STATE_ENTRY;
|
|
||||||
ERROR=0;
|
|
||||||
SIMPLE_MICRO=0;
|
|
||||||
instruction_size_init=1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
always @(posedge reset) begin
|
||||||
|
state <= `PROC_RESET;
|
||||||
|
end
|
||||||
|
/* verilator lint_on MULTIDRIVEN */
|
||||||
|
|
||||||
/*** Processor stages ***/
|
/*** Processor stages ***/
|
||||||
`define invalid_instruction state=`PROC_IF_STATE_ENTRY;ERROR=1;
|
`define invalid_instruction state <= `PROC_IF_STATE_ENTRY;ERROR <= 1;
|
||||||
|
|
||||||
always @(posedge clock) begin
|
always @(posedge clock) begin
|
||||||
case(state)
|
case(state)
|
||||||
|
`PROC_RESET:begin
|
||||||
|
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
||||||
|
ProgCount <= 0;//TODO: Reset Vector
|
||||||
|
HALT <= 0;
|
||||||
|
ERROR <= 0;
|
||||||
|
IOMEM <= 0;
|
||||||
|
SIMPLE_MICRO <= 0;
|
||||||
|
reg_write_we <= 1;
|
||||||
|
instruction_size_init <= 1;
|
||||||
|
state <= `PROC_IF_STATE_ENTRY;
|
||||||
|
end
|
||||||
`PROC_HALT_STATE:begin
|
`PROC_HALT_STATE:begin
|
||||||
end
|
end
|
||||||
`PROC_IF_STATE_ENTRY:begin
|
`PROC_IF_STATE_ENTRY:begin
|
||||||
@ -214,13 +218,13 @@ always @(posedge clock) begin
|
|||||||
$display("Fetched instruction at %0x",ProgCount - 0);
|
$display("Fetched instruction at %0x",ProgCount - 0);
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
BHE = 0;
|
BHE <= 0;
|
||||||
external_address_bus = ProgCount;
|
external_address_bus <= {4'b0,ProgCount};
|
||||||
read = 0;
|
read <= 0;
|
||||||
write = 1;
|
write <= 1;
|
||||||
reg_write_we=1;
|
reg_write_we <= 1;
|
||||||
state=`PROC_IF_WRITE_CIR;
|
state <= `PROC_IF_WRITE_CIR;
|
||||||
reg_write_in_sel=2'b00;
|
reg_write_in_sel <= 2'b00;
|
||||||
end
|
end
|
||||||
`PROC_IF_WRITE_CIR:begin
|
`PROC_IF_WRITE_CIR:begin
|
||||||
/*I built the entire decode stage with CIR
|
/*I built the entire decode stage with CIR
|
||||||
@ -228,40 +232,40 @@ always @(posedge clock) begin
|
|||||||
|
|
||||||
if(instruction_size==1)begin
|
if(instruction_size==1)begin
|
||||||
/*Half on CIR half on this address */
|
/*Half on CIR half on this address */
|
||||||
state=`PROC_DE_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
if(ProgCount[0:0]==1)begin
|
if(ProgCount[0:0]==1)begin
|
||||||
CIR = {CIR[7:0],external_data_bus[15:8]};
|
CIR <= {CIR[7:0],external_data_bus[15:8]};
|
||||||
end else begin
|
end else begin
|
||||||
CIR = {CIR[7:0],external_data_bus[7:0]};
|
CIR <= {CIR[7:0],external_data_bus[7:0]};
|
||||||
end
|
end
|
||||||
ProgCount=ProgCount+1;
|
ProgCount <= ProgCount+1;
|
||||||
end else begin
|
end else begin
|
||||||
if(ProgCount[0:0]==1)begin
|
if(ProgCount[0:0]==1)begin
|
||||||
/* Half on this address half on the next*/
|
/* Half on this address half on the next*/
|
||||||
ProgCount=ProgCount+1;
|
ProgCount <= ProgCount+1;
|
||||||
CIR[15:8] <= external_data_bus[15:8];
|
CIR[15:8] <= external_data_bus[15:8];
|
||||||
state=`PROC_IF_STATE_EXTRA_FETCH_SET;
|
state <= `PROC_IF_STATE_EXTRA_FETCH_SET;
|
||||||
end else begin
|
end else begin
|
||||||
/* Both on this address! */
|
/* Both on this address! */
|
||||||
ProgCount=ProgCount+2;
|
ProgCount <= ProgCount+2;
|
||||||
CIR <= {external_data_bus[7:0],external_data_bus[15:8]};
|
CIR <= {external_data_bus[7:0],external_data_bus[15:8]};
|
||||||
state=`PROC_DE_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
`PROC_IF_STATE_EXTRA_FETCH_SET:begin
|
`PROC_IF_STATE_EXTRA_FETCH_SET:begin
|
||||||
external_address_bus = ProgCount;
|
external_address_bus <= {4'b0,ProgCount};
|
||||||
BHE=0;
|
BHE <= 0;
|
||||||
state=`PROC_IF_STATE_EXTRA_FETCH;
|
state <= `PROC_IF_STATE_EXTRA_FETCH;
|
||||||
end
|
end
|
||||||
`PROC_IF_STATE_EXTRA_FETCH:begin
|
`PROC_IF_STATE_EXTRA_FETCH:begin
|
||||||
CIR[7:0] <= external_data_bus[7:0];
|
CIR[7:0] <= external_data_bus[7:0];
|
||||||
ProgCount=ProgCount+1;
|
ProgCount <= ProgCount+1;
|
||||||
state=`PROC_DE_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
`PROC_DE_STATE_ENTRY:begin
|
`PROC_DE_STATE_ENTRY:begin
|
||||||
external_address_bus = ProgCount;
|
external_address_bus <= {4'b0,ProgCount};
|
||||||
if(SIMPLE_MICRO==0)begin
|
if(SIMPLE_MICRO==0)begin
|
||||||
/*This flag is set at reset and jump because
|
/*This flag is set at reset and jump because
|
||||||
* at IF we need to know the size of the
|
* at IF we need to know the size of the
|
||||||
@ -270,110 +274,110 @@ always @(posedge clock) begin
|
|||||||
* incorrect in both cases. So when it gets
|
* incorrect in both cases. So when it gets
|
||||||
* set reset it only at the start of the next
|
* set reset it only at the start of the next
|
||||||
* 8086 instruction */
|
* 8086 instruction */
|
||||||
instruction_size_init=0;
|
instruction_size_init <= 0;
|
||||||
|
|
||||||
/* We cannot set these directly within
|
/* We cannot set these directly within
|
||||||
* microcode so don't overwrite useful values
|
* microcode so don't overwrite useful values
|
||||||
* each time the next microcode is executed.
|
* each time the next microcode is executed.
|
||||||
* Note this still allows to set initial values
|
* Note this still allows to set initial values
|
||||||
* at the start of the microcode */
|
* at the start of the microcode */
|
||||||
PARAM1=DE_PARAM1;
|
PARAM1 <= DE_PARAM1;
|
||||||
PARAM2=DE_PARAM2;
|
PARAM2 <= DE_PARAM2;
|
||||||
end
|
end
|
||||||
ERROR=DE_ERROR;
|
ERROR <= DE_ERROR;
|
||||||
HALT=DE_HALT;
|
HALT <= DE_HALT;
|
||||||
reg_read_port1_addr=DE_reg_read_port1_addr;
|
reg_read_port1_addr <= DE_reg_read_port1_addr;
|
||||||
reg_read_port2_addr=DE_reg_read_port2_addr;
|
reg_read_port2_addr <= DE_reg_read_port2_addr;
|
||||||
reg_write_addr=DE_reg_write_addr;
|
reg_write_addr <= DE_reg_write_addr;
|
||||||
if ( (ucode_seq_addr==`UCODE_NO_INSTRUCTION) && (ucode_seq_addr_entry!=`UCODE_NO_INSTRUCTION) )begin
|
if ( (ucode_seq_addr==`UCODE_NO_INSTRUCTION) && (ucode_seq_addr_entry!=`UCODE_NO_INSTRUCTION) )begin
|
||||||
/*switch to microcode decoding*/
|
/*switch to microcode decoding*/
|
||||||
ucode_seq_addr=ucode_seq_addr_entry;
|
ucode_seq_addr <= ucode_seq_addr_entry;
|
||||||
SIMPLE_MICRO=1;
|
SIMPLE_MICRO <= 1;
|
||||||
/*keep state the same and rerun decode this time with all the data from the microcode rom*/
|
/*keep state the same and rerun decode this time with all the data from the microcode rom*/
|
||||||
end else begin
|
end else begin
|
||||||
state=next_state;
|
state <= next_state;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`PROC_DE_LOAD_REG_TO_PARAM:begin
|
`PROC_DE_LOAD_REG_TO_PARAM:begin
|
||||||
PARAM2=reg_read_port2_data;
|
PARAM2<=reg_read_port2_data;
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state=`PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state=`PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`PROC_DE_LOAD_8_PARAM:begin
|
`PROC_DE_LOAD_8_PARAM:begin
|
||||||
if(opcode_size==0)begin
|
if(opcode_size==0)begin
|
||||||
if({Sbit,Wbit}==2'b11)begin
|
if({Sbit,Wbit}==2'b11)begin
|
||||||
/*signed "16bit" read*/
|
/*signed "16bit" read*/
|
||||||
PARAM1 = {{8{CIR[7:7]}},CIR[7:0]};
|
PARAM1 <= {{8{CIR[7:7]}},CIR[7:0]};
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[7:0] = CIR[7:0];
|
PARAM1[7:0] <= CIR[7:0];
|
||||||
end
|
end
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state=`PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state=`PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end else begin
|
end else begin
|
||||||
if(ProgCount[0:0]==1)begin
|
if(ProgCount[0:0]==1)begin
|
||||||
if({Sbit,Wbit}==2'b11)begin
|
if({Sbit,Wbit}==2'b11)begin
|
||||||
/*signed "16bit" read*/
|
/*signed "16bit" read*/
|
||||||
PARAM1 = {{8{external_data_bus[15:15]}},external_data_bus[15:8]};
|
PARAM1 <= {{8{external_data_bus[15:15]}},external_data_bus[15:8]};
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[7:0] = external_data_bus[15:8];
|
PARAM1[7:0] <= external_data_bus[15:8];
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if({Sbit,Wbit}==2'b11)begin
|
if({Sbit,Wbit}==2'b11)begin
|
||||||
/*signed "16bit" read*/
|
/*signed "16bit" read*/
|
||||||
PARAM1 = {{8{external_data_bus[7:7]}},external_data_bus[7:0]};
|
PARAM1 <= {{8{external_data_bus[7:7]}},external_data_bus[7:0]};
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[7:0] = external_data_bus[7:0];
|
PARAM1[7:0] <= external_data_bus[7:0];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ProgCount=ProgCount+1;
|
ProgCount <= ProgCount+1;
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state=`PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state=`PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`PROC_DE_LOAD_16_PARAM:begin
|
`PROC_DE_LOAD_16_PARAM:begin
|
||||||
if(opcode_size==0)begin
|
if(opcode_size==0)begin
|
||||||
PARAM1[7:0] = CIR[7:0];
|
PARAM1[7:0] <= CIR[7:0];
|
||||||
if(ProgCount[0:0]==1)begin
|
if(ProgCount[0:0]==1)begin
|
||||||
PARAM1[15:8] = external_data_bus[15:8];
|
PARAM1[15:8] <= external_data_bus[15:8];
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[15:8] = external_data_bus[7:0];
|
PARAM1[15:8] <= external_data_bus[7:0];
|
||||||
end
|
end
|
||||||
ProgCount=ProgCount+1;
|
ProgCount <= ProgCount+1;
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state=`PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state=`PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end else begin
|
end else begin
|
||||||
if(ProgCount[0:0]==1)begin
|
if(ProgCount[0:0]==1)begin
|
||||||
ProgCount=ProgCount+1;
|
ProgCount <= ProgCount+1;
|
||||||
PARAM1[7:0] = external_data_bus[15:8];
|
PARAM1[7:0] <= external_data_bus[15:8];
|
||||||
state=`PROC_DE_LOAD_16_EXTRA_FETCH_SET;
|
state <= `PROC_DE_LOAD_16_EXTRA_FETCH_SET;
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1 = external_data_bus;
|
PARAM1 <= external_data_bus;
|
||||||
ProgCount=ProgCount+2;
|
ProgCount <= ProgCount+2;
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state=`PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state=`PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`PROC_DE_LOAD_16_EXTRA_FETCH_SET:begin
|
`PROC_DE_LOAD_16_EXTRA_FETCH_SET:begin
|
||||||
external_address_bus = ProgCount;
|
external_address_bus <= {4'b0,ProgCount};
|
||||||
state=`PROC_DE_LOAD_16_EXTRA_FETCH;
|
state <= `PROC_DE_LOAD_16_EXTRA_FETCH;
|
||||||
end
|
end
|
||||||
`PROC_DE_LOAD_16_EXTRA_FETCH:begin
|
`PROC_DE_LOAD_16_EXTRA_FETCH:begin
|
||||||
ProgCount=ProgCount+1;
|
ProgCount <= ProgCount+1;
|
||||||
PARAM1[15:8] = external_data_bus[7:0];
|
PARAM1[15:8] <= external_data_bus[7:0];
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state=`PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state=`PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_READ:begin
|
`PROC_MEMIO_READ:begin
|
||||||
@ -401,13 +405,13 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
3'b100:begin
|
3'b100:begin
|
||||||
/*[SI]*/
|
/*[SI]*/
|
||||||
reg_read_port1_addr=4'b1110;
|
reg_read_port1_addr <= 4'b1110;
|
||||||
state=`PROC_MEMIO_READ_SETADDR;
|
state <= `PROC_MEMIO_READ_SETADDR;
|
||||||
end
|
end
|
||||||
3'b101:begin
|
3'b101:begin
|
||||||
/*[DI]*/
|
/*[DI]*/
|
||||||
reg_read_port1_addr=4'b1111;
|
reg_read_port1_addr <= 4'b1111;
|
||||||
state=`PROC_MEMIO_READ_SETADDR;
|
state <= `PROC_MEMIO_READ_SETADDR;
|
||||||
end
|
end
|
||||||
3'b110:begin
|
3'b110:begin
|
||||||
/*d16 */
|
/*d16 */
|
||||||
@ -415,8 +419,8 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
3'b111:begin
|
3'b111:begin
|
||||||
/*[BX]*/
|
/*[BX]*/
|
||||||
reg_read_port1_addr=4'b1011;
|
reg_read_port1_addr <= 4'b1011;
|
||||||
state=`PROC_MEMIO_READ_SETADDR;
|
state <= `PROC_MEMIO_READ_SETADDR;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
if(IN_MOD!=3'b000)begin
|
if(IN_MOD!=3'b000)begin
|
||||||
@ -425,8 +429,8 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
3'b110:begin /* SP Indirect read*/
|
3'b110:begin /* SP Indirect read*/
|
||||||
reg_read_port1_addr=4'b1100;
|
reg_read_port1_addr <= 4'b1100;
|
||||||
state=`PROC_MEMIO_READ_SETADDR;
|
state <= `PROC_MEMIO_READ_SETADDR;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`invalid_instruction
|
`invalid_instruction
|
||||||
@ -434,32 +438,32 @@ always @(posedge clock) begin
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_READ_SETADDR:begin
|
`PROC_MEMIO_READ_SETADDR:begin
|
||||||
external_address_bus = {5'b0000,reg_read_port1_data[15:0]};
|
external_address_bus <= {4'b0,reg_read_port1_data[15:0]};
|
||||||
state=reg_read_port1_data[0:0]?`PROC_MEMIO_GET_UNALIGNED_DATA:`PROC_MEMIO_GET_ALIGNED_DATA;
|
state <= reg_read_port1_data[0:0]?`PROC_MEMIO_GET_UNALIGNED_DATA:`PROC_MEMIO_GET_ALIGNED_DATA;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_GET_ALIGNED_DATA:begin
|
`PROC_MEMIO_GET_ALIGNED_DATA:begin
|
||||||
PARAM2=(Wbit==1)? external_data_bus : {8'b00000000,external_data_bus[7:0]} ;
|
PARAM2 <= (Wbit==1)? external_data_bus : {8'b0,external_data_bus[7:0]} ;
|
||||||
state=`PROC_EX_STATE_ENTRY;
|
state <= `PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_GET_UNALIGNED_DATA:begin
|
`PROC_MEMIO_GET_UNALIGNED_DATA:begin
|
||||||
PARAM2={8'b00000000,external_data_bus[15:8]};
|
PARAM2 <= {8'b0,external_data_bus[15:8]};
|
||||||
if(Wbit==1) begin
|
if(Wbit==1) begin
|
||||||
state=`PROC_MEMIO_GET_SECOND_BYTE;
|
state <= `PROC_MEMIO_GET_SECOND_BYTE;
|
||||||
end else begin
|
end else begin
|
||||||
state=`PROC_EX_STATE_ENTRY;
|
state <= `PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_GET_SECOND_BYTE:begin
|
`PROC_MEMIO_GET_SECOND_BYTE:begin
|
||||||
external_address_bus=external_address_bus+1;
|
external_address_bus <= external_address_bus+1;
|
||||||
state=`PROC_MEMIO_GET_SECOND_BYTE1;
|
state <= `PROC_MEMIO_GET_SECOND_BYTE1;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_GET_SECOND_BYTE1:begin
|
`PROC_MEMIO_GET_SECOND_BYTE1:begin
|
||||||
PARAM2[15:8]=external_data_bus[7:0];
|
PARAM2[15:8] <= external_data_bus[7:0];
|
||||||
state=`PROC_EX_STATE_ENTRY;
|
state <= `PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
`PROC_EX_STATE_ENTRY:begin
|
`PROC_EX_STATE_ENTRY:begin
|
||||||
external_address_bus = ProgCount;
|
external_address_bus <= {4'b0,ProgCount};
|
||||||
FLAGS[7:0] = ALU_1FLAGS[7:0];
|
FLAGS[7:0] <= ALU_1FLAGS[7:0];
|
||||||
case(OUT_MOD)
|
case(OUT_MOD)
|
||||||
3'b000,
|
3'b000,
|
||||||
3'b001,
|
3'b001,
|
||||||
@ -483,13 +487,13 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
3'b100:begin
|
3'b100:begin
|
||||||
/*[SI]*/
|
/*[SI]*/
|
||||||
reg_read_port1_addr=4'b1110;
|
reg_read_port1_addr <= 4'b1110;
|
||||||
state=`PROC_MEMIO_WRITE;
|
state <= `PROC_MEMIO_WRITE;
|
||||||
end
|
end
|
||||||
3'b101:begin
|
3'b101:begin
|
||||||
/*[DI]*/
|
/*[DI]*/
|
||||||
reg_read_port1_addr=4'b1111;
|
reg_read_port1_addr <= 4'b1111;
|
||||||
state=`PROC_MEMIO_WRITE;
|
state <= `PROC_MEMIO_WRITE;
|
||||||
end
|
end
|
||||||
3'b110:begin
|
3'b110:begin
|
||||||
/*d16 */
|
/*d16 */
|
||||||
@ -497,35 +501,35 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
3'b111:begin
|
3'b111:begin
|
||||||
/*[BX]*/
|
/*[BX]*/
|
||||||
reg_read_port1_addr=4'b1011;
|
reg_read_port1_addr <= 4'b1011;
|
||||||
state=`PROC_MEMIO_WRITE;
|
state <= `PROC_MEMIO_WRITE;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
3'b011:begin
|
3'b011:begin
|
||||||
reg_write_we=0;
|
reg_write_we <= 0;
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state=`PROC_IF_STATE_ENTRY;
|
state <= `PROC_IF_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state=`PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
end
|
end
|
||||||
3'b100:begin /*No output*/
|
3'b100:begin /*No output*/
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state=`PROC_IF_STATE_ENTRY;
|
state <= `PROC_IF_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state=`PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
end
|
end
|
||||||
3'b101:begin /* Program Counter*/
|
3'b101:begin /* Program Counter*/
|
||||||
ProgCount={5'b0000,ALU_1O[15:0]};
|
ProgCount <= ALU_1O[15:0];
|
||||||
instruction_size_init=1;
|
instruction_size_init <= 1;
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state=`PROC_IF_STATE_ENTRY;
|
state <= `PROC_IF_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state=`PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
end
|
end
|
||||||
3'b110:begin /* SP Indirect write*/
|
3'b110:begin /* SP Indirect write*/
|
||||||
reg_read_port1_addr=4'b1100;
|
reg_read_port1_addr <= 4'b1100;
|
||||||
state=`PROC_MEMIO_WRITE;
|
state <= `PROC_MEMIO_WRITE;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`invalid_instruction
|
`invalid_instruction
|
||||||
@ -537,65 +541,66 @@ always @(posedge clock) begin
|
|||||||
`ifdef DEBUG_MEMORY_WRITES
|
`ifdef DEBUG_MEMORY_WRITES
|
||||||
$display("Writing at %04x , %04x",reg_read_port1_data,ALU_1O);
|
$display("Writing at %04x , %04x",reg_read_port1_data,ALU_1O);
|
||||||
`endif
|
`endif
|
||||||
external_address_bus = {5'b0000,reg_read_port1_data[15:0]};
|
external_address_bus <= {4'b0,reg_read_port1_data[15:0]};
|
||||||
state = (Wbit==0) ? `PROC_MEMIO_PUT_BYTE : (reg_read_port1_data[0:0]?`PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA:`PROC_MEMIO_PUT_ALIGNED_16BIT_DATA) ;
|
state <= (Wbit==0) ? `PROC_MEMIO_PUT_BYTE : (reg_read_port1_data[0:0]?`PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA:`PROC_MEMIO_PUT_ALIGNED_16BIT_DATA) ;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA:begin
|
`PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA:begin
|
||||||
read=1;
|
read <= 1;
|
||||||
BHE=0;
|
BHE <= 0;
|
||||||
data_bus_output_register={ALU_1O[7:0],ALU_1O[15:8]};
|
data_bus_output_register <= {ALU_1O[7:0],ALU_1O[15:8]};
|
||||||
state=`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT;
|
state <= `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT:begin
|
`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT:begin
|
||||||
write=0;
|
write <= 0;
|
||||||
state=`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2;
|
state <= `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2:begin
|
`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2:begin
|
||||||
write=1;
|
write <= 1;
|
||||||
external_address_bus=external_address_bus+1;
|
external_address_bus <= external_address_bus+1;
|
||||||
BHE=1;
|
BHE <= 1;
|
||||||
state=`PROC_MEMIO_WRITE_EXIT;
|
state <= `PROC_MEMIO_WRITE_EXIT;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_PUT_ALIGNED_16BIT_DATA:begin
|
`PROC_MEMIO_PUT_ALIGNED_16BIT_DATA:begin
|
||||||
read=1;
|
read <= 1;
|
||||||
data_bus_output_register={ALU_1O[15:8],ALU_1O[7:0]};
|
data_bus_output_register <= {ALU_1O[15:8],ALU_1O[7:0]};
|
||||||
state=`PROC_MEMIO_WRITE_EXIT;
|
state <= `PROC_MEMIO_WRITE_EXIT;
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_PUT_BYTE:begin
|
`PROC_MEMIO_PUT_BYTE:begin
|
||||||
read=1;
|
read <= 1;
|
||||||
state=`PROC_MEMIO_WRITE_EXIT;
|
state <= `PROC_MEMIO_WRITE_EXIT;
|
||||||
if(reg_read_port1_data[0:0]==0) begin
|
if(reg_read_port1_data[0:0]==0) begin
|
||||||
BHE=1;
|
BHE <= 1;
|
||||||
data_bus_output_register={8'b0,ALU_1O[7:0]};
|
data_bus_output_register <= {8'b0,ALU_1O[7:0]};
|
||||||
end else begin
|
end else begin
|
||||||
data_bus_output_register={ALU_1O[7:0],8'b0};
|
data_bus_output_register <= {ALU_1O[7:0],8'b0};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_WRITE_EXIT:begin
|
`PROC_MEMIO_WRITE_EXIT:begin
|
||||||
write=0;
|
write <= 0;
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state=`PROC_IF_STATE_ENTRY;
|
state <= `PROC_IF_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state=`PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
end
|
end
|
||||||
`PROC_NEXT_MICROCODE:begin
|
`PROC_NEXT_MICROCODE:begin
|
||||||
read=0;
|
read <= 0;
|
||||||
write=1; // maybe we are coming from MEMIO_WRITE
|
write <= 1; // maybe we are coming from MEMIO_WRITE
|
||||||
BHE=0;
|
BHE <= 0;
|
||||||
ucode_seq_addr=ucode_seq_addr_entry; /*Reused for next address*/
|
ucode_seq_addr <= ucode_seq_addr_entry; /*Reused for next address*/
|
||||||
if( ucode_seq_addr == `UCODE_NO_INSTRUCTION )begin
|
if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin
|
||||||
/*Finished microcode*/
|
/*Finished microcode*/
|
||||||
SIMPLE_MICRO=0;
|
SIMPLE_MICRO <= 0;
|
||||||
state=`PROC_IF_STATE_ENTRY;
|
state <= `PROC_IF_STATE_ENTRY;
|
||||||
end else begin
|
end else begin
|
||||||
state=`PROC_DE_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
reg_write_we=1;
|
reg_write_we <= 1;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
`undef invalid_instruction
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -34,11 +34,11 @@ reg [15:0] registers [7:0];
|
|||||||
|
|
||||||
assign read_port1_data[15:8] = read_port1_addr[3:3] ? registers[read_port1_addr[2:0]][15:8] : 8'hz ;
|
assign read_port1_data[15:8] = read_port1_addr[3:3] ? registers[read_port1_addr[2:0]][15:8] : 8'hz ;
|
||||||
assign read_port1_data[7:0] = ( read_port1_addr[3:3] ? registers[read_port1_addr[2:0]][7:0] :
|
assign read_port1_data[7:0] = ( read_port1_addr[3:3] ? registers[read_port1_addr[2:0]][7:0] :
|
||||||
( read_port1_addr[2:2] ? {8'b0,registers[read_port1_addr[1:0]][15:8]} : {8'b0,registers[read_port1_addr[1:0]][7:0]} ) );
|
( read_port1_addr[2:2] ? registers[ {1'b0,read_port1_addr[1:0]} ][15:8] : registers[ {1'b0,read_port1_addr[1:0]} ][7:0] ) );
|
||||||
|
|
||||||
assign read_port2_data[15:8] = read_port2_addr[3:3] ? registers[read_port2_addr[2:0]][15:8] : 8'hz ;
|
assign read_port2_data[15:8] = read_port2_addr[3:3] ? registers[read_port2_addr[2:0]][15:8] : 8'hz ;
|
||||||
assign read_port2_data[7:0] = ( read_port2_addr[3:3] ? registers[read_port2_addr[2:0]][7:0] :
|
assign read_port2_data[7:0] = ( read_port2_addr[3:3] ? registers[read_port2_addr[2:0]][7:0] :
|
||||||
( read_port2_addr[2:2] ? {8'b0,registers[read_port2_addr[1:0]][15:8]} : {8'b0,registers[read_port2_addr[1:0]][7:0]} ) );
|
( read_port2_addr[2:2] ? registers[ {1'b0,read_port2_addr[1:0]} ][15:8] : registers[ {1'b0,read_port2_addr[1:0]} ][7:0] ) );
|
||||||
|
|
||||||
`ifdef DEBUG_REG_WRITES
|
`ifdef DEBUG_REG_WRITES
|
||||||
string debug_name;
|
string debug_name;
|
||||||
@ -50,15 +50,15 @@ assign write_Wbit=write_port1_addr[3:3];
|
|||||||
always @(negedge write_port1_we) begin
|
always @(negedge write_port1_we) begin
|
||||||
if(write_Wbit==1)begin
|
if(write_Wbit==1)begin
|
||||||
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
|
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
|
||||||
registers[write_port1_addr[2:0]]=write_port1_data;
|
registers[write_port1_addr[2:0]] <= write_port1_data;
|
||||||
end else begin
|
end else begin
|
||||||
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
|
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
|
||||||
if(write_port1_addr[2:2]==1)begin
|
if(write_port1_addr[2:2]==1)begin
|
||||||
/* Byte */
|
/* Byte */
|
||||||
registers[write_port1_addr[1:0]][15:8]=write_port1_data[7:0];
|
registers[ {1'b0,write_port1_addr[1:0]} ][15:8] <= write_port1_data[7:0];
|
||||||
end else begin
|
end else begin
|
||||||
/* Byte */
|
/* Byte */
|
||||||
registers[write_port1_addr[1:0]][7:0]=write_port1_data[7:0];
|
registers[ {1'b0,write_port1_addr[1:0]} ][7:0] <= write_port1_data[7:0];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -46,10 +46,12 @@ initial begin
|
|||||||
$dumpfile(waveform_name);
|
$dumpfile(waveform_name);
|
||||||
$dumpvars(0,p,u1);
|
$dumpvars(0,p,u1);
|
||||||
end
|
end
|
||||||
reset = 0;
|
|
||||||
clk_enable = 1;
|
clk_enable = 1;
|
||||||
|
|
||||||
#($random%500)
|
reset = 1;
|
||||||
|
#(`CPU_SPEED*2)
|
||||||
|
reset = 0;
|
||||||
|
#($random%1000)
|
||||||
#(`CPU_SPEED)
|
#(`CPU_SPEED)
|
||||||
reset = 1;
|
reset = 1;
|
||||||
end
|
end
|
||||||
@ -76,6 +78,8 @@ end
|
|||||||
always @(posedge clock)begin
|
always @(posedge clock)begin
|
||||||
if(reset==1)
|
if(reset==1)
|
||||||
cycles=cycles+1;
|
cycles=cycles+1;
|
||||||
|
else
|
||||||
|
cycles=0;
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -17,14 +17,14 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
`define UCODE_ADDR_BITS 5
|
|
||||||
`define UCODE_DATA_BITS 38
|
|
||||||
`define UCODE_SIZE 12
|
`define UCODE_SIZE 12
|
||||||
|
`define UCODE_DATA_BITS 38
|
||||||
|
`define UCODE_ADDR_BITS $clog2(`UCODE_SIZE)
|
||||||
|
|
||||||
/* DEFINE ADDRESSES IN THE MICROCODE */
|
/* DEFINE ADDRESSES IN THE MICROCODE */
|
||||||
`define UCODE_NO_INSTRUCTION 5'b00000
|
`define UCODE_NO_INSTRUCTION 4'b0000
|
||||||
`define UCODE_CALL_ENTRY 5'b00001
|
`define UCODE_CALL_ENTRY 4'b0001
|
||||||
`define UCODE_RET_ENTRY 5'b00100
|
`define UCODE_RET_ENTRY 4'b0100
|
||||||
`define UCODE_STOS_ENTRY 5'b00110
|
`define UCODE_STOS_ENTRY 4'b0110
|
||||||
`define UCODE_PUSH_ENTRY 5'b01000
|
`define UCODE_PUSH_ENTRY 4'b1000
|
||||||
`define UCODE_POP_ENTRY 5'b01010
|
`define UCODE_POP_ENTRY 4'b1010
|
||||||
|
Loading…
Reference in New Issue
Block a user