Cleaned the decoder a bit and laid down some of the groundwork for microcode

This commit is contained in:
(Tim) Efthimis Kritikos 2023-02-19 16:22:23 +00:00
parent e6c9c722e3
commit e2e9a92832
7 changed files with 199 additions and 240 deletions

View File

@ -19,6 +19,7 @@
SYSTEM_VVP=system/system.vvp SYSTEM_VVP=system/system.vvp
BOOT_CODE=boot_code/brainfuck.txt BOOT_CODE=boot_code/brainfuck.txt
GTKWSAVE=./gtkwave_savefile.gtkw GTKWSAVE=./gtkwave_savefile.gtkw
MICROCODE=system/ucode.hex
include common.mk include common.mk

View File

@ -11,6 +11,7 @@ A CPU that aims to be binary compatible with the 8086 and with as many optimisat
* [ ] Is pipelined * [ ] Is pipelined
* [ ] Is Out of Order * [ ] Is Out of Order
* [ ] Is superscalar * [ ] Is superscalar
* [ ] Has been successfully synthesized
### Simulating it ### Simulating it
To simulate this project you need Icarus Verilog, bin86, GNU make, xxd and the posix coreutils. To simulate this project you need Icarus Verilog, bin86, GNU make, xxd and the posix coreutils.

View File

@ -34,13 +34,13 @@ disas: $(subst .txt,.disas,${BOOT_CODE})
# Running simulation # Running simulation
%.lx2 %.memdump: %.txt ${SYSTEM_VVP} %.lx2 %.memdump: %.txt ${SYSTEM_VVP}
${QUIET_VVP} ${QUIET_VVP}
${Q}vvp "${SYSTEM_VVP}" -lxt2 +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.lx2,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" ${Q}vvp "${SYSTEM_VVP}" -lxt2 +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.lx2,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
${Q}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)" ${Q}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
${Q}rm "$(subst .txt,.memdumptxt,$<)" ${Q}rm "$(subst .txt,.memdumptxt,$<)"
%.run: %.txt ${SYSTEM_VVP} %.run: %.txt ${SYSTEM_VVP}
${QUIET_VVP} ${QUIET_VVP}
${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" ${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
%.disas: %.bin %.disas: %.bin
objdump -D -b binary -m i8086 $^ | less objdump -D -b binary -m i8086 $^ | less

View File

@ -16,10 +16,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
SOURCES=processor.v testbench.v memory.v registers.v alu.v decoder.v general.v SOURCES=processor.v testbench.v memory.v registers.v alu.v decoder.v general.v
INCLUDES=proc_state_def.v alu_header.v config.v INCLUDES=proc_state_def.v alu_header.v config.v ucode_header.v ucode.hex
SYSTEM_VVP=system.vvp SYSTEM_VVP=system.vvp
BOOT_CODE=boot_code.txt BOOT_CODE=boot_code.txt
GTKWSAVE=../gtkwave_savefile.gtkw GTKWSAVE=../gtkwave_savefile.gtkw
MICROCODE=ucode.hex
include ../common.mk include ../common.mk

View File

@ -19,7 +19,28 @@
`include "proc_state_def.v" `include "proc_state_def.v"
`include "alu_header.v" `include "alu_header.v"
`include "ucode_header.v"
module microcode(
input [`UCODE_ADDR_BITS-1:0] ADDR,
output [`UCODE_DATA_BITS-1:0] DATA
);
initial begin
string ucode_path;
if($value$plusargs("MICROCODE=%s",ucode_path))begin
$readmemb(ucode_path,ucode,0,`UCODE_SIZE-1);
end else begin
$display("Please supply microcode rom file as a runtime vvp argument +MICROCODE=<path>");
$finish;
end
end
reg [`UCODE_DATA_BITS-1:0] ucode [ 0:`UCODE_SIZE-1 ];
assign DATA=ucode[ADDR];
endmodule
module decoder( module decoder(
input wire [15:0] CIR,input wire [15:0] FLAGS, output reg Wbit, output reg Sbit, output reg unaligning ,output reg opcode_size, output reg ERROR,output reg [`PROC_STATE_BITS-1:0]next_state input wire [15:0] CIR,input wire [15:0] FLAGS, output reg Wbit, output reg Sbit, output reg unaligning ,output reg opcode_size, output reg ERROR,output reg [`PROC_STATE_BITS-1:0]next_state
@ -29,6 +50,10 @@ module decoder(
,output reg [2:0]ALU_1OP ,output reg [2:0]ALU_1OP
); );
wire [`UCODE_DATA_BITS-1:0] ucode_data;
reg [`UCODE_ADDR_BITS-1:0] UCODE_ADDR;
microcode ucode(UCODE_ADDR,ucode_data);
/* 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */ /* 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */
`define invalid_instruction next_state=`PROC_IF_STATE_ENTRY;ERROR=1;MOD=2'b11; `define invalid_instruction next_state=`PROC_IF_STATE_ENTRY;ERROR=1;MOD=2'b11;
@ -38,10 +63,8 @@ module decoder(
always @( CIR ) begin always @( CIR ) begin
ERROR=0;HALT=0; ERROR=0;HALT=0;
case(CIR[15:10]) casex({CIR[15:8],CIR[5:3]})
6'b000001 : begin 11'b0000_010x_xxx : begin
/* ADD, ... */
if ( CIR[9:9] == 0 )begin
/* Add Immediate word/byte to accumulator */ /* Add Immediate word/byte to accumulator */
/* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/ /* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/
opcode_size=0; opcode_size=0;
@ -64,14 +87,8 @@ always @( CIR ) begin
PARAM1[7:0]=CIR[7:0]; PARAM1[7:0]=CIR[7:0];
next_state=`PROC_EX_STATE_ENTRY; next_state=`PROC_EX_STATE_ENTRY;
end end
end else begin
`invalid_instruction
end end
end 11'b1000_00xx_000 : begin
6'b100000 : begin
/* ADD, ADC, SUB, SBB, CMP , AND, ... */
case (CIR[5:3])
3'b000 : begin
/* Add Immediate word/byte to register/memory */ /* Add Immediate word/byte to register/memory */
/* 1 0 0 0 0 0 S W | MOD 0 0 0 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */ /* 1 0 0 0 0 0 S W | MOD 0 0 0 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */
`start_aligning_instruction `start_aligning_instruction
@ -93,7 +110,7 @@ always @( CIR ) begin
`invalid_instruction /*do 8bit loads*/ `invalid_instruction /*do 8bit loads*/
end end
end end
3'b111 : begin 11'b1000_00xx_111 : begin
/* CMP - compare Immediate with register / memory */ /* CMP - compare Immediate with register / memory */
/* 1 0 0 0 0 0 S W | MOD 1 1 1 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */ /* 1 0 0 0 0 0 S W | MOD 1 1 1 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */
opcode_size=1; opcode_size=1;
@ -117,15 +134,8 @@ always @( CIR ) begin
end else begin end else begin
`invalid_instruction `invalid_instruction
end end
end end
default:begin 11'b1011_0xxx_xxx : begin
`invalid_instruction
end
endcase
end
6'b101100,
6'b101101:begin
/* MOV - Move Immediate byte to register */ /* MOV - Move Immediate byte to register */
/* 1 0 1 1 W REG | DATA | DATA if W |*/ /* 1 0 1 1 W REG | DATA | DATA if W |*/
`start_aligning_instruction `start_aligning_instruction
@ -142,8 +152,7 @@ always @( CIR ) begin
ALU_1OP=`ALU_OP_ADD; ALU_1OP=`ALU_OP_ADD;
next_state=`PROC_EX_STATE_ENTRY; next_state=`PROC_EX_STATE_ENTRY;
end end
6'b101110, 11'b1011_1xxx_xxx : begin
6'b101111 : begin
/*MOV - Move Immediate word to register*/ /*MOV - Move Immediate word to register*/
`start_unaligning_instruction `start_unaligning_instruction
has_operands=1; has_operands=1;
@ -159,7 +168,7 @@ always @( CIR ) begin
next_state=`PROC_DE_LOAD_16_PARAM; next_state=`PROC_DE_LOAD_16_PARAM;
end end
6'b100010 : begin 11'b1000_10xx_xxx : begin
/* MOV - Reg/Mem to/from register */ /* MOV - Reg/Mem to/from register */
/* 1 0 0 0 1 0 D W | MOD REG RM | < DISP LO > | < DISP HI > |*/ /* 1 0 0 0 1 0 D W | MOD REG RM | < DISP LO > | < DISP HI > |*/
has_operands=0; has_operands=0;
@ -204,10 +213,7 @@ always @( CIR ) begin
ALU_1OP=`ALU_OP_ADD; ALU_1OP=`ALU_OP_ADD;
PARAM2=0; PARAM2=0;
end end
6'b010000,//INC 11'b0100_xxxx_xxx:begin//DEC
6'b010001,//INC
6'b010010,//DEC
6'b010011:begin//DEC
/* DEC - Decrement Register */ /* DEC - Decrement Register */
/* | 0 1 0 0 1 REG | */ /* | 0 1 0 0 1 REG | */
/* INC - Increment Register */ /* INC - Increment Register */
@ -229,11 +235,7 @@ always @( CIR ) begin
ALU_1OP=`ALU_OP_SUB; ALU_1OP=`ALU_OP_SUB;
next_state=`PROC_EX_STATE_ENTRY; next_state=`PROC_EX_STATE_ENTRY;
end end
6'b111111 : begin 11'b1111_111x_00x : begin
/* INC */
if (CIR[9:9] == 1 ) begin
case (CIR[5:3])
3'b000,3'b001 :begin
/* INC - Register/Memory */ /* INC - Register/Memory */
/* 1 1 1 1 1 1 1 W | MOD 0 0 0 R/M | < DISP LO> | < DISP HI> */ /* 1 1 1 1 1 1 1 W | MOD 0 0 0 R/M | < DISP LO> | < DISP HI> */
/* DEC - Register/Memory */ /* DEC - Register/Memory */
@ -259,18 +261,7 @@ always @( CIR ) begin
else else
next_state=`RPOC_MEMIO_READ; next_state=`RPOC_MEMIO_READ;
end end
default:begin 11'b1111_0100_xxx : begin
`invalid_instruction
end
endcase
end else begin
`invalid_instruction
end
end
6'b111101 : begin
/*HLT, CMC, TEST, NOT, NEG, MUL, IMUL, .... */
case (CIR[9:8])
2'b00:begin
/* HLT - Halt */ /* HLT - Halt */
/* 1 1 1 1 0 1 0 0 | */ /* 1 1 1 1 0 1 0 0 | */
has_operands=0; has_operands=0;
@ -280,14 +271,7 @@ always @( CIR ) begin
HALT=1; HALT=1;
next_state=`PROC_HALT_STATE; next_state=`PROC_HALT_STATE;
end end
default:begin 11'b0011_110x_xxx : begin
`invalid_instruction;
end
endcase
end
6'b001111 : begin
if ( CIR[9:9] == 0 ) begin
/* CMP - Compare Immediate with accumulator */ /* CMP - Compare Immediate with accumulator */
/* 0 0 1 1 1 1 0 W | DATA | DATA if W |*/ /* 0 0 1 1 1 1 0 W | DATA | DATA if W |*/
/* */ /* */
@ -312,14 +296,8 @@ always @( CIR ) begin
PARAM1[7:0]=CIR[7:0]; PARAM1[7:0]=CIR[7:0];
next_state=`PROC_EX_STATE_ENTRY; next_state=`PROC_EX_STATE_ENTRY;
end end
end else begin
`invalid_instruction
end end
end 11'b0111_xxxx_xxx:begin
6'b011100,
6'b011101,
6'b011110,
6'b011111:begin
/* Conditional relative jumps */ /* Conditional relative jumps */
/* JE/JZ - Jump on Zero */ /* JE/JZ - Jump on Zero */
/* 0 1 1 1 0 1 0 0 | IP-INC8 |*/ /* 0 1 1 1 0 1 0 0 | IP-INC8 |*/
@ -372,27 +350,9 @@ always @( CIR ) begin
end end
endcase endcase
end end
6'b111010:begin 11'b1110_1011_xxx:begin
/* JMP,CALL */
case(CIR[9:8])
2'b00: begin
/* CALL - Call direct within segment */
/* 1 1 1 0 1 0 0 0 | IP-INC-LO | IP-INC-HI |*/
`invalid_instruction
end
2'b01: begin
/* JMP - Unconditional Jump direct within segment */
/* 1 1 1 0 1 0 0 1 | IP-INC-LO | IP-INC-HI |*/
`invalid_instruction
end
2'b10: begin
/* JMP - Unconditional jump direct intersegment */
/* 0 0 0 0 0 0 0 0 | IP-LO | IP-HI | CS-LO | CS-HI | */
`invalid_instruction
end
2'b11: begin
/* JMP - Unconditional jump direct within segment (short) */ /* JMP - Unconditional jump direct within segment (short) */
/* | 1 1 1 0 1 0 0 1 | IP-INC-LO | */ /* | 1 1 1 0 1 0 1 1 | IP-INC-LO | */
`start_aligning_instruction `start_aligning_instruction
opcode_size=0; opcode_size=0;
has_operands=1; has_operands=1;
@ -404,36 +364,17 @@ always @( CIR ) begin
out_alu1_sel=3'b101; out_alu1_sel=3'b101;
next_state=`PROC_EX_STATE_ENTRY; next_state=`PROC_EX_STATE_ENTRY;
end end
endcase 11'b1100_1101_xxx:begin
end
6'b110011:begin
case(CIR[9:8])
2'b00:begin
`invalid_instruction
end
2'b01:begin
if(CIR[7:0]==8'h21) begin
/* INT - execute interrupt handler */ /* INT - execute interrupt handler */
/* 1 1 0 0 1 1 0 1 | DATA |*/ /* 1 1 0 0 1 1 0 1 | DATA |*/
has_operands=1; has_operands=1;
opcode_size=0; opcode_size=0;
`start_aligning_instruction `start_aligning_instruction
/* Emulate MS-DOS print routines */ /* Emulate MS-DOS print routines */
if(register_file.registers[0][15:8]==8'h02)begin if(CIR[7:0]==8'h21 && register_file.registers[0][15:8]==8'h02)begin
$write("%s" ,register_file.registers[2][7:0]); /*TODO:Could trigger erroneously while CIR is not final*/ $write("%s" ,register_file.registers[2][7:0]); /*TODO:Could trigger erroneously while CIR is not final*/
end end
next_state=`PROC_IF_STATE_ENTRY; next_state=`PROC_IF_STATE_ENTRY;
end else begin
`invalid_instruction
end
end
2'b10:begin
`invalid_instruction
end
2'b11:begin
`invalid_instruction
end
endcase
end end
default:begin default:begin
`invalid_instruction `invalid_instruction

9
system/ucode.hex Normal file
View File

@ -0,0 +1,9 @@
//s : Opcode size 0:8bit 1:16bit
//h : Has operands as part of the instruction: 0: No 1: Yes
// |sh
@000 01_11
@001 11_10
@002 1000
@003 0010

6
system/ucode_header.v Normal file
View File

@ -0,0 +1,6 @@
`define UCODE_ADDR_BITS 9
`define UCODE_DATA_BITS 32
`define UCODE_SIZE 4
`define ADD_AL_IB 0
`define ADD_AX_IW 1