First draft of a bus interface unit in an effort to make the CPU pipelined. Currently supports code prefetching
This commit is contained in:
parent
88a47cc4a9
commit
da51dd6da7
@ -1,43 +1,62 @@
|
|||||||
[*]
|
[*]
|
||||||
[*] GTKWave Analyzer v3.3.111 (w)1999-2020 BSI
|
[*] 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] "/home/user/9086/system/boot_code.fst"
|
||||||
[dumpfile_mtime] "Thu Mar 9 04:18:18 2023"
|
[dumpfile_mtime] "Sun May 7 11:35:19 2023"
|
||||||
[dumpfile_size] 8510
|
[dumpfile_size] 13013
|
||||||
[savefile] "/home/user/9086/gtkwave_savefile.gtkw"
|
[savefile] "/home/user/9086/gtkwave_savefile.gtkw"
|
||||||
[timestart] 198700000000
|
[timestart] 500000000
|
||||||
[size] 1236 1017
|
[size] 1524 993
|
||||||
[pos] -1 -1
|
[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.
|
||||||
[treeopen] TOP.system.
|
[treeopen] TOP.system.
|
||||||
[sst_width] 221
|
[treeopen] TOP.system.p.
|
||||||
|
[treeopen] TOP.system.p.BIU.
|
||||||
|
[sst_width] 263
|
||||||
[signals_width] 293
|
[signals_width] 293
|
||||||
[sst_expanded] 1
|
[sst_expanded] 1
|
||||||
[sst_vpaned_height] 312
|
[sst_vpaned_height] 312
|
||||||
@28
|
@28
|
||||||
TOP.system.clock
|
TOP.system.clock
|
||||||
TOP.system.reset
|
TOP.system.reset
|
||||||
TOP.system.p.state[5:0]
|
|
||||||
@22
|
@22
|
||||||
TOP.system.p.ucode_seq_addr[4:0]
|
|
||||||
TOP.system.address_bus[19:0]
|
TOP.system.address_bus[19:0]
|
||||||
TOP.system.data_bus[15:0]
|
TOP.system.data_bus[15:0]
|
||||||
TOP.system.p.CIR[15:0]
|
TOP.system.p.BIU.biu_state[3:0]
|
||||||
TOP.system.p.PARAM1[15:0]
|
|
||||||
TOP.system.p.PARAM2[15:0]
|
|
||||||
@28
|
@28
|
||||||
TOP.system.p.read
|
TOP.system.p.read
|
||||||
TOP.system.p.write
|
TOP.system.p.write
|
||||||
@29
|
|
||||||
TOP.system.IOMEM
|
TOP.system.IOMEM
|
||||||
@22
|
TOP.system.p.ERROR[2:0]
|
||||||
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.HALT
|
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] 1
|
||||||
[pattern_trace] 0
|
[pattern_trace] 0
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
TOP_LEVEL_SOURCE=system.v
|
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
|
EVENT_SIM_TESTBENCH=testbench.v
|
||||||
VERILATOR_TESTBENCH=testbench.cpp
|
VERILATOR_TESTBENCH=testbench.cpp
|
||||||
INCLUDES=proc_state_def.v alu_header.v config.v ucode_header.v
|
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
|
#optimisation options
|
||||||
VERILATOR_OPTS += -x-assign fast --x-initial fast
|
VERILATOR_OPTS += -x-assign fast --x-initial fast
|
||||||
#For testing use:
|
#For testing use:
|
||||||
#VERILATOR_OPTS=-x-assign unique --x-initial unique
|
#VERILATOR_OPTS += -x-assign unique --x-initial unique
|
||||||
|
|
||||||
# COMPILING
|
# COMPILING
|
||||||
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
|
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
|
||||||
|
305
system/biu.v
Normal file
305
system/biu.v
Normal file
@ -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 <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
//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
|
@ -20,6 +20,7 @@
|
|||||||
`include "proc_state_def.v"
|
`include "proc_state_def.v"
|
||||||
`include "alu_header.v"
|
`include "alu_header.v"
|
||||||
`include "ucode_header.v"
|
`include "ucode_header.v"
|
||||||
|
`include "error_header.v"
|
||||||
|
|
||||||
module microcode(
|
module microcode(
|
||||||
input [`UCODE_ADDR_BITS-1:0] ADDR,
|
input [`UCODE_ADDR_BITS-1:0] ADDR,
|
||||||
@ -44,7 +45,7 @@ endmodule
|
|||||||
|
|
||||||
// verilator lint_off UNUSEDSIGNAL
|
// verilator lint_off UNUSEDSIGNAL
|
||||||
module decoder(
|
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 [2:0]IN_MOD, output reg [2:0]RM, output reg [15:0] PARAM1,output reg [15:0] PARAM2
|
||||||
,output reg [1:0]in_alu1_sel1,output reg [1:0]in_alu1_sel2,output reg [2:0]OUT_MOD
|
,output reg [1:0]in_alu1_sel1,output reg [1:0]in_alu1_sel2,output reg [2:0]OUT_MOD
|
||||||
,output wire [11:0]REGISTER_FILE_CONTROL
|
,output wire [11:0]REGISTER_FILE_CONTROL
|
||||||
@ -65,7 +66,8 @@ assign REGISTER_FILE_CONTROL={reg_write_addr,reg_read_port1_addr,reg_read_port2_
|
|||||||
reg Wbit,Sbit,opcode_size;
|
reg Wbit,Sbit,opcode_size;
|
||||||
assign INSTRUCTION_INFO={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};
|
assign DECODER_SIGNALS={ERROR,HALT};
|
||||||
|
|
||||||
|
|
||||||
@ -76,14 +78,15 @@ wire [`UCODE_DATA_BITS-1:0] ucode_data;
|
|||||||
|
|
||||||
microcode ucode(seq_addr_input,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
|
//TODO: A possible optimisation for instruction with 8bit parameter and
|
||||||
//opcode_size=0 would be to set PARAM1 here instead of sending execution over
|
//opcode_size=0 would be to set PARAM1 here instead of sending execution over
|
||||||
//to PROC_DE_LOAD_8_PARAM
|
//to PROC_DE_LOAD_8_PARAM
|
||||||
|
|
||||||
`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=0;HALT<=0;
|
`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
|
// 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
|
// 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;
|
opcode_size=0;
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
HALT<=1;
|
HALT<=1;
|
||||||
ERROR<=0;
|
ERROR<=`ERR_NO_ERROR;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO=0;
|
||||||
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||||
next_state=`PROC_HALT_STATE;
|
next_state=`PROC_HALT_STATE;
|
||||||
@ -397,7 +400,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
3'b000: begin
|
3'b000: begin
|
||||||
/* Jump on (not) Overflow */
|
/* Jump on (not) Overflow */
|
||||||
if(FLAGS[11:11]==CIR[8:8])
|
if(FLAGS[11:11]==CIR[8:8])
|
||||||
next_state=`PROC_IF_STATE_ENTRY;
|
next_state=`PROC_NEXT_INSTRUCTION;
|
||||||
else begin
|
else begin
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
@ -405,21 +408,21 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
3'b010: begin
|
3'b010: begin
|
||||||
/* Jump on (not) Zero */
|
/* Jump on (not) Zero */
|
||||||
if(FLAGS[6:6]==CIR[8:8])
|
if(FLAGS[6:6]==CIR[8:8])
|
||||||
next_state=`PROC_IF_STATE_ENTRY;
|
next_state=`PROC_NEXT_INSTRUCTION;
|
||||||
else
|
else
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
3'b100: begin
|
3'b100: begin
|
||||||
/* Jump on (not) Sign */
|
/* Jump on (not) Sign */
|
||||||
if(FLAGS[7:7]==CIR[8:8])
|
if(FLAGS[7:7]==CIR[8:8])
|
||||||
next_state=`PROC_IF_STATE_ENTRY;
|
next_state=`PROC_NEXT_INSTRUCTION;
|
||||||
else
|
else
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
3'b101: begin
|
3'b101: begin
|
||||||
/* Jump on (not) Parity */
|
/* Jump on (not) Parity */
|
||||||
if(FLAGS[2:2]==CIR[8:8])
|
if(FLAGS[2:2]==CIR[8:8])
|
||||||
next_state=`PROC_IF_STATE_ENTRY;
|
next_state=`PROC_NEXT_INSTRUCTION;
|
||||||
else
|
else
|
||||||
next_state=`PROC_EX_STATE_ENTRY;
|
next_state=`PROC_EX_STATE_ENTRY;
|
||||||
end
|
end
|
||||||
@ -457,6 +460,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Sbit=1;
|
Sbit=1;
|
||||||
PARAM2=2; //subtract from sp
|
PARAM2=2; //subtract from sp
|
||||||
seq_addr_entry<=`UCODE_CALL_ENTRY;
|
seq_addr_entry<=`UCODE_CALL_ENTRY;
|
||||||
|
`normal_microcoded
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
11'b1100_0011_???:begin
|
11'b1100_0011_???:begin
|
||||||
@ -470,6 +474,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM1=2;
|
PARAM1=2;
|
||||||
seq_addr_entry<=`UCODE_RET_ENTRY;
|
seq_addr_entry<=`UCODE_RET_ENTRY;
|
||||||
|
`normal_microcoded
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
11'b1010_101?_???:begin
|
11'b1010_101?_???:begin
|
||||||
@ -481,6 +486,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Sbit=0;
|
Sbit=0;
|
||||||
RM=3'b101;
|
RM=3'b101;
|
||||||
seq_addr_entry<=`UCODE_STOS_ENTRY;
|
seq_addr_entry<=`UCODE_STOS_ENTRY;
|
||||||
|
`normal_microcoded
|
||||||
PARAM2=(Wbit==1)?2:1;
|
PARAM2=(Wbit==1)?2:1;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -494,6 +500,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
PARAM2=2;
|
PARAM2=2;
|
||||||
reg_read_port2_addr={1'b1,CIR[10:8]};
|
reg_read_port2_addr={1'b1,CIR[10:8]};
|
||||||
seq_addr_entry<=`UCODE_PUSH_ENTRY;
|
seq_addr_entry<=`UCODE_PUSH_ENTRY;
|
||||||
|
`normal_microcoded
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
11'b1111_011?_000:begin
|
11'b1111_011?_000:begin
|
||||||
@ -536,6 +543,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
PARAM1=2;
|
PARAM1=2;
|
||||||
reg_write_addr={1'b1,CIR[10:8]};
|
reg_write_addr={1'b1,CIR[10:8]};
|
||||||
seq_addr_entry<=`UCODE_POP_ENTRY;
|
seq_addr_entry<=`UCODE_POP_ENTRY;
|
||||||
|
`normal_microcoded
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
11'b1111_1111_100:begin
|
11'b1111_1111_100:begin
|
||||||
@ -598,6 +606,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM2=2;
|
PARAM2=2;
|
||||||
seq_addr_entry<=`UCODE_INT_ENTRY;
|
seq_addr_entry<=`UCODE_INT_ENTRY;
|
||||||
|
`normal_microcoded
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
11'b1110_011?_???:begin
|
11'b1110_011?_???:begin
|
||||||
@ -627,6 +636,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM1=2;
|
PARAM1=2;
|
||||||
seq_addr_entry<=`UCODE_RET_ENTRY;
|
seq_addr_entry<=`UCODE_RET_ENTRY;
|
||||||
|
`normal_microcoded
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
@ -673,6 +683,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Wbit=ucode_data[38:38];
|
Wbit=ucode_data[38:38];
|
||||||
memio_address_select=ucode_data[39:39];
|
memio_address_select=ucode_data[39:39];
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO=0;
|
||||||
|
HALT <= 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`undef invalid_instruction
|
`undef invalid_instruction
|
||||||
|
4
system/error_header.v
Normal file
4
system/error_header.v
Normal file
@ -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
|
@ -18,46 +18,29 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
`define PROC_STATE_BITS 6
|
`define PROC_STATE_BITS 4
|
||||||
|
|
||||||
|
|
||||||
`define PROC_HALT_STATE 6'b000000
|
`define PROC_HALT_STATE 4'b0000
|
||||||
|
|
||||||
/*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
|
|
||||||
|
|
||||||
|
|
||||||
/*DECODE SATE*/
|
/*DECODE SATE*/
|
||||||
`define PROC_DE_STATE_ENTRY 6'b001000
|
`define PROC_DE_STATE_ENTRY 4'b0001
|
||||||
`define PROC_DE_LOAD_16_PARAM 6'b001001
|
`define PROC_DE_LOAD_16_PARAM 4'b0010
|
||||||
`define PROC_DE_LOAD_16_EXTRA_FETCH_SET 6'b001010
|
`define PROC_DE_LOAD_REG_TO_PARAM 4'b0011
|
||||||
`define PROC_DE_LOAD_16_EXTRA_FETCH 6'b001011
|
`define PROC_DE_LOAD_8_PARAM 4'b0100
|
||||||
`define PROC_DE_LOAD_REG_TO_PARAM 6'b001100
|
|
||||||
|
|
||||||
/*MEM/IO READ*/
|
/*MEM/IO READ*/
|
||||||
`define PROC_MEMIO_READ 6'b010000
|
`define PROC_MEMIO_READ 4'b0101
|
||||||
`define PROC_MEMIO_READ_SETADDR 6'b010001
|
`define PROC_MEMIO_READ_SETADDR 4'b0110
|
||||||
`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
|
|
||||||
|
|
||||||
/*EXECUTE STATE*/
|
/*EXECUTE STATE*/
|
||||||
`define PROC_EX_STATE_ENTRY 6'b100000
|
`define PROC_EX_STATE_ENTRY 4'b1000
|
||||||
|
|
||||||
/*MEM/IO WRITE*/
|
/*MEM/IO WRITE*/
|
||||||
`define PROC_MEMIO_WRITE 6'b101000
|
`define PROC_MEMIO_WRITE 4'b0111
|
||||||
`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_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
|
||||||
|
@ -21,84 +21,109 @@
|
|||||||
`include "alu_header.v"
|
`include "alu_header.v"
|
||||||
`include "config.v"
|
`include "config.v"
|
||||||
`include "ucode_header.v"
|
`include "ucode_header.v"
|
||||||
|
`include "error_header.v"
|
||||||
|
|
||||||
//HALT: active high
|
//HALT: active high
|
||||||
//ERROR: active high
|
|
||||||
//IOMEM: 1=IO 0=MEM
|
//IOMEM: 1=IO 0=MEM
|
||||||
//write: active low
|
//write: active low
|
||||||
//read: active low
|
//read: active low
|
||||||
//reset: 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);
|
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);
|
||||||
|
|
||||||
/*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;
|
|
||||||
|
|
||||||
/*** Global Definitions ***/
|
/*** Global Definitions ***/
|
||||||
|
|
||||||
reg [`PROC_STATE_BITS-1:0] state;
|
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 ########################################################## */
|
/*############ 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 [`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_PARAM1;// Input param1 form decoder to alu
|
||||||
wire [15:0]DE_PARAM2;
|
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 [3:0]DE_reg_read_port1_addr,DE_reg_write_addr,DE_reg_read_port2_addr;
|
||||||
wire [11:0]DE_REGISTER_CONTROL;
|
wire [11:0]DE_REGISTER_CONTROL;
|
||||||
wire [2:0]INSTRUCTION_INFO;
|
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;
|
wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry;
|
||||||
|
|
||||||
reg SIMPLE_MICRO; /* output simple decodings (=0) or microcode data (=1) */
|
reg SIMPLE_MICRO; /* output simple decodings (=0) or microcode data (=1) */
|
||||||
wire [2:0] DE_instruction_size;
|
wire [2:0] DE_instruction_size;
|
||||||
reg instruction_size_init;
|
reg instruction_size_init;
|
||||||
|
//TODO : remove completely?
|
||||||
|
/* verilator lint_off UNUSEDSIGNAL */
|
||||||
wire [2:0] instruction_size;
|
wire [2:0] instruction_size;
|
||||||
|
/* verilator lint_on UNUSEDSIGNAL */
|
||||||
assign instruction_size = instruction_size_init ? 3'b010 : DE_instruction_size;
|
assign instruction_size = instruction_size_init ? 3'b010 : DE_instruction_size;
|
||||||
wire memio_address_select;
|
reg memio_address_select;
|
||||||
wire MEM_OR_IO;
|
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(
|
decoder decoder(
|
||||||
.CIR(CIR),
|
.CIR(INSTRUCTION[31:16]),
|
||||||
.FLAGS(FLAGS),
|
.FLAGS(FLAGS),
|
||||||
.INSTRUCTION_INFO(INSTRUCTION_INFO),
|
.INSTRUCTION_INFO(INSTRUCTION_INFO),
|
||||||
.DECODER_SIGNALS(DECODER_SIGNALS),
|
.DECODER_SIGNALS(DECODER_SIGNALS),
|
||||||
.next_state(next_state),
|
.next_state(next_state),
|
||||||
.IN_MOD(IN_MOD),
|
.IN_MOD(DE_IN_MOD),
|
||||||
.RM(RM),
|
.RM(DE_RM),
|
||||||
.PARAM1(DE_PARAM1),
|
.PARAM1(DE_PARAM1),
|
||||||
.PARAM2(DE_PARAM2),
|
.PARAM2(DE_PARAM2),
|
||||||
.in_alu1_sel1(in_alu1_sel1),
|
.in_alu1_sel1(DE_in_alu1_sel1),
|
||||||
.in_alu1_sel2(in_alu1_sel2),
|
.in_alu1_sel2(DE_in_alu1_sel2),
|
||||||
.OUT_MOD(OUT_MOD),
|
.OUT_MOD(DE_OUT_MOD),
|
||||||
.REGISTER_FILE_CONTROL(DE_REGISTER_CONTROL),
|
.REGISTER_FILE_CONTROL(DE_REGISTER_CONTROL),
|
||||||
.ALU_1OP(ALU_1OP),
|
.ALU_1OP(DE_ALU_1OP),
|
||||||
.seq_addr_entry(ucode_seq_addr_entry),
|
.seq_addr_entry(ucode_seq_addr_entry),
|
||||||
.SIMPLE_MICRO(SIMPLE_MICRO),
|
.SIMPLE_MICRO(SIMPLE_MICRO),
|
||||||
.seq_addr_input(ucode_seq_addr),
|
.seq_addr_input(ucode_seq_addr),
|
||||||
.instruction_size(DE_instruction_size),
|
.instruction_size(DE_instruction_size),
|
||||||
.memio_address_select(memio_address_select),
|
.memio_address_select(DE_memio_address_select),
|
||||||
.MEM_OR_IO(MEM_OR_IO)
|
.MEM_OR_IO(DE_MEM_OR_IO)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign Wbit=INSTRUCTION_INFO[2:2];
|
assign DE_Wbit=INSTRUCTION_INFO[2:2];
|
||||||
assign Sbit=INSTRUCTION_INFO[1:1];
|
assign DE_Sbit=INSTRUCTION_INFO[1:1];
|
||||||
assign opcode_size=INSTRUCTION_INFO[0:0];
|
assign DE_opcode_size=INSTRUCTION_INFO[0:0];
|
||||||
|
|
||||||
assign DE_reg_write_addr=DE_REGISTER_CONTROL[11:8];
|
assign DE_reg_write_addr=DE_REGISTER_CONTROL[11:8];
|
||||||
assign DE_reg_read_port1_addr=DE_REGISTER_CONTROL[7:4];
|
assign DE_reg_read_port1_addr=DE_REGISTER_CONTROL[7:4];
|
||||||
assign DE_reg_read_port2_addr=DE_REGISTER_CONTROL[3:0];
|
assign DE_reg_read_port2_addr=DE_REGISTER_CONTROL[3:0];
|
||||||
|
|
||||||
assign DE_HALT=DECODER_SIGNALS[0: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;
|
reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr;
|
||||||
|
|
||||||
/*############ REGISTERS ########################################################## */
|
/*############ REGISTERS ########################################################## */
|
||||||
|
|
||||||
reg [15:0] CIR;
|
|
||||||
reg [15:0] PARAM1;
|
reg [15:0] PARAM1;
|
||||||
reg [15:0] PARAM2;
|
reg [15:0] PARAM2;
|
||||||
|
|
||||||
@ -185,84 +210,34 @@ end
|
|||||||
/* verilator lint_on MULTIDRIVEN */
|
/* verilator lint_on MULTIDRIVEN */
|
||||||
|
|
||||||
/*** Processor stages ***/
|
/*** 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
|
always @(posedge clock) begin
|
||||||
case(state)
|
case(state)
|
||||||
`PROC_RESET:begin
|
`PROC_RESET:begin
|
||||||
|
BIU_NEXT_POSITION <= 0;
|
||||||
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
||||||
ProgCount <= 'hFFF0;//TODO: Implement Segmentation and set to zero
|
|
||||||
HALT <= 0;
|
HALT <= 0;
|
||||||
ERROR <= 0;
|
ERROR <= `ERR_NO_ERROR;
|
||||||
SIMPLE_MICRO <= 0;
|
SIMPLE_MICRO <= 0;
|
||||||
reg_write_we <= 1;
|
reg_write_we <= 1;
|
||||||
instruction_size_init <= 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
|
end
|
||||||
`PROC_HALT_STATE:begin
|
`PROC_HALT_STATE:begin
|
||||||
end
|
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
|
`PROC_DE_STATE_ENTRY:begin
|
||||||
external_address_bus <= {4'b0,ProgCount};
|
reg_write_we <= 1;
|
||||||
|
if(VALID_INSTRUCTION==1) begin
|
||||||
if(SIMPLE_MICRO==0)begin
|
if(SIMPLE_MICRO==0)begin
|
||||||
/*This flag is set at reset and jump because
|
/*This flag is set at reset and jump because
|
||||||
* at IF we need to know the size of the
|
* at IF we need to know the size of the
|
||||||
@ -275,24 +250,46 @@ always @(posedge clock) begin
|
|||||||
|
|
||||||
/* We cannot set these directly within
|
/* We cannot set these directly within
|
||||||
* microcode so don't overwrite useful values
|
* microcode so don't overwrite useful values
|
||||||
* each time the next microcode is executed.
|
* each tie the next microcode is executed.
|
||||||
* Note this still allows to set initial values
|
* Note this still allows to set initial values
|
||||||
* at the start of the microcode */
|
* at the start of the microcode */
|
||||||
PARAM1 <= DE_PARAM1;
|
PARAM1 <= DE_PARAM1;
|
||||||
PARAM2 <= DE_PARAM2;
|
PARAM2 <= DE_PARAM2;
|
||||||
|
`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
|
end
|
||||||
|
IN_MOD <= DE_IN_MOD;
|
||||||
|
OUT_MOD <= DE_OUT_MOD;
|
||||||
|
RM <= DE_RM;
|
||||||
ERROR <= DE_ERROR;
|
ERROR <= DE_ERROR;
|
||||||
HALT <= DE_HALT;
|
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 <= DE_reg_read_port1_addr;
|
||||||
reg_read_port2_addr <= DE_reg_read_port2_addr;
|
reg_read_port2_addr <= DE_reg_read_port2_addr;
|
||||||
reg_write_addr <= DE_reg_write_addr;
|
reg_write_addr <= DE_reg_write_addr;
|
||||||
|
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
|
if ( (ucode_seq_addr==`UCODE_NO_INSTRUCTION) && (ucode_seq_addr_entry!=`UCODE_NO_INSTRUCTION) )begin
|
||||||
/*switch to microcode decoding*/
|
/*switch to microcode decoding*/
|
||||||
ucode_seq_addr <= ucode_seq_addr_entry;
|
ucode_seq_addr <= ucode_seq_addr_entry;
|
||||||
SIMPLE_MICRO <= 1;
|
SIMPLE_MICRO <= 1;
|
||||||
/*keep state the same and rerun decode this time with all the data from the microcode rom*/
|
/*keep state the same and rerun decode this time with all the data from the microcode rom*/
|
||||||
|
BIU_NEXT_POSITION <= 2'b00;
|
||||||
end else begin
|
end else begin
|
||||||
state <= next_state;
|
state <= next_state;
|
||||||
|
if ( SIMPLE_MICRO == 0 ) begin
|
||||||
|
BIU_NEXT_POSITION <= 2'b00;
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`PROC_DE_LOAD_REG_TO_PARAM:begin
|
`PROC_DE_LOAD_REG_TO_PARAM:begin
|
||||||
@ -306,72 +303,35 @@ always @(posedge clock) begin
|
|||||||
if(opcode_size==0)begin
|
if(opcode_size==0)begin
|
||||||
if({Sbit,Wbit}==2'b11)begin
|
if({Sbit,Wbit}==2'b11)begin
|
||||||
/*signed "16bit" read*/
|
/*signed "16bit" read*/
|
||||||
PARAM1 <= {{8{CIR[7:7]}},CIR[7:0]};
|
PARAM1 <= {{8{INSTRUCTION_BUFFER[23:23]}},INSTRUCTION_BUFFER[23:16]};
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[7:0] <= CIR[7:0];
|
PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16];
|
||||||
end
|
end
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state <= `PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end else begin
|
end else begin
|
||||||
if(ProgCount[0:0]==1)begin
|
|
||||||
if({Sbit,Wbit}==2'b11)begin
|
if({Sbit,Wbit}==2'b11)begin
|
||||||
/*signed "16bit" read*/
|
/*signed "16bit" read*/
|
||||||
PARAM1 <= {{8{external_data_bus[15:15]}},external_data_bus[15:8]};
|
PARAM1 <= {{8{INSTRUCTION_BUFFER[15:15]}},INSTRUCTION_BUFFER[15:8]};
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[7:0] <= external_data_bus[15:8];
|
PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8];
|
||||||
end
|
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
ProgCount <= ProgCount+1;
|
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state <= `PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
|
||||||
`PROC_DE_LOAD_16_PARAM:begin
|
`PROC_DE_LOAD_16_PARAM:begin
|
||||||
if(opcode_size==0)begin
|
if(opcode_size==0)begin
|
||||||
PARAM1[7:0] <= CIR[7:0];
|
PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16];
|
||||||
if(ProgCount[0:0]==1)begin
|
PARAM1[15:8] <= INSTRUCTION_BUFFER[15:8];
|
||||||
PARAM1[15:8] <= external_data_bus[15:8];
|
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[15:8] <= external_data_bus[7:0];
|
PARAM1[15:8] <= INSTRUCTION_BUFFER[7:0];
|
||||||
|
PARAM1[7:0] <= INSTRUCTION_BUFFER[15:8];
|
||||||
end
|
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 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
|
|
||||||
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)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||||
default: state <= `PROC_EX_STATE_ENTRY;
|
default: state <= `PROC_EX_STATE_ENTRY;
|
||||||
@ -386,19 +346,19 @@ always @(posedge clock) begin
|
|||||||
case (RM)
|
case (RM)
|
||||||
3'b000:begin
|
3'b000:begin
|
||||||
/*[BX]+[SI]*/
|
/*[BX]+[SI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b001:begin
|
3'b001:begin
|
||||||
/*[BX]+[SI]*/
|
/*[BX]+[SI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b010:begin
|
3'b010:begin
|
||||||
/*[BP]+[SI]*/
|
/*[BP]+[SI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b011:begin
|
3'b011:begin
|
||||||
/*[BP]+[DI]*/
|
/*[BP]+[DI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b100:begin
|
3'b100:begin
|
||||||
/*[SI]*/
|
/*[SI]*/
|
||||||
@ -412,7 +372,7 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
3'b110:begin
|
3'b110:begin
|
||||||
/*d16 */
|
/*d16 */
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b111:begin
|
3'b111:begin
|
||||||
/*[BX]*/
|
/*[BX]*/
|
||||||
@ -422,7 +382,7 @@ always @(posedge clock) begin
|
|||||||
endcase
|
endcase
|
||||||
if(IN_MOD!=3'b000)begin
|
if(IN_MOD!=3'b000)begin
|
||||||
/*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/
|
/*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/
|
||||||
`invalid_instruction;
|
`unimpl_addressing_mode;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
3'b110:begin /* SP Indirect read*/
|
3'b110:begin /* SP Indirect read*/
|
||||||
@ -430,39 +390,31 @@ always @(posedge clock) begin
|
|||||||
state <= `PROC_MEMIO_READ_SETADDR;
|
state <= `PROC_MEMIO_READ_SETADDR;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_READ_SETADDR:begin
|
`PROC_MEMIO_READ_SETADDR:begin
|
||||||
if(memio_address_select==0)
|
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
|
else
|
||||||
external_address_bus <= {4'b0,ALU_1O};
|
BIU_ADDRESS_INPUT <= 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
|
if ( BIU_VALID_DATA == 1 ) begin
|
||||||
`PROC_MEMIO_GET_ALIGNED_DATA:begin
|
|
||||||
PARAM2 <= (Wbit==1)? external_data_bus : {8'b0,external_data_bus[7:0]} ;
|
|
||||||
state <= `PROC_EX_STATE_ENTRY;
|
state <= `PROC_EX_STATE_ENTRY;
|
||||||
end
|
PARAM2 <= BIU_DATA;
|
||||||
`PROC_MEMIO_GET_UNALIGNED_DATA:begin
|
biu_read_request <= 0;
|
||||||
PARAM2 <= {8'b0,external_data_bus[15:8]};
|
biu_data_direction <= 0;
|
||||||
if(Wbit==1) begin
|
|
||||||
state <= `PROC_MEMIO_GET_SECOND_BYTE;
|
|
||||||
end else begin
|
end else begin
|
||||||
state <= `PROC_EX_STATE_ENTRY;
|
biu_data_direction <= 1;
|
||||||
|
biu_read_request <= 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`PROC_MEMIO_GET_SECOND_BYTE:begin
|
`PROC_NEXT_INSTRUCTION:begin
|
||||||
external_address_bus <= external_address_bus+1;
|
BIU_NEXT_POSITION <= 2'b01;
|
||||||
state <= `PROC_MEMIO_GET_SECOND_BYTE1;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
end
|
|
||||||
`PROC_MEMIO_GET_SECOND_BYTE1:begin
|
|
||||||
PARAM2[15:8] <= external_data_bus[7:0];
|
|
||||||
state <= `PROC_EX_STATE_ENTRY;
|
|
||||||
end
|
end
|
||||||
`PROC_EX_STATE_ENTRY:begin
|
`PROC_EX_STATE_ENTRY:begin
|
||||||
external_address_bus <= {4'b0,ProgCount};
|
|
||||||
FLAGS[7:0] <= ALU_1FLAGS[7:0];
|
FLAGS[7:0] <= ALU_1FLAGS[7:0];
|
||||||
case(OUT_MOD)
|
case(OUT_MOD)
|
||||||
3'b000,
|
3'b000,
|
||||||
@ -474,19 +426,19 @@ always @(posedge clock) begin
|
|||||||
case (RM) /* Duplicate code with write... */
|
case (RM) /* Duplicate code with write... */
|
||||||
3'b000:begin
|
3'b000:begin
|
||||||
/*[BX]+[SI]*/
|
/*[BX]+[SI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b001:begin
|
3'b001:begin
|
||||||
/*[BX]+[SI]*/
|
/*[BX]+[SI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b010:begin
|
3'b010:begin
|
||||||
/*[BP]+[SI]*/
|
/*[BP]+[SI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b011:begin
|
3'b011:begin
|
||||||
/*[BP]+[DI]*/
|
/*[BP]+[DI]*/
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b100:begin
|
3'b100:begin
|
||||||
/*[SI]*/
|
/*[SI]*/
|
||||||
@ -500,7 +452,7 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
3'b110:begin
|
3'b110:begin
|
||||||
/*d16 */
|
/*d16 */
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b111:begin
|
3'b111:begin
|
||||||
/*[BX]*/
|
/*[BX]*/
|
||||||
@ -508,41 +460,52 @@ always @(posedge clock) begin
|
|||||||
state <= `PROC_MEMIO_WRITE;
|
state <= `PROC_MEMIO_WRITE;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
if(BIU_NEXT_POSITION != 2'b10 )
|
||||||
|
BIU_NEXT_POSITION <= 2'b01;
|
||||||
end
|
end
|
||||||
3'b011:begin
|
3'b011:begin
|
||||||
reg_write_we <= 0;
|
reg_write_we <= 0;
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state <= `PROC_IF_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state <= `PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
|
if(BIU_NEXT_POSITION != 2'b10 )
|
||||||
|
BIU_NEXT_POSITION <= 2'b01;
|
||||||
end
|
end
|
||||||
3'b100:begin /*No output*/
|
3'b100:begin /*No output*/
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state <= `PROC_IF_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state <= `PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
|
if(BIU_NEXT_POSITION != 2'b10 )
|
||||||
|
BIU_NEXT_POSITION <= 2'b01;
|
||||||
end
|
end
|
||||||
3'b101:begin /* Program Counter*/
|
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;
|
instruction_size_init <= 1;
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state <= `PROC_IF_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state <= `PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
end
|
end
|
||||||
3'b110:begin /* SP Indirect write*/
|
3'b110:begin /* SP Indirect write*/
|
||||||
reg_read_port1_addr <= 4'b1100;
|
reg_read_port1_addr <= 4'b1100;
|
||||||
state <= `PROC_MEMIO_WRITE;
|
state <= `PROC_MEMIO_WRITE;
|
||||||
|
if(BIU_NEXT_POSITION != 2'b10 )
|
||||||
|
BIU_NEXT_POSITION <= 2'b01;
|
||||||
end
|
end
|
||||||
3'b111:begin /* Write to PRAM1 (for microcode calculations) */
|
3'b111:begin /* Write to PRAM1 (for microcode calculations) */
|
||||||
PARAM1 <= ALU_1O;
|
PARAM1 <= ALU_1O;
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state <= `PROC_IF_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state <= `PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
|
if(BIU_NEXT_POSITION != 2'b10 )
|
||||||
|
BIU_NEXT_POSITION <= 2'b01;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`invalid_instruction
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
@ -552,81 +515,37 @@ always @(posedge clock) begin
|
|||||||
`ifdef DEBUG_MEMORY_WRITES
|
`ifdef DEBUG_MEMORY_WRITES
|
||||||
$display("Writing at %04x , %04x",reg_read_port1_data,ALU_1O);
|
$display("Writing at %04x , %04x",reg_read_port1_data,ALU_1O);
|
||||||
`endif
|
`endif
|
||||||
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;
|
biu_write_request <= 1;
|
||||||
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;
|
|
||||||
if(memio_address_select==0)
|
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
|
else
|
||||||
data_bus_output_register <= {reg_read_port1_data[7:0],reg_read_port1_data[15:8]};
|
BIU_ADDRESS_INPUT <= ALU_1O;
|
||||||
state <= `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT;
|
|
||||||
end
|
if (write == 0) begin
|
||||||
`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT:begin
|
biu_write_request <= 0;
|
||||||
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]};
|
|
||||||
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};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
`PROC_MEMIO_WRITE_EXIT:begin
|
|
||||||
write <= 0;
|
|
||||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||||
state <= `PROC_IF_STATE_ENTRY;
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
else
|
else
|
||||||
state <= `PROC_NEXT_MICROCODE;
|
state <= `PROC_NEXT_MICROCODE;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
`PROC_NEXT_MICROCODE:begin
|
`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*/
|
ucode_seq_addr <= ucode_seq_addr_entry; /*Reused for next address*/
|
||||||
if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin
|
if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin
|
||||||
/*Finished microcode*/
|
/*Finished microcode*/
|
||||||
SIMPLE_MICRO <= 0;
|
SIMPLE_MICRO <= 0;
|
||||||
state <= `PROC_IF_STATE_ENTRY;
|
|
||||||
end else begin
|
|
||||||
state <= `PROC_DE_STATE_ENTRY;
|
|
||||||
end
|
end
|
||||||
|
state <= `PROC_DE_STATE_ENTRY;
|
||||||
reg_write_we <= 1;
|
reg_write_we <= 1;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`undef invalid_instruction
|
`undef unimpl_addressing_mode
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -18,9 +18,10 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
`timescale 1ns/1ps
|
`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);
|
processor p(clock,reset,address_bus,data_bus,rd,wr,BHE,IOMEM,HALT,ERROR);
|
||||||
|
|
||||||
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
||||||
@ -33,6 +34,17 @@ initial begin
|
|||||||
end
|
end
|
||||||
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
|
always @(negedge wr) begin
|
||||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
|
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
|
||||||
$write("%s" ,data_bus[15:8]);
|
$write("%s" ,data_bus[15:8]);
|
||||||
@ -59,12 +71,25 @@ always @(posedge clock) begin
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge ERROR) begin
|
always @( ERROR ) begin
|
||||||
$display("PROCESSOR RUN INTO AN ERROR.\nCycles run for: %d",cycles-1);
|
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
|
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||||
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
||||||
end
|
end
|
||||||
finish<=2'd1;
|
finish<=2'd1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
integer cycles=0;
|
integer cycles=0;
|
||||||
|
@ -27,7 +27,7 @@ reg clk_enable;
|
|||||||
wire [19:0]address_bus;
|
wire [19:0]address_bus;
|
||||||
wire [15:0]data_bus;
|
wire [15:0]data_bus;
|
||||||
wire rd,wr,HALT;
|
wire rd,wr,HALT;
|
||||||
wire ERROR;
|
wire [2:0] ERROR;
|
||||||
wire IOMEM;
|
wire IOMEM;
|
||||||
|
|
||||||
system system( .clock(clock),
|
system system( .clock(clock),
|
||||||
|
Loading…
Reference in New Issue
Block a user