Compare commits
No commits in common. "d7eb4f36c0be566b1cdc3d4825c18cc71ebe15d7" and "fc4ecdb8d2646cdee24b10eb5d0d386bc1cae846" have entirely different histories.
d7eb4f36c0
...
fc4ecdb8d2
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,6 +5,4 @@
|
|||||||
*.swp
|
*.swp
|
||||||
cpu/boot_code.bin
|
cpu/boot_code.bin
|
||||||
cpu/boot_code.txt
|
cpu/boot_code.txt
|
||||||
cpu/brainfuck.bin
|
|
||||||
cpu/brainfuck.txt
|
|
||||||
cpu/memdump.txt
|
cpu/memdump.txt
|
||||||
|
@ -4,7 +4,7 @@ A CPU that aims to be binary compatible with the 8086 and with as many optimisat
|
|||||||
|
|
||||||
### Progress
|
### Progress
|
||||||
* [X] Executing code
|
* [X] Executing code
|
||||||
* [ ] Is turing complete
|
* [ ] can calculate the sieve of Eratosthenes
|
||||||
* [ ] can boot up MS-DOS / FreeDOS
|
* [ ] can boot up MS-DOS / FreeDOS
|
||||||
* [ ] Is completely binary compatible
|
* [ ] Is completely binary compatible
|
||||||
* [ ] Is pipelined
|
* [ ] Is pipelined
|
||||||
|
40
cpu/Makefile
40
cpu/Makefile
@ -2,38 +2,34 @@ SOURCES=processor.v testbench.v memory.v registers.v alu.v
|
|||||||
INCLUDES=proc_state_def.v
|
INCLUDES=proc_state_def.v
|
||||||
VVP=processor.vvp
|
VVP=processor.vvp
|
||||||
|
|
||||||
.PHONY: brainf
|
|
||||||
brainf: ${VVP} brainfuck.txt
|
|
||||||
vvp ${VVP} +BOOT_CODE=brainfuck.txt
|
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: ${VVP} boot_code.txt
|
run: ${VVP}
|
||||||
vvp ${VVP}
|
vvp ${VVP}
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: ${VVP}
|
build: ${VVP}
|
||||||
|
|
||||||
.PHONY: wave
|
.PHONY: wave
|
||||||
wave: ${VVP} brainfuck.txt
|
wave: ${VVP}
|
||||||
vvp ${VVP} -lxt2 +BOOT_CODE=brainfuck.txt
|
vvp ${VVP} -lxt2
|
||||||
gtkwave test.lx2 gtkwave_savefile.gtkw
|
gtkwave test.lx2 gtkwave_savefile.gtkw
|
||||||
|
|
||||||
${VVP} : ${SOURCES} ${INCLUDES}
|
${VVP} : ${SOURCES} ${INCLUDES} boot_code.txt
|
||||||
iverilog -g2012 ${SOURCES} -o $@
|
iverilog -g2012 ${SOURCES} -o $@
|
||||||
|
|
||||||
%.txt:%.bin
|
|
||||||
dd if=/dev/zero bs=1 count=1200 of=$(subst .bin,.stage,$^) status=none
|
|
||||||
dd if=$^ of=$(subst .bin,.stage,$^) conv=notrunc,nocreat status=none
|
|
||||||
xxd -ps -c 2 $(subst .bin,.stage,$^) > $@
|
|
||||||
rm $(subst .bin,.stage,$^)
|
|
||||||
|
|
||||||
%.bin:%.asm
|
|
||||||
as86 -0 $< -b $@
|
|
||||||
|
|
||||||
.PHONY: disas
|
|
||||||
disas: brainfuck.bin
|
|
||||||
objdump -D -b binary -m i8086 $^
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f ${VVP} test.lx2 boot_code.txt boot_code.bin brainfuck.txt brainfuck.bin
|
rm -f ${VVP} test.lx2 boot_code.txt boot_code.bin
|
||||||
|
|
||||||
|
boot_code.txt:boot_code.bin
|
||||||
|
dd if=/dev/zero bs=1 count=256 of=boot_code.stage status=none
|
||||||
|
dd if=boot_code.bin of=boot_code.stage conv=notrunc,nocreat status=none
|
||||||
|
xxd -ps -c 2 boot_code.stage > boot_code.txt
|
||||||
|
rm boot_code.stage
|
||||||
|
|
||||||
|
boot_code.bin:boot_code.asm
|
||||||
|
as86 -0 $< -b $@
|
||||||
|
|
||||||
|
.PHONY: disas
|
||||||
|
disas: boot_code.bin
|
||||||
|
objdump -D -b binary -m i8086 boot_code.bin
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
mov si,#prog
|
|
||||||
mov BX,#data
|
|
||||||
mov CX,#bracket
|
|
||||||
dec si
|
|
||||||
INTERPRET:
|
|
||||||
inc si
|
|
||||||
mov al,[si]
|
|
||||||
cmp al,#'+
|
|
||||||
jz WAS_PLUS
|
|
||||||
cmp al,#'-
|
|
||||||
jz WAS_MINUS
|
|
||||||
cmp al,#'>
|
|
||||||
jz WAS_MR
|
|
||||||
cmp al,#'<
|
|
||||||
jz WAS_ML
|
|
||||||
cmp al,#'[
|
|
||||||
jz WAS_PL
|
|
||||||
cmp al,#']
|
|
||||||
jz WAS_PR
|
|
||||||
cmp al,#'.
|
|
||||||
jz WAS_PRINT
|
|
||||||
jmp PROG_END
|
|
||||||
|
|
||||||
WAS_PLUS:
|
|
||||||
inc BYTE [BX]
|
|
||||||
JMP INTERPRET
|
|
||||||
|
|
||||||
WAS_MINUS:
|
|
||||||
dec BYTE [BX]
|
|
||||||
JMP INTERPRET
|
|
||||||
|
|
||||||
WAS_MR:
|
|
||||||
inc bx
|
|
||||||
JMP INTERPRET
|
|
||||||
|
|
||||||
WAS_ML:
|
|
||||||
dec bx
|
|
||||||
JMP INTERPRET
|
|
||||||
|
|
||||||
WAS_PL:
|
|
||||||
MOV AL,[BX]
|
|
||||||
cmp AL,#0
|
|
||||||
jz SKIP_CODE_BLOCK
|
|
||||||
;have to enter loop
|
|
||||||
MOV AX,SI
|
|
||||||
inc CX
|
|
||||||
inc CX
|
|
||||||
push SI
|
|
||||||
MOV SI,CX
|
|
||||||
mov [SI],AX
|
|
||||||
POP SI
|
|
||||||
JMP INTERPRET
|
|
||||||
|
|
||||||
SKIP_CODE_BLOCK:
|
|
||||||
;have to skip loop
|
|
||||||
MOV DX,#0
|
|
||||||
SKIP_LOOP:
|
|
||||||
INC SI
|
|
||||||
mov AL,[SI]
|
|
||||||
CMP AL,#']
|
|
||||||
JZ WAS_CLOSE1
|
|
||||||
CMP AL,#'[
|
|
||||||
JZ WAS_OPEN1
|
|
||||||
JMP SKIP_LOOP
|
|
||||||
|
|
||||||
WAS_CLOSE1:
|
|
||||||
CMP DX,#0
|
|
||||||
JZ INTERPRET
|
|
||||||
DEC DX
|
|
||||||
JMP SKIP_LOOP
|
|
||||||
WAS_OPEN1:
|
|
||||||
INC DX
|
|
||||||
JMP SKIP_LOOP
|
|
||||||
|
|
||||||
WAS_PR:
|
|
||||||
mov AL,[BX]
|
|
||||||
cmp AL,#0
|
|
||||||
JZ EXIT_PR
|
|
||||||
push SI
|
|
||||||
MOV SI,CX
|
|
||||||
mov ax,[SI]
|
|
||||||
POP SI
|
|
||||||
mov si,ax
|
|
||||||
JMP INTERPRET
|
|
||||||
|
|
||||||
|
|
||||||
EXIT_PR:
|
|
||||||
DEC CX
|
|
||||||
DEC CX
|
|
||||||
jmp INTERPRET
|
|
||||||
|
|
||||||
|
|
||||||
WAS_PRINT:
|
|
||||||
mov ah, #0x02
|
|
||||||
MOV DL,[BX]
|
|
||||||
int #0x21
|
|
||||||
JMP INTERPRET
|
|
||||||
|
|
||||||
PROG_END:
|
|
||||||
hlt
|
|
||||||
|
|
||||||
bracket: .BLKB 280
|
|
||||||
data: .BLKB 560
|
|
||||||
;prog db '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.f'
|
|
||||||
prog:.ASCII '++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.'
|
|
@ -1,10 +1,7 @@
|
|||||||
module rom(input [19:0] address,output wire [15:0] data ,input rd,input cs);
|
module rom(input [19:0] address,output wire [15:0] data ,input rd,input cs);
|
||||||
reg [15:0] memory [0:599];
|
reg [15:0] memory [0:127];
|
||||||
initial begin
|
initial begin
|
||||||
string boot_code;
|
$readmemh("boot_code.txt", memory);
|
||||||
if(!$value$plusargs("BOOT_CODE=%s",boot_code))
|
|
||||||
boot_code="boot_code.txt";
|
|
||||||
$readmemh(boot_code, memory);
|
|
||||||
end
|
end
|
||||||
assign data = !rd & !cs ? memory[address]: 'hz;
|
assign data = !rd & !cs ? memory[address]: 'hz;
|
||||||
endmodule
|
endmodule
|
||||||
|
BIN
cpu/out.bin
BIN
cpu/out.bin
Binary file not shown.
@ -11,7 +11,7 @@ assign out = (sel == 'b00) ? in1 :
|
|||||||
in4;
|
in4;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
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 HALT,output reg ERROR);
|
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 HALT);
|
||||||
|
|
||||||
/*** Global Definitions ***/
|
/*** Global Definitions ***/
|
||||||
// State
|
// State
|
||||||
@ -35,6 +35,7 @@ always @(negedge reset) begin
|
|||||||
@(posedge clock);
|
@(posedge clock);
|
||||||
state=`PROC_HALT_STATE;
|
state=`PROC_HALT_STATE;
|
||||||
ProgCount=0;//TODO: Reset Vector
|
ProgCount=0;//TODO: Reset Vector
|
||||||
|
EXCEPTION=0;
|
||||||
HALT=0;
|
HALT=0;
|
||||||
reg_read=1;
|
reg_read=1;
|
||||||
reg_write=1;
|
reg_write=1;
|
||||||
@ -47,6 +48,8 @@ always @(negedge reset) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
reg EXCEPTION;
|
||||||
|
|
||||||
/*** ALU and EXEC stage logic ***/
|
/*** ALU and EXEC stage logic ***/
|
||||||
|
|
||||||
//Architectural Register file
|
//Architectural Register file
|
||||||
@ -88,7 +91,7 @@ ADDER16 ADDER16_1(ADDER16_1A,ADDER16_1B,ALU_OUT,ADDER16_1O,ADDER16_1C);
|
|||||||
|
|
||||||
/*** Processor stages ***/
|
/*** Processor stages ***/
|
||||||
|
|
||||||
`define invalid_instruction state=`PROC_IF_STATE_ENTRY;ERROR=1;
|
`define invalid_instruction state=`PROC_IF_STATE_ENTRY;EXCEPTION=1;
|
||||||
|
|
||||||
always @(negedge clock) begin
|
always @(negedge clock) begin
|
||||||
case(state)
|
case(state)
|
||||||
@ -129,7 +132,7 @@ always @(posedge clock) begin
|
|||||||
`PROC_HALT_STATE:begin
|
`PROC_HALT_STATE:begin
|
||||||
end
|
end
|
||||||
`PROC_IF_STATE_ENTRY:begin
|
`PROC_IF_STATE_ENTRY:begin
|
||||||
ERROR=0;
|
EXCEPTION=0;
|
||||||
external_address_bus <= ProgCount;
|
external_address_bus <= ProgCount;
|
||||||
read <= 0;
|
read <= 0;
|
||||||
write <= 1;
|
write <= 1;
|
||||||
@ -265,7 +268,7 @@ always @(posedge clock) begin
|
|||||||
`PROC_EX_STATE_ENTRY:begin
|
`PROC_EX_STATE_ENTRY:begin
|
||||||
reg_data=ADDER16_1O;
|
reg_data=ADDER16_1O;
|
||||||
state=`PROC_EX_STATE_EXIT;
|
state=`PROC_EX_STATE_EXIT;
|
||||||
ERROR=0;
|
EXCEPTION=0;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
@ -7,9 +7,8 @@ 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,romcs,HALT;
|
wire rd,wr,romcs,HALT;
|
||||||
wire ERROR;
|
|
||||||
|
|
||||||
processor p(clock,reset,address_bus,data_bus,rd,wr,HALT,ERROR);
|
processor p(clock,reset,address_bus,data_bus,rd,wr,HALT);
|
||||||
rom bootrom(address_bus,data_bus,rd,romcs);
|
rom bootrom(address_bus,data_bus,rd,romcs);
|
||||||
|
|
||||||
`define CPU_SPEED 1000
|
`define CPU_SPEED 1000
|
||||||
@ -37,13 +36,6 @@ always @(posedge HALT) begin
|
|||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge ERROR) begin
|
|
||||||
$display("PROCESSOR RUN INTO AN ERROR.\nCycles run for: %d",cycles);
|
|
||||||
$writememh("memdump.txt", bootrom.memory);
|
|
||||||
#(`CPU_SPEED) //Just for the waveform
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clock)begin
|
always @(posedge clock)begin
|
||||||
if(reset==1)
|
if(reset==1)
|
||||||
cycles=cycles+1;
|
cycles=cycles+1;
|
||||||
|
Loading…
Reference in New Issue
Block a user