diff --git a/gtkwave_savefile.gtkw b/gtkwave_savefile.gtkw index c347388..68b2324 100644 --- a/gtkwave_savefile.gtkw +++ b/gtkwave_savefile.gtkw @@ -1,23 +1,24 @@ [*] [*] GTKWave Analyzer v3.3.111 (w)1999-2020 BSI -[*] Sun May 7 11:35:53 2023 +[*] Thu May 11 08:14:36 2023 [*] [dumpfile] "/home/user/9086/system/boot_code.fst" -[dumpfile_mtime] "Sun May 7 11:35:19 2023" -[dumpfile_size] 13013 +[dumpfile_mtime] "Thu May 11 08:13:23 2023" +[dumpfile_size] 2215158 [savefile] "/home/user/9086/gtkwave_savefile.gtkw" -[timestart] 500000000 -[size] 1524 993 +[timestart] 29810000000 +[size] 1236 993 [pos] -1 -1 -*-36.395050 127070000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +*-31.895050 34640000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [treeopen] TOP. [treeopen] TOP.system. [treeopen] TOP.system.p. [treeopen] TOP.system.p.BIU. +[treeopen] TOP.system.p.execute_unit. [sst_width] 263 [signals_width] 293 [sst_expanded] 1 -[sst_vpaned_height] 312 +[sst_vpaned_height] 295 @28 TOP.system.clock TOP.system.reset @@ -31,13 +32,10 @@ TOP.system.p.write TOP.system.IOMEM TOP.system.p.ERROR[2:0] TOP.system.p.HALT -@29 -TOP.system.p.state[3:0] @22 TOP.system.p.BIU.INSTRUCTION[31:0] @28 TOP.system.p.BIU.VALID_INSTRUCTION -TOP.system.p.BIU.NEXT_POSITION[1:0] @22 TOP.system.p.BIU.FIFO_end[3:0] TOP.system.p.BIU.FIFO_start[3:0] @@ -58,5 +56,12 @@ TOP.system.p.BIU.INPUT_FIFO[13][7:0] TOP.system.p.BIU.INPUT_FIFO[14][7:0] TOP.system.p.BIU.INPUT_FIFO[15][7:0] TOP.system.p.ucode_seq_addr[4:0] +@28 +TOP.system.p.execute_unit.exec_state[3:0] +TOP.system.p.state[2:0] +TOP.system.p.valid_exec_data +TOP.system.p.reg_write_we +@29 +TOP.system.p.SIMPLE_MICRO [pattern_trace] 1 [pattern_trace] 0 diff --git a/system/Makefile b/system/Makefile index 33d1e2a..5ac9085 100644 --- a/system/Makefile +++ b/system/Makefile @@ -16,10 +16,10 @@ # along with this program. If not, see . # TOP_LEVEL_SOURCE=system.v -SOURCES=processor.v memory.v registers.v alu.v decoder.v general.v biu.v +SOURCES=processor.v memory.v registers.v alu.v decoder.v general.v biu.v execute.v EVENT_SIM_TESTBENCH=testbench.v VERILATOR_TESTBENCH=testbench.cpp -INCLUDES=proc_state_def.v alu_header.v config.v ucode_header.v +INCLUDES=exec_state_def.v alu_header.v config.v ucode_header.v SYSTEM_VVP=system.vvp VERILATOR_BIN=obj_dir/Vsystem BOOT_CODE=boot_code.txt diff --git a/system/decoder.v b/system/decoder.v index 3dbfa5e..1a908c2 100644 --- a/system/decoder.v +++ b/system/decoder.v @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -`include "proc_state_def.v" +`include "exec_state_def.v" `include "alu_header.v" `include "ucode_header.v" `include "error_header.v" @@ -45,13 +45,12 @@ endmodule // verilator lint_off UNUSEDSIGNAL module decoder( - input wire [15:0] CIR,input wire [15:0] FLAGS, output wire [2:0] INSTRUCTION_INFO, output wire [`ERROR_BITS: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 [`ERROR_BITS:0] DECODER_SIGNALS, output reg [`EXEC_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 [1:0]in_alu1_sel1,output reg [1:0]in_alu1_sel2,output reg [2:0]OUT_MOD + ,output reg [1:0]in_alu_sel1,output reg [1:0]in_alu_sel2,output reg [2:0]OUT_MOD ,output wire [11:0]REGISTER_FILE_CONTROL ,output reg [2:0]ALU_1OP ,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 memio_address_select ,output reg MEM_OR_IO ); @@ -78,12 +77,12 @@ wire [`UCODE_DATA_BITS-1:0] ucode_data; microcode ucode(seq_addr_input,ucode_data); -`define invalid_instruction next_state=`PROC_DE_STATE_ENTRY;ERROR<=`ERR_UNIMPL_INSTRUCTION;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION; +`define invalid_instruction next_state=`EXEC_DONE;ERROR<=`ERR_UNIMPL_INSTRUCTION;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION; //TODO: A possible optimisation for instruction with 8bit parameter and //opcode_size=0 would be to set PARAM1 here instead of sending execution over -//to PROC_DE_LOAD_8_PARAM +//to EXEC_DE_LOAD_8_PARAM `define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO=0; `define normal_microcoded ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO=0; @@ -98,16 +97,11 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin 11'b0000_010?_??? : begin /* ADD - Add Immediate word/byte to accumulator */ /* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/ - opcode_size=0; + opcode_size=0; //TODO: move the decoding done in BIU here and use theat size checker Wbit=CIR[8:8]; - if(Wbit)begin - instruction_size=3; - end else begin - instruction_size=2; - end IN_MOD=3'b011; - in_alu1_sel1=2'b00; - in_alu1_sel2=2'b01; + in_alu_sel1=2'b00; + in_alu_sel2=2'b01; OUT_MOD=3'b011; MEM_OR_IO=0; reg_read_port2_addr={Wbit,3'b000}; @@ -115,9 +109,9 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin ALU_1OP=`ALU_OP_ADD; memio_address_select=0; if(Wbit) - next_state=`PROC_DE_LOAD_16_PARAM; + next_state=`EXEC_DE_LOAD_16_PARAM; else - next_state=`PROC_DE_LOAD_8_PARAM; + next_state=`EXEC_DE_LOAD_8_PARAM; `normal_instruction; end 11'b1000_00??_101, /* SUB */ @@ -131,25 +125,23 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin Sbit=CIR[9:9]; IN_MOD={1'b0,CIR[7:6]}; RM=CIR[2:0]; - in_alu1_sel1=2'b00; + in_alu_sel1=2'b00; if(IN_MOD==3'b011)begin - in_alu1_sel2=2'b01; + in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; reg_write_addr={Wbit,RM}; end else begin - in_alu1_sel2=2'b00; + in_alu_sel2=2'b00; end OUT_MOD=IN_MOD; MEM_OR_IO=0; memio_address_select=0; case({Sbit,Wbit}) 2'b00,2'b11:begin - next_state=`PROC_DE_LOAD_8_PARAM; - instruction_size=3; + next_state=`EXEC_DE_LOAD_8_PARAM; end 2'b01:begin - next_state=`PROC_DE_LOAD_16_PARAM; - instruction_size=4; + next_state=`EXEC_DE_LOAD_16_PARAM; end default:begin `invalid_instruction @@ -173,32 +165,24 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin Sbit=CIR[9:9]; IN_MOD={1'b0,CIR[7:6]}; RM=CIR[2:0]; - case({Sbit,Wbit}) - 2'b00,2'b11:begin - instruction_size=3; - end - 2'b01:begin - instruction_size=4; - end - 2'b10:begin - `invalid_instruction - end - endcase - in_alu1_sel1=2'b00; + if ( {Sbit,Wbit} == 2'b10 )begin + `invalid_instruction + end + in_alu_sel1=2'b00; OUT_MOD=3'b100; MEM_OR_IO=0; ALU_1OP=`ALU_OP_SUB; memio_address_select=0; if(IN_MOD==3'b011)begin /*compare register with param*/ - in_alu1_sel2=2'b01; + in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; - next_state=`PROC_DE_LOAD_8_PARAM; + next_state=`EXEC_DE_LOAD_8_PARAM; end else begin /*compare register indirect access * with param */ - in_alu1_sel2=2'b00; - next_state=`PROC_DE_LOAD_16_PARAM; /*will then call MEMIO_READ*/ + in_alu_sel2=2'b00; + next_state=`EXEC_DE_LOAD_16_PARAM; /*will then call MEMIO_READ*/ end `normal_instruction; end @@ -206,35 +190,33 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* MOV - Move Immediate byte to register */ /* 1 0 1 1 W REG | DATA | DATA if W |*/ Wbit=CIR[11:11]; /* IS 0 */ - instruction_size=2; opcode_size=0; IN_MOD=3'b011; - in_alu1_sel1=2'b00; - in_alu1_sel2=2'b00; + in_alu_sel1=2'b00; + in_alu_sel2=2'b00; OUT_MOD=3'b011; MEM_OR_IO=0; reg_write_addr={1'b0,CIR[10:8]}; PARAM1[7:0]=CIR[7:0]; PARAM2=0; ALU_1OP=`ALU_OP_ADD; - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; `normal_instruction; memio_address_select=0; end 11'b1011_1???_??? : begin /*MOV - Move Immediate word to register*/ Wbit=CIR[11:11]; /*IS 1 */ - instruction_size=3; opcode_size=0; IN_MOD=3'b011; - in_alu1_sel1=2'b00; - in_alu1_sel2=2'b00; + in_alu_sel1=2'b00; + in_alu_sel2=2'b00; OUT_MOD=3'b011; MEM_OR_IO=0; reg_write_addr={1'b1,CIR[10:8]}; ALU_1OP=`ALU_OP_ADD; PARAM2=0; - next_state=`PROC_DE_LOAD_16_PARAM; + next_state=`EXEC_DE_LOAD_16_PARAM; `normal_instruction; memio_address_select=0; end @@ -242,10 +224,9 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* MOV - Reg/Mem to/from register */ /* 1 0 0 0 1 0 D W | MOD REG RM | < DISP LO > | < DISP HI > |*/ opcode_size=1; - instruction_size=2; RM=CIR[2:0]; Wbit=CIR[8:8]; - in_alu1_sel1=2'b00; + in_alu_sel1=2'b00; PARAM1=0; MEM_OR_IO=0; if(CIR[9:9] == 1)begin @@ -253,13 +234,13 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin IN_MOD={1'b0,CIR[7:6]}; if(IN_MOD==3'b011)begin /*Reg to Reg*/ - in_alu1_sel2=2'b01; + in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end else begin /*Mem to Reg*/ - in_alu1_sel2=2'b00; - next_state=`PROC_MEMIO_READ; + in_alu_sel2=2'b00; + next_state=`EXEC_MEMIO_READ; end OUT_MOD=3'b011; reg_write_addr={Wbit,CIR[5:3]}; @@ -269,13 +250,13 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin OUT_MOD={1'b0,CIR[7:6]}; if(IN_MOD==3'b011)begin /*Reg to Reg*/ - in_alu1_sel2=2'b01; + in_alu_sel2=2'b01; reg_write_addr={Wbit,RM}; - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end else begin /*Reg to Mem*/ - in_alu1_sel2=2'b00; - next_state=`PROC_DE_LOAD_REG_TO_PARAM; + in_alu_sel2=2'b00; + next_state=`EXEC_DE_LOAD_REG_TO_PARAM; end reg_read_port2_addr={Wbit,CIR[5:3]}; end @@ -289,11 +270,10 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* | 0 1 0 0 1 REG | */ /* INC - Increment Register */ /* | 0 1 0 0 0 REG | */ - instruction_size=1; opcode_size=0; Wbit=1; - in_alu1_sel1=2'b01; - in_alu1_sel2=2'b00; + in_alu_sel1=2'b01; + in_alu_sel2=2'b00; OUT_MOD=3'b011; MEM_OR_IO=0; IN_MOD=3'b011; @@ -304,7 +284,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin ALU_1OP=`ALU_OP_ADD; else ALU_1OP=`ALU_OP_SUB; - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; `normal_instruction; memio_address_select=0; end @@ -313,13 +293,12 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* 1 1 1 1 1 1 1 W | MOD 0 0 0 R/M | < DISP LO> | < DISP HI> */ /* DEC - Register/Memory */ /* 1 1 1 1 1 1 1 W | MOD 0 0 1 R/M | < DISP LO> | < DISP HI> */ - instruction_size=2; opcode_size=1; Wbit=CIR[8:8]; IN_MOD={1'b0,CIR[7:6]}; RM=CIR[2:0]; - in_alu1_sel2=(IN_MOD==3'b011)? 2'b01 : 2'b00; - in_alu1_sel1=2'b00;/* number 1 */ + in_alu_sel2=(IN_MOD==3'b011)? 2'b01 : 2'b00; + in_alu_sel1=2'b00;/* number 1 */ PARAM1=1; OUT_MOD=IN_MOD; MEM_OR_IO=0; @@ -330,23 +309,22 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin ALU_1OP=(CIR[3:3]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD; if ( IN_MOD == 3'b011 ) - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; else - next_state=`PROC_MEMIO_READ; + next_state=`EXEC_MEMIO_READ; `normal_instruction; memio_address_select=0; end 11'b1111_0100_??? : begin /* HLT - Halt */ /* 1 1 1 1 0 1 0 0 | */ - instruction_size=1; opcode_size=0; IN_MOD=3'b011; HALT<=1; ERROR<=`ERR_NO_ERROR; MEM_OR_IO=0; seq_addr_entry<=`UCODE_NO_INSTRUCTION; - next_state=`PROC_HALT_STATE; + next_state=`EXEC_HALT; memio_address_select=0; end 11'b0011_110?_??? : begin @@ -357,23 +335,18 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* W flag and my assembler seem to disagree */ Wbit=CIR[8:8]; opcode_size=0; - if(Wbit)begin - instruction_size=3; - end else begin - instruction_size=2; - end IN_MOD=3'b011; - in_alu1_sel1=2'b00; - in_alu1_sel2=2'b01; + in_alu_sel1=2'b00; + in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,3'b000}; OUT_MOD=3'b100; ALU_1OP=`ALU_OP_SUB; MEM_OR_IO=0; if(Wbit==1) - next_state=`PROC_DE_LOAD_16_PARAM; + next_state=`EXEC_DE_LOAD_16_PARAM; else begin PARAM1[7:0]=CIR[7:0]; - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end `normal_instruction; memio_address_select=0; @@ -387,11 +360,10 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* JNS -Jump on not Sign */ /* 0 1 1 1 1 0 0 1 | IP-INC8 |*/ /* .... */ - instruction_size=2; Wbit=1; opcode_size=0; - in_alu1_sel1=2'b10; - in_alu1_sel2=2'b00; + in_alu_sel1=2'b10; + in_alu_sel2=2'b00; PARAM2={{8{CIR[7:7]}},CIR[7:0]}; ALU_1OP=`ALU_OP_ADD_SIGNED_B; MEM_OR_IO=0; @@ -400,31 +372,31 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin 3'b000: begin /* Jump on (not) Overflow */ if(FLAGS[11:11]==CIR[8:8]) - next_state=`PROC_NEXT_INSTRUCTION; + next_state=`EXEC_NEXT_INSTRUCTION; else begin - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end end 3'b010: begin /* Jump on (not) Zero */ if(FLAGS[6:6]==CIR[8:8]) - next_state=`PROC_NEXT_INSTRUCTION; + next_state=`EXEC_NEXT_INSTRUCTION; else - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end 3'b100: begin /* Jump on (not) Sign */ if(FLAGS[7:7]==CIR[8:8]) - next_state=`PROC_NEXT_INSTRUCTION; + next_state=`EXEC_NEXT_INSTRUCTION; else - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end 3'b101: begin /* Jump on (not) Parity */ if(FLAGS[2:2]==CIR[8:8]) - next_state=`PROC_NEXT_INSTRUCTION; + next_state=`EXEC_NEXT_INSTRUCTION; else - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end default:begin `invalid_instruction; /*We don't support that condition*/ @@ -436,16 +408,15 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin 11'b1110_1011_???:begin /* JMP - Unconditional jump direct within segment (short) */ /* | 1 1 1 0 1 0 1 1 | IP-INC-LO | */ - instruction_size=2; opcode_size=0; Wbit=1; - in_alu1_sel1=2'b10; - in_alu1_sel2=2'b00; + in_alu_sel1=2'b10; + in_alu_sel2=2'b00; PARAM2={{8{CIR[7:7]}},CIR[7:0]}; ALU_1OP=`ALU_OP_ADD_SIGNED_B; OUT_MOD=3'b101; MEM_OR_IO=0; - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; `normal_instruction; memio_address_select=0; end @@ -454,7 +425,6 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* 1 1 1 0 1 0 0 0 | IP-INC-LO | IP-INC-HI |*/ // Microcode instruction - instruction_size=3; opcode_size=0; Wbit=1; Sbit=1; @@ -468,7 +438,6 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* | 1 1 0 0 0 0 1 1 | */ // Microcode instruction - instruction_size=1; opcode_size=0; Wbit=1; Sbit=0; @@ -481,7 +450,6 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* STOS - Write byte/word to [DI] and increment accordingly */ /* | 1 0 1 0 1 0 1 W | */ opcode_size=0; - instruction_size=1; Wbit=CIR[8:8]; Sbit=0; RM=3'b101; @@ -494,7 +462,6 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* PUSH - SP-=2; [SP]=REG */ /* | 0 1 0 1 0 REG | */ opcode_size=0; - instruction_size=1; Wbit=1; Sbit=0; PARAM2=2; @@ -512,17 +479,15 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin RM={CIR[2:0]}; MEM_OR_IO=0; if(Wbit==1)begin - instruction_size=4; - next_state=`PROC_DE_LOAD_16_PARAM; + next_state=`EXEC_DE_LOAD_16_PARAM; end else begin - instruction_size=3; - next_state=`PROC_DE_LOAD_8_PARAM; + next_state=`EXEC_DE_LOAD_8_PARAM; end - in_alu1_sel1=2'b00; /* PARAM1 */ + in_alu_sel1=2'b00; /* PARAM1 */ ALU_1OP=`ALU_OP_AND; case(IN_MOD) 3'b011:begin - in_alu1_sel2=2'b01; + in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; end default:begin @@ -537,7 +502,6 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* POP - REG=[SP]; SP+=2 */ /* | 0 1 0 1 1 REG | */ opcode_size=0; - instruction_size=1; Wbit=1; Sbit=0; PARAM1=2; @@ -550,19 +514,18 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* JMP - Unconditional indirect within segment jump */ /* 1 1 1 1 1 1 1 1 | MOD 1 0 0 R/M | < DISP-LO > | < DISP-HI > */ opcode_size=1; - instruction_size=2; Wbit=1; IN_MOD={1'b0,CIR[7:6]}; RM=CIR[2:0]; MEM_OR_IO=0; - in_alu1_sel1=2'b11; + in_alu_sel1=2'b11; if (IN_MOD==3'b011)begin - in_alu1_sel2=2'b01; + in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; - next_state=`PROC_EX_STATE_ENTRY; + next_state=`EXEC_WRITE_ENTRY; end else begin - in_alu1_sel2=2'b00; - next_state=`PROC_MEMIO_READ; + in_alu_sel2=2'b00; + next_state=`EXEC_MEMIO_READ; end ALU_1OP=`ALU_OP_ADD; OUT_MOD=3'b101; @@ -574,15 +537,13 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* 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]; opcode_size=1; - in_alu1_sel1=2'b00; - in_alu1_sel2=2'b11; + in_alu_sel1=2'b00; + in_alu_sel2=2'b11; MEM_OR_IO=0; if(Wbit==1)begin - instruction_size=4; - next_state=`PROC_DE_LOAD_16_PARAM; + next_state=`EXEC_DE_LOAD_16_PARAM; end else begin - instruction_size=3; - next_state=`PROC_DE_LOAD_8_PARAM; + next_state=`EXEC_DE_LOAD_8_PARAM; end OUT_MOD={1'b0,CIR[7:6]}; @@ -600,7 +561,6 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin // [skipped] 4) fetch CS from interrupt table // 5) push ProgCount // 6) fetch ProgCount from interrupt table - instruction_size=2; opcode_size=0; Wbit=1; Sbit=0; @@ -615,11 +575,10 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin memio_address_select=1; Wbit=CIR[8:8]; opcode_size=0; - instruction_size=2; - in_alu1_sel1=2'b00; - in_alu1_sel2=2'b11; + in_alu_sel1=2'b00; + in_alu_sel2=2'b11; reg_read_port1_addr={Wbit,3'b000}; - next_state=`PROC_DE_LOAD_8_PARAM; + next_state=`EXEC_DE_LOAD_8_PARAM; MEM_OR_IO=1; HALT <= 0; PARAM1=0; @@ -631,7 +590,6 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* | 1 1 0 0 1 1 1 1 | */ // Since we only push one thing on the stack // on INT we can just reuse the code from RET - instruction_size=1; opcode_size=0; Wbit=1; Sbit=0; @@ -650,17 +608,17 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin //from when we ordered the switch to microcode seq_addr_entry <= ucode_data[`UCODE_ADDR_BITS-1:0]; case(ucode_data[8:6]) - 3'b000: next_state=`PROC_EX_STATE_ENTRY; - 3'b001: next_state=`PROC_DE_LOAD_16_PARAM; - 3'b010: next_state=`PROC_DE_LOAD_8_PARAM; - 3'b011: next_state=`PROC_MEMIO_READ; - 3'b100: next_state=`PROC_MEMIO_READ_SETADDR; + 3'b000: next_state=`EXEC_WRITE_ENTRY; + 3'b001: next_state=`EXEC_DE_LOAD_16_PARAM; + 3'b010: next_state=`EXEC_DE_LOAD_8_PARAM; + 3'b011: next_state=`EXEC_MEMIO_READ; + 3'b100: next_state=`EXEC_MEMIO_READ_SETADDR; default: begin end /*impossible*/ endcase if(ucode_data[36:36]==0) /*Set reg write address*/ reg_write_addr = ucode_data[12:9 ]; - in_alu1_sel1 = ucode_data[14:13]; - in_alu1_sel2 = ucode_data[16:15]; + in_alu_sel1 = ucode_data[14:13]; + in_alu_sel2 = ucode_data[16:15]; OUT_MOD = ucode_data[19:17]; /*1:1 map essentially but I want to keep the spec for these bits separate * from the alu op select bits*/ diff --git a/system/proc_state_def.v b/system/exec_state_def.v similarity index 60% rename from system/proc_state_def.v rename to system/exec_state_def.v index 8203c0a..97d9d2b 100644 --- a/system/proc_state_def.v +++ b/system/exec_state_def.v @@ -1,4 +1,4 @@ -/* proc_state_def.v - Definitions of the states in the main state machine +/* exec_state_def.v - Definitions of the states in the main state machine of the 9086 CPU. This file is part of the 9086 project. @@ -18,29 +18,30 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -`define PROC_STATE_BITS 4 +`define EXEC_STATE_BITS 4 -`define PROC_HALT_STATE 4'b0000 +`define EXEC_HALT 4'b0000 + +`define EXEC_DONE 4'b1100 /*DECODE SATE*/ -`define PROC_DE_STATE_ENTRY 4'b0001 -`define PROC_DE_LOAD_16_PARAM 4'b0010 -`define PROC_DE_LOAD_REG_TO_PARAM 4'b0011 -`define PROC_DE_LOAD_8_PARAM 4'b0100 +`define EXEC_DE_LOAD_16_PARAM 4'b0010 +`define EXEC_DE_LOAD_REG_TO_PARAM 4'b0011 +`define EXEC_DE_LOAD_8_PARAM 4'b0100 /*MEM/IO READ*/ -`define PROC_MEMIO_READ 4'b0101 -`define PROC_MEMIO_READ_SETADDR 4'b0110 +`define EXEC_MEMIO_READ 4'b0101 +`define EXEC_MEMIO_READ_SETADDR 4'b0110 /*EXECUTE STATE*/ -`define PROC_EX_STATE_ENTRY 4'b1000 +`define EXEC_WRITE_ENTRY 4'b1000 /*MEM/IO WRITE*/ -`define PROC_MEMIO_WRITE 4'b0111 +`define EXEC_MEMIO_WRITE 4'b0111 -`define PROC_NEXT_INSTRUCTION 4'b1001 +`define EXEC_NEXT_INSTRUCTION 4'b1001 -`define PROC_NEXT_MICROCODE 4'b1010 +`define EXEC_NEXT_MICROCODE 4'b1010 -`define PROC_RESET 4'b1011 +`define EXEC_RESET 4'b1011 diff --git a/system/execute.v b/system/execute.v new file mode 100644 index 0000000..a72c199 --- /dev/null +++ b/system/execute.v @@ -0,0 +1,321 @@ +module execute_unit ( + /* GENERAL */ input clock, input reset ,input Wbit, input Sbit, input opcode_size,input [23:0] INSTRUCTION_BUFFER,input valid_input + /* */ ,input [2:0] IN_MOD, input [2:0] OUT_MOD, input memio_address_select, input [15:0] ProgCount, input [2:0] RM, output reg [`ERROR_BITS-1:0] ERROR , input write /*TODO: REMOVE!!*/ + /* */ ,input set_initial_values + /* PARAM */ ,input [15:0] PARAM1_INIT, input [15:0] PARAM2_INIT + /* STATE CONTROL */ ,output [`EXEC_STATE_BITS-1:0] _exec_state_, input [`EXEC_STATE_BITS-1:0] init_state + /* ALU CONTROL */ ,input [1:0] in_alu_sel1, input [1:0] in_alu_sel2, input [`ALU_OP_BITS-1:0] ALU_OP, output [15:0] _ALU_O_ + /* REGISTER DATA */ ,input [15:0] reg_read_port1_data ,input [15:0] reg_read_port2_data, output reg [3:0] reg_read_port1_addr, output reg use_exec_reg_addr, output reg reg_write_we + /* FLAFS */ ,output reg [7:0] FLAGS + /* BIU */ ,output reg [15:0] BIU_ADDRESS_INPUT,output reg biu_write_request, output reg biu_read_request, input BIU_VALID_DATA, input [15:0] BIU_DATA, output reg biu_data_direction, output reg biu_jump_req + ); + +assign _exec_state_ = exec_state; +assign _ALU_O_ = ALU_O; + +/*############ ALU / Execution units ########################################################## */ +// ALU 1 +reg [`EXEC_STATE_BITS-1:0] exec_state; + +reg [15:0] PARAM1,PARAM2; + +mux4 #(.WIDTH(16)) MUX16_1A( +/*0*/ PARAM1, +/*1*/ reg_read_port1_data, +/*2*/ ProgCount[15:0], +/*3*/ 16'd0, /*0 Constant*/ + in_alu_sel1, + ALU_A); + +mux4 #(.WIDTH(16)) MUX16_1B( +/*0*/ PARAM2, +/*1*/ reg_read_port2_data, +/*2*/ ProgCount[15:0], +/*3*/ 16'd0, /*0 Constant*/ + in_alu_sel2, + ALU_B); + +wire [15:0] ALU_A; +wire [15:0] ALU_B; +wire [15:0] ALU_O; +wire [7:0] ALU_FLAGS; + +ALU ALU1( + .A(ALU_A), + .B(ALU_B), + .OUT(ALU_O), + .op(ALU_OP), + .FLAGS(ALU_FLAGS), + .Wbit(Wbit) +); + +//reg valid_input_; + +always @(posedge valid_input) begin + exec_state <= init_state; + //valid_input_ <= 1; +end + +always @(negedge set_initial_values) begin + PARAM1 <= PARAM1_INIT; + PARAM2 <= PARAM2_INIT; +end +//always @(negedge valid_input) begin +// valid_input_ <= 0; +//end + +always @(negedge reset) begin + exec_state <= `EXEC_HALT; +end + +always @(posedge reset) begin + exec_state <= `EXEC_RESET; +end + +`define unimpl_addressing_mode exec_state <= `EXEC_DONE;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE; +always @(posedge clock) begin + case (exec_state) + `EXEC_RESET: begin + //valid_input_ <= 0; + biu_write_request <= 0; + biu_read_request <= 0; + biu_data_direction <= 0; + biu_jump_req <= 0; + reg_write_we <= 1; + exec_state <= `EXEC_DONE; + ERROR <= `ERR_NO_ERROR; + end + `EXEC_DONE:begin + reg_write_we <= 1; + //valid_input_ <= 0; + biu_jump_req <= 0; + use_exec_reg_addr <= 0; + end + `EXEC_DE_LOAD_REG_TO_PARAM:begin + PARAM2<=reg_read_port2_data; + case(IN_MOD) + 3'b000,3'b001,3'b010: exec_state <= `EXEC_MEMIO_READ; + default: exec_state <= `EXEC_WRITE_ENTRY; + endcase + end + `EXEC_DE_LOAD_8_PARAM:begin + if(opcode_size==0)begin + if({Sbit,Wbit}==2'b11)begin + /*signed "16bit" read*/ + PARAM1 <= {{8{INSTRUCTION_BUFFER[23:23]}},INSTRUCTION_BUFFER[23:16]}; + end else begin + PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16]; + end + case(IN_MOD) + 3'b000,3'b001,3'b010: exec_state <= `EXEC_MEMIO_READ; + default: exec_state <= `EXEC_WRITE_ENTRY; + endcase + end else begin + if({Sbit,Wbit}==2'b11)begin + /*signed "16bit" read*/ + PARAM1 <= {{8{INSTRUCTION_BUFFER[15:15]}},INSTRUCTION_BUFFER[15:8]}; + end else begin + PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8]; + end + end + case(IN_MOD) + 3'b000,3'b001,3'b010: exec_state <= `EXEC_MEMIO_READ; + default: exec_state <= `EXEC_WRITE_ENTRY; + endcase + end + `EXEC_DE_LOAD_16_PARAM:begin + if(opcode_size==0)begin + PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16]; + PARAM1[15:8] <= INSTRUCTION_BUFFER[15:8]; + end else begin + PARAM1[15:8] <= INSTRUCTION_BUFFER[7:0]; + PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8]; + end + case(IN_MOD) + 3'b000,3'b001,3'b010: exec_state <= `EXEC_MEMIO_READ; + default: exec_state <= `EXEC_WRITE_ENTRY; + endcase + end + `EXEC_MEMIO_READ:begin + /*Decode MOD R/M, read the data and place it to PARAM1*/ + case (IN_MOD) + 3'b000, + 3'b001, + 3'b010:begin + case (RM) + 3'b000:begin + /*[BX]+[SI]*/ + `unimpl_addressing_mode + end + 3'b001:begin + /*[BX]+[SI]*/ + `unimpl_addressing_mode + end + 3'b010:begin + /*[BP]+[SI]*/ + `unimpl_addressing_mode + end + 3'b011:begin + /*[BP]+[DI]*/ + `unimpl_addressing_mode + end + 3'b100:begin + /*[SI]*/ + reg_read_port1_addr <= 4'b1110; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_READ_SETADDR; + end + 3'b101:begin + /*[DI]*/ + reg_read_port1_addr <= 4'b1111; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_READ_SETADDR; + end + 3'b110:begin + /*d16 */ + `unimpl_addressing_mode + end + 3'b111:begin + /*[BX]*/ + reg_read_port1_addr <= 4'b1011; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_READ_SETADDR; + end + endcase + if(IN_MOD!=3'b000)begin + /*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/ + `unimpl_addressing_mode; + end + end + 3'b110:begin /* SP Indirect read*/ + reg_read_port1_addr <= 4'b1100; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_READ_SETADDR; + end + default:begin + `unimpl_addressing_mode + end + endcase + end + `EXEC_MEMIO_READ_SETADDR:begin + if(memio_address_select==0) + BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0]; + else + BIU_ADDRESS_INPUT <= ALU_O; + + if ( BIU_VALID_DATA == 1 ) begin + exec_state <= `EXEC_WRITE_ENTRY; + PARAM2 <= BIU_DATA; + biu_read_request <= 0; + biu_data_direction <= 0; + end else begin + biu_data_direction <= 1; + biu_read_request <= 1; + end + end + `EXEC_NEXT_INSTRUCTION:begin + /*necessary for biu to see we went on another state from decode to give us a new instruction*/ + exec_state <= `EXEC_DONE; + end + `EXEC_WRITE_ENTRY:begin + FLAGS[7:0] <= ALU_FLAGS[7:0]; + case(OUT_MOD) + 3'b000, + 3'b001, + 3'b010 : begin + if(memio_address_select==1) + exec_state <= `EXEC_MEMIO_WRITE; + else + case (RM) /* Duplicate code with write... */ + 3'b000:begin + /*[BX]+[SI]*/ + `unimpl_addressing_mode + end + 3'b001:begin + /*[BX]+[SI]*/ + `unimpl_addressing_mode + end + 3'b010:begin + /*[BP]+[SI]*/ + `unimpl_addressing_mode + end + 3'b011:begin + /*[BP]+[DI]*/ + `unimpl_addressing_mode + end + 3'b100:begin + /*[SI]*/ + reg_read_port1_addr <= 4'b1110; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_WRITE; + end + 3'b101:begin + /*[DI]*/ + reg_read_port1_addr <= 4'b1111; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_WRITE; + end + 3'b110:begin + /*d16 */ + `unimpl_addressing_mode + end + 3'b111:begin + /*[BX]*/ + reg_read_port1_addr <= 4'b1011; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_WRITE; + end + endcase + end + 3'b011:begin + reg_write_we <= 0; + exec_state <= `EXEC_DONE; + end + 3'b100:begin /*No output*/ + exec_state <= `EXEC_DONE; + end + 3'b101:begin /* Program Counter*/ + BIU_ADDRESS_INPUT <= ALU_O[15:0]; + biu_jump_req <= 1; + exec_state <= `EXEC_DONE; + end + 3'b110:begin /* SP Indirect write*/ + reg_read_port1_addr <= 4'b1100; + use_exec_reg_addr <= 1; + exec_state <= `EXEC_MEMIO_WRITE; + end + 3'b111:begin /* Write to PRAM1 (for microcode calculations) */ + PARAM1 <= ALU_O; + exec_state <= `EXEC_DONE; + end + default:begin + `unimpl_addressing_mode + end + endcase + end + `EXEC_MEMIO_WRITE:begin + /* if memio_address_select == 0 ADDRESS: reg_read_port1_data DATA:ALU1_O */ + /* if memio_address_select == 1 ADDRESS: ALU1_O DATA: reg_read_port1_data */ + + biu_write_request <= 1; + + if(memio_address_select==0) + BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0]; + else + BIU_ADDRESS_INPUT <= ALU_O; + + if (write == 0) begin //TODO: don't do it that was or better yet don't do it at all somehow + biu_write_request <= 0; + exec_state <= `EXEC_DONE; + end + + end + `EXEC_HALT:begin + end + default:begin + end + endcase +end +`undef unimpl_addressing_mode + +endmodule diff --git a/system/processor.v b/system/processor.v index 78cf3f1..aa40d0c 100644 --- a/system/processor.v +++ b/system/processor.v @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -`include "proc_state_def.v" +`include "exec_state_def.v" `include "alu_header.v" `include "config.v" `include "ucode_header.v" @@ -29,35 +29,78 @@ //read: active low //reset: active low -module processor ( input clock, input reset, output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM, output reg HALT,output reg [`ERROR_BITS-1:0] ERROR); +`define PROC_STATE_BITS 3 +`define PROC_RESET 3'b000 +`define PROC_DE_STATE_ENTRY 3'b001 +`define PROC_WAIT 3'b010 +`define PROC_HALT 3'b011 + +module processor ( input clock, input reset, output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM, output reg HALT,output [`ERROR_BITS-1:0] ERROR); + +/* If there is an error either from the decoder or execution unit set it to ERROR */ +assign ERROR=(DE_ERROR_sampled!=`ERR_NO_ERROR)?DE_ERROR_sampled:(EXEC_ERROR!=`ERR_NO_ERROR)?EXEC_ERROR:`ERR_NO_ERROR; /*** Global Definitions ***/ reg [`PROC_STATE_BITS-1:0] state; +/*############ Execution Unit ################################################## */ +reg [1:0] in_alu_sel1; +reg [1:0] in_alu_sel2; + +wire [`EXEC_STATE_BITS-1:0] exec_state; + +reg valid_exec_data; + +wire [`ERROR_BITS-1:0] EXEC_ERROR; + +wire use_exec_reg_addr; + +wire [3:0] EXEC_reg_read_port1_addr; +reg [2:0] IN_MOD,OUT_MOD; +reg [`EXEC_STATE_BITS-1:0] exec_state_init; +reg [`ALU_OP_BITS-1:0] ALU_OP; +wire [15:0] ALU_O; +wire [7:0]EXEC_FLAGS; +reg [15:0] PARAM1_INIT; +reg [15:0] PARAM2_INIT; +reg set_initial_values; + +execute_unit execute_unit ( + /* GENERAL */ clock, reset, Wbit, Sbit, opcode_size, INSTRUCTION_BUFFER,valid_exec_data + /* */ ,IN_MOD, OUT_MOD,memio_address_select, ProgCount, RM, EXEC_ERROR, write + /* */ ,set_initial_values + /* PARAM */ ,PARAM1_INIT,PARAM2_INIT + /* STATE CONTROL */ ,exec_state, exec_state_init + /* ALU CONTROL */ ,in_alu_sel1, in_alu_sel2, ALU_OP, ALU_O + /* REGISTER DATA */ ,reg_read_port1_data, reg_read_port2_data, EXEC_reg_read_port1_addr, use_exec_reg_addr, reg_write_we + /* FLAFS */ ,EXEC_FLAGS + /* BIU */ ,BIU_ADDRESS_INPUT, biu_write_request, biu_read_request, BIU_VALID_DATA, BIU_DATA, biu_data_direction, biu_jump_req + ); + /*############ Bus Interface Unit ############################################### */ wire [31:0] INSTRUCTION; -reg jump_req; +wire biu_jump_req; wire VALID_INSTRUCTION; wire [15:0] INSTRUCTION_LOCATION; -reg [15:0] BIU_ADDRESS_INPUT; +wire [15:0] BIU_ADDRESS_INPUT; wire [15:0] BIU_DATA; -reg biu_write_request; -reg biu_data_direction; -reg biu_read_request; +wire biu_write_request; +wire biu_data_direction; +wire biu_read_request; wire BIU_VALID_DATA; BIU BIU( clock,reset,external_address_bus,external_data_bus,read,write,BHE,IOMEM, - INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION,jump_req,BIU_ADDRESS_INPUT,BIU_DATA,biu_write_request,biu_read_request,Wbit,BIU_VALID_DATA,MEM_OR_IO, + INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION,biu_jump_req,BIU_ADDRESS_INPUT,BIU_DATA,biu_write_request,biu_read_request,Wbit,BIU_VALID_DATA,MEM_OR_IO, state,SIMPLE_MICRO ); -assign BIU_DATA= biu_data_direction ? 16'hz : (memio_address_select?reg_read_port1_data:ALU_1O); +assign BIU_DATA= biu_data_direction ? 16'hz : (memio_address_select ? reg_read_port1_data : ALU_O); /*############ Decoder ########################################################## */ reg Wbit, Sbit, opcode_size; wire DE_Wbit, DE_Sbit, DE_opcode_size; -wire [`PROC_STATE_BITS-1:0] next_state; +wire [`EXEC_STATE_BITS-1:0] next_state; reg [2:0]RM; wire [15:0]DE_PARAM1;// Input param1 form decoder to alu wire [15:0]DE_PARAM2; @@ -73,20 +116,14 @@ wire [`ERROR_BITS:0]DECODER_SIGNALS; wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry; reg SIMPLE_MICRO; /* output simple decodings (=0) or microcode data (=1) */ -wire [2:0] DE_instruction_size; -reg instruction_size_init; //TODO : remove completely? -/* verilator lint_off UNUSEDSIGNAL */ -wire [2:0] instruction_size; -/* verilator lint_on UNUSEDSIGNAL */ -assign instruction_size = instruction_size_init ? 3'b010 : DE_instruction_size; reg memio_address_select; wire DE_memio_address_select; wire DE_MEM_OR_IO; reg MEM_OR_IO; -wire [1:0] DE_in_alu1_sel1; -wire [1:0] DE_in_alu1_sel2; -reg [`ALU_OP_BITS-1:0] DE_ALU_1OP; +wire [1:0] DE_in_alu_sel1; +wire [1:0] DE_in_alu_sel2; +reg [`ALU_OP_BITS-1:0] DE_ALU_OP; decoder decoder( .CIR(INSTRUCTION[31:16]), .FLAGS(FLAGS), @@ -97,15 +134,14 @@ decoder decoder( .RM(DE_RM), .PARAM1(DE_PARAM1), .PARAM2(DE_PARAM2), - .in_alu1_sel1(DE_in_alu1_sel1), - .in_alu1_sel2(DE_in_alu1_sel2), + .in_alu_sel1(DE_in_alu_sel1), + .in_alu_sel2(DE_in_alu_sel2), .OUT_MOD(DE_OUT_MOD), .REGISTER_FILE_CONTROL(DE_REGISTER_CONTROL), - .ALU_1OP(DE_ALU_1OP), + .ALU_1OP(DE_ALU_OP), .seq_addr_entry(ucode_seq_addr_entry), .SIMPLE_MICRO(SIMPLE_MICRO), .seq_addr_input(ucode_seq_addr), - .instruction_size(DE_instruction_size), .memio_address_select(DE_memio_address_select), .MEM_OR_IO(DE_MEM_OR_IO) ); @@ -120,13 +156,12 @@ assign DE_reg_read_port2_addr=DE_REGISTER_CONTROL[3:0]; assign DE_HALT=DECODER_SIGNALS[0:0]; assign DE_ERROR=DECODER_SIGNALS[`ERROR_BITS:1]; +reg [`ERROR_BITS-1:0] DE_ERROR_sampled; reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr; /*############ REGISTERS ########################################################## */ -reg [15:0] PARAM1; -reg [15:0] PARAM2; // verilator lint_off UNDRIVEN reg [15:0] FLAGS; @@ -135,19 +170,21 @@ reg [15:0] FLAGS; //Architectural Register file reg [3:0] reg_write_addr; wire [15:0] reg_write_data; -reg reg_write_we; -reg [3:0] reg_read_port1_addr; +wire reg_write_we; +wire [3:0] reg_read_port1_addr; reg [15:0] reg_read_port1_data; reg [3:0] reg_read_port2_addr; reg [15:0] reg_read_port2_data; reg [1:0] reg_write_in_sel; + mux4 #(.WIDTH(16)) REG_FILE_WRITE_IN_MUX( - ALU_1O, + ALU_O, 16'hz, 16'hz, 16'hz, reg_write_in_sel, reg_write_data); + register_file register_file( .write_port1_addr(reg_write_addr), .write_port1_data(reg_write_data), @@ -158,52 +195,17 @@ register_file register_file( .read_port2_data(reg_read_port2_data) ); +assign reg_read_port1_addr = use_exec_reg_addr ? EXEC_reg_read_port1_addr : reg_read_port1_addr_latched; + reg [15:0] ProgCount; -/*############ ALU / Execution units ########################################################## */ -// ALU 1 -reg [1:0] in_alu1_sel1; -reg [1:0] in_alu1_sel2; -/* OUT_MOD : { EXTRA_FUNCTIONS_BIT[0:0], MOD_OR_EXTRA_FUNCTION[1:0] } */ -reg [2:0] IN_MOD; -reg [2:0] OUT_MOD; - -mux4 #(.WIDTH(16)) MUX16_1A( -/*0*/ PARAM1, -/*1*/ reg_read_port1_data, -/*2*/ ProgCount[15:0], -/*3*/ 16'd0, /*0 Constant*/ - in_alu1_sel1, - ALU_1A); - -mux4 #(.WIDTH(16)) MUX16_1B( -/*0*/ PARAM2, -/*1*/ reg_read_port2_data, -/*2*/ ProgCount[15:0], -/*3*/ 16'd0, /*0 Constant*/ - in_alu1_sel2, - ALU_1B); - -wire [15:0] ALU_1A; -wire [15:0] ALU_1B; -wire [15:0] ALU_1O; -reg [`ALU_OP_BITS-1:0]ALU_1OP; -wire [7:0] ALU_1FLAGS; -ALU ALU1( - .A(ALU_1A), - .B(ALU_1B), - .OUT(ALU_1O), - .op(ALU_1OP), - .FLAGS(ALU_1FLAGS), - .Wbit(Wbit) -); - /*############ Processor state machine ########################################################## */ +reg [3:0] reg_read_port1_addr_latched; /*** RESET LOGIC ***/ /* verilator lint_off MULTIDRIVEN */ always @(negedge reset) begin - state <= `PROC_HALT_STATE; //TODO: race condition ?? + state <= `PROC_HALT; //TODO: race condition ?? end always @(posedge reset) begin state <= `PROC_RESET; @@ -211,329 +213,88 @@ end /* verilator lint_on MULTIDRIVEN */ /*** Processor stages ***/ -`define unimpl_addressing_mode state <= `PROC_DE_STATE_ENTRY;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE; wire [2:0] instr_end; InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},instr_end); reg [23:0] INSTRUCTION_BUFFER; + always @(posedge clock) begin case(state) `PROC_RESET:begin - jump_req <= 0; ucode_seq_addr <= `UCODE_NO_INSTRUCTION; HALT <= 0; - ERROR <= `ERR_NO_ERROR; SIMPLE_MICRO <= 0; - reg_write_we <= 1; - instruction_size_init <= 1; state <= `PROC_DE_STATE_ENTRY; reg_write_in_sel <= 2'b00; //only got wirtten in IF - biu_write_request <= 0; - biu_data_direction <= 0; - biu_read_request <= 0; - end - `PROC_HALT_STATE:begin end `PROC_DE_STATE_ENTRY:begin - reg_write_we <= 1; if(VALID_INSTRUCTION==1) begin if(SIMPLE_MICRO==0)begin - /*This flag is set at reset and jump because - * at IF we need to know the size of the - * previous instruction (specifically if it was - * a single byte and the value would be - * incorrect in both cases. So when it gets - * set reset it only at the start of the next - * 8086 instruction */ - instruction_size_init <= 0; - /* We cannot set these directly within * microcode so don't overwrite useful values * each tie the next microcode is executed. * Note this still allows to set initial values * at the start of the microcode */ - PARAM1 <= DE_PARAM1; - PARAM2 <= DE_PARAM2; + PARAM1_INIT <= DE_PARAM1; + PARAM2_INIT <= DE_PARAM2; `ifdef DEBUG_PC_ADDRESS $display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,INSTRUCTION); `endif ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end}; INSTRUCTION_BUFFER<=INSTRUCTION[23:0]; + set_initial_values<=0; end + DE_ERROR_sampled <= DE_ERROR; IN_MOD <= DE_IN_MOD; OUT_MOD <= DE_OUT_MOD; RM <= DE_RM; - ERROR <= DE_ERROR; HALT <= DE_HALT; Wbit <= DE_Wbit; Sbit <= DE_Sbit; opcode_size <= DE_opcode_size; memio_address_select<=DE_memio_address_select; - reg_read_port1_addr <= DE_reg_read_port1_addr; + reg_read_port1_addr_latched <= DE_reg_read_port1_addr; reg_read_port2_addr <= DE_reg_read_port2_addr; reg_write_addr <= DE_reg_write_addr; MEM_OR_IO <= DE_MEM_OR_IO; - in_alu1_sel1 <= DE_in_alu1_sel1; - in_alu1_sel2 <= DE_in_alu1_sel2; - ALU_1OP <= DE_ALU_1OP; - + in_alu_sel1 <= DE_in_alu_sel1; + in_alu_sel2 <= DE_in_alu_sel2; + ALU_OP <= DE_ALU_OP; if ( (ucode_seq_addr==`UCODE_NO_INSTRUCTION) && (ucode_seq_addr_entry!=`UCODE_NO_INSTRUCTION) )begin /*switch to microcode decoding*/ ucode_seq_addr <= ucode_seq_addr_entry; SIMPLE_MICRO <= 1; /*keep state the same and rerun decode this time with all the data from the microcode rom*/ - jump_req <= 0; end else begin - state <= next_state; - if ( SIMPLE_MICRO == 0 ) begin - jump_req <= 0; + valid_exec_data <= 1; + exec_state_init <= next_state; + state <= `PROC_WAIT; + end + end + end + `PROC_WAIT:begin + set_initial_values<=1; + if( exec_state == `EXEC_DONE ) begin + FLAGS[7:0] <= EXEC_FLAGS; //don't set all of them all the time! + valid_exec_data<=0; + state <= `PROC_DE_STATE_ENTRY; + if(SIMPLE_MICRO == 1 ) begin + ucode_seq_addr <= ucode_seq_addr_entry; /*Reused for next address*/ + if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin + /*Finished microcode*/ + SIMPLE_MICRO <= 0; end end end end - `PROC_DE_LOAD_REG_TO_PARAM:begin - PARAM2<=reg_read_port2_data; - case(IN_MOD) - 3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ; - default: state <= `PROC_EX_STATE_ENTRY; - endcase - end - `PROC_DE_LOAD_8_PARAM:begin - if(opcode_size==0)begin - if({Sbit,Wbit}==2'b11)begin - /*signed "16bit" read*/ - PARAM1 <= {{8{INSTRUCTION_BUFFER[23:23]}},INSTRUCTION_BUFFER[23:16]}; - end else begin - PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16]; - end - case(IN_MOD) - 3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ; - default: state <= `PROC_EX_STATE_ENTRY; - endcase - end else begin - if({Sbit,Wbit}==2'b11)begin - /*signed "16bit" read*/ - PARAM1 <= {{8{INSTRUCTION_BUFFER[15:15]}},INSTRUCTION_BUFFER[15:8]}; - end else begin - PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8]; - end - end - case(IN_MOD) - 3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ; - default: state <= `PROC_EX_STATE_ENTRY; - endcase - end - `PROC_DE_LOAD_16_PARAM:begin - if(opcode_size==0)begin - PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16]; - PARAM1[15:8] <= INSTRUCTION_BUFFER[15:8]; - end else begin - PARAM1[15:8] <= INSTRUCTION_BUFFER[7:0]; - PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8]; - end - case(IN_MOD) - 3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ; - default: state <= `PROC_EX_STATE_ENTRY; - endcase - end - `PROC_MEMIO_READ:begin - /*Decode MOD R/M, read the data and place it to PARAM1*/ - case (IN_MOD) - 3'b000, - 3'b001, - 3'b010:begin - case (RM) - 3'b000:begin - /*[BX]+[SI]*/ - `unimpl_addressing_mode - end - 3'b001:begin - /*[BX]+[SI]*/ - `unimpl_addressing_mode - end - 3'b010:begin - /*[BP]+[SI]*/ - `unimpl_addressing_mode - end - 3'b011:begin - /*[BP]+[DI]*/ - `unimpl_addressing_mode - end - 3'b100:begin - /*[SI]*/ - reg_read_port1_addr <= 4'b1110; - state <= `PROC_MEMIO_READ_SETADDR; - end - 3'b101:begin - /*[DI]*/ - reg_read_port1_addr <= 4'b1111; - state <= `PROC_MEMIO_READ_SETADDR; - end - 3'b110:begin - /*d16 */ - `unimpl_addressing_mode - end - 3'b111:begin - /*[BX]*/ - reg_read_port1_addr <= 4'b1011; - state <= `PROC_MEMIO_READ_SETADDR; - end - endcase - if(IN_MOD!=3'b000)begin - /*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/ - `unimpl_addressing_mode; - end - end - 3'b110:begin /* SP Indirect read*/ - reg_read_port1_addr <= 4'b1100; - state <= `PROC_MEMIO_READ_SETADDR; - end - default:begin - `unimpl_addressing_mode - end - endcase - end - `PROC_MEMIO_READ_SETADDR:begin - if(memio_address_select==0) - BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0]; - else - BIU_ADDRESS_INPUT <= ALU_1O; - - if ( BIU_VALID_DATA == 1 ) begin - state <= `PROC_EX_STATE_ENTRY; - PARAM2 <= BIU_DATA; - biu_read_request <= 0; - biu_data_direction <= 0; - end else begin - biu_data_direction <= 1; - biu_read_request <= 1; - end - end - `PROC_NEXT_INSTRUCTION:begin - /*necessary for biu to see we went on another state from decode to give us a new instruction*/ - state <= `PROC_DE_STATE_ENTRY; - end - `PROC_EX_STATE_ENTRY:begin - FLAGS[7:0] <= ALU_1FLAGS[7:0]; - case(OUT_MOD) - 3'b000, - 3'b001, - 3'b010 : begin - if(memio_address_select==1) - state <= `PROC_MEMIO_WRITE; - else - case (RM) /* Duplicate code with write... */ - 3'b000:begin - /*[BX]+[SI]*/ - `unimpl_addressing_mode - end - 3'b001:begin - /*[BX]+[SI]*/ - `unimpl_addressing_mode - end - 3'b010:begin - /*[BP]+[SI]*/ - `unimpl_addressing_mode - end - 3'b011:begin - /*[BP]+[DI]*/ - `unimpl_addressing_mode - end - 3'b100:begin - /*[SI]*/ - reg_read_port1_addr <= 4'b1110; - state <= `PROC_MEMIO_WRITE; - end - 3'b101:begin - /*[DI]*/ - reg_read_port1_addr <= 4'b1111; - state <= `PROC_MEMIO_WRITE; - end - 3'b110:begin - /*d16 */ - `unimpl_addressing_mode - end - 3'b111:begin - /*[BX]*/ - reg_read_port1_addr <= 4'b1011; - state <= `PROC_MEMIO_WRITE; - end - endcase - end - 3'b011:begin - reg_write_we <= 0; - if (ucode_seq_addr==`UCODE_NO_INSTRUCTION) - state <= `PROC_DE_STATE_ENTRY; - else - state <= `PROC_NEXT_MICROCODE; - end - 3'b100:begin /*No output*/ - if (ucode_seq_addr==`UCODE_NO_INSTRUCTION) - state <= `PROC_DE_STATE_ENTRY; - else - state <= `PROC_NEXT_MICROCODE; - end - 3'b101:begin /* Program Counter*/ - BIU_ADDRESS_INPUT <= ALU_1O[15:0]; - jump_req <= 1; - instruction_size_init <= 1; - if (ucode_seq_addr==`UCODE_NO_INSTRUCTION) - state <= `PROC_DE_STATE_ENTRY; - else - state <= `PROC_NEXT_MICROCODE; - end - 3'b110:begin /* SP Indirect write*/ - reg_read_port1_addr <= 4'b1100; - state <= `PROC_MEMIO_WRITE; - end - 3'b111:begin /* Write to PRAM1 (for microcode calculations) */ - PARAM1 <= ALU_1O; - if (ucode_seq_addr==`UCODE_NO_INSTRUCTION) - state <= `PROC_DE_STATE_ENTRY; - else - state <= `PROC_NEXT_MICROCODE; - end - default:begin - `unimpl_addressing_mode - end - endcase - end - `PROC_MEMIO_WRITE:begin - /* if memio_address_select == 0 ADDRESS: reg_read_port1_data DATA:ALU1_O */ - /* if memio_address_select == 1 ADDRESS: ALU1_O DATA: reg_read_port1_data */ - - biu_write_request <= 1; - - if(memio_address_select==0) - BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0]; - else - BIU_ADDRESS_INPUT <= ALU_1O; - - if (write == 0) begin - biu_write_request <= 0; - if (ucode_seq_addr==`UCODE_NO_INSTRUCTION) - state <= `PROC_DE_STATE_ENTRY; - else - state <= `PROC_NEXT_MICROCODE; - end - - end - `PROC_NEXT_MICROCODE:begin - ucode_seq_addr <= ucode_seq_addr_entry; /*Reused for next address*/ - if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin - /*Finished microcode*/ - SIMPLE_MICRO <= 0; - end - state <= `PROC_DE_STATE_ENTRY; - reg_write_we <= 1; + `PROC_HALT:begin end default:begin end endcase end -`undef unimpl_addressing_mode endmodule