From a693b87e96e5d63422a7440f502d211e79d56841 Mon Sep 17 00:00:00 2001 From: "(Tim) Efthimis Kritikos" Date: Mon, 29 May 2023 02:28:56 +0100 Subject: [PATCH] General cleanup and moved the reading of instruction parameters from a separate stage in execute to circuitry during the decode --- system/decoder.v | 348 +++++++++++++++++++++++----------------- system/exec_state_def.v | 2 - system/execute.v | 44 +---- system/processor.v | 18 +-- 4 files changed, 206 insertions(+), 206 deletions(-) diff --git a/system/decoder.v b/system/decoder.v index f4018e7..b873e0d 100644 --- a/system/decoder.v +++ b/system/decoder.v @@ -1,4 +1,4 @@ -/* decoder.v - Implementation of instruction opcode decoding logic +/* decoder.v - Implementation of instruction decoding logic This file is part of the 9086 project. @@ -23,56 +23,53 @@ `include "error_header.v" `include "config.v" -//TODO: rename CIR to OPCODE where applicable -//TODO: check all includes +`define DE_STATE_BITS 2 +`define DE_RESET 2'b00 +`define DE_STATE_ENTRY 2'b01 +`define DE_HALT 2'b10 module decoder( /* GENERAL */ input clock, input reset /* INPUT FROM IF */ ,input wire [31:0] IF2DE_INSTRUCTION,input wire VALID_INSTRUCTION, input [15:0] INSTRUCTION_LOCATION /* INPUT FROM EX */ ,input wire [7:0] EX2DE_FLAGS,input wire next_exec - /* OUTPUT TO EX */ ,output reg [`EXEC_STATE_BITS+`ERROR_BITS+65:0] DE_OUTPUT_sampled, output reg [23:0] DE2EX_INSTRUCTION + /* OUTPUT TO EX */ ,output reg [`EXEC_STATE_BITS+`ERROR_BITS+65:0] DE_OUTPUT_sampled /* */ ,output reg [15:0] ProgCount, output reg set_initial_values,output reg valid_exec_data /* OUTPUT TO IF */ ,output reg VALID_INSTRUCTION_ACK `ifdef CALCULATE_IPC /* STATISTICS */ ,output reg new_instruction `endif -`ifdef DEBUG_PC_ADDRESS - /* DEBUG */ ,input FULL_INSTRUCTION -`endif ); -reg SIMPLE_MICRO; /* output simple decodings (=0) or microcode data (=1) */ +reg SIMPLE_MICRO; /* use simple decodings (=0) or microcode data (=1) */ wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry; reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr; wire DEPENDS_ON_PREVIOUS; - wire [`EXEC_STATE_BITS+`ERROR_BITS+65:0] DE_OUTPUT; +wire set_params; instruction_decode instruction_decode( - /* INPUT */ IF2DE_INSTRUCTION[31:16],{8'h0,EX2DE_FLAGS}, + /* INPUT */ IF2DE_INSTRUCTION,{8'h0,EX2DE_FLAGS}, /* MICROCODE */ ucode_seq_addr_entry,SIMPLE_MICRO,ucode_seq_addr, - /* OUTPUT */ DE_OUTPUT,DEPENDS_ON_PREVIOUS + /* OUTPUT */ DE_OUTPUT,DEPENDS_ON_PREVIOUS, set_params ); -reg [`PROC_STATE_BITS-1:0] proc_state; +reg [`DE_STATE_BITS-1:0] de_state; -/*** RESET LOGIC ***/ always @(negedge reset) begin - proc_state <= `PROC_HALT; //TODO: race condition ?? + de_state <= `DE_HALT; //TODO: race condition ?? `ifdef CALCULATE_IPC new_instruction<=0; `endif end always @(posedge reset) begin - proc_state <= `PROC_RESET; + de_state <= `DE_RESET; /* need early init */ VALID_INSTRUCTION_ACK <= 0; instant_response <= 0; stalled_response <= 0; end -/*** Processor stages ***/ wire [2:0] instr_end; InstrSize InstrSize({IF2DE_INSTRUCTION[31:24],IF2DE_INSTRUCTION[21:19]},instr_end); @@ -88,7 +85,7 @@ reg instant_response, stalled_response; reg wait_exec; always @(next_exec) begin - proc_state<=`PROC_DE_STATE_ENTRY; + de_state<=`DE_STATE_ENTRY; if ( VALID_INSTRUCTION_lc == 1 && DEPENDS_ON_PREVIOUS == 0 && ucode_seq_addr_entry==`UCODE_NO_INSTRUCTION) begin instant_response <= !instant_response; end else begin @@ -96,30 +93,36 @@ always @(next_exec) begin end end +reg first_ucode; + always @(instant_response or stalled_response) begin DE_OUTPUT_sampled <= DE_OUTPUT; - if(SIMPLE_MICRO==0||owe_set_init==1)begin - /* This runs at the start of the execution of an 8086 instruction */ - `ifdef DEBUG_PC_ADDRESS - $display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,FULL_INSTRUCTION); - `endif - `ifdef CALCULATE_IPC - new_instruction <= !new_instruction; - `endif - VALID_INSTRUCTION_ACK <= !VALID_INSTRUCTION_ACK; - owe_set_init<=0; - set_initial_values <= !set_initial_values; - ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end}; - DE2EX_INSTRUCTION <= IF2DE_INSTRUCTION[23:0]; // First byte is never useful to execute - end 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 proc_state the same and rerun decode this time with all the data from the microcode rom*/ + first_ucode <= 1; + set_initial_values <= !set_initial_values; + /*keep de_state the same and rerun decode this time with all the data from the microcode rom*/ end else begin + if(SIMPLE_MICRO==0||first_ucode==1||owe_set_init==1)begin + first_ucode <= 0; + /* This runs at the start of the execution of an 8086 instruction */ + `ifdef DEBUG_PC_ADDRESS + $display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,IF2DE_INSTRUCTION); + `endif + `ifdef CALCULATE_IPC + new_instruction <= !new_instruction; + `endif + owe_set_init<=0; + ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end}; + VALID_INSTRUCTION_ACK <= !VALID_INSTRUCTION_ACK; + end + if(set_params)begin + set_initial_values <= !set_initial_values; + end /* This runs at the start of each execution cycle, with microcode this is more than once per 8086 instruction */ valid_exec_data<=!valid_exec_data; if( SIMPLE_MICRO == 1 ) begin @@ -134,23 +137,24 @@ always @(instant_response or stalled_response) begin end always @(posedge clock) begin - case(proc_state) - `PROC_RESET:begin + case(de_state) + `DE_RESET:begin ucode_seq_addr <= `UCODE_NO_INSTRUCTION; DE_OUTPUT_sampled <= 0; SIMPLE_MICRO <= 0; - proc_state <= `PROC_DE_STATE_ENTRY; + de_state <= `DE_STATE_ENTRY; owe_set_init <= 0; set_initial_values<=0; wait_exec<=0; valid_exec_data<=0; + first_ucode <= 0; end - `PROC_DE_STATE_ENTRY:begin + `DE_STATE_ENTRY:begin if ( ( VALID_INSTRUCTION==1 || SIMPLE_MICRO == 1 ) && wait_exec==0) begin stalled_response <= !stalled_response; end end - `PROC_HALT:begin + `DE_HALT:begin end default:begin end @@ -160,7 +164,7 @@ end endmodule - +/************************ Instruction specific decoding **********************************/ module microcode( @@ -185,9 +189,9 @@ assign DATA=ucode_rom[ADDR]; endmodule module instruction_decode( - /* INPUTS */ input wire [15:0] CIR,input wire [15:0] FLAGS + /* INPUTS */ input wire [31:0] INSTRUCTION,input wire [15:0] FLAGS /* MICROCODE */ ,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 */ ,output wire [`EXEC_STATE_BITS+`ERROR_BITS+65:0] OUTPUT, output reg DEPENDS_ON_PREVIOUS + /* OUTPUT */ ,output wire [`EXEC_STATE_BITS+`ERROR_BITS+65:0] OUTPUT, output reg DEPENDS_ON_PREVIOUS, output reg set_params ); /* DEPENDS_ON_PREVIOUS - This encodes weather the instruction requires the previous to be finished in order to be decoded. This, for example, affects @@ -260,18 +264,26 @@ microcode ucode(seq_addr_input,ucode_data); `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; -// I use blocking for basically putting names on the different fields of CIR and +reg [1:0] PARAM_ACTION; +`define NO_LOAD 2'b00 +`define LOAD_8 2'b01 +`define LOAD_16 2'b10 + +// I use blocking for basically putting names on the different fields of INSTRUCTION and // then branching off of that instead of the raw bits. otherwise the code // would be identical // verilator lint_off BLKSEQ -always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin +always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin + set_params = 1; + PARAM_ACTION = `NO_LOAD; + Sbit=0;//TODO: If no Sbit we assume it's 0,right? if (SIMPLE_MICRO==0)begin - casez({CIR[15:8],CIR[5:3]}) + casez({INSTRUCTION[31:24],INSTRUCTION[21:19]}) 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; - Wbit=CIR[8:8]; + Wbit=INSTRUCTION[24:24]; IN_MOD=3'b011; in_alu_sel1=2'b00; in_alu_sel2=2'b01; @@ -282,9 +294,9 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin ALU_OP=`ALU_OP_ADD; memio_address_select=0; if(Wbit) - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; else - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; DEPENDS_ON_PREVIOUS<=0; `normal_instruction; end @@ -295,10 +307,10 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* SUB - Subtract immediate word/byte from register/memory */ /* 1 0 0 0 0 0 S W | MOD 1 0 1 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */ opcode_size=1; - Wbit=CIR[8:8]; - Sbit=CIR[9:9]; - IN_MOD={1'b0,CIR[7:6]}; - RM=CIR[2:0]; + Wbit=INSTRUCTION[24:24]; + Sbit=INSTRUCTION[25:25]; + IN_MOD={1'b0,INSTRUCTION[23:22]}; + RM=INSTRUCTION[18:16]; in_alu_sel1=2'b00; if(IN_MOD==3'b011)begin in_alu_sel2=2'b01; @@ -310,18 +322,18 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin OUT_MOD=IN_MOD; MEM_OR_IO=0; memio_address_select=0; - case({Sbit,Wbit}) + case({Sbit,Wbit}) // TODO: Isn't this supposed to be just a LOAD_8? 2'b00,2'b11:begin - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; end 2'b01:begin - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; end default:begin `invalid_instruction end endcase - case(CIR[5:3]) + case(INSTRUCTION[21:19]) 3'b000: ALU_OP=`ALU_OP_ADD; 3'b101: ALU_OP=`ALU_OP_SUB_REVERSE; default:begin @@ -336,10 +348,10 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* 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 | */ opcode_size=1; - Wbit=CIR[8:8]; - Sbit=CIR[9:9]; - IN_MOD={1'b0,CIR[7:6]}; - RM=CIR[2:0]; + Wbit=INSTRUCTION[24:24]; + Sbit=INSTRUCTION[25:25]; + IN_MOD={1'b0,INSTRUCTION[23:22]}; + RM=INSTRUCTION[18:16]; if ( {Sbit,Wbit} == 2'b10 )begin `invalid_instruction end @@ -352,31 +364,36 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /*compare register with param*/ in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; + next_state=`EXEC_WRITE_ENTRY; end else begin /*compare register indirect access * with param */ in_alu_sel2=2'b00; + next_state=`EXEC_MEMIO_READ; /*will call MEMIO_READ after EXEC_DE_LOAD..*/ end if(Wbit) - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; else - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; DEPENDS_ON_PREVIOUS<=0; `normal_instruction; end - 11'b1011_0???_??? : begin + 11'b1011_????_??? : begin /* MOV - Move Immediate byte to register */ /* 1 0 1 1 W REG | DATA | DATA if W |*/ - Wbit=CIR[11:11]; /* IS 0 */ + Wbit=INSTRUCTION[27:27]; /* IS 0 */ opcode_size=0; IN_MOD=3'b011; 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]; + reg_write_addr={Wbit,INSTRUCTION[26:24]}; + if(Wbit) + PARAM_ACTION=`LOAD_16; + else + PARAM_ACTION=`LOAD_8; PARAM2=0; ALU_OP=`ALU_OP_ADD; next_state=`EXEC_WRITE_ENTRY; @@ -384,35 +401,18 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin DEPENDS_ON_PREVIOUS<=0; memio_address_select=0; end - 11'b1011_1???_??? : begin - /*MOV - Move Immediate word to register*/ - Wbit=CIR[11:11]; /*IS 1 */ - opcode_size=0; - IN_MOD=3'b011; - 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_OP=`ALU_OP_ADD; - PARAM2=0; - next_state=`EXEC_DE_LOAD_16_PARAM; - `normal_instruction; - DEPENDS_ON_PREVIOUS<=0; - memio_address_select=0; - end 11'b1000_10??_??? : 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; - RM=CIR[2:0]; - Wbit=CIR[8:8]; + RM=INSTRUCTION[18:16]; + Wbit=INSTRUCTION[24:24]; in_alu_sel1=2'b00; PARAM1=0; MEM_OR_IO=0; - if(CIR[9:9] == 1)begin + if(INSTRUCTION[25:25] == 1)begin /* Mem/Reg to reg */ - IN_MOD={1'b0,CIR[7:6]}; + IN_MOD={1'b0,INSTRUCTION[23:22]}; if(IN_MOD==3'b011)begin /*Reg to Reg*/ in_alu_sel2=2'b01; @@ -424,11 +424,11 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin next_state=`EXEC_MEMIO_READ; end OUT_MOD=3'b011; - reg_write_addr={Wbit,CIR[5:3]}; + reg_write_addr={Wbit,INSTRUCTION[21:19]}; end else begin /* Reg to Mem/Reg */ IN_MOD=3'b011; - OUT_MOD={1'b0,CIR[7:6]}; + OUT_MOD={1'b0,INSTRUCTION[23:22]}; if(IN_MOD==3'b011)begin /*Reg to Reg*/ in_alu_sel2=2'b01; @@ -439,7 +439,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin in_alu_sel2=2'b00; next_state=`EXEC_DE_LOAD_REG_TO_PARAM; end - reg_read_port2_addr={Wbit,CIR[5:3]}; + reg_read_port2_addr={Wbit,INSTRUCTION[21:19]}; end ALU_OP=`ALU_OP_ADD; @@ -460,9 +460,9 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin MEM_OR_IO=0; IN_MOD=3'b011; PARAM2=1; - reg_read_port1_addr={1'b1,CIR[10:8]}; - reg_write_addr={1'b1,CIR[10:8]}; - if(CIR[11:11]==0) + reg_read_port1_addr={1'b1,INSTRUCTION[26:24]}; + reg_write_addr={1'b1,INSTRUCTION[26:24]}; + if(INSTRUCTION[27:27]==0) ALU_OP=`ALU_OP_ADD; else ALU_OP=`ALU_OP_SUB; @@ -477,9 +477,9 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* DEC - Register/Memory */ /* 1 1 1 1 1 1 1 W | MOD 0 0 1 R/M | < DISP LO> | < DISP HI> */ opcode_size=1; - Wbit=CIR[8:8]; - IN_MOD={1'b0,CIR[7:6]}; - RM=CIR[2:0]; + Wbit=INSTRUCTION[24:24]; + IN_MOD={1'b0,INSTRUCTION[23:22]}; + RM=INSTRUCTION[18:16]; in_alu_sel2=(IN_MOD==3'b011)? 2'b01 : 2'b00; in_alu_sel1=2'b00;/* number 1 */ PARAM1=1; @@ -490,7 +490,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin reg_read_port2_addr={1'b0,RM}; reg_write_addr={1'b0,RM}; - ALU_OP=(CIR[3:3]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD; + ALU_OP=(INSTRUCTION[19:19]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD; if ( IN_MOD == 3'b011 ) next_state=`EXEC_WRITE_ENTRY; else @@ -518,7 +518,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* */ /* NOTE: 8086 doc doesn't show the third byte but the */ /* W flag and my assembler seem to disagree */ - Wbit=CIR[8:8]; + Wbit=INSTRUCTION[24:24]; opcode_size=0; IN_MOD=3'b011; in_alu_sel1=2'b00; @@ -528,11 +528,12 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin ALU_OP=`ALU_OP_SUB_REVERSE; MEM_OR_IO=0; if(Wbit==1) - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; else begin - PARAM1[7:0]=CIR[7:0]; - next_state=`EXEC_WRITE_ENTRY; + PARAM_ACTION=`LOAD_8; + //PARAM1[7:0]=INSTRUCTION[7:0]; TODO:needed? end + next_state=`EXEC_WRITE_ENTRY; `normal_instruction; DEPENDS_ON_PREVIOUS<=0; memio_address_select=0; @@ -550,14 +551,14 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin opcode_size=0; in_alu_sel1=2'b10; in_alu_sel2=2'b00; - PARAM2={{8{CIR[7:7]}},CIR[7:0]}; + PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]}; ALU_OP=`ALU_OP_ADD_SIGNED_B; MEM_OR_IO=0; OUT_MOD=3'b101; - case(CIR[11:9]) + case(INSTRUCTION[27:25]) 3'b000: begin /* Jump on (not) Overflow */ - if(FLAGS[11:11]==CIR[8:8]) + if(FLAGS[11:11]==INSTRUCTION[24:24]) next_state=`EXEC_NEXT_INSTRUCTION; else begin next_state=`EXEC_WRITE_ENTRY; @@ -566,7 +567,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin end 3'b010: begin /* Jump on (not) Zero */ - if(FLAGS[6:6]==CIR[8:8]) + if(FLAGS[6:6]==INSTRUCTION[24:24]) next_state=`EXEC_NEXT_INSTRUCTION; else next_state=`EXEC_WRITE_ENTRY; @@ -574,7 +575,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin end 3'b100: begin /* Jump on (not) Sign */ - if(FLAGS[7:7]==CIR[8:8]) + if(FLAGS[7:7]==INSTRUCTION[24:24]) next_state=`EXEC_NEXT_INSTRUCTION; else next_state=`EXEC_WRITE_ENTRY; @@ -582,7 +583,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin end 3'b101: begin /* Jump on (not) Parity */ - if(FLAGS[2:2]==CIR[8:8]) + if(FLAGS[2:2]==INSTRUCTION[24:24]) next_state=`EXEC_NEXT_INSTRUCTION; else next_state=`EXEC_WRITE_ENTRY; @@ -590,7 +591,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin end 3'b001: begin /* Jump on (not) Carry */ - if(FLAGS[0:0]==CIR[8:8]) + if(FLAGS[0:0]==INSTRUCTION[24:24]) next_state=`EXEC_NEXT_INSTRUCTION; else next_state=`EXEC_WRITE_ENTRY; @@ -610,7 +611,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin Wbit=1; in_alu_sel1=2'b10; in_alu_sel2=2'b00; - PARAM2={{8{CIR[7:7]}},CIR[7:0]}; + PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]}; ALU_OP=`ALU_OP_ADD_SIGNED_B; OUT_MOD=3'b101; MEM_OR_IO=0; @@ -651,7 +652,7 @@ 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; - Wbit=CIR[8:8]; + Wbit=INSTRUCTION[24:24]; Sbit=0; RM=3'b101; seq_addr_entry<=`UCODE_STOS_ENTRY; @@ -667,7 +668,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin Wbit=1; Sbit=0; PARAM2=2; - reg_read_port2_addr={1'b1,CIR[10:8]}; + reg_read_port2_addr={1'b1,INSTRUCTION[26:24]}; seq_addr_entry<=`UCODE_PUSH_ENTRY; `normal_microcoded memio_address_select=0; @@ -677,14 +678,14 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* TEST - Bitwise AND of immediate and registers/memory 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 */ opcode_size=1; - Wbit=CIR[8:8]; - IN_MOD={1'b0,CIR[7:6]}; - RM={CIR[2:0]}; + Wbit=INSTRUCTION[24:24]; + IN_MOD={1'b0,INSTRUCTION[23:22]}; + RM={INSTRUCTION[18:16]}; MEM_OR_IO=0; if(Wbit==1)begin - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; end else begin - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; end in_alu_sel1=2'b00; /* PARAM1 */ ALU_OP=`ALU_OP_AND; @@ -692,9 +693,11 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin 3'b011:begin in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; + next_state=`EXEC_WRITE_ENTRY; end default:begin `invalid_instruction + next_state=`EXEC_MEMIO_READ; end endcase OUT_MOD=3'b100;/*NULL*/ @@ -706,15 +709,16 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* TEST - Bitwise AND of immediate and accumulator affecting only flags */ /* 1 0 1 0 1 0 0 W | DATA | DATA if W | */ opcode_size=0; - Wbit=CIR[8:8]; + Wbit=INSTRUCTION[24:24]; IN_MOD=3'b011; RM=3'b000; MEM_OR_IO=0; if(Wbit==1)begin - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; end else begin - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; end + next_state=`EXEC_WRITE_ENTRY; in_alu_sel1=2'b00; /* PARAM1 */ ALU_OP=`ALU_OP_AND; in_alu_sel2=2'b01; @@ -731,7 +735,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin Wbit=1; Sbit=0; PARAM1=2; - reg_write_addr={1'b1,CIR[10:8]}; + reg_write_addr={1'b1,INSTRUCTION[26:24]}; seq_addr_entry<=`UCODE_POP_ENTRY; `normal_microcoded DEPENDS_ON_PREVIOUS<=0; @@ -742,8 +746,8 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* 1 1 1 1 1 1 1 1 | MOD 1 0 0 R/M | < DISP-LO > | < DISP-HI > */ opcode_size=1; Wbit=1; - IN_MOD={1'b0,CIR[7:6]}; - RM=CIR[2:0]; + IN_MOD={1'b0,INSTRUCTION[23:22]}; + RM=INSTRUCTION[18:16]; MEM_OR_IO=0; in_alu_sel1=2'b11; if (IN_MOD==3'b011)begin @@ -763,23 +767,24 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin 11'b1100_011?_000:begin /* 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 */ - Wbit=CIR[8:8]; + Wbit=INSTRUCTION[24:24]; opcode_size=1; in_alu_sel1=2'b00; in_alu_sel2=2'b11; MEM_OR_IO=0; if(Wbit==1)begin - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; end else begin - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; end - OUT_MOD={1'b0,CIR[7:6]}; + OUT_MOD={1'b0,INSTRUCTION[23:22]}; IN_MOD=3'b011; - RM=CIR[2:0]; + RM=INSTRUCTION[18:16]; `normal_instruction; DEPENDS_ON_PREVIOUS<=0; memio_address_select=0; + next_state=`EXEC_WRITE_ENTRY; end 11'b1100_1101_???:begin /* INT - Execute interrupt handler */ @@ -803,18 +808,19 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* OUT - Write AL or AX to a defined output port */ /* | 1 1 1 0 0 1 1 W | DATA 8 | */ memio_address_select=1; - Wbit=CIR[8:8]; + Wbit=INSTRUCTION[24:24]; opcode_size=0; in_alu_sel1=2'b00; in_alu_sel2=2'b11; reg_read_port1_addr={Wbit,3'b000}; - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; MEM_OR_IO=1; HALT <= 0; PARAM1=0; OUT_MOD={3'b000}; DEPENDS_ON_PREVIOUS<=0; IN_MOD=3'b011; + next_state=`EXEC_WRITE_ENTRY; end 11'b1100_1111_???:begin /* IRET - Return from interrupt */ @@ -836,17 +842,17 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* AND - Bitwise AND immediate and register/mem */ /* 1 0 0 0 0 0 0 W | MOD 1 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */ opcode_size=1; - Wbit=CIR[8:8]; - IN_MOD={1'b0,CIR[7:6]}; - RM={CIR[2:0]}; + Wbit=INSTRUCTION[24:24]; + IN_MOD={1'b0,INSTRUCTION[23:22]}; + RM={INSTRUCTION[18:16]}; MEM_OR_IO=0; if(Wbit==1)begin - next_state=`EXEC_DE_LOAD_16_PARAM; + PARAM_ACTION=`LOAD_16; end else begin - next_state=`EXEC_DE_LOAD_8_PARAM; + PARAM_ACTION=`LOAD_8; end in_alu_sel1=2'b00; /* PARAM1 */ - case(CIR[5:3]) + case(INSTRUCTION[21:19]) 3'b100: ALU_OP=`ALU_OP_AND; 3'b001: ALU_OP=`ALU_OP_OR; default:begin end @@ -856,9 +862,11 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; reg_write_addr={Wbit,RM}; + next_state=`EXEC_WRITE_ENTRY; end default:begin `unimpl_addressing_mode + next_state=`EXEC_MEMIO_READ; end endcase OUT_MOD=IN_MOD; @@ -874,12 +882,12 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin /* ADD - Reg/memory with register to either */ /* 0 0 0 0 0 0 D W | MOD REG R/M | < DISP LO > | < DISP HI > | */ opcode_size=1; - Wbit=CIR[8:8]; + Wbit=INSTRUCTION[24:24]; Sbit=0; IN_MOD=3'b011; - RM=CIR[2:0]; + RM=INSTRUCTION[18:16]; in_alu_sel1=2'b01;//constantly register - reg_read_port1_addr={Wbit,CIR[5:3]}; + reg_read_port1_addr={Wbit,INSTRUCTION[21:19]}; if(IN_MOD==3'b011)begin in_alu_sel2=2'b01; reg_read_port2_addr={Wbit,RM}; @@ -887,27 +895,29 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin next_state=`EXEC_WRITE_ENTRY; end else begin in_alu_sel2=2'b00; - if(Wbit) - next_state=`EXEC_DE_LOAD_16_PARAM; - else - next_state=`EXEC_DE_LOAD_8_PARAM; + if(Wbit==1)begin + PARAM_ACTION=`LOAD_16; + end else begin + PARAM_ACTION=`LOAD_8; + end end MEM_OR_IO=0; memio_address_select=0; - case (CIR[13:10]) + case (INSTRUCTION[29:26]) 4'b0000: ALU_OP=`ALU_OP_ADD; 4'b1010: ALU_OP=`ALU_OP_SUB; 4'b1110: ALU_OP=`ALU_OP_SUB_REVERSE; default: begin end endcase - case (CIR[13:10]) - 4'b0000: OUT_MOD={1'b0,CIR[7:6]}; - 4'b1010: OUT_MOD={1'b0,CIR[7:6]}; + case (INSTRUCTION[29:26]) + 4'b0000: OUT_MOD={1'b0,INSTRUCTION[23:22]}; + 4'b1010: OUT_MOD={1'b0,INSTRUCTION[23:22]}; 4'b1110: OUT_MOD=3'b100; /* NULL */ default: begin end endcase DEPENDS_ON_PREVIOUS<=0; - if(CIR[9:9]==1'b0) begin + next_state=`EXEC_WRITE_ENTRY; + if(INSTRUCTION[25:25]==1'b0) begin `normal_instruction; end else begin `unimpl_addressing_mode; @@ -923,11 +933,11 @@ 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=`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; + 3'b000: begin next_state=`EXEC_WRITE_ENTRY; set_params = 0; end + 3'b001: begin next_state=`EXEC_WRITE_ENTRY; PARAM_ACTION=`LOAD_16;end + 3'b010: begin next_state=`EXEC_WRITE_ENTRY; PARAM_ACTION=`LOAD_8;end + 3'b011: begin next_state=`EXEC_MEMIO_READ;set_params = 0; end + 3'b100: begin next_state=`EXEC_MEMIO_READ_SETADDR;set_params = 0; end default: begin end /*impossible*/ endcase if(ucode_data[36:36]==0) /*Set reg write address*/ @@ -959,6 +969,42 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin MEM_OR_IO=0; HALT <= 0; end + + if(PARAM_ACTION==`LOAD_8)begin + if(opcode_size==0)begin + if({Sbit,Wbit}==2'b11)begin + /*signed "16bit" read*/ + PARAM1 = {{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]}; + end else begin + //PARAM1[7:0] = INSTRUCTION[23:16]; + PARAM1 = {8'b0,INSTRUCTION[23:16]}; + end + end else begin + if({Sbit,Wbit}==2'b11)begin + /*signed "16bit" read*/ + PARAM1 = {{8{INSTRUCTION[15:15]}},INSTRUCTION[15:8]}; + end else begin + //PARAM1[7:0] = INSTRUCTION[15:8]; + PARAM1 = {8'b0,INSTRUCTION[15:8]}; + end + end + case(IN_MOD) + 3'b000,3'b001,3'b010: next_state = `EXEC_MEMIO_READ; + default: next_state = `EXEC_WRITE_ENTRY; + endcase + end else if (PARAM_ACTION == `LOAD_16) begin + if(opcode_size==0)begin + PARAM1[7:0] = INSTRUCTION[23:16]; + PARAM1[15:8] = INSTRUCTION[15:8]; + end else begin + PARAM1[15:8] = INSTRUCTION[7:0]; + PARAM1[7:0] = INSTRUCTION[15:8]; + end + case(IN_MOD) + 3'b000,3'b001,3'b010: next_state = `EXEC_MEMIO_READ; + default: next_state = `EXEC_WRITE_ENTRY; + endcase + end end `undef invalid_instruction @@ -966,7 +1012,7 @@ endmodule // verilator lint_on BLKSEQ -/* IN: {CIR[15:8],CIR[5:3]} */ +/* IN: {INSTRUCTION[31:24],INSTRUCTION[21:19]} */ /* OUT: number in bytes */ module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT ); always @( IN ) begin diff --git a/system/exec_state_def.v b/system/exec_state_def.v index b3c9c11..446b351 100644 --- a/system/exec_state_def.v +++ b/system/exec_state_def.v @@ -24,9 +24,7 @@ `define EXEC_WAIT 4'b1100 /*DECODE SATE*/ -`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 EXEC_MEMIO_READ 4'b0101 diff --git a/system/execute.v b/system/execute.v index 93afb87..05caba7 100644 --- a/system/execute.v +++ b/system/execute.v @@ -17,8 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +`include "exec_state_def.v" +`include "alu_header.v" +`include "error_header.v" + module execute_unit ( - /* GENERAL */ input clock, input reset ,input Wbit, input Sbit, input opcode_size,input [23:0] INSTRUCTION_BUFFER,input valid_input + /* GENERAL */ input clock, input reset ,input Wbit , 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, output reg next_exec /* PARAM */ ,input [15:0] PARAM1_INIT, input [15:0] PARAM2_INIT @@ -115,44 +119,6 @@ always @(posedge clock) begin 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) diff --git a/system/processor.v b/system/processor.v index 9506760..78abf51 100644 --- a/system/processor.v +++ b/system/processor.v @@ -20,13 +20,6 @@ `include "exec_state_def.v" `include "alu_header.v" `include "config.v" -`include "ucode_header.v" -`include "error_header.v" - -`define PROC_STATE_BITS 3 -`define PROC_RESET 3'b000 -`define PROC_DE_STATE_ENTRY 3'b001 -`define PROC_HALT 3'b011 //HALT: active high //IOMEM: 1=IO 0=MEM @@ -82,11 +75,9 @@ assign OUT_MOD=DE_OUTPUT[49:47]; wire [`ALU_OP_BITS-1:0] ALU_OP; assign ALU_OP = DE_OUTPUT[42:40]; -wire [23:0] DE2EX_INSTRUCTION; - wire next_exec; execute_unit execute_unit ( - /* GENERAL */ clock, reset, Wbit, Sbit, opcode_size, DE2EX_INSTRUCTION[23:0] , valid_exec_data + /* GENERAL */ clock, reset, Wbit, valid_exec_data /* */ ,IN_MOD, OUT_MOD,memio_address_select, ProgCount, RM, EXEC_ERROR, write /* */ ,set_initial_values,next_exec /* PARAM */ ,PARAM1_INIT,PARAM2_INIT @@ -122,13 +113,14 @@ assign BIU_DATA= biu_data_direction ? 16'hz : (memio_address_select ? reg_read_p /*############ Decoder ########################################################## */ +/* verilator lint_off UNUSEDSIGNAL */ //TODO wire [`EXEC_STATE_BITS+`ERROR_BITS+65:0] DE_OUTPUT; decoder decoder( /* GENERAL */ clock, reset, /* INPUT FROM IF */ INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION /* INPUT FROM EX */ ,EX2DE_FLAGS[7:0],next_exec - /* OUTPUT TO EX */ ,DE_OUTPUT,DE2EX_INSTRUCTION + /* OUTPUT TO EX */ ,DE_OUTPUT /* */ ,ProgCount,set_initial_values,valid_exec_data /* OUTPUT TO IF */ ,VALID_INSTRUCTION_ACK `ifdef CALCULATE_IPC @@ -152,9 +144,7 @@ assign reg_write_addr=DE_OUTPUT[61:58]; wire MEM_OR_IO; assign MEM_OR_IO = DE_OUTPUT[7:7]; -wire Wbit, Sbit, opcode_size; -assign opcode_size=DE_OUTPUT[62:62]; -assign Sbit=DE_OUTPUT[63:63]; +wire Wbit; assign Wbit=DE_OUTPUT[64:64]; wire [`ERROR_BITS-1:0] DE_ERROR;