Compare commits

..

2 Commits

8 changed files with 146 additions and 27 deletions

2
.gitignore vendored
View File

@ -5,4 +5,6 @@
*.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

View File

@ -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
* [ ] can calculate the sieve of Eratosthenes * [ ] Is turing complete
* [ ] can boot up MS-DOS / FreeDOS * [ ] can boot up MS-DOS / FreeDOS
* [ ] Is completely binary compatible * [ ] Is completely binary compatible
* [ ] Is pipelined * [ ] Is pipelined

View File

@ -2,34 +2,38 @@ 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} run: ${VVP} boot_code.txt
vvp ${VVP} vvp ${VVP}
.PHONY: build .PHONY: build
build: ${VVP} build: ${VVP}
.PHONY: wave .PHONY: wave
wave: ${VVP} wave: ${VVP} brainfuck.txt
vvp ${VVP} -lxt2 vvp ${VVP} -lxt2 +BOOT_CODE=brainfuck.txt
gtkwave test.lx2 gtkwave_savefile.gtkw gtkwave test.lx2 gtkwave_savefile.gtkw
${VVP} : ${SOURCES} ${INCLUDES} boot_code.txt ${VVP} : ${SOURCES} ${INCLUDES}
iverilog -g2012 ${SOURCES} -o $@ iverilog -g2012 ${SOURCES} -o $@
.PHONY: clean %.txt:%.bin
clean: dd if=/dev/zero bs=1 count=1200 of=$(subst .bin,.stage,$^) status=none
rm -f ${VVP} test.lx2 boot_code.txt boot_code.bin dd if=$^ of=$(subst .bin,.stage,$^) conv=notrunc,nocreat status=none
xxd -ps -c 2 $(subst .bin,.stage,$^) > $@
rm $(subst .bin,.stage,$^)
boot_code.txt:boot_code.bin %.bin:%.asm
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 $@ as86 -0 $< -b $@
.PHONY: disas .PHONY: disas
disas: boot_code.bin disas: brainfuck.bin
objdump -D -b binary -m i8086 boot_code.bin objdump -D -b binary -m i8086 $^
.PHONY: clean
clean:
rm -f ${VVP} test.lx2 boot_code.txt boot_code.bin brainfuck.txt brainfuck.bin

105
cpu/brainfuck.asm Normal file
View File

@ -0,0 +1,105 @@
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 '++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.'

View File

@ -1,7 +1,10 @@
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:127]; reg [15:0] memory [0:599];
initial begin initial begin
$readmemh("boot_code.txt", memory); string boot_code;
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 Normal file

Binary file not shown.

View File

@ -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); 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);
/*** Global Definitions ***/ /*** Global Definitions ***/
// State // State
@ -35,7 +35,6 @@ 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;
@ -48,8 +47,6 @@ 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
@ -91,7 +88,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;EXCEPTION=1; `define invalid_instruction state=`PROC_IF_STATE_ENTRY;ERROR=1;
always @(negedge clock) begin always @(negedge clock) begin
case(state) case(state)
@ -132,7 +129,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
EXCEPTION=0; ERROR=0;
external_address_bus <= ProgCount; external_address_bus <= ProgCount;
read <= 0; read <= 0;
write <= 1; write <= 1;
@ -268,7 +265,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;
EXCEPTION=0; ERROR=0;
end end
endcase endcase
end end

View File

@ -7,8 +7,9 @@ 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); processor p(clock,reset,address_bus,data_bus,rd,wr,HALT,ERROR);
rom bootrom(address_bus,data_bus,rd,romcs); rom bootrom(address_bus,data_bus,rd,romcs);
`define CPU_SPEED 1000 `define CPU_SPEED 1000
@ -36,6 +37,13 @@ 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;