diff --git a/gtkwave_savefile.gtkw b/gtkwave_savefile.gtkw
index 48fe1cc..c347388 100644
--- a/gtkwave_savefile.gtkw
+++ b/gtkwave_savefile.gtkw
@@ -1,43 +1,62 @@
[*]
[*] GTKWave Analyzer v3.3.111 (w)1999-2020 BSI
-[*] Thu Mar 9 04:20:33 2023
+[*] Sun May 7 11:35:53 2023
[*]
[dumpfile] "/home/user/9086/system/boot_code.fst"
-[dumpfile_mtime] "Thu Mar 9 04:18:18 2023"
-[dumpfile_size] 8510
+[dumpfile_mtime] "Sun May 7 11:35:19 2023"
+[dumpfile_size] 13013
[savefile] "/home/user/9086/gtkwave_savefile.gtkw"
-[timestart] 198700000000
-[size] 1236 1017
+[timestart] 500000000
+[size] 1524 993
[pos] -1 -1
-*-34.595051 280500000000 -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
+*-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
[treeopen] TOP.
[treeopen] TOP.system.
-[sst_width] 221
+[treeopen] TOP.system.p.
+[treeopen] TOP.system.p.BIU.
+[sst_width] 263
[signals_width] 293
[sst_expanded] 1
[sst_vpaned_height] 312
@28
TOP.system.clock
TOP.system.reset
-TOP.system.p.state[5:0]
@22
-TOP.system.p.ucode_seq_addr[4:0]
TOP.system.address_bus[19:0]
TOP.system.data_bus[15:0]
-TOP.system.p.CIR[15:0]
-TOP.system.p.PARAM1[15:0]
-TOP.system.p.PARAM2[15:0]
+TOP.system.p.BIU.biu_state[3:0]
@28
TOP.system.p.read
TOP.system.p.write
-@29
TOP.system.IOMEM
-@22
-TOP.system.p.ALU_1A[15:0]
-TOP.system.p.ALU_1B[15:0]
-TOP.system.p.ALU_1O[15:0]
-@28
-TOP.system.p.ERROR
+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]
+TOP.system.p.BIU.INPUT_FIFO[0][7:0]
+TOP.system.p.BIU.INPUT_FIFO[1][7:0]
+TOP.system.p.BIU.INPUT_FIFO[2][7:0]
+TOP.system.p.BIU.INPUT_FIFO[3][7:0]
+TOP.system.p.BIU.INPUT_FIFO[4][7:0]
+TOP.system.p.BIU.INPUT_FIFO[5][7:0]
+TOP.system.p.BIU.INPUT_FIFO[6][7:0]
+TOP.system.p.BIU.INPUT_FIFO[7][7:0]
+TOP.system.p.BIU.INPUT_FIFO[8][7:0]
+TOP.system.p.BIU.INPUT_FIFO[9][7:0]
+TOP.system.p.BIU.INPUT_FIFO[10][7:0]
+TOP.system.p.BIU.INPUT_FIFO[11][7:0]
+TOP.system.p.BIU.INPUT_FIFO[12][7:0]
+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]
[pattern_trace] 1
[pattern_trace] 0
diff --git a/system/Makefile b/system/Makefile
index cdb7321..33d1e2a 100644
--- a/system/Makefile
+++ b/system/Makefile
@@ -16,7 +16,7 @@
# 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
+SOURCES=processor.v memory.v registers.v alu.v decoder.v general.v biu.v
EVENT_SIM_TESTBENCH=testbench.v
VERILATOR_TESTBENCH=testbench.cpp
INCLUDES=proc_state_def.v alu_header.v config.v ucode_header.v
@@ -41,7 +41,7 @@ VERILATOR_OPTS += -Wall --Wno-DECLFILENAME -Wno-SYNCASYNCNET -Wno-MULTIDRIVEN
#optimisation options
VERILATOR_OPTS += -x-assign fast --x-initial fast
#For testing use:
-#VERILATOR_OPTS=-x-assign unique --x-initial unique
+#VERILATOR_OPTS += -x-assign unique --x-initial unique
# COMPILING
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
diff --git a/system/biu.v b/system/biu.v
new file mode 100644
index 0000000..e4f4939
--- /dev/null
+++ b/system/biu.v
@@ -0,0 +1,305 @@
+/* processor.v - implementation of the 9086 bus interface unit. The logic that
+ controls all external bus functions
+
+ This file is part of the 9086 project.
+
+ Copyright (c) 2023 Efthymios Kritikos
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+//IOMEM: 1=IO 0=MEM
+
+`define BIU_HALT 4'b0000
+`define BIU_NEXT_ACTION 4'b0001
+`define BIU_READ 4'b0010
+`define BIU_RESET 4'b0011
+
+`define BIU_PUT_BYTE 4'b0100
+`define BIU_PUT_UNALIGNED_16BIT_DATA 4'b0101
+`define BIU_PUT_ALIGNED_16BIT_DATA 4'b0110
+`define BIU_PUT_UNALIGNED_PREP_NEXT 4'b0111
+`define BIU_PUT_UNALIGNED_PREP_NEXT2 4'b1000
+`define BIU_WRITE_EXIT 4'b1001
+`define BIU_WRITE_RELEASE 4'b1010
+
+`define BIU_GET_ALIGNED_DATA 4'b1011
+`define BIU_GET_UNALIGNED_DATA 4'b1100
+`define BIU_GET_SECOND_BYTE 4'b1101
+`define BIU_GET_SECOND_BYTE1 4'b1110
+
+module BIU (
+/*outside world*/ input clock, input reset, output reg [19:0] external_address_bus,
+/* */ inout [15:0] external_data_bus,output reg read, output reg write,output reg BHE,output reg IOMEM,
+/* internal */ output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION, input [1:0] NEXT_POSITION,
+/* */ input[15:0] ADDRESS_INPUT, inout [15:0] DATA, input write_request, input read_request, input Wbit, output reg VALID_DATA, input MEM_OR_IO
+ );
+
+reg [15:0] data_bus_output_register;
+assign external_data_bus=read?data_bus_output_register:16'hz;
+
+reg [15:0] DATA_OUT;
+reg DATA_DIR;
+assign DATA=DATA_DIR ? 16'hz:DATA_OUT;
+
+reg [7:0] INPUT_FIFO [15:0]; //8bit fifo memory with 4bit address bus
+
+reg [3:0] FIFO_start; /*inclusive*/
+reg [3:0] FIFO_end; /*exclusive*/
+
+reg [3:0] biu_state;
+
+always @(negedge reset) begin
+ biu_state <= `BIU_HALT;
+end
+
+always @(posedge reset) begin
+ biu_state <= `BIU_RESET;
+end
+
+reg jump_req;
+
+reg func;
+reg [19:0]INSTRUCTION_ADDRESS;
+reg [19:0]DATA_ADDRESS;
+assign external_address_bus= func? INSTRUCTION_ADDRESS : DATA_ADDRESS ;
+
+/* Read into the FIFO */
+always @(posedge clock) begin
+ if ( jump_req ) begin
+ /* verilator lint_off BLKSEQ */
+ FIFO_start = 4'b0;
+ /* verilator lint_on BLKSEQ */
+ FIFO_end <= 4'b0;
+ INSTRUCTION_ADDRESS <= { 4'b0 , ADDRESS_INPUT-16'd1 };
+ INSTRUCTION_LOCATION <= ADDRESS_INPUT;
+ func <= 1;
+ jump_req <= 0;
+ if (biu_state==`BIU_READ)
+ biu_state <= `BIU_NEXT_ACTION;
+ end else begin
+ case(biu_state)
+ `BIU_HALT: begin
+ end
+ `BIU_NEXT_ACTION: begin /* decide if we can read, if we are full or if we need to do something else */
+ if (write_request) begin
+ func<=0;
+ DATA_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
+ DATA_DIR <= 1 ;
+ VALID_INSTRUCTION <= 0;
+ IOMEM <= MEM_OR_IO;
+ biu_state <= (Wbit==0) ? `BIU_PUT_BYTE : (ADDRESS_INPUT[0:0]?`BIU_PUT_UNALIGNED_16BIT_DATA:`BIU_PUT_ALIGNED_16BIT_DATA) ;
+ end else if ( read_request ) begin
+ func<=0;
+ DATA_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
+ VALID_INSTRUCTION <= 0;
+ DATA_DIR <= 0;
+ read <=0;
+ biu_state <= (ADDRESS_INPUT[0:0])?`BIU_GET_UNALIGNED_DATA:`BIU_GET_ALIGNED_DATA;
+ end else begin
+ if((FIFO_end-FIFO_start)>4'b0011)begin
+ VALID_INSTRUCTION <= 1;
+ INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
+ INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+4'd1];
+ INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+4'd2];
+ INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+4'd3];
+ end
+ if ( FIFO_end[3:0]+4'b0001 != FIFO_start[3:0] ) begin
+ func<=1;
+ biu_state <= `BIU_READ;
+ INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+1;
+ write <= 1;
+ read <= 0;
+ IOMEM <= 0;
+ BHE <= 0;
+ end else begin
+ biu_state <= `BIU_NEXT_ACTION;
+ end
+ end
+ end
+
+ /*************** INSTRUCTION FIFO READ ***************/
+ `BIU_READ: begin
+ /* verilator lint_off BLKSEQ */
+ if(INSTRUCTION_ADDRESS[0:0]==0)begin
+ INPUT_FIFO[FIFO_end] = external_data_bus[7:0];
+ end else begin
+ INPUT_FIFO[FIFO_end] = external_data_bus[15:8];
+ end
+ /* verilator lint_on BLKSEQ */
+ FIFO_end <= FIFO_end+1;
+ biu_state <= `BIU_NEXT_ACTION;
+ read<=1;
+ end
+
+
+ /*************** DATA WRITE ***************/
+ //TODO TODO TODO flush fifo, self modifying code
+ `BIU_PUT_UNALIGNED_16BIT_DATA:begin
+ BHE <= 0;
+ data_bus_output_register <= {DATA[7:0],DATA[15:8]};
+ biu_state <= `BIU_PUT_UNALIGNED_PREP_NEXT;
+ end
+ `BIU_PUT_UNALIGNED_PREP_NEXT:begin
+ write <= 0;
+ biu_state <= `BIU_PUT_UNALIGNED_PREP_NEXT2;
+ end
+ `BIU_PUT_UNALIGNED_PREP_NEXT2:begin
+ write <= 1;
+ DATA_ADDRESS <= DATA_ADDRESS+1;
+ BHE <= 1;
+ biu_state <= `BIU_WRITE_EXIT;
+ end
+ `BIU_PUT_ALIGNED_16BIT_DATA:begin
+ data_bus_output_register <= {DATA[15:8],DATA[7:0]};
+ biu_state <= `BIU_WRITE_EXIT;
+ end
+ `BIU_PUT_BYTE:begin
+ biu_state <= `BIU_WRITE_EXIT;
+ if(ADDRESS_INPUT[0:0]==0) begin
+ BHE <= 1;
+ data_bus_output_register <= {8'b0,DATA[7:0]};
+ end else begin
+ BHE <= 0;
+ data_bus_output_register <= {DATA[7:0],8'b0};
+ end
+ end
+ `BIU_WRITE_EXIT:begin
+ write <= 0;
+ biu_state <= `BIU_WRITE_RELEASE;
+ end
+ `BIU_WRITE_RELEASE:begin
+ write <= 1;
+ biu_state <= `BIU_NEXT_ACTION;
+ end
+
+
+ /*************** DATA READ ***************/
+ `define finished_read \
+ DATA_DIR <= 0; \
+ VALID_DATA <= 1;\
+ if ( read_request == 0 ) begin \
+ biu_state <= `BIU_NEXT_ACTION;\
+ VALID_DATA <= 0;\
+ end
+ `BIU_GET_ALIGNED_DATA:begin
+ DATA_OUT <= (Wbit==1)? external_data_bus : {8'b0,external_data_bus[7:0]} ;
+ read <=1;
+ `finished_read
+ end
+ `BIU_GET_UNALIGNED_DATA:begin
+ DATA_OUT[7:0] <= external_data_bus[15:8];
+ read <=1;
+ if(Wbit==1) begin
+ biu_state <= `BIU_GET_SECOND_BYTE;
+ end else begin
+ `finished_read
+ end
+ end
+ `BIU_GET_SECOND_BYTE:begin
+ DATA_ADDRESS <= DATA_ADDRESS+1;
+ biu_state <= `BIU_GET_SECOND_BYTE1;
+ read <=0;
+ end
+ `BIU_GET_SECOND_BYTE1:begin
+ DATA_OUT[15:8] <= external_data_bus[7:0];
+ `finished_read
+ read <=1;
+ end
+
+ /*************** HOUSE KEEPING ***************/
+ `BIU_RESET: begin
+ /* verilator lint_off BLKSEQ */
+ FIFO_start = 4'b0;
+ /* verilator lint_on BLKSEQ */
+ FIFO_end <= 4'b0;
+ biu_state <= `BIU_NEXT_ACTION;
+ INSTRUCTION_ADDRESS <= 20'h0FFEF;
+ INSTRUCTION_LOCATION <= 16'hFFF0;
+ VALID_INSTRUCTION <= 0;
+ VALID_DATA <= 0;
+ DATA_DIR <= 0;
+ end
+ default: begin
+ biu_state <= `BIU_NEXT_ACTION;/*Should be unreachable*/
+ end
+ endcase
+ end
+end
+
+wire [2:0] Isize;
+InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},Isize);
+
+always @( NEXT_POSITION ) begin
+ case(NEXT_POSITION)
+ 2'b00:begin end /* no action */
+ 2'b01:begin /* Next instruction */
+ /* verilator lint_off BLKSEQ */
+ FIFO_start = FIFO_start + {1'b0,Isize};
+ INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {12'b0,Isize};;
+ /* verilator lint_on BLKSEQ */
+ if((FIFO_end-FIFO_start)>4'b0011)begin
+ VALID_INSTRUCTION <= 1;
+ INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
+ INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+4'd1];
+ INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+4'd2];
+ INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+4'd3];
+ end else begin
+ VALID_INSTRUCTION <= 0;
+ end
+
+ end
+ 2'b10:begin /* Jump to specific location based on register */
+ jump_req <= 1;
+ VALID_INSTRUCTION <= 0;
+ end
+ 2'b11:begin /* Jump to absolute location */
+ end
+ endcase
+end
+
+endmodule
+
+/* Pre-Decode the instruction size */
+/* IN: {CIR[15:8],CIR[5:3]} */
+/* OUT: number in bytes */
+module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT );
+ always @( IN ) begin
+ casez(IN)
+ 11'b0000_010?_??? : VERDICT <= 3'd2+{2'b0,IN[3:3]}; /* ADD - Add Immediate word/byte to accumulator */
+ 11'b1000_00??_101 : VERDICT <= 3'd3+{2'b0,(IN[4:3]==2'b01)}; /* SUB - Subtract immediate word/byte from register/memory */
+ 11'b1000_00??_000 : VERDICT <= 3'd3+{2'b0,(IN[4:3]==2'b01)}; /* ADD - Add Immediate word/byte to register/memory */
+ 11'b1000_00??_111 : VERDICT <= 3'd3+{2'b0,(IN[4:3]==2'b01)}; /* CMP - compare Immediate with register / memory */
+ 11'b1011_????_??? : VERDICT <= 3'd2+{2'b0,IN[6:6]}; /* MOV - Move Immediate byte to register */
+ 11'b1000_10??_??? : VERDICT <= 3'd2; /* MOV - Reg/Mem to/from register */
+ 11'b0100_????_??? : VERDICT <= 3'd1; /* DEC - Decrement Register | INC - Increment Register */
+ 11'b1111_111?_00? : VERDICT <= 3'd2; /* INC - Register/Memory | DEC - Register/Memory */
+ 11'b1111_0100_??? : VERDICT <= 3'd1; /* HLT - Halt */
+ 11'b0011_110?_??? : VERDICT <= 3'd2+{2'b0,IN[3:3]}; /* CMP - Compare Immediate with accumulator */
+ 11'b0111_????_??? : VERDICT <= 3'd2; /* Conditional relative jumps ( JE/JZ, JS/JNS ... ) */
+ 11'b1110_1011_??? : VERDICT <= 3'd2; /* JMP - Unconditional jump direct within segment (short) */
+ 11'b1110_1000_??? : VERDICT <= 3'd3; /* CALL - Direct call within segment */
+ 11'b1100_0011_??? : VERDICT <= 3'd1; /* RET - Return from call within segment */
+ 11'b1010_101?_??? : VERDICT <= 3'd1; /* STOS - Write byte/word to [DI] and increment accordingly */
+ 11'b0101_0???_??? : VERDICT <= 3'd1; /* PUSH - SP-=2; [SP]=REG */
+ 11'b1111_011?_000 : VERDICT <= 3'd3+{2'b0,IN[3:3]}; /* TEST - Bitwise AND affecting only flags */
+ 11'b0101_1???_??? : VERDICT <= 3'd1; /* POP - REG=[SP]; SP+=2 */
+ 11'b1111_1111_100 : VERDICT <= 3'd2; /* JMP - Unconditional indirect within segment jump */
+ 11'b1100_011?_000 : VERDICT <= 3'd3+{2'b0,IN[3:3]}; /* MOV - Move immediate to register/memory */
+ 11'b1100_1101_??? : VERDICT <= 3'd2; /* INT - execute interrupt handler */
+ 11'b1110_011?_??? : VERDICT <= 3'd2; /* OUT - write AL or AX to a defined output port */
+ 11'b1100_1111_??? : VERDICT <= 3'd1; /* IRET - Return from interrupt */
+ default:begin end
+ endcase
+ end
+endmodule
diff --git a/system/decoder.v b/system/decoder.v
index 33d1dc0..a8c620a 100644
--- a/system/decoder.v
+++ b/system/decoder.v
@@ -20,6 +20,7 @@
`include "proc_state_def.v"
`include "alu_header.v"
`include "ucode_header.v"
+`include "error_header.v"
module microcode(
input [`UCODE_ADDR_BITS-1:0] ADDR,
@@ -44,7 +45,7 @@ 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 [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 [`ERROR_BITS: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 [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
@@ -65,7 +66,8 @@ assign REGISTER_FILE_CONTROL={reg_write_addr,reg_read_port1_addr,reg_read_port2_
reg Wbit,Sbit,opcode_size;
assign INSTRUCTION_INFO={Wbit,Sbit,opcode_size};
-reg ERROR, HALT;
+reg [`ERROR_BITS-1:0] ERROR;
+reg HALT;
assign DECODER_SIGNALS={ERROR,HALT};
@@ -76,14 +78,15 @@ wire [`UCODE_DATA_BITS-1:0] ucode_data;
microcode ucode(seq_addr_input,ucode_data);
-`define invalid_instruction next_state=`PROC_IF_STATE_ENTRY;ERROR<=1;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
+`define invalid_instruction next_state=`PROC_DE_STATE_ENTRY;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
-`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=0;HALT<=0;
+`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=`ERR_NO_ERROR;HALT<=0;
+`define normal_microcoded ERROR<=`ERR_NO_ERROR;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
@@ -340,7 +343,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
opcode_size=0;
IN_MOD=3'b011;
HALT<=1;
- ERROR<=0;
+ ERROR<=`ERR_NO_ERROR;
MEM_OR_IO=0;
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
next_state=`PROC_HALT_STATE;
@@ -397,7 +400,7 @@ always @( 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_IF_STATE_ENTRY;
+ next_state=`PROC_NEXT_INSTRUCTION;
else begin
next_state=`PROC_EX_STATE_ENTRY;
end
@@ -405,21 +408,21 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
3'b010: begin
/* Jump on (not) Zero */
if(FLAGS[6:6]==CIR[8:8])
- next_state=`PROC_IF_STATE_ENTRY;
+ next_state=`PROC_NEXT_INSTRUCTION;
else
next_state=`PROC_EX_STATE_ENTRY;
end
3'b100: begin
/* Jump on (not) Sign */
if(FLAGS[7:7]==CIR[8:8])
- next_state=`PROC_IF_STATE_ENTRY;
+ next_state=`PROC_NEXT_INSTRUCTION;
else
next_state=`PROC_EX_STATE_ENTRY;
end
3'b101: begin
/* Jump on (not) Parity */
if(FLAGS[2:2]==CIR[8:8])
- next_state=`PROC_IF_STATE_ENTRY;
+ next_state=`PROC_NEXT_INSTRUCTION;
else
next_state=`PROC_EX_STATE_ENTRY;
end
@@ -457,6 +460,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
Sbit=1;
PARAM2=2; //subtract from sp
seq_addr_entry<=`UCODE_CALL_ENTRY;
+ `normal_microcoded
memio_address_select=0;
end
11'b1100_0011_???:begin
@@ -470,6 +474,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
Sbit=0;
PARAM1=2;
seq_addr_entry<=`UCODE_RET_ENTRY;
+ `normal_microcoded
memio_address_select=0;
end
11'b1010_101?_???:begin
@@ -481,6 +486,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
Sbit=0;
RM=3'b101;
seq_addr_entry<=`UCODE_STOS_ENTRY;
+ `normal_microcoded
PARAM2=(Wbit==1)?2:1;
memio_address_select=0;
end
@@ -494,6 +500,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
PARAM2=2;
reg_read_port2_addr={1'b1,CIR[10:8]};
seq_addr_entry<=`UCODE_PUSH_ENTRY;
+ `normal_microcoded
memio_address_select=0;
end
11'b1111_011?_000:begin
@@ -536,6 +543,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
PARAM1=2;
reg_write_addr={1'b1,CIR[10:8]};
seq_addr_entry<=`UCODE_POP_ENTRY;
+ `normal_microcoded
memio_address_select=0;
end
11'b1111_1111_100:begin
@@ -598,6 +606,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
Sbit=0;
PARAM2=2;
seq_addr_entry<=`UCODE_INT_ENTRY;
+ `normal_microcoded
memio_address_select=0;
end
11'b1110_011?_???:begin
@@ -627,6 +636,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
Sbit=0;
PARAM1=2;
seq_addr_entry<=`UCODE_RET_ENTRY;
+ `normal_microcoded
memio_address_select=0;
end
default:begin
@@ -673,6 +683,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
Wbit=ucode_data[38:38];
memio_address_select=ucode_data[39:39];
MEM_OR_IO=0;
+ HALT <= 0;
end
end
`undef invalid_instruction
diff --git a/system/error_header.v b/system/error_header.v
new file mode 100644
index 0000000..2691a9a
--- /dev/null
+++ b/system/error_header.v
@@ -0,0 +1,4 @@
+`define ERROR_BITS 3
+`define ERR_NO_ERROR 3'b000
+`define ERR_UNIMPL_INSTRUCTION 3'b001
+`define ERR_UNIMPL_ADDRESSING_MODE 3'b010
diff --git a/system/proc_state_def.v b/system/proc_state_def.v
index 3d8dd53..8203c0a 100644
--- a/system/proc_state_def.v
+++ b/system/proc_state_def.v
@@ -18,46 +18,29 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
-`define PROC_STATE_BITS 6
+`define PROC_STATE_BITS 4
-`define PROC_HALT_STATE 6'b000000
-
-/*INSTRUCTION FETCH STATE*/
-`define PROC_IF_STATE_ENTRY 6'b000001
-`define PROC_IF_WRITE_CIR 6'b000010
-`define PROC_IF_STATE_EXTRA_FETCH_SET 6'b000011
-`define PROC_IF_STATE_EXTRA_FETCH 6'b000100
-
+`define PROC_HALT_STATE 4'b0000
/*DECODE SATE*/
-`define PROC_DE_STATE_ENTRY 6'b001000
-`define PROC_DE_LOAD_16_PARAM 6'b001001
-`define PROC_DE_LOAD_16_EXTRA_FETCH_SET 6'b001010
-`define PROC_DE_LOAD_16_EXTRA_FETCH 6'b001011
-`define PROC_DE_LOAD_REG_TO_PARAM 6'b001100
+`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
/*MEM/IO READ*/
-`define PROC_MEMIO_READ 6'b010000
-`define PROC_MEMIO_READ_SETADDR 6'b010001
-`define PROC_MEMIO_GET_ALIGNED_DATA 6'b010010 /* :) */
-`define PROC_MEMIO_GET_UNALIGNED_DATA 6'b010011 /* :( */
-`define PROC_MEMIO_GET_SECOND_BYTE 6'b010100
-`define PROC_MEMIO_GET_SECOND_BYTE1 6'b010101
-`define PROC_DE_LOAD_8_PARAM 6'b010110
+`define PROC_MEMIO_READ 4'b0101
+`define PROC_MEMIO_READ_SETADDR 4'b0110
/*EXECUTE STATE*/
-`define PROC_EX_STATE_ENTRY 6'b100000
+`define PROC_EX_STATE_ENTRY 4'b1000
/*MEM/IO WRITE*/
-`define PROC_MEMIO_WRITE 6'b101000
-`define PROC_MEMIO_PUT_ALIGNED_16BIT_DATA 6'b101001
-`define PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA 6'b101010
-`define PROC_MEMIO_PUT_BYTE 6'b101011
-`define PROC_MEMIO_WRITE_EXIT 6'b101101
-`define PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT 6'b101111
-`define PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2 6'b110010
+`define PROC_MEMIO_WRITE 4'b0111
-`define PROC_NEXT_MICROCODE 6'b111000
+`define PROC_NEXT_INSTRUCTION 4'b1001
-`define PROC_RESET 6'b111100
+`define PROC_NEXT_MICROCODE 4'b1010
+
+`define PROC_RESET 4'b1011
diff --git a/system/processor.v b/system/processor.v
index 261bf07..15bc2f6 100644
--- a/system/processor.v
+++ b/system/processor.v
@@ -21,84 +21,109 @@
`include "alu_header.v"
`include "config.v"
`include "ucode_header.v"
+`include "error_header.v"
//HALT: active high
-//ERROR: active high
//IOMEM: 1=IO 0=MEM
//write: active low
//read: active low
//reset: active low
-module processor ( input clock, input reset, output reg [19:0] external_address_bus, inout [15:0] external_data_bus,output reg read, output reg write,output reg BHE,output reg IOMEM, output reg HALT,output reg ERROR);
-
-/*if we don't read, output the register to have the bus stable by the write falling edge*/
-reg [15:0] data_bus_output_register;
-assign external_data_bus=read?data_bus_output_register:16'hz;
+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);
/*** Global Definitions ***/
-
reg [`PROC_STATE_BITS-1:0] state;
+/*############ Bus Interface Unit ############################################### */
+
+wire [31:0] INSTRUCTION;
+reg [1:0] BIU_NEXT_POSITION;
+wire VALID_INSTRUCTION;
+wire [15:0] INSTRUCTION_LOCATION;
+reg [15:0] BIU_ADDRESS_INPUT;
+wire [15:0] BIU_DATA;
+reg biu_write_request;
+reg biu_data_direction;
+reg 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,BIU_NEXT_POSITION,BIU_ADDRESS_INPUT,BIU_DATA,biu_write_request,biu_read_request,Wbit,BIU_VALID_DATA,MEM_OR_IO
+);
+assign BIU_DATA= biu_data_direction ? 16'hz : (memio_address_select?reg_read_port1_data:ALU_1O);
+
/*############ Decoder ########################################################## */
-wire Wbit, Sbit, opcode_size;
+reg Wbit, Sbit, opcode_size;
+wire DE_Wbit, DE_Sbit, DE_opcode_size;
wire [`PROC_STATE_BITS-1:0] next_state;
-wire [2:0]RM;
+reg [2:0]RM;
wire [15:0]DE_PARAM1;// Input param1 form decoder to alu
wire [15:0]DE_PARAM2;
-wire DE_ERROR,DE_HALT;
+wire [2:0]DE_IN_MOD;
+wire [2:0]DE_RM;
+wire [2:0]DE_OUT_MOD;
+wire [`ERROR_BITS-1:0] DE_ERROR;
+wire DE_HALT;
wire [3:0]DE_reg_read_port1_addr,DE_reg_write_addr,DE_reg_read_port2_addr;
wire [11:0]DE_REGISTER_CONTROL;
wire [2:0]INSTRUCTION_INFO;
-wire [1:0]DECODER_SIGNALS;
+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;
-wire memio_address_select;
-wire MEM_OR_IO;
-
+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;
decoder decoder(
- .CIR(CIR),
+ .CIR(INSTRUCTION[31:16]),
.FLAGS(FLAGS),
.INSTRUCTION_INFO(INSTRUCTION_INFO),
.DECODER_SIGNALS(DECODER_SIGNALS),
.next_state(next_state),
- .IN_MOD(IN_MOD),
- .RM(RM),
+ .IN_MOD(DE_IN_MOD),
+ .RM(DE_RM),
.PARAM1(DE_PARAM1),
.PARAM2(DE_PARAM2),
- .in_alu1_sel1(in_alu1_sel1),
- .in_alu1_sel2(in_alu1_sel2),
- .OUT_MOD(OUT_MOD),
+ .in_alu1_sel1(DE_in_alu1_sel1),
+ .in_alu1_sel2(DE_in_alu1_sel2),
+ .OUT_MOD(DE_OUT_MOD),
.REGISTER_FILE_CONTROL(DE_REGISTER_CONTROL),
- .ALU_1OP(ALU_1OP),
+ .ALU_1OP(DE_ALU_1OP),
.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(memio_address_select),
- .MEM_OR_IO(MEM_OR_IO)
+ .memio_address_select(DE_memio_address_select),
+ .MEM_OR_IO(DE_MEM_OR_IO)
);
-assign Wbit=INSTRUCTION_INFO[2:2];
-assign Sbit=INSTRUCTION_INFO[1:1];
-assign opcode_size=INSTRUCTION_INFO[0:0];
+assign DE_Wbit=INSTRUCTION_INFO[2:2];
+assign DE_Sbit=INSTRUCTION_INFO[1:1];
+assign DE_opcode_size=INSTRUCTION_INFO[0:0];
assign DE_reg_write_addr=DE_REGISTER_CONTROL[11:8];
assign DE_reg_read_port1_addr=DE_REGISTER_CONTROL[7:4];
assign DE_reg_read_port2_addr=DE_REGISTER_CONTROL[3:0];
assign DE_HALT=DECODER_SIGNALS[0:0];
-assign DE_ERROR=DECODER_SIGNALS[1:1];
+assign DE_ERROR=DECODER_SIGNALS[`ERROR_BITS:1];
reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr;
/*############ REGISTERS ########################################################## */
-reg [15:0] CIR;
reg [15:0] PARAM1;
reg [15:0] PARAM2;
@@ -185,114 +210,86 @@ end
/* verilator lint_on MULTIDRIVEN */
/*** Processor stages ***/
-`define invalid_instruction state <= `PROC_IF_STATE_ENTRY;ERROR <= 1;
+`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
+ BIU_NEXT_POSITION <= 0;
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
- ProgCount <= 'hFFF0;//TODO: Implement Segmentation and set to zero
HALT <= 0;
- ERROR <= 0;
+ ERROR <= `ERR_NO_ERROR;
SIMPLE_MICRO <= 0;
reg_write_we <= 1;
instruction_size_init <= 1;
- state <= `PROC_IF_STATE_ENTRY;
+ 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_IF_STATE_ENTRY:begin
- BHE <= 0;
- external_address_bus <= {4'b0,ProgCount};
- IOMEM <= 0;
- read <= 0;
- write <= 1;
- reg_write_we <= 1;
- state <= `PROC_IF_WRITE_CIR;
- reg_write_in_sel <= 2'b00;
- end
- `PROC_IF_WRITE_CIR:begin
- `ifdef DEBUG_PC_ADDRESS
- /* Weird (possible bug) where even though the
- * testbench stop the clock after ERROR gets
- * raised the logic for the rising edge still
- * gets triggered printing this debug message. */
- if(ERROR!=1)begin
- if(instruction_size==1)
- $display("Fetched instruction at %0x",ProgCount - 1);
- else
- $display("Fetched instruction at %0x",ProgCount - 0);
- end
- `endif
- /*I built the entire decode stage with CIR
- * being big endian so just convert it here*/
-
- if(instruction_size==1)begin
- /*Half on CIR half on this address */
- state <= `PROC_DE_STATE_ENTRY;
- if(ProgCount[0:0]==1)begin
- CIR <= {CIR[7:0],external_data_bus[15:8]};
- end else begin
- CIR <= {CIR[7:0],external_data_bus[7:0]};
- end
- ProgCount <= ProgCount+1;
- end else begin
- if(ProgCount[0:0]==1)begin
- /* Half on this address half on the next*/
- ProgCount <= ProgCount+1;
- CIR[15:8] <= external_data_bus[15:8];
- state <= `PROC_IF_STATE_EXTRA_FETCH_SET;
- end else begin
- /* Both on this address! */
- ProgCount <= ProgCount+2;
- CIR <= {external_data_bus[7:0],external_data_bus[15:8]};
- state <= `PROC_DE_STATE_ENTRY;
- end
- end
-
- end
- `PROC_IF_STATE_EXTRA_FETCH_SET:begin
- external_address_bus <= {4'b0,ProgCount};
- BHE <= 0;
- state <= `PROC_IF_STATE_EXTRA_FETCH;
- end
- `PROC_IF_STATE_EXTRA_FETCH:begin
- CIR[7:0] <= external_data_bus[7:0];
- ProgCount <= ProgCount+1;
- state <= `PROC_DE_STATE_ENTRY;
- end
`PROC_DE_STATE_ENTRY:begin
- external_address_bus <= {4'b0,ProgCount};
- 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;
+ 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 time 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;
- end
- ERROR <= DE_ERROR;
- HALT <= DE_HALT;
- reg_read_port1_addr <= DE_reg_read_port1_addr;
- reg_read_port2_addr <= DE_reg_read_port2_addr;
- reg_write_addr <= DE_reg_write_addr;
- 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*/
- end else begin
- state <= next_state;
+ /* 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;
+ `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];
+ end
+ 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_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;
+
+ 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*/
+ BIU_NEXT_POSITION <= 2'b00;
+ end else begin
+ state <= next_state;
+ if ( SIMPLE_MICRO == 0 ) begin
+ BIU_NEXT_POSITION <= 2'b00;
+ end
+ end
end
end
`PROC_DE_LOAD_REG_TO_PARAM:begin
@@ -306,72 +303,35 @@ always @(posedge clock) begin
if(opcode_size==0)begin
if({Sbit,Wbit}==2'b11)begin
/*signed "16bit" read*/
- PARAM1 <= {{8{CIR[7:7]}},CIR[7:0]};
+ PARAM1 <= {{8{INSTRUCTION_BUFFER[23:23]}},INSTRUCTION_BUFFER[23:16]};
end else begin
- PARAM1[7:0] <= CIR[7:0];
+ 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(ProgCount[0:0]==1)begin
- if({Sbit,Wbit}==2'b11)begin
- /*signed "16bit" read*/
- PARAM1 <= {{8{external_data_bus[15:15]}},external_data_bus[15:8]};
- end else begin
- PARAM1[7:0] <= external_data_bus[15:8];
- end
+ if({Sbit,Wbit}==2'b11)begin
+ /*signed "16bit" read*/
+ PARAM1 <= {{8{INSTRUCTION_BUFFER[15:15]}},INSTRUCTION_BUFFER[15:8]};
end else begin
- if({Sbit,Wbit}==2'b11)begin
- /*signed "16bit" read*/
- PARAM1 <= {{8{external_data_bus[7:7]}},external_data_bus[7:0]};
- end else begin
- PARAM1[7:0] <= external_data_bus[7:0];
- end
+ PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8];
end
- ProgCount <= ProgCount+1;
- case(IN_MOD)
- 3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
- default: state <= `PROC_EX_STATE_ENTRY;
- endcase
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] <= CIR[7:0];
- if(ProgCount[0:0]==1)begin
- PARAM1[15:8] <= external_data_bus[15:8];
- end else begin
- PARAM1[15:8] <= external_data_bus[7:0];
- end
- ProgCount <= ProgCount+1;
- case(IN_MOD)
- 3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
- default: state <= `PROC_EX_STATE_ENTRY;
- endcase
+ PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16];
+ PARAM1[15:8] <= INSTRUCTION_BUFFER[15:8];
end else begin
- if(ProgCount[0:0]==1)begin
- ProgCount <= ProgCount+1;
- PARAM1[7:0] <= external_data_bus[15:8];
- state <= `PROC_DE_LOAD_16_EXTRA_FETCH_SET;
- end else begin
- PARAM1 <= external_data_bus;
- ProgCount <= ProgCount+2;
- case(IN_MOD)
- 3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
- default: state <= `PROC_EX_STATE_ENTRY;
- endcase
- end
+ PARAM1[15:8] <= INSTRUCTION_BUFFER[7:0];
+ PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8];
end
- end
- `PROC_DE_LOAD_16_EXTRA_FETCH_SET:begin
- external_address_bus <= {4'b0,ProgCount};
- state <= `PROC_DE_LOAD_16_EXTRA_FETCH;
- end
- `PROC_DE_LOAD_16_EXTRA_FETCH:begin
- ProgCount <= ProgCount+1;
- PARAM1[15:8] <= external_data_bus[7:0];
case(IN_MOD)
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
default: state <= `PROC_EX_STATE_ENTRY;
@@ -386,19 +346,19 @@ always @(posedge clock) begin
case (RM)
3'b000:begin
/*[BX]+[SI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b001:begin
/*[BX]+[SI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b010:begin
/*[BP]+[SI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b011:begin
/*[BP]+[DI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b100:begin
/*[SI]*/
@@ -412,7 +372,7 @@ always @(posedge clock) begin
end
3'b110:begin
/*d16 */
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b111:begin
/*[BX]*/
@@ -422,7 +382,7 @@ always @(posedge clock) begin
endcase
if(IN_MOD!=3'b000)begin
/*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/
- `invalid_instruction;
+ `unimpl_addressing_mode;
end
end
3'b110:begin /* SP Indirect read*/
@@ -430,39 +390,31 @@ always @(posedge clock) begin
state <= `PROC_MEMIO_READ_SETADDR;
end
default:begin
- `invalid_instruction
+ `unimpl_addressing_mode
end
endcase
end
`PROC_MEMIO_READ_SETADDR:begin
if(memio_address_select==0)
- external_address_bus <= {4'b0,reg_read_port1_data[15:0]};
+ BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
else
- external_address_bus <= {4'b0,ALU_1O};
- state <= (memio_address_select?ALU_1O[0:0]:reg_read_port1_data[0:0])?`PROC_MEMIO_GET_UNALIGNED_DATA:`PROC_MEMIO_GET_ALIGNED_DATA;
- end
- `PROC_MEMIO_GET_ALIGNED_DATA:begin
- PARAM2 <= (Wbit==1)? external_data_bus : {8'b0,external_data_bus[7:0]} ;
- state <= `PROC_EX_STATE_ENTRY;
- end
- `PROC_MEMIO_GET_UNALIGNED_DATA:begin
- PARAM2 <= {8'b0,external_data_bus[15:8]};
- if(Wbit==1) begin
- state <= `PROC_MEMIO_GET_SECOND_BYTE;
- end else begin
+ 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_MEMIO_GET_SECOND_BYTE:begin
- external_address_bus <= external_address_bus+1;
- state <= `PROC_MEMIO_GET_SECOND_BYTE1;
- end
- `PROC_MEMIO_GET_SECOND_BYTE1:begin
- PARAM2[15:8] <= external_data_bus[7:0];
- state <= `PROC_EX_STATE_ENTRY;
+ `PROC_NEXT_INSTRUCTION:begin
+ BIU_NEXT_POSITION <= 2'b01;
+ state <= `PROC_DE_STATE_ENTRY;
end
`PROC_EX_STATE_ENTRY:begin
- external_address_bus <= {4'b0,ProgCount};
FLAGS[7:0] <= ALU_1FLAGS[7:0];
case(OUT_MOD)
3'b000,
@@ -474,19 +426,19 @@ always @(posedge clock) begin
case (RM) /* Duplicate code with write... */
3'b000:begin
/*[BX]+[SI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b001:begin
/*[BX]+[SI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b010:begin
/*[BP]+[SI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b011:begin
/*[BP]+[DI]*/
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b100:begin
/*[SI]*/
@@ -500,7 +452,7 @@ always @(posedge clock) begin
end
3'b110:begin
/*d16 */
- `invalid_instruction
+ `unimpl_addressing_mode
end
3'b111:begin
/*[BX]*/
@@ -508,41 +460,52 @@ always @(posedge clock) begin
state <= `PROC_MEMIO_WRITE;
end
endcase
+ if(BIU_NEXT_POSITION != 2'b10 )
+ BIU_NEXT_POSITION <= 2'b01;
end
3'b011:begin
reg_write_we <= 0;
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
- state <= `PROC_IF_STATE_ENTRY;
+ state <= `PROC_DE_STATE_ENTRY;
else
state <= `PROC_NEXT_MICROCODE;
+ if(BIU_NEXT_POSITION != 2'b10 )
+ BIU_NEXT_POSITION <= 2'b01;
end
3'b100:begin /*No output*/
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
- state <= `PROC_IF_STATE_ENTRY;
+ state <= `PROC_DE_STATE_ENTRY;
else
state <= `PROC_NEXT_MICROCODE;
+ if(BIU_NEXT_POSITION != 2'b10 )
+ BIU_NEXT_POSITION <= 2'b01;
end
3'b101:begin /* Program Counter*/
- ProgCount <= ALU_1O[15:0];
+ BIU_ADDRESS_INPUT <= ALU_1O[15:0];
+ BIU_NEXT_POSITION <= 2'b10;
instruction_size_init <= 1;
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
- state <= `PROC_IF_STATE_ENTRY;
+ 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;
+ if(BIU_NEXT_POSITION != 2'b10 )
+ BIU_NEXT_POSITION <= 2'b01;
end
3'b111:begin /* Write to PRAM1 (for microcode calculations) */
PARAM1 <= ALU_1O;
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
- state <= `PROC_IF_STATE_ENTRY;
+ state <= `PROC_DE_STATE_ENTRY;
else
state <= `PROC_NEXT_MICROCODE;
+ if(BIU_NEXT_POSITION != 2'b10 )
+ BIU_NEXT_POSITION <= 2'b01;
end
default:begin
- `invalid_instruction
+ `unimpl_addressing_mode
end
endcase
end
@@ -552,81 +515,37 @@ always @(posedge clock) begin
`ifdef DEBUG_MEMORY_WRITES
$display("Writing at %04x , %04x",reg_read_port1_data,ALU_1O);
`endif
- if(memio_address_select==0)
- external_address_bus <= {4'b0,reg_read_port1_data[15:0]};
- else
- external_address_bus <= {4'b0,ALU_1O};
- IOMEM <= MEM_OR_IO;
- 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
- `PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA:begin
- read <= 1;
- BHE <= 0;
+ biu_write_request <= 1;
+
if(memio_address_select==0)
- data_bus_output_register <= {ALU_1O[7:0],ALU_1O[15:8]};
+ BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
else
- data_bus_output_register <= {reg_read_port1_data[7:0],reg_read_port1_data[15:8]};
- state <= `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT;
- end
- `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT:begin
- write <= 0;
- state <= `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2;
- end
- `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2:begin
- write <= 1;
- external_address_bus <= external_address_bus+1;
- BHE <= 1;
- state <= `PROC_MEMIO_WRITE_EXIT;
- end
- `PROC_MEMIO_PUT_ALIGNED_16BIT_DATA:begin
- read <= 1;
- data_bus_output_register <= {ALU_1O[15:8],ALU_1O[7:0]};
- state <= `PROC_MEMIO_WRITE_EXIT;
- end
- `PROC_MEMIO_PUT_BYTE:begin
- read <= 1;
- state <= `PROC_MEMIO_WRITE_EXIT;
- if((memio_address_select?ALU_1O[0:0]:reg_read_port1_data[0:0])==0) begin
- BHE <= 1;
- if(memio_address_select==0)
- data_bus_output_register <= {8'b0,ALU_1O[7:0]};
+ 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
- data_bus_output_register <= {8'b0,reg_read_port1_data[7:0]};
- end else begin
- BHE <= 0;
- if(memio_address_select==0)
- data_bus_output_register <= {ALU_1O[7:0],8'b0};
- else
- data_bus_output_register <= {reg_read_port1_data[7:0],8'b0};
+ state <= `PROC_NEXT_MICROCODE;
end
- end
- `PROC_MEMIO_WRITE_EXIT:begin
- write <= 0;
- if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
- state <= `PROC_IF_STATE_ENTRY;
- else
- state <= `PROC_NEXT_MICROCODE;
+
end
`PROC_NEXT_MICROCODE:begin
- read <= 0;
- write <= 1; // maybe we are coming from MEMIO_WRITE
- BHE <= 0;
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;
- state <= `PROC_IF_STATE_ENTRY;
- end else begin
- state <= `PROC_DE_STATE_ENTRY;
end
+ state <= `PROC_DE_STATE_ENTRY;
reg_write_we <= 1;
end
default:begin
end
endcase
end
-`undef invalid_instruction
+`undef unimpl_addressing_mode
endmodule
diff --git a/system/system.v b/system/system.v
index 0c651bc..7bea1f1 100644
--- a/system/system.v
+++ b/system/system.v
@@ -18,9 +18,10 @@
along with this program. If not, see . */
`timescale 1ns/1ps
+`include "error_header.v"
-module system ( input clock,input reset, output [19:0]address_bus, inout [15:0]data_bus,output BHE, output rd, output wr, output IOMEM, output HALT, output ERROR);
+module system ( input clock,input reset, output [19:0]address_bus, inout [15:0]data_bus,output BHE, output rd, output wr, output IOMEM, output HALT, output [`ERROR_BITS-1:0] ERROR);
processor p(clock,reset,address_bus,data_bus,rd,wr,BHE,IOMEM,HALT,ERROR);
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
@@ -33,6 +34,17 @@ initial begin
end
end
+//integer killswitch=0;
+//always @(posedge clock) begin
+// killswitch <= killswitch +1;
+// if( killswitch == 20000 )begin
+// if($value$plusargs("MEMDUMP=%s",memdump_name))begin
+// $writememh(memdump_name, system.sysmem.memory,0,32767);
+// end
+// $finish;
+// end
+//end
+
always @(negedge wr) begin
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
$write("%s" ,data_bus[15:8]);
@@ -59,12 +71,25 @@ always @(posedge clock) begin
endcase
end
-always @(posedge ERROR) begin
- $display("PROCESSOR RUN INTO AN ERROR.\nCycles run for: %d",cycles-1);
- if($value$plusargs("MEMDUMP=%s",memdump_name))begin
- $writememh(memdump_name, system.sysmem.memory,0,32767);
+always @( ERROR ) begin
+ if ( ERROR != `ERR_NO_ERROR ) begin
+ $display("PROCESSOR RUN INTO AN ERROR.");
+ case (ERROR)
+ default:begin
+ end
+ `ERR_UNIMPL_INSTRUCTION:begin
+ $display("Unimplemented instruction");
+ end
+ `ERR_UNIMPL_ADDRESSING_MODE: begin
+ $display("Unimplemented addressing mode");
+ end
+ endcase
+ $display("Cycles run for: %d",cycles-1);
+ if($value$plusargs("MEMDUMP=%s",memdump_name))begin
+ $writememh(memdump_name, system.sysmem.memory,0,32767);
+ end
+ finish<=2'd1;
end
- finish<=2'd1;
end
integer cycles=0;
diff --git a/system/testbench.v b/system/testbench.v
index 006567a..aec22e8 100644
--- a/system/testbench.v
+++ b/system/testbench.v
@@ -27,7 +27,7 @@ reg clk_enable;
wire [19:0]address_bus;
wire [15:0]data_bus;
wire rd,wr,HALT;
-wire ERROR;
+wire [2:0] ERROR;
wire IOMEM;
system system( .clock(clock),