First draft of a bus interface unit in an effort to make the CPU pipelined. Currently supports code prefetching

This commit is contained in:
(Tim) Efthimis Kritikos 2023-05-07 13:34:15 +01:00
parent 88a47cc4a9
commit da51dd6da7
9 changed files with 603 additions and 337 deletions

View File

@ -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

View File

@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
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}

305
system/biu.v Normal file
View 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

View File

@ -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

4
system/error_header.v Normal file
View 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

View File

@ -18,46 +18,29 @@
You should have received a copy of the GNU General Public License
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
/*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

View File

@ -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,84 +210,34 @@ 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};
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
@ -275,24 +250,46 @@ always @(posedge clock) begin
/* We cannot set these directly within
* 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
* 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]};
PARAM1 <= {{8{INSTRUCTION_BUFFER[15:15]}},INSTRUCTION_BUFFER[15:8]};
end else begin
PARAM1[7:0] <= external_data_bus[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];
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
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];
PARAM1[7:0] <= INSTRUCTION_BUFFER[23:16];
PARAM1[15:8] <= INSTRUCTION_BUFFER[15:8];
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
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)
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]} ;
BIU_ADDRESS_INPUT <= ALU_1O;
if ( BIU_VALID_DATA == 1 ) begin
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;
PARAM2 <= BIU_DATA;
biu_read_request <= 0;
biu_data_direction <= 0;
end else begin
state <= `PROC_EX_STATE_ENTRY;
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]};
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;
BIU_ADDRESS_INPUT <= ALU_1O;
if (write == 0) begin
biu_write_request <= 0;
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
state <= `PROC_IF_STATE_ENTRY;
state <= `PROC_DE_STATE_ENTRY;
else
state <= `PROC_NEXT_MICROCODE;
end
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

View File

@ -18,9 +18,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
`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);
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
end
integer cycles=0;

View File

@ -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),