Fixed copyright notices, did some major cleanup and bumped README's versions
This commit is contained in:
parent
a8ab6b2dc7
commit
539fb8416b
@ -19,11 +19,11 @@ A CPU that aims to be binary compatible with the 8086 and with as many optimisat
|
||||
Both Verilator and Icarus Verilog can be used for simulation. You can select which one you want with the SIM variable on [common.mk](./common.mk)
|
||||
Specifically this list shows the software needed and the versions used during development (other versions should work as well)
|
||||
|
||||
* Icarus Verilog : version 11.0 OR **(preferred)** Verilator : 5.006
|
||||
* Icarus Verilog : version 11.0 OR **(preferred)** Verilator : 5.008
|
||||
* bin86 : 0.16.21
|
||||
* GNU Make : 4.4.1
|
||||
* xxd : 2022-01-14
|
||||
* POSIX coreutils : GNU coreutils 9.1
|
||||
* POSIX coreutils : GNU coreutils 9.3
|
||||
|
||||
After that you can run `make` on the top level directory and it should build everything and start the simulation
|
||||
|
||||
|
86
system/biu.v
86
system/biu.v
@ -1,4 +1,4 @@
|
||||
/* processor.v - implementation of the 9086 bus interface unit. The logic that
|
||||
/* biu.v - implementation of the 9086 bus interface unit. The logic that
|
||||
controls all external bus functions
|
||||
|
||||
This file is part of the 9086 project.
|
||||
@ -18,7 +18,7 @@
|
||||
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
|
||||
`include "config.v"
|
||||
|
||||
`define BIU_HALT 4'b0000
|
||||
`define BIU_NEXT_ACTION 4'b0001
|
||||
@ -38,9 +38,9 @@
|
||||
`define BIU_GET_SECOND_BYTE1 4'b1110
|
||||
|
||||
module BIU (
|
||||
/*outside world*/ input clock, input reset, output reg [19:0] external_address_bus,
|
||||
/* 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 jump_req,
|
||||
/* Internal */ output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION, input jump_req,
|
||||
/* */ 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,
|
||||
/* */ input [`PROC_STATE_BITS-1:0] proc_state, input SIMPLE_MICRO
|
||||
);
|
||||
@ -52,9 +52,8 @@ reg [15:0] DATA_OUT;
|
||||
reg DATA_DIR;
|
||||
assign DATA=DATA_DIR ? 16'hz:DATA_OUT;
|
||||
|
||||
`define L1_CACHE_SIZE 4 // Don't change this! some parts of the code assume this
|
||||
`define FIFO_SIZE_BYTES $rtoi($pow(2,`L1_CACHE_SIZE))
|
||||
|
||||
`define FIFO_SIZE_BYTES 16 //$pow(2,`L1_CACHE_SIZE)
|
||||
reg [7:0] INPUT_FIFO [`FIFO_SIZE_BYTES-1:0];
|
||||
reg [`L1_CACHE_SIZE-1:0] FIFO_start; /*inclusive*/
|
||||
reg [`L1_CACHE_SIZE-1:0] FIFO_end; /*exclusive*/
|
||||
@ -65,7 +64,6 @@ reg [3:0] biu_state;
|
||||
always @(negedge reset) begin
|
||||
biu_state <= `BIU_HALT;
|
||||
end
|
||||
|
||||
always @(posedge reset) begin
|
||||
biu_state <= `BIU_RESET;
|
||||
end
|
||||
@ -76,10 +74,8 @@ 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_latch ) begin
|
||||
/* verilator lint_off BLKSEQ */
|
||||
@ -145,33 +141,30 @@ always @(posedge clock) begin
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
/*************** INSTRUCTION FIFO READ ***************/
|
||||
`BIU_READ: begin
|
||||
/* verilator lint_off BLKSEQ */
|
||||
if(INSTRUCTION_ADDRESS[0:0]==0 && FIFO_SIZE<4'hD)begin
|
||||
INPUT_FIFO[FIFO_end] = external_data_bus[7:0];
|
||||
INPUT_FIFO[FIFO_end+4'd1] = external_data_bus[15:8];
|
||||
INPUT_FIFO[FIFO_end] <= external_data_bus[7:0];
|
||||
INPUT_FIFO[FIFO_end+4'd1] <= external_data_bus[15:8];
|
||||
FIFO_end <= FIFO_end+4'd2;
|
||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd2;
|
||||
end else if(INSTRUCTION_ADDRESS[0:0]==0)begin
|
||||
INPUT_FIFO[FIFO_end] = external_data_bus[7:0];
|
||||
INPUT_FIFO[FIFO_end] <= external_data_bus[7:0];
|
||||
FIFO_end <= FIFO_end+4'd1;
|
||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+1;
|
||||
end else begin
|
||||
INPUT_FIFO[FIFO_end] = external_data_bus[15:8];
|
||||
INPUT_FIFO[FIFO_end] <= external_data_bus[15:8];
|
||||
FIFO_end <= FIFO_end+4'd1;
|
||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+1;
|
||||
end
|
||||
/* verilator lint_on BLKSEQ */
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
read<=1;
|
||||
end
|
||||
|
||||
|
||||
/*************** DATA WRITE ***************/
|
||||
//TODO TODO TODO flush fifo, self modifying code
|
||||
`BIU_PUT_UNALIGNED_16BIT_DATA:begin
|
||||
//TODO Put that in the previous stage, save a clock cycle
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Writing 16bit %04x at %04x",DATA,DATA_ADDRESS);
|
||||
`endif
|
||||
@ -194,7 +187,6 @@ always @(posedge clock) begin
|
||||
write <= 0;
|
||||
biu_state <= `BIU_WRITE_RELEASE;
|
||||
end
|
||||
|
||||
`BIU_PUT_BYTE:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Writing 8bit %02x at %04x",DATA[7:0],DATA_ADDRESS);
|
||||
@ -288,10 +280,9 @@ end
|
||||
|
||||
wire [2:0] Isize;
|
||||
InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},Isize);
|
||||
/* verilator lint_off UNDRIVEN */
|
||||
|
||||
wire [2:0] fifoIsize;
|
||||
wire Isit1;
|
||||
/* verilator lint_on UNDRIVEN */
|
||||
`ifdef EARLY_VALID_INSTRUCTION
|
||||
InstrSize fifoInstrSize({INPUT_FIFO[FIFO_start][7:0],INPUT_FIFO[FIFO_start+1][5:3]},fifoIsize);
|
||||
Is1 Is1(INPUT_FIFO[FIFO_start][7:0],Isit1);
|
||||
@ -310,16 +301,16 @@ always @( proc_state ) begin
|
||||
was_dec<=0;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
FIFO_start = FIFO_start + {1'b0,Isize};
|
||||
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {12'b0,Isize};;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {12'b0,Isize};;
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end else if ( SIMPLE_MICRO==1 && was_simple == 1) begin
|
||||
was_simple<=0;
|
||||
was_dec<=0;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
FIFO_start = FIFO_start + {1'b0,Isize};
|
||||
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {12'b0,Isize};;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {12'b0,Isize};;
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end
|
||||
end
|
||||
@ -336,54 +327,3 @@ always @( posedge jump_req ) begin
|
||||
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
|
||||
|
||||
`ifdef EARLY_VALID_INSTRUCTION
|
||||
module Is1 ( input [7:0] IN, output reg VERDICT );
|
||||
always @( IN ) begin
|
||||
casez(IN)
|
||||
8'b0100_???? : VERDICT <= 1; /* DEC - Decrement Register | INC - Increment Register */
|
||||
8'b1111_0100 : VERDICT <= 1; /* HLT - Halt */
|
||||
8'b1100_0011 : VERDICT <= 1; /* RET - Return from call within segment */
|
||||
8'b1010_101? : VERDICT <= 1; /* STOS - Write byte/word to [DI] and increment accordingly */
|
||||
8'b0101_0??? : VERDICT <= 1; /* PUSH - SP-=2; [SP]=REG */
|
||||
8'b0101_1??? : VERDICT <= 1; /* POP - REG=[SP]; SP+=2 */
|
||||
8'b1100_1111 : VERDICT <= 1; /* IRET - Return from interrupt */
|
||||
default:begin VERDICT<= 0; end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
`endif
|
||||
|
@ -29,9 +29,16 @@
|
||||
* for the maximum instruction size worth of bytes */
|
||||
`define EARLY_VALID_INSTRUCTION
|
||||
|
||||
/* Size is in powers of two with minimal 3.
|
||||
* 3 : 8 Bytes
|
||||
* 4 : 16 Bytes
|
||||
* 5 : 32 Bytes
|
||||
* . : ... */
|
||||
`define L1_CACHE_SIZE 4 // Don't change it! some parts of code still assume it to be 4
|
||||
|
||||
|
||||
/* Internal */
|
||||
|
||||
/********** Internal **********/
|
||||
`ifdef EARLY_VALID_INSTRUCTION
|
||||
`define EARLY_VALID_INSTRUCTION_ 1
|
||||
`else
|
||||
|
164
system/decoder.v
164
system/decoder.v
@ -43,37 +43,64 @@ assign DATA=ucode_rom[ADDR];
|
||||
|
||||
endmodule
|
||||
|
||||
// verilator lint_off UNUSEDSIGNAL
|
||||
module decoder(
|
||||
input wire [15:0] CIR,input wire [15:0] FLAGS, output wire [2:0] INSTRUCTION_INFO, output wire [`ERROR_BITS:0] DECODER_SIGNALS, output reg [`EXEC_STATE_BITS-1:0] next_state
|
||||
,output reg [2:0]IN_MOD, output reg [2:0]RM, output reg [15:0] PARAM1,output reg [15:0] PARAM2
|
||||
,output reg [1:0]in_alu_sel1,output reg [1:0]in_alu_sel2,output reg [2:0]OUT_MOD
|
||||
,output wire [11:0]REGISTER_FILE_CONTROL
|
||||
,output reg [2:0]ALU_1OP
|
||||
,output reg [`UCODE_ADDR_BITS-1:0] seq_addr_entry, input wire SIMPLE_MICRO, input wire [`UCODE_ADDR_BITS-1:0] seq_addr_input
|
||||
,output reg memio_address_select
|
||||
,output reg MEM_OR_IO
|
||||
/* INPUTS */ input wire [15:0] CIR,input wire [15:0] FLAGS
|
||||
/* MICROCODE */ ,output reg [`UCODE_ADDR_BITS-1:0] seq_addr_entry, input wire SIMPLE_MICRO, input wire [`UCODE_ADDR_BITS-1:0] seq_addr_input
|
||||
/* OUTPUT */ ,output wire [`EXEC_STATE_BITS+`ERROR_BITS+65:0] OUTPUT
|
||||
);
|
||||
// verilator lint_on UNUSEDSIGNAL
|
||||
|
||||
reg [2:0]IN_MOD;
|
||||
assign OUTPUT[2:0] = IN_MOD;
|
||||
|
||||
reg [2:0]RM;
|
||||
assign OUTPUT[5:3] = RM;
|
||||
|
||||
reg memio_address_select;
|
||||
assign OUTPUT[6:6] = memio_address_select;
|
||||
|
||||
reg MEM_OR_IO;
|
||||
assign OUTPUT[7:7] = MEM_OR_IO;
|
||||
|
||||
reg [15:0] PARAM1;
|
||||
assign OUTPUT[23:8] = PARAM1;
|
||||
|
||||
reg [15:0] PARAM2;
|
||||
assign OUTPUT[39:24] = PARAM2;
|
||||
|
||||
reg [2:0]ALU_OP;
|
||||
assign OUTPUT[42:40] = ALU_OP;
|
||||
|
||||
reg [1:0]in_alu_sel1;
|
||||
assign OUTPUT[44:43] = in_alu_sel1;
|
||||
|
||||
reg [1:0]in_alu_sel2;
|
||||
assign OUTPUT[46:45] = in_alu_sel2;
|
||||
|
||||
reg [2:0]OUT_MOD;
|
||||
assign OUTPUT[49:47] = OUT_MOD;
|
||||
|
||||
reg [3:0]reg_read_port1_addr;
|
||||
reg [3:0]reg_read_port2_addr;
|
||||
reg [3:0]reg_write_addr;
|
||||
assign REGISTER_FILE_CONTROL={reg_write_addr,reg_read_port1_addr,reg_read_port2_addr};
|
||||
assign OUTPUT[53:50] = reg_read_port1_addr;
|
||||
|
||||
reg [3:0]reg_read_port2_addr;
|
||||
assign OUTPUT[57:54] = reg_read_port2_addr;
|
||||
|
||||
reg [3:0]reg_write_addr;
|
||||
assign OUTPUT[61:58] = reg_write_addr;
|
||||
|
||||
/* For correct fetching of instructions and global options for the alu */
|
||||
reg Wbit,Sbit,opcode_size;
|
||||
assign INSTRUCTION_INFO={Wbit,Sbit,opcode_size};
|
||||
assign OUTPUT[64:62] = {Wbit,Sbit,opcode_size};
|
||||
|
||||
reg [`ERROR_BITS-1:0] ERROR;
|
||||
reg HALT;
|
||||
assign DECODER_SIGNALS={ERROR,HALT};
|
||||
assign OUTPUT[`ERROR_BITS+65:65]={ERROR,HALT};
|
||||
|
||||
reg [`EXEC_STATE_BITS-1:0] next_state;
|
||||
assign OUTPUT[`EXEC_STATE_BITS+`ERROR_BITS+65:`ERROR_BITS+66] = next_state;
|
||||
|
||||
|
||||
// verilator lint_off UNUSEDSIGNAL
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
wire [`UCODE_DATA_BITS-1:0] ucode_data;
|
||||
// verilator lint_on UNUSEDSIGNAL
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
microcode ucode(seq_addr_input,ucode_data);
|
||||
|
||||
@ -97,7 +124,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
11'b0000_010?_??? : begin
|
||||
/* ADD - Add Immediate word/byte to accumulator */
|
||||
/* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/
|
||||
opcode_size=0; //TODO: move the decoding done in BIU here and use theat size checker
|
||||
opcode_size=0;
|
||||
Wbit=CIR[8:8];
|
||||
IN_MOD=3'b011;
|
||||
in_alu_sel1=2'b00;
|
||||
@ -106,7 +133,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
MEM_OR_IO=0;
|
||||
reg_read_port2_addr={Wbit,3'b000};
|
||||
reg_write_addr={Wbit,3'b000};
|
||||
ALU_1OP=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
memio_address_select=0;
|
||||
if(Wbit)
|
||||
next_state=`EXEC_DE_LOAD_16_PARAM;
|
||||
@ -148,8 +175,8 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
end
|
||||
endcase
|
||||
case(CIR[5:3])
|
||||
3'b000: ALU_1OP=`ALU_OP_ADD;
|
||||
3'b101: ALU_1OP=`ALU_OP_SUB_REVERSE;
|
||||
3'b000: ALU_OP=`ALU_OP_ADD;
|
||||
3'b101: ALU_OP=`ALU_OP_SUB_REVERSE;
|
||||
default:begin
|
||||
/*Should be impossible*/
|
||||
`invalid_instruction
|
||||
@ -171,7 +198,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
in_alu_sel1=2'b00;
|
||||
OUT_MOD=3'b100;
|
||||
MEM_OR_IO=0;
|
||||
ALU_1OP=`ALU_OP_SUB;
|
||||
ALU_OP=`ALU_OP_SUB;
|
||||
memio_address_select=0;
|
||||
if(IN_MOD==3'b011)begin
|
||||
/*compare register with param*/
|
||||
@ -199,7 +226,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
reg_write_addr={1'b0,CIR[10:8]};
|
||||
PARAM1[7:0]=CIR[7:0];
|
||||
PARAM2=0;
|
||||
ALU_1OP=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction;
|
||||
memio_address_select=0;
|
||||
@ -214,7 +241,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
OUT_MOD=3'b011;
|
||||
MEM_OR_IO=0;
|
||||
reg_write_addr={1'b1,CIR[10:8]};
|
||||
ALU_1OP=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
PARAM2=0;
|
||||
next_state=`EXEC_DE_LOAD_16_PARAM;
|
||||
`normal_instruction;
|
||||
@ -260,7 +287,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
end
|
||||
reg_read_port2_addr={Wbit,CIR[5:3]};
|
||||
end
|
||||
ALU_1OP=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
|
||||
`normal_instruction;
|
||||
memio_address_select=0;
|
||||
@ -281,9 +308,9 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
reg_read_port1_addr={1'b1,CIR[10:8]};
|
||||
reg_write_addr={1'b1,CIR[10:8]};
|
||||
if(CIR[11:11]==0)
|
||||
ALU_1OP=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
else
|
||||
ALU_1OP=`ALU_OP_SUB;
|
||||
ALU_OP=`ALU_OP_SUB;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction;
|
||||
memio_address_select=0;
|
||||
@ -307,7 +334,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
reg_read_port2_addr={1'b0,RM};
|
||||
reg_write_addr={1'b0,RM};
|
||||
|
||||
ALU_1OP=(CIR[3:3]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
||||
ALU_OP=(CIR[3:3]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
||||
if ( IN_MOD == 3'b011 )
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
else
|
||||
@ -340,7 +367,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr={Wbit,3'b000};
|
||||
OUT_MOD=3'b100;
|
||||
ALU_1OP=`ALU_OP_SUB;
|
||||
ALU_OP=`ALU_OP_SUB;
|
||||
MEM_OR_IO=0;
|
||||
if(Wbit==1)
|
||||
next_state=`EXEC_DE_LOAD_16_PARAM;
|
||||
@ -365,7 +392,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
in_alu_sel1=2'b10;
|
||||
in_alu_sel2=2'b00;
|
||||
PARAM2={{8{CIR[7:7]}},CIR[7:0]};
|
||||
ALU_1OP=`ALU_OP_ADD_SIGNED_B;
|
||||
ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
||||
MEM_OR_IO=0;
|
||||
OUT_MOD=3'b101;
|
||||
case(CIR[11:9])
|
||||
@ -413,7 +440,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
in_alu_sel1=2'b10;
|
||||
in_alu_sel2=2'b00;
|
||||
PARAM2={{8{CIR[7:7]}},CIR[7:0]};
|
||||
ALU_1OP=`ALU_OP_ADD_SIGNED_B;
|
||||
ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
||||
OUT_MOD=3'b101;
|
||||
MEM_OR_IO=0;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
@ -484,7 +511,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
next_state=`EXEC_DE_LOAD_8_PARAM;
|
||||
end
|
||||
in_alu_sel1=2'b00; /* PARAM1 */
|
||||
ALU_1OP=`ALU_OP_AND;
|
||||
ALU_OP=`ALU_OP_AND;
|
||||
case(IN_MOD)
|
||||
3'b011:begin
|
||||
in_alu_sel2=2'b01;
|
||||
@ -527,7 +554,7 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
in_alu_sel2=2'b00;
|
||||
next_state=`EXEC_MEMIO_READ;
|
||||
end
|
||||
ALU_1OP=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
OUT_MOD=3'b101;
|
||||
`normal_instruction;
|
||||
memio_address_select=0;
|
||||
@ -623,14 +650,14 @@ always @( FLAGS or CIR or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
/*1:1 map essentially but I want to keep the spec for these bits separate
|
||||
* from the alu op select bits*/
|
||||
case(ucode_data[22:20])
|
||||
3'b000: ALU_1OP=`ALU_OP_ADD;
|
||||
3'b001: ALU_1OP=`ALU_OP_SUB;
|
||||
3'b010: ALU_1OP=`ALU_OP_AND;
|
||||
3'b011: ALU_1OP=`ALU_OP_OR;
|
||||
3'b100: ALU_1OP=`ALU_OP_XOR;
|
||||
3'b101: ALU_1OP=`ALU_OP_ADD_SIGNED_B;
|
||||
3'b110: ALU_1OP=`ALU_OP_SUB_REVERSE;
|
||||
3'b111: ALU_1OP=`ALU_OP_SHIFT_LEFT;
|
||||
3'b000: ALU_OP=`ALU_OP_ADD;
|
||||
3'b001: ALU_OP=`ALU_OP_SUB;
|
||||
3'b010: ALU_OP=`ALU_OP_AND;
|
||||
3'b011: ALU_OP=`ALU_OP_OR;
|
||||
3'b100: ALU_OP=`ALU_OP_XOR;
|
||||
3'b101: ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
||||
3'b110: ALU_OP=`ALU_OP_SUB_REVERSE;
|
||||
3'b111: ALU_OP=`ALU_OP_SHIFT_LEFT;
|
||||
default: begin end
|
||||
endcase
|
||||
if(ucode_data[34:34]==0) /* Set reg read port 1 address */
|
||||
@ -649,3 +676,54 @@ end
|
||||
|
||||
endmodule
|
||||
// verilator lint_on BLKSEQ
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
`ifdef EARLY_VALID_INSTRUCTION
|
||||
module Is1 ( input [7:0] IN, output reg VERDICT );
|
||||
always @( IN ) begin
|
||||
casez(IN)
|
||||
8'b0100_???? : VERDICT <= 1; /* DEC - Decrement Register | INC - Increment Register */
|
||||
8'b1111_0100 : VERDICT <= 1; /* HLT - Halt */
|
||||
8'b1100_0011 : VERDICT <= 1; /* RET - Return from call within segment */
|
||||
8'b1010_101? : VERDICT <= 1; /* STOS - Write byte/word to [DI] and increment accordingly */
|
||||
8'b0101_0??? : VERDICT <= 1; /* PUSH - SP-=2; [SP]=REG */
|
||||
8'b0101_1??? : VERDICT <= 1; /* POP - REG=[SP]; SP+=2 */
|
||||
8'b1100_1111 : VERDICT <= 1; /* IRET - Return from interrupt */
|
||||
default:begin VERDICT<= 0; end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
`endif
|
||||
|
@ -1,3 +1,22 @@
|
||||
/* execute.v - Implements the instruction execution logic
|
||||
|
||||
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/>. */
|
||||
|
||||
module execute_unit (
|
||||
/* GENERAL */ input clock, input reset ,input Wbit, input Sbit, input opcode_size,input [23:0] INSTRUCTION_BUFFER,input valid_input
|
||||
/* */ ,input [2:0] IN_MOD, input [2:0] OUT_MOD, input memio_address_select, input [15:0] ProgCount, input [2:0] RM, output reg [`ERROR_BITS-1:0] ERROR , input write /*TODO: REMOVE!!*/
|
||||
@ -13,12 +32,11 @@ module execute_unit (
|
||||
assign _exec_state_ = exec_state;
|
||||
assign _ALU_O_ = ALU_O;
|
||||
|
||||
/*############ ALU / Execution units ########################################################## */
|
||||
// ALU 1
|
||||
reg [`EXEC_STATE_BITS-1:0] exec_state;
|
||||
|
||||
reg [15:0] PARAM1,PARAM2;
|
||||
|
||||
/*############ ALU / Execution units ################################################## */
|
||||
|
||||
mux4 #(.WIDTH(16)) MUX16_1A(
|
||||
/*0*/ PARAM1,
|
||||
/*1*/ reg_read_port1_data,
|
||||
@ -41,28 +59,24 @@ wire [15:0] ALU_O;
|
||||
wire [7:0] ALU_FLAGS;
|
||||
|
||||
ALU ALU1(
|
||||
.A(ALU_A),
|
||||
.B(ALU_B),
|
||||
.OUT(ALU_O),
|
||||
.op(ALU_OP),
|
||||
.FLAGS(ALU_FLAGS),
|
||||
.Wbit(Wbit)
|
||||
);
|
||||
/* INPUT 1 */ .A(ALU_A),
|
||||
/* INPUT 2 */ .B(ALU_B),
|
||||
/* OUTPUT */ .OUT(ALU_O),
|
||||
/* OPERATION */ .op(ALU_OP),
|
||||
/* FLAGS */ .FLAGS(ALU_FLAGS),
|
||||
/* Wbit */ .Wbit(Wbit)
|
||||
);
|
||||
|
||||
//reg valid_input_;
|
||||
/*############ Execute logic ########################################################## */
|
||||
|
||||
always @(posedge valid_input) begin
|
||||
exec_state <= init_state;
|
||||
//valid_input_ <= 1;
|
||||
end
|
||||
|
||||
always @(negedge set_initial_values) begin
|
||||
PARAM1 <= PARAM1_INIT;
|
||||
PARAM2 <= PARAM2_INIT;
|
||||
end
|
||||
//always @(negedge valid_input) begin
|
||||
// valid_input_ <= 0;
|
||||
//end
|
||||
|
||||
always @(negedge reset) begin
|
||||
exec_state <= `EXEC_HALT;
|
||||
@ -76,7 +90,6 @@ end
|
||||
always @(posedge clock) begin
|
||||
case (exec_state)
|
||||
`EXEC_RESET: begin
|
||||
//valid_input_ <= 0;
|
||||
biu_write_request <= 0;
|
||||
biu_read_request <= 0;
|
||||
biu_data_direction <= 0;
|
||||
@ -87,7 +100,6 @@ always @(posedge clock) begin
|
||||
end
|
||||
`EXEC_DONE:begin
|
||||
reg_write_we <= 1;
|
||||
//valid_input_ <= 0;
|
||||
biu_jump_req <= 0;
|
||||
use_exec_reg_addr <= 0;
|
||||
end
|
||||
|
@ -23,54 +23,61 @@
|
||||
`include "ucode_header.v"
|
||||
`include "error_header.v"
|
||||
|
||||
//HALT: active high
|
||||
//IOMEM: 1=IO 0=MEM
|
||||
//write: active low
|
||||
//read: active low
|
||||
//reset: active low
|
||||
|
||||
`define PROC_STATE_BITS 3
|
||||
`define PROC_RESET 3'b000
|
||||
`define PROC_DE_STATE_ENTRY 3'b001
|
||||
`define PROC_WAIT 3'b010
|
||||
`define PROC_HALT 3'b011
|
||||
|
||||
module processor ( input clock, input reset, output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM, output reg HALT,output [`ERROR_BITS-1:0] ERROR);
|
||||
//HALT: active high
|
||||
//IOMEM: 1=IO 0=MEM
|
||||
//BHE: active low
|
||||
//write: active low
|
||||
//read: active low
|
||||
//reset: active low
|
||||
|
||||
module processor ( input clock, input reset, output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM, output wire HALT,output [`ERROR_BITS-1:0] ERROR);
|
||||
|
||||
/* If there is an error either from the decoder or execution unit set it to ERROR */
|
||||
assign ERROR=(DE_ERROR_sampled!=`ERR_NO_ERROR)?DE_ERROR_sampled:(EXEC_ERROR!=`ERR_NO_ERROR)?EXEC_ERROR:`ERR_NO_ERROR;
|
||||
assign ERROR=(DE_ERROR!=`ERR_NO_ERROR)?DE_ERROR:(EXEC_ERROR!=`ERR_NO_ERROR)?EXEC_ERROR:`ERR_NO_ERROR;
|
||||
|
||||
/*** Global Definitions ***/
|
||||
reg [`PROC_STATE_BITS-1:0] state;
|
||||
|
||||
/*############ Execution Unit ################################################## */
|
||||
reg [1:0] in_alu_sel1;
|
||||
reg [1:0] in_alu_sel2;
|
||||
/*############ Execution Unit ################################################### */
|
||||
|
||||
wire [1:0] in_alu_sel1, in_alu_sel2;
|
||||
assign in_alu_sel1 = DE_OUTPUT_sampled[44:43];
|
||||
assign in_alu_sel2 = DE_OUTPUT_sampled[46:45];
|
||||
|
||||
wire [`EXEC_STATE_BITS-1:0] exec_state;
|
||||
|
||||
reg valid_exec_data;
|
||||
reg valid_exec_data, set_initial_values;
|
||||
|
||||
wire [`ERROR_BITS-1:0] EXEC_ERROR;
|
||||
|
||||
wire use_exec_reg_addr;
|
||||
|
||||
wire [3:0] EXEC_reg_read_port1_addr;
|
||||
reg [2:0] IN_MOD,OUT_MOD;
|
||||
reg [`EXEC_STATE_BITS-1:0] exec_state_init;
|
||||
reg [`ALU_OP_BITS-1:0] ALU_OP;
|
||||
wire [15:0] ALU_O;
|
||||
wire [7:0]EXEC_FLAGS;
|
||||
reg [15:0] PARAM1_INIT;
|
||||
reg [15:0] PARAM2_INIT;
|
||||
reg set_initial_values;
|
||||
|
||||
wire [15:0] PARAM1_INIT, PARAM2_INIT;
|
||||
assign PARAM1_INIT = DE_OUTPUT_sampled[23:8];
|
||||
assign PARAM2_INIT = DE_OUTPUT_sampled[39:24];
|
||||
|
||||
wire [2:0] IN_MOD,OUT_MOD;
|
||||
assign IN_MOD=DE_OUTPUT_sampled[2:0];
|
||||
assign OUT_MOD=DE_OUTPUT_sampled[49:47];
|
||||
|
||||
wire [`ALU_OP_BITS-1:0] ALU_OP;
|
||||
assign ALU_OP = DE_OUTPUT_sampled[42:40];
|
||||
|
||||
execute_unit execute_unit (
|
||||
/* GENERAL */ clock, reset, Wbit, Sbit, opcode_size, INSTRUCTION_BUFFER,valid_exec_data
|
||||
/* */ ,IN_MOD, OUT_MOD,memio_address_select, ProgCount, RM, EXEC_ERROR, write
|
||||
/* */ ,set_initial_values
|
||||
/* PARAM */ ,PARAM1_INIT,PARAM2_INIT
|
||||
/* STATE CONTROL */ ,exec_state, exec_state_init
|
||||
/* STATE CONTROL */ ,exec_state, next_state
|
||||
/* ALU CONTROL */ ,in_alu_sel1, in_alu_sel2, ALU_OP, ALU_O
|
||||
/* REGISTER DATA */ ,reg_read_port1_data, reg_read_port2_data, EXEC_reg_read_port1_addr, use_exec_reg_addr, reg_write_we
|
||||
/* FLAFS */ ,EXEC_FLAGS
|
||||
@ -79,138 +86,96 @@ execute_unit execute_unit (
|
||||
|
||||
/*############ Bus Interface Unit ############################################### */
|
||||
|
||||
wire [31:0] INSTRUCTION;
|
||||
wire biu_jump_req;
|
||||
wire VALID_INSTRUCTION;
|
||||
wire [15:0] INSTRUCTION_LOCATION;
|
||||
wire [15:0] BIU_ADDRESS_INPUT;
|
||||
wire [15:0] INSTRUCTION_LOCATION, BIU_ADDRESS_INPUT;
|
||||
wire [15:0] BIU_DATA;
|
||||
wire biu_write_request;
|
||||
wire biu_data_direction;
|
||||
wire biu_read_request;
|
||||
wire BIU_VALID_DATA;
|
||||
wire [31:0] INSTRUCTION;
|
||||
wire biu_write_request, biu_read_request, BIU_VALID_DATA;
|
||||
wire biu_jump_req, biu_data_direction,VALID_INSTRUCTION;
|
||||
|
||||
BIU BIU(
|
||||
clock,reset,external_address_bus,external_data_bus,read,write,BHE,IOMEM,
|
||||
INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION,biu_jump_req,BIU_ADDRESS_INPUT,BIU_DATA,biu_write_request,biu_read_request,Wbit,BIU_VALID_DATA,MEM_OR_IO,
|
||||
state,SIMPLE_MICRO
|
||||
);
|
||||
/* Outside world */ clock,reset,external_address_bus
|
||||
/* */ ,external_data_bus,read,write,BHE,IOMEM
|
||||
/* Internal */ ,INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION,biu_jump_req
|
||||
/* */ ,BIU_ADDRESS_INPUT,BIU_DATA,biu_write_request,biu_read_request,Wbit,BIU_VALID_DATA,MEM_OR_IO
|
||||
/* */ ,state,SIMPLE_MICRO
|
||||
);
|
||||
assign BIU_DATA= biu_data_direction ? 16'hz : (memio_address_select ? reg_read_port1_data : ALU_O);
|
||||
|
||||
/*############ Decoder ########################################################## */
|
||||
reg Wbit, Sbit, opcode_size;
|
||||
wire DE_Wbit, DE_Sbit, DE_opcode_size;
|
||||
wire [`EXEC_STATE_BITS-1:0] next_state;
|
||||
reg [2:0]RM;
|
||||
wire [15:0]DE_PARAM1;// Input param1 form decoder to alu
|
||||
wire [15:0]DE_PARAM2;
|
||||
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 [`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) */
|
||||
//TODO : remove completely?
|
||||
reg memio_address_select;
|
||||
wire DE_memio_address_select;
|
||||
wire DE_MEM_OR_IO;
|
||||
reg MEM_OR_IO;
|
||||
wire [1:0] DE_in_alu_sel1;
|
||||
wire [1:0] DE_in_alu_sel2;
|
||||
reg [`ALU_OP_BITS-1:0] DE_ALU_OP;
|
||||
decoder decoder(
|
||||
.CIR(INSTRUCTION[31:16]),
|
||||
.FLAGS(FLAGS),
|
||||
.INSTRUCTION_INFO(INSTRUCTION_INFO),
|
||||
.DECODER_SIGNALS(DECODER_SIGNALS),
|
||||
.next_state(next_state),
|
||||
.IN_MOD(DE_IN_MOD),
|
||||
.RM(DE_RM),
|
||||
.PARAM1(DE_PARAM1),
|
||||
.PARAM2(DE_PARAM2),
|
||||
.in_alu_sel1(DE_in_alu_sel1),
|
||||
.in_alu_sel2(DE_in_alu_sel2),
|
||||
.OUT_MOD(DE_OUT_MOD),
|
||||
.REGISTER_FILE_CONTROL(DE_REGISTER_CONTROL),
|
||||
.ALU_1OP(DE_ALU_OP),
|
||||
.seq_addr_entry(ucode_seq_addr_entry),
|
||||
.SIMPLE_MICRO(SIMPLE_MICRO),
|
||||
.seq_addr_input(ucode_seq_addr),
|
||||
.memio_address_select(DE_memio_address_select),
|
||||
.MEM_OR_IO(DE_MEM_OR_IO)
|
||||
);
|
||||
|
||||
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[`ERROR_BITS:1];
|
||||
reg [`ERROR_BITS-1:0] DE_ERROR_sampled;
|
||||
|
||||
reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr;
|
||||
reg SIMPLE_MICRO; /* output simple decodings (=0) or microcode data (=1) */
|
||||
|
||||
/*############ REGISTERS ########################################################## */
|
||||
wire [`EXEC_STATE_BITS+`ERROR_BITS+65:0] DE_OUTPUT;
|
||||
reg [`EXEC_STATE_BITS+`ERROR_BITS+65:0] DE_OUTPUT_sampled;
|
||||
|
||||
decoder decoder(
|
||||
/* INPUTS */ INSTRUCTION[31:16],FLAGS,
|
||||
/* MICROCODE */ ucode_seq_addr_entry,SIMPLE_MICRO,ucode_seq_addr,
|
||||
/* OUTPUT */ DE_OUTPUT
|
||||
);
|
||||
|
||||
wire [2:0] RM;
|
||||
assign RM = DE_OUTPUT_sampled[5:3];
|
||||
|
||||
wire memio_address_select;
|
||||
assign memio_address_select=DE_OUTPUT_sampled[6:6];
|
||||
|
||||
wire [3:0] DE_reg_read_port1_addr,DE_reg_read_port2_addr;
|
||||
assign DE_reg_read_port1_addr=DE_OUTPUT_sampled[53:50];
|
||||
assign DE_reg_read_port2_addr=DE_OUTPUT_sampled[57:54];
|
||||
|
||||
wire [3:0] reg_write_addr;
|
||||
assign reg_write_addr=DE_OUTPUT_sampled[61:58];
|
||||
|
||||
wire MEM_OR_IO;
|
||||
assign MEM_OR_IO = DE_OUTPUT_sampled[7:7];
|
||||
|
||||
wire Wbit, Sbit, opcode_size;
|
||||
assign opcode_size=DE_OUTPUT_sampled[62:62];
|
||||
assign Sbit=DE_OUTPUT_sampled[63:63];
|
||||
assign Wbit=DE_OUTPUT_sampled[64:64];
|
||||
|
||||
wire [`ERROR_BITS-1:0] DE_ERROR;
|
||||
assign HALT = DE_OUTPUT_sampled[65:65];
|
||||
assign DE_ERROR = DE_OUTPUT_sampled[`ERROR_BITS+65:66];
|
||||
|
||||
wire [`EXEC_STATE_BITS-1:0] next_state;
|
||||
assign next_state=DE_OUTPUT_sampled[`EXEC_STATE_BITS+`ERROR_BITS+65:`ERROR_BITS+66];
|
||||
|
||||
/*############ Registers ######################################################## */
|
||||
|
||||
// verilator lint_off UNDRIVEN
|
||||
reg [15:0] FLAGS;
|
||||
// verilator lint_on UNDRIVEN
|
||||
|
||||
//Architectural Register file
|
||||
reg [3:0] reg_write_addr;
|
||||
wire [15:0] reg_write_data;
|
||||
wire reg_write_we;
|
||||
wire [3:0] reg_read_port1_addr;
|
||||
reg [15:0] reg_read_port1_data;
|
||||
reg [3:0] reg_read_port2_addr;
|
||||
reg [15:0] reg_read_port2_data;
|
||||
reg [1:0] reg_write_in_sel;
|
||||
|
||||
mux4 #(.WIDTH(16)) REG_FILE_WRITE_IN_MUX(
|
||||
ALU_O,
|
||||
16'hz,
|
||||
16'hz,
|
||||
16'hz,
|
||||
reg_write_in_sel,
|
||||
reg_write_data);
|
||||
|
||||
register_file register_file(
|
||||
.write_port1_addr(reg_write_addr),
|
||||
.write_port1_data(reg_write_data),
|
||||
.write_port1_we(reg_write_we),
|
||||
.read_port1_addr(reg_read_port1_addr),
|
||||
.read_port1_data(reg_read_port1_data),
|
||||
.read_port2_addr(reg_read_port2_addr),
|
||||
.read_port2_data(reg_read_port2_data)
|
||||
);
|
||||
|
||||
assign reg_read_port1_addr = use_exec_reg_addr ? EXEC_reg_read_port1_addr : reg_read_port1_addr_latched;
|
||||
|
||||
reg [15:0] ProgCount;
|
||||
|
||||
/*############ Processor state machine ########################################################## */
|
||||
reg [3:0] reg_read_port1_addr_latched;
|
||||
wire [3:0] reg_read_port1_addr;
|
||||
assign reg_read_port1_addr = use_exec_reg_addr ? EXEC_reg_read_port1_addr : DE_reg_read_port1_addr;
|
||||
|
||||
wire [15:0] reg_read_port1_data, reg_read_port2_data;
|
||||
|
||||
wire reg_write_we;
|
||||
|
||||
register_file register_file(
|
||||
/* WRITE */ .write_port1_addr(reg_write_addr),
|
||||
/* */ .write_port1_data(ALU_O),
|
||||
/* */ .write_port1_we(reg_write_we),
|
||||
/* READ 1 */ .read_port1_addr(reg_read_port1_addr),
|
||||
/* */ .read_port1_data(reg_read_port1_data),
|
||||
/* READ 2 */ .read_port2_addr(DE_reg_read_port2_addr),
|
||||
/* */ .read_port2_data(reg_read_port2_data)
|
||||
);
|
||||
|
||||
/*############ Processor State Machine ########################################## */
|
||||
|
||||
/*** RESET LOGIC ***/
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
|
||||
always @(negedge reset) begin
|
||||
state <= `PROC_HALT; //TODO: race condition ??
|
||||
end
|
||||
always @(posedge reset) begin
|
||||
state <= `PROC_RESET;
|
||||
end
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
|
||||
/*** Processor stages ***/
|
||||
|
||||
@ -219,49 +184,28 @@ InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},instr_end);
|
||||
|
||||
reg [23:0] INSTRUCTION_BUFFER;
|
||||
|
||||
|
||||
always @(posedge clock) begin
|
||||
case(state)
|
||||
`PROC_RESET:begin
|
||||
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
||||
HALT <= 0;
|
||||
DE_OUTPUT_sampled <= 0;
|
||||
SIMPLE_MICRO <= 0;
|
||||
state <= `PROC_DE_STATE_ENTRY;
|
||||
reg_write_in_sel <= 2'b00; //only got wirtten in IF
|
||||
end
|
||||
`PROC_DE_STATE_ENTRY:begin
|
||||
if(VALID_INSTRUCTION==1) begin
|
||||
|
||||
DE_OUTPUT_sampled <= DE_OUTPUT;
|
||||
|
||||
if(SIMPLE_MICRO==0)begin
|
||||
/* We cannot set these directly within
|
||||
* microcode so don't overwrite useful values
|
||||
* each tie the next microcode is executed.
|
||||
* Note this still allows to set initial values
|
||||
* at the start of the microcode */
|
||||
PARAM1_INIT <= DE_PARAM1;
|
||||
PARAM2_INIT <= DE_PARAM2;
|
||||
set_initial_values<=0;
|
||||
|
||||
`ifdef DEBUG_PC_ADDRESS
|
||||
$display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,INSTRUCTION);
|
||||
`endif
|
||||
ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end};
|
||||
INSTRUCTION_BUFFER<=INSTRUCTION[23:0];
|
||||
set_initial_values<=0;
|
||||
end
|
||||
DE_ERROR_sampled <= DE_ERROR;
|
||||
IN_MOD <= DE_IN_MOD;
|
||||
OUT_MOD <= DE_OUT_MOD;
|
||||
RM <= DE_RM;
|
||||
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_latched <= DE_reg_read_port1_addr;
|
||||
reg_read_port2_addr <= DE_reg_read_port2_addr;
|
||||
reg_write_addr <= DE_reg_write_addr;
|
||||
MEM_OR_IO <= DE_MEM_OR_IO;
|
||||
in_alu_sel1 <= DE_in_alu_sel1;
|
||||
in_alu_sel2 <= DE_in_alu_sel2;
|
||||
ALU_OP <= DE_ALU_OP;
|
||||
if ( (ucode_seq_addr==`UCODE_NO_INSTRUCTION) && (ucode_seq_addr_entry!=`UCODE_NO_INSTRUCTION) )begin
|
||||
/*switch to microcode decoding*/
|
||||
ucode_seq_addr <= ucode_seq_addr_entry;
|
||||
@ -269,7 +213,6 @@ always @(posedge clock) begin
|
||||
/*keep state the same and rerun decode this time with all the data from the microcode rom*/
|
||||
end else begin
|
||||
valid_exec_data <= 1;
|
||||
exec_state_init <= next_state;
|
||||
state <= `PROC_WAIT;
|
||||
end
|
||||
end
|
||||
@ -277,10 +220,10 @@ always @(posedge clock) begin
|
||||
`PROC_WAIT:begin
|
||||
set_initial_values<=1;
|
||||
if( exec_state == `EXEC_DONE ) begin
|
||||
FLAGS[7:0] <= EXEC_FLAGS; //don't set all of them all the time!
|
||||
FLAGS <= {8'b0,EXEC_FLAGS}; //TODO: don't set all of them all the time!
|
||||
valid_exec_data<=0;
|
||||
state <= `PROC_DE_STATE_ENTRY;
|
||||
if(SIMPLE_MICRO == 1 ) begin
|
||||
if( SIMPLE_MICRO == 1 ) begin
|
||||
ucode_seq_addr <= ucode_seq_addr_entry; /*Reused for next address*/
|
||||
if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin
|
||||
/*Finished microcode*/
|
||||
@ -296,5 +239,4 @@ always @(posedge clock) begin
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
Loading…
Reference in New Issue
Block a user