diff --git a/.gitignore b/.gitignore
index 9bd1180..58ab0dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,8 +13,10 @@ abc.history
system/synth_ecp5_out.config
boot_code/*.bin
boot_code/*.txt
+boot_code/*.stxt
system/boot_code.bin
system/boot_code.txt
system/obj_dir/
system/simplified_ucode.txt
tools/*svg
+system/external_ip/litedram_core_ecp5_phy.v
diff --git a/Makefile b/Makefile
index f49664b..4426486 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ VERILATOR_BIN=system/obj_dir/Vsystem
BOOT_CODE=boot_code/brainfuck_mandelbrot.txt
GTKWSAVE=./gtkwave_savefile.gtkw
MICROCODE=system/ucode.txt
-BOOTABLES=boot_code/brainfuck_compiled.txt boot_code/brainfuck_interpreted.txt boot_code/pipeline_ideal.txt boot_code/fibonacci.txt boot_code/gnome_sort.txt boot_code/cache_fill_and_empty.txt ${BOOT_CODE} boot_code/colored_led.txt
+BOOTABLES=boot_code/brainfuck_compiled.txt boot_code/brainfuck_interpreted.txt boot_code/pipeline_ideal.txt boot_code/fibonacci.txt boot_code/gnome_sort.txt boot_code/cache_fill_and_empty.txt ${BOOT_CODE} boot_code/colored_led.txt boot_code/bios.stxt
NO_ASM=1
include common.mk
@@ -29,7 +29,7 @@ include common.mk
.PHONY: ${BOOTABLES}
.PHONY: ${subst .txt,.bin,${BOOTABLES}}
-${BOOTABLES} ${subst .txt,.bin,${BOOTABLES}} :
+${BOOTABLES} ${subst .stxt,.bin,${subst .txt,.bin,${BOOTABLES}}} :
${Q}make ${MAKEOPTS} -C boot_code $(subst boot_code/,,$@)
boot_code/%.txt:
@@ -48,5 +48,5 @@ clean:
${Q}make ${MAKEOPTS} -C system clean
${Q}make ${MAKEOPTS} -C boot_code clean
-upload: boot_code/brainfuck_compiled.txt
+upload: boot_code/bios.stxt
make -C system upload
diff --git a/README.md b/README.md
index 310bcda..688bbf6 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,12 @@ Additionally, for ECP5 FPGAs:
* prjtrellis : 1.4 ( database commit 4dda149b9e4f1753ebc8b011ece2fe794be1281a )
* nextpnr : 0.6
+Additionally, if you need a DRAM/DDR controller, the project supports litedram:
+
+* Litedram : 2023.08
+* Migen : 0.9.2
+* Litex : 2023.08
+
Additionally, for FPGAs using the [foboot](https://github.com/im-tomu/foboot) bootloader
* dfu-util : 0.11
diff --git a/boot_code/Makefile b/boot_code/Makefile
index 4fa7926..a9d1bba 100644
--- a/boot_code/Makefile
+++ b/boot_code/Makefile
@@ -1,5 +1,5 @@
-SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm pipeline_ideal.asm fibonacci.asm gnome_sort.asm cache_fill_and_empty.asm colored_led.asm
-BINARIES=$(subst .asm,.txt,${SOURCE})
+SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm pipeline_ideal.asm fibonacci.asm gnome_sort.asm cache_fill_and_empty.asm colored_led.asm bios.asm
+BINARIES=$(subst .asm,.txt,${SOURCE}) $(subst .asm,.stxt,${SOURCE})
BUILD_FILES=${BINARIES}
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})
BUILD_FILES+=$(subst .asm,.fst,${SOURCE})
diff --git a/boot_code/bios.asm b/boot_code/bios.asm
new file mode 100644
index 0000000..01da10c
--- /dev/null
+++ b/boot_code/bios.asm
@@ -0,0 +1,395 @@
+.org 0xF800
+mov sp,#STACK
+mov bx,#initdram_txt
+call print
+
+WAIT_PLL:
+inw #0x20
+test al,#0x04
+jz WAIT_PLL
+;;; DO ALL INIT STUFF ;;;
+
+;////sdram_software_control_on///
+MOV BX,#0x0000
+MOV AX,#0x000E
+call sdram_dfii_control_write
+;/////////////////////////////////
+
+MOV BX,#0x0000
+MOV AX,#0x0000
+CALL ddrctrl_init_done_write
+
+mov bx,#0x0000
+mov ax,#0x0000
+call ddrctrl_init_error_write
+
+mov bx,#0x0000
+mov ax,#0x000C
+call sdram_dfii_control_write
+
+MOV DL,#0xF0
+DELAY11:
+MOV AX,#0xF000
+DELAY1:
+INC AX
+JNZ DELAY1
+INC DL
+JNZ DELAY11
+
+MOV BX,#0x0000
+MOV AX,#0x0000
+call sdram_dfii_pi0_address_write
+
+mov bx,#0x0000
+mov ax,#0x0000
+call sdram_dfii_pi0_baddress_write
+
+mov bx,#0x0000
+mov ax,#0x000E
+call sdram_dfii_control_write
+
+MOV DL,#0xF0
+DELAY21:
+MOV AX,#0xF000
+DELAY2:
+INC AX
+JNZ DELAY2
+INC DL
+JNZ DELAY21
+
+MOV BX,#0x0000
+MOV AX,#0x0200
+call sdram_dfii_pi0_address_write
+mov bx,#0x0000
+mov ax,#0x0002
+call sdram_dfii_pi0_baddress_write
+mov bx,#0x0000
+mov ax,#0x000F
+call command_p0
+
+
+MOV BX,#0x0000
+MOV AX,#0x0000
+call sdram_dfii_pi0_address_write
+mov bx,#0x0000
+mov ax,#0x0003
+call sdram_dfii_pi0_baddress_write
+mov bx,#0x0000
+mov ax,#0x000F
+call command_p0
+
+
+MOV BX,#0x0000
+MOV AX,#0x0006
+call sdram_dfii_pi0_address_write
+mov bx,#0x0000
+mov ax,#0x0001
+call sdram_dfii_pi0_baddress_write
+mov bx,#0x0000
+mov ax,#0x000F
+call command_p0
+
+
+MOV BX,#0x0000
+MOV AX,#0x0320
+call sdram_dfii_pi0_address_write
+mov bx,#0x0000
+mov ax,#0x0000
+call sdram_dfii_pi0_baddress_write
+mov bx,#0x0000
+mov ax,#0x000F
+call command_p0
+
+MOV DL,#0xF0
+DELAY31:
+MOV AX,#0xF000
+DELAY3:
+INC AX
+JNZ DELAY3
+INC DL
+JNZ DELAY31
+
+MOV BX,#0x0000
+MOV AX,#0x0400
+call sdram_dfii_pi0_address_write
+mov bx,#0x0000
+mov ax,#0x0000
+call sdram_dfii_pi0_baddress_write
+mov bx,#0x0000
+mov ax,#0x0003
+call command_p0
+
+
+
+
+;////sdram_software_control_off///
+MOV BX,#0x0000
+MOV AX,#0x0001
+call sdram_dfii_control_write
+;////////////////////////////////
+
+;Signify end of init
+MOV BX,#0x0000
+MOV AX,#0x0001
+CALL ddrctrl_init_done_write
+
+;;;;;;;;;; PROBABLY NOT NECESSARY
+MOV DL,#0xF0
+DELAY41:
+MOV AX,#0xF000
+DELAY4:
+INC AX
+JNZ DELAY4
+INC DL
+JNZ DELAY41
+
+
+;;; CHECK ;;;
+inw #0x20
+test al,#0x01
+jz failram
+mov bx,#OK_txt
+call print
+JMP FINISHED_DDR
+failram:
+mov bx,#FAIL_txt
+call print
+mov bx,#NOT_RDY_txt
+call print
+
+inw #0x20
+test al,#0x02
+jz skip_err
+mov bx,#ERR_ASRT_txt
+call print
+skip_err:
+
+inw #0x20
+test al,#0x04
+jnz skip_pll
+mov bx,#PLL_ERR_txt
+call print
+skip_pll:
+hlt
+
+FINISHED_DDR:
+
+MOV DI,#0x2000
+MOV AX,#0xAAAA
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV AX,#0x6666
+MOV AX,[DI]
+CMP AX,#0xAAAA
+JNZ FAILED
+MOV BX,#MEMTEST_PASS
+CALL print
+
+MOV AL,#0x48
+MOV [DI],AX
+MOV AL,#0x00
+MOV AX,[DI]
+out byte #0xA5
+
+MOV DI,#0x3000
+MOV AL,#0x65
+MOV [DI],AX
+MOV AL,#0x00
+MOV AX,[DI]
+out byte #0xA5
+
+MOV DI,#0x4000
+MOV AL,#0x6c
+MOV [DI],AX
+MOV AL,#0x00
+MOV AX,[DI]
+out byte #0xA5
+
+MOV DI,#0x5000
+MOV AL,#0x6c
+MOV [DI],AX
+MOV AL,#0x00
+MOV AX,[DI]
+out byte #0xA5
+
+MOV DI,#0x6000
+MOV AL,#0x6f
+MOV [DI],AX
+MOV AL,#0x00
+MOV AX,[DI]
+out byte #0xA5
+
+HLT
+FAILED:
+MOV BX,#MEMTEST_FAIL
+CALL print
+
+MOV DL,#0xF0
+DELAY51:
+MOV AX,#0x5000
+DELAY5:
+INC AX
+JNZ DELAY5
+INC DL
+JNZ DELAY51
+
+MOV DI,#0x2000
+MOV AX,#0xAAAA
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV [DI],AX
+MOV AX,#0x0000
+MOV AX,[DI]
+CMP AL,#0xAA
+JNZ FAILED2
+MOV BX,#MEMTEST_PASS
+CALL print
+HLT
+FAILED2:
+MOV BX,#MEMTEST_FAIL
+CALL print
+MOV AX,[DI]
+CMP AL,#0xAA
+JNZ FAILED3
+MOV BX,#MEMTEST_PASS
+CALL print
+HLT
+FAILED3:
+MOV BX,#MEMTEST_FAIL
+CALL print
+HLT
+
+
+;;; HELPER FUNCTION
+command_p0:
+call WISHBONE_SET_DATA
+MOV AX,#0x0401 ;ORIG=0x1804L
+CALL WISHBONE_SET_ADDRESS
+CALL DO_WRITE_TRANSACTION
+MOV AX,#0x0001
+MOV BX,#0x0000
+call WISHBONE_SET_DATA
+MOV AX,#0x0402 ;ORIG=0x1808L
+CALL WISHBONE_SET_ADDRESS
+CALL DO_WRITE_TRANSACTION
+ret
+
+#AX: Lower 16 bits data
+#BX: Upper 16 bits data
+sdram_dfii_pi0_address_write:
+call WISHBONE_SET_DATA
+MOV AX,#0x0403 ;ORIG=0x180cL
+CALL WISHBONE_SET_ADDRESS
+CALL DO_WRITE_TRANSACTION
+ret
+
+sdram_dfii_pi0_baddress_write:
+call WISHBONE_SET_DATA
+MOV AX,#0x0404 ;ORIG=0x1810L
+CALL WISHBONE_SET_ADDRESS
+CALL DO_WRITE_TRANSACTION
+ret
+
+sdram_dfii_control_write:
+call WISHBONE_SET_DATA
+MOV AX,#0x0400 ;ORIG=0x1800L
+CALL WISHBONE_SET_ADDRESS
+CALL DO_WRITE_TRANSACTION
+ret
+
+ddrctrl_init_done_write:
+call WISHBONE_SET_DATA
+MOV AX,#0x0000 ;ORIG=0x0L
+CALL WISHBONE_SET_ADDRESS
+CALL DO_WRITE_TRANSACTION
+ret
+
+ddrctrl_init_error_write:
+call WISHBONE_SET_DATA
+MOV AX,#0x0001 ;ORIG=0x4L
+CALL WISHBONE_SET_ADDRESS
+CALL DO_WRITE_TRANSACTION
+ret
+;
+DO_WRITE_TRANSACTION:
+mov ax,#0x01
+outw #0x46
+mov bl,#0x01
+WB_WRITE_LOOP:
+inc bl
+jz WB_WRITE_TIMEOUT
+inw #0x44
+test al,#0x01
+jz WB_WRITE_LOOP
+test al,#0x04
+jnz WB_WRITE_ERR
+ret
+WB_WRITE_TIMEOUT:
+mov bx,#WISHBONE_TIMEOUT_txt
+call print
+hlt
+WB_WRITE_ERR:
+mov bx,#WISHBONE_ERROR_txt
+call print
+hlt
+
+#AX: address
+WISHBONE_SET_ADDRESS:
+outw #0x44
+ret
+
+#AX: Lower 16bits
+#BX: Upper 16bits
+WISHBONE_SET_DATA:
+outw #0x40
+MOV AX,BX
+outw #0x42
+ret
+
+print:
+mov al,[bx]
+cmp al,#0
+je print_exit
+out byte #0xA5
+inc bx
+jmp print
+print_exit:
+ret
+
+initdram_txt: .ASCII 'Init LiteDram: \0'
+OK_txt: .ASCII 'OK\n\0'
+PLL_ERR_txt: .ASCII 'PLL_ERR \0' ; PLL_ERR: pll_lock is not asserted
+ERR_ASRT_txt: .ASCII 'ERR_ASRT \0' ; ERR_ASRT: init_error is asserted
+NOT_RDY_txt: .ASCII 'NOT_RDY \0' ; NOT READY: init_done is not asserted
+FAIL_txt: .ASCII 'FAIL\n\0'
+WISHBONE_TIMEOUT_txt: .ASCII 'FAIL\nWISHBONE TIMEOUT\0'
+WISHBONE_ERROR_txt: .ASCII 'FAIL\nWISHBONE ERROR\0'
+MEMTEST_PASS: .ASCII 'MEMTEST PASSED\n\0'
+MEMTEST_FAIL: .ASCII 'MEMTEST FAILED\n\0'
+ .BLKB 18 ; Using the text as stack space for the compiled program
+STACK: ; brainfuck_mandelbrot depends on stack being at the end
+
+.ORG 0xFFF0
+MOV AX,#0xF800
+JMP AX
+
+
+.ORG 0xFFFF
+DB 0x00 ;Make sure a full 64KiB image
diff --git a/boot_code/brainfuck_compiled.asm b/boot_code/brainfuck_compiled.asm
index 5a61d47..fdc37a4 100644
--- a/boot_code/brainfuck_compiled.asm
+++ b/boot_code/brainfuck_compiled.asm
@@ -1,15 +1,22 @@
; Interrupt table and routines
-INCLUDE dos_layer.asm
org 0x100
-INCLUDE brainfuck_compiler_v1.asm
+output_program:
+org 0xF800
+mov sp,#SMALL_STACK
+call INIT_INT_VECT_TABLE
+INCLUDE brainfuck_compiler_v1.asm
+SMALL_STACK:
+
+INCLUDE dos_layer.asm
prog:
INCLUDE hello_9086.bf.asm
-output_program:
-
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xF800
JMP AX
+
+.ORG 0xFFFF
+DB 0x00 ;Make sure a full 64KiB image
diff --git a/boot_code/brainfuck_compiler_v1.asm b/boot_code/brainfuck_compiler_v1.asm
index 791e4cf..87e39df 100644
--- a/boot_code/brainfuck_compiler_v1.asm
+++ b/boot_code/brainfuck_compiler_v1.asm
@@ -17,6 +17,8 @@
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
+; 0x0000-0x0100 int vector 0x0100-0x0700 data 0x0700-0xC000 program data
+
mov sp,#STACK
mov bx,#bootup_msg
mov ah,#0x02
@@ -39,7 +41,7 @@ jmp print2
exit:
MOV SI,#prog
-MOV DI,#output_program
+MOV DI,#0x0700
;CL: write concat CH: move concat
MOV CX,#0
JMP COMPILE ; Moving some functions above the main switch to make shot jumps work
@@ -148,8 +150,9 @@ jne print3
MOV AL,#0xF4 ; hlt
MOV [DI],AL
-MOV BX,#DATA
-MOV AX,#output_program
+; From 0x100 its free but i'll do 0x200 in case it start writing earlier
+MOV BX,#0x0200
+MOV AX,#0x0700
JMP AX
;;;;;;;;; . ;;;;;;;;;
@@ -250,18 +253,19 @@ MOV AL,#0x43 ; inc %bx
STOSB
JMP MOVES_FLUSHED
+
MOVES_ONE_LEFT:
MOV AL,#0x4b ; dec %bx
STOSB
JMP MOVES_FLUSHED
+
MOVES_FLUSHED:
MOV CH,#0
RET
-bootup_msg: .ASCII 'Native 8086 brainfuck compiler v1\n'
-compiling: .ASCII 'Compiling...\0'
compiled: .ASCII '\rCompiled! \n'
-DATA: .BLKB 560
- .BLKB 200
-STACK:
+compiling: .ASCII 'Compiling...\0'
+bootup_msg: .ASCII 'Native 8086 brainfuck compiler v1\n'
+ .BLKB 6 ; Using the text as stack space for the compiled program
+STACK: ; brainfuck_mandelbrot depends on stack being at the end
diff --git a/boot_code/brainfuck_interpreted.asm b/boot_code/brainfuck_interpreted.asm
index 221e59d..b96aef6 100644
--- a/boot_code/brainfuck_interpreted.asm
+++ b/boot_code/brainfuck_interpreted.asm
@@ -1,16 +1,16 @@
-; Interrupt table and routines
-INCLUDE dos_layer.asm
-ORG 0x100
+ORG 0xF000
mov sp,#STACK
+call INIT_INT_VECT_TABLE
INCLUDE brainfuck_interpreter_v0.asm
.BLKB 200
STACK:
+INCLUDE dos_layer.asm
prog:
INCLUDE hello_9086.bf.asm
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xF000
JMP AX
diff --git a/boot_code/brainfuck_mandelbrot.asm b/boot_code/brainfuck_mandelbrot.asm
index a3bd259..ecce2d3 100644
--- a/boot_code/brainfuck_mandelbrot.asm
+++ b/boot_code/brainfuck_mandelbrot.asm
@@ -1,14 +1,22 @@
-; Interrupt table and routines
-INCLUDE dos_layer.asm
+;I got this down to 11428 bytes
-.ORG 0x100
+org 0x100
+output_program:
+
+org 0xD000
+mov sp,#SMALL_STACK
+call INIT_INT_VECT_TABLE
INCLUDE brainfuck_compiler_v1.asm
+SMALL_STACK:;Stack of compiler is at the end of file
+INCLUDE dos_layer.asm
prog:
INCLUDE mandelbrot.bf.asm
-output_program:
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xD000
JMP AX
+
+.ORG 0xFFFF
+DB 0x00 ;Make sure a full 64KiB image
diff --git a/boot_code/colored_led.asm b/boot_code/colored_led.asm
index 0b41e93..e453bd0 100644
--- a/boot_code/colored_led.asm
+++ b/boot_code/colored_led.asm
@@ -1,6 +1,4 @@
-INCLUDE dos_layer.asm
-
-.org 0x100
+.org 0xE000
mov sp,#STACK
MAIN_LOOP:
@@ -19,13 +17,14 @@ out byte #0xB0
MOV SI,#RESERVED
MOV DI,#RESERVED
MOV AL,#0x68 ; 'h'
-STOSB
-MOV AL,#0x00
-MOV AL,[SI]
+#STOSB
+#MOV AL,#0x00
+#MOV AL,[SI]
-MOV AH,#0x02
-MOV DL,AL
-INT #0x21
+#MOV AH,#0x02
+#MOV DL,AL
+#INT #0x21
+out byte #0xA5
MOV AL,#0x65
out byte #0xA5
@@ -49,13 +48,18 @@ JNZ DELAY21
MOV AL,#0x00
out byte #0xB0
-MOV AX,#0x0100
+MOV AX,#0xE000
JMP AX
RESERVED: DB 0x48 ; 'H'
-.BLKB 200
+.BLKB 100
STACK:
+#INCLUDE dos_layer.asm
+
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xE000
JMP AX
+
+.ORG 0xFFFF
+DB 0x00 ;Make sure a full 64KiB image
diff --git a/boot_code/dos_layer.asm b/boot_code/dos_layer.asm
index f27ef3b..853c5ec 100644
--- a/boot_code/dos_layer.asm
+++ b/boot_code/dos_layer.asm
@@ -1,7 +1,3 @@
-.ORG 0x84 ; INT 21
-DW 0xFFFF ; Code Segment
-DW PRINT_INT_HANDLE ; Program Counter
-
PRINT_INT_HANDLE:
push AX
CMP AH,#0x02
@@ -14,3 +10,15 @@ MOV AL,DL
out byte #0xA5
POP AX
iret
+
+INIT_INT_VECT_TABLE:
+push AX
+push DI
+MOV DI,#0x0084
+MOV AX,#0xFFFF
+STOSW
+MOV AX,#PRINT_INT_HANDLE
+STOSW
+POP DI
+POP AX
+RET
diff --git a/boot_code/fibonacci.asm b/boot_code/fibonacci.asm
index 8c879e2..f24dc01 100644
--- a/boot_code/fibonacci.asm
+++ b/boot_code/fibonacci.asm
@@ -1,8 +1,8 @@
-INCLUDE dos_layer.asm
-org 0x100
+org 0xF000
mov sp,#STACK
+call INIT_INT_VECT_TABLE
MOV AX,#0x1
MOV BX,#0x1
@@ -26,6 +26,7 @@ MOV DL,#0x0a
INT #0x21
hlt
+INCLUDE dos_layer.asm
.BLKB 200
@@ -33,6 +34,6 @@ STACK:
INCLUDE helpers.asm
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xF000
JMP AX
diff --git a/boot_code/gnome_sort.asm b/boot_code/gnome_sort.asm
index 1918a01..c66690c 100644
--- a/boot_code/gnome_sort.asm
+++ b/boot_code/gnome_sort.asm
@@ -1,8 +1,8 @@
-INCLUDE dos_layer.asm
-.org 0x100
+.org 0xF000
mov sp,#STACK
MOV SI,#DATA
+call INIT_INT_VECT_TABLE
GNOME_SORT:
CMP SI,#DATA+23
@@ -37,6 +37,7 @@ MOV DL,#0x0a
INT #0x21
hlt
+INCLUDE dos_layer.asm
DATA: DB 0x51, 0x17, 0x37, 0x5d, 0x06, 0x3f, 0x51, 0x8b
DB 0xa5, 0x33, 0x54, 0xdf, 0xae, 0xee, 0x3a, 0x18
@@ -48,6 +49,8 @@ STACK:
INCLUDE helpers.asm
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xF000
JMP AX
+.ORG 0xFFFF
+DB 0x00 ;Make sure a full 64KiB image
diff --git a/boot_code/pipeline_ideal.asm b/boot_code/pipeline_ideal.asm
index 6ef3a20..2acf319 100644
--- a/boot_code/pipeline_ideal.asm
+++ b/boot_code/pipeline_ideal.asm
@@ -1,4 +1,4 @@
-org 0x100
+org 0xF000
inc ax
inc bx
inc ax
@@ -102,5 +102,5 @@ inc bx
hlt
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xF000
JMP AX
diff --git a/common.mk b/common.mk
index 01fc0a1..a445d2e 100644
--- a/common.mk
+++ b/common.mk
@@ -39,7 +39,9 @@ ifeq "${QUIET}" "1"
QUIET_DFU_SUFFIX = @echo ' DFU-SUFFIX '$@;
QUIET_DFU_UTIL = @echo ' DFU-UTIL '$<;
- QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
+ QUIET_DOWNLOAD = @echo ' DOWNLOAD '$@;
+
+ QUIET_CLEAN = @echo ' CLEAN '$1;
QUIET_VERILATOR_RUN = @printf ' %s %s\n' $1 $2;
Q = @
MAKEOPTS=--no-print-directory
@@ -54,6 +56,13 @@ run: $(subst .txt,.run,${BOOT_CODE})
wave: $(subst .txt,.wave,${BOOT_CODE})
disas: $(subst .txt,.disas,${BOOT_CODE})
+# Assembling code
+%.stxt: %.bin
+ ${Q}dd if=/dev/zero bs=1 count=2048 of="$(subst .bin,.stage,$<)" status=none
+ ${Q}dd if="$<" bs=1 skip=63488 of="$(subst .bin,.stage,$<)" conv=notrunc,nocreat status=none
+ ${Q}xxd -ps -c 2 "$(subst .bin,.stage,$<)" > "$@"
+ ${Q}rm "$(subst .bin,.stage,$<)"
+
# Assembling code
%.txt:%.bin
${Q}dd if=/dev/zero bs=1 count=65536 of="$(subst .bin,.stage,$<)" status=none
@@ -61,6 +70,7 @@ disas: $(subst .txt,.disas,${BOOT_CODE})
${Q}xxd -ps -c 2 "$(subst .bin,.stage,$<)" > "$@"
${Q}rm "$(subst .bin,.stage,$<)"
+
ifeq "${NO_ASM}" "0"
%.bin:%.asm
${QUIET_AS}
diff --git a/system/Makefile b/system/Makefile
index 495b679..25a9a71 100644
--- a/system/Makefile
+++ b/system/Makefile
@@ -46,14 +46,14 @@ VERILATOR_OPTS += -x-assign fast --x-initial fast
# COMPILING
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
${QUIET_IVERILOG}
- ${Q}iverilog -g2012 -DBUILTIN_RAM=32768 -D CALCULATE_IPC -D OUTPUT_JSON_STATISTICS -o "$@" ${TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
+ ${Q}iverilog -g2012 -D CALCULATE_IPC -D OUTPUT_JSON_STATISTICS -o "$@" ${TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
${VERILATOR_BIN}: ${VERILATOR_BIN}.mk
${Q}make ${MAKEOPTS} OPT_FAST="-O2 -march=native -mtune=native" -C obj_dir -f ../verilator_makefile Vsystem
${VERILATOR_BIN}.mk: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
${QUIET_VERILATOR}
- ${Q}verilator -DBUILTIN_RAM=32768 -UNOT_FULL -DCALCULATE_IPC -DOUTPUT_JSON_STATISTICS ${VERILATOR_OPTS} $^
+ ${Q}verilator -DCALCULATE_IPC -DOUTPUT_JSON_STATISTICS ${VERILATOR_OPTS} $^
include fpga_config/${FPGA_BOARD}/config.mk
@@ -69,22 +69,23 @@ endif
ECP5_TARGETS=synth_ecp5.json synth_ecp5_out.config synth_ecp5.bit synth_ecp5.dfu synth_pnr_report.json
ECP5_TARGETS+=abc.history # created from yosys
-EXTRA_SYNTHESIS_SOURCES=peripherals/I2C_driver.v peripherals/ascii_to_HD44780_driver.v peripherals/pcf8574_for_HD44780.v
+EXTRA_SYNTHESIS_SOURCES=peripherals/I2C_driver.v peripherals/ascii_to_HD44780_driver.v peripherals/pcf8574_for_HD44780.v peripherals/Wishbone_IO_driver.v peripherals/Wishbone_memory_driver.v
+EXTERNAL_IP_SOURCES=external_ip/litedram_core_ecp5_phy.v
simplified_ucode.txt:ucode.txt
${Q}tr 'x' '0' < $^ | sed 's@//.*@@' | grep ^@ |sort | sed 's/.* .//;s/ $$//' | tr -d _ > $@
#TODO: we are relying on yosys to trim the input program txt file and hope its enough for the whole program...
-synth_ecp5.json: ${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ${INCLUDES} ../boot_code/brainfuck_compiled.txt simplified_ucode.txt
+synth_ecp5.json: ${SOURCES} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ${EXTERNAL_IP_SOURCES} ${INCLUDES} ../boot_code/bios.stxt simplified_ucode.txt
${QUIET_YOSYS}
- ${Q} yosys -q -D BUILTIN_RAM=2048 -D NOT_FULL -p 'read -sv '"${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ; synth_ecp5 -json $@ -abc9 -top fpga_top"
+ ${Q} yosys -q -p 'read_verilog -defer -noautowire -sv '"${SOURCES} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ${EXTERNAL_IP_SOURCES}; attrmap -tocase keep -imap keep="true" keep=1 -imap keep="false" keep=0 -remove keep=0; synth_ecp5 -json $@ -abc9 -top fpga_top"
RANDOM :::= $(shell seq 1 200|sort -R|head -n1)
synth_ecp5_out.config:synth_ecp5.json
${QUIET_NEXTPNR}
${Q}printf '\e[1;30mNotice: nextpnr rng seed is : %s\e[0m\n' "${RANDOM}"
- ${Q} nextpnr-ecp5 --seed ${RANDOM} --Werror -q --json $< --textcfg $@.1 ${NEXTPNR_ECP5_DEV} --package ${ECP5_PACKAGE} --lpf fpga_config/${FPGA_BOARD}/pin_constraint.pcf --report=synth_pnr_report.json
+ ${Q} nextpnr-ecp5 --threads 5 --timing-allow-fail --seed ${RANDOM} --Werror -q --json $< --textcfg $@.1 ${NEXTPNR_ECP5_DEV} --package ${ECP5_PACKAGE} --speed 8 --lpf fpga_config/${FPGA_BOARD}/pin_constraint.pcf --report=synth_pnr_report.json
${Q}../tools/parse_nextpnr_stats.sh --brief synth_pnr_report.json
${Q}mv "$@.1" "$@"
@@ -103,8 +104,15 @@ upload_orangecrab:synth_ecp5.dfu
${QUIET_DFU_UTIL}
${Q}stdbuf -o0 dfu-util --download "$<" |stdbuf -o0 tr '\n' '\a' | stdbuf -o0 tr '\r' '\n' | grep Download --line-buffered | stdbuf -o0 tr '\n' '\r' |stdbuf -o0 tr '\a' '\n'
+NEXTPNR_SEED=186
+
nextpnr-gui: synth_ecp5.json
- ${Q} nextpnr-ecp5 --json $< ${NEXTPNR_ECP5_DEV} --package ${ECP5_PACKAGE} --lpf fpga_config/${FPGA_BOARD}/pin_constraint.pcf --gui
+ ${QUIET_NEXTPNR}
+ ${Q} nextpnr-ecp5 --seed ${NEXTPNR_SEED} --json $< ${NEXTPNR_ECP5_DEV} --package ${ECP5_PACKAGE} --speed 8 --lpf fpga_config/${FPGA_BOARD}/pin_constraint.pcf --gui
+
+external_ip/litedram_core_ecp5_phy.v:
+ ${QUIET_DOWNLOAD}
+ ${Q}../tools/gen_litedram.sh "$@"
upload: upload_orangecrab
diff --git a/system/biu.v b/system/biu.v
index 8715237..838968d 100644
--- a/system/biu.v
+++ b/system/biu.v
@@ -46,6 +46,7 @@ module BIU (
/**************** OUTSIDE WORLD ****************/
/* */ ,output wire [19:0] external_address_bus
/* */ ,input [15:0] external_data_bus_read,output [15:0] external_data_bus_write,output reg read, output reg write,output reg BHE,output reg IOMEM
+ /* */ ,input wait_state
/**************** OUTPUT TO DE ****************/
/* */ ,output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION
@@ -105,7 +106,7 @@ always @(posedge clock) begin
FIFO_end <= `L1_CACHE_SIZE'b0;
end else if ( jump_req ) begin
FIFO_start <= FIFO_end ;
- INSTRUCTION_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
+ INSTRUCTION_ADDRESS <= { 4'hF , ADDRESS_INPUT };
INSTRUCTION_LOCATION <= ADDRESS_INPUT;
func <= 1;
if (biu_state==`BIU_READ)
@@ -115,6 +116,8 @@ always @(posedge clock) begin
FIFO_start <= FIFO_start + {{`L1_CACHE_SIZE-3{1'b0}},Isize};
/* verilator lint_on BLKSEQ */
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {13'd0,Isize};
+ end else if (wait_state==1)begin
+ // nothing...
end else begin
case(biu_state)
`BIU_HALT: begin
@@ -122,14 +125,14 @@ always @(posedge clock) begin
`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_ADDRESS <= { 4'hF , ADDRESS_INPUT };
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) ;
- INSTRUCTION_ADDRESS <= {4'b0,INSTRUCTION_LOCATION} ;
+ INSTRUCTION_ADDRESS <= {4'hF,INSTRUCTION_LOCATION} ;
FIFO_end<=FIFO_start;
end else if ( read_request ) begin
func<=0;
- DATA_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
+ DATA_ADDRESS <= { 4'hF , ADDRESS_INPUT };
IOMEM <= MEM_OR_IO;
read <= 0;
BHE <= 0;
@@ -275,7 +278,7 @@ always @(posedge clock) begin
FIFO_end <= `L1_CACHE_SIZE'b0;
/* verilator lint_on BLKSEQ */
biu_state <= `BIU_NEXT_ACTION;
- INSTRUCTION_ADDRESS <= 20'h0FFF0;
+ INSTRUCTION_ADDRESS <= 20'hFFFF0;
INSTRUCTION_LOCATION <= 16'hFFF0;
VALID_DATA <= 0;
sane<=1;
diff --git a/system/boot_code.asm b/system/boot_code.asm
index 1cfea54..d7fc602 100644
--- a/system/boot_code.asm
+++ b/system/boot_code.asm
@@ -1,8 +1,4 @@
-.ORG 0x84 ; INT 21
-DW 0xFFFF ; Code Segment
-DW PRINT_INT_HANDLE ; Program Counter
-
-.ORG 0x0100
+.ORG 0xFF00
start:
MOV SP,#STACK
MOV AX,#0x0000
@@ -26,20 +22,14 @@ dec cx
cmp CX,#0x00
MOV CH,#0x9A
inw #0x20
-CMP AL,#0xCD
+CMP AX,#0xABCD
jz WAZZ
mov al,#'0
out byte #0xA5
hlt
WAZZ:
-CMP AH,#0xAB
-jz WAZZ2
-mov al,#'0
-out byte #0xA5
-hlt
-WAZZ2:
mov al,#'1
-outb #0xA5
+out byte #0xA5
hlt
TEST_:
ADD AX,#0xDEAD
@@ -57,5 +47,5 @@ iret
STACK:
.ORG 0xFFF0
-MOV AX,#0x0100
+MOV AX,#0xFF00
JMP AX
diff --git a/system/config.v b/system/config.v
index 3e8e74f..a475d49 100644
--- a/system/config.v
+++ b/system/config.v
@@ -46,15 +46,6 @@
* . : ... */
`define L1_CACHE_SIZE 4
-//// These are usually set at build time
-//
-// /* This is the "virtual" synthesised ram, so for example on an FPGA
-// * This would be made inside the fabric of the fpga. */
-// `define BUILTIN_RAM 512
-// ////// ATTENTION: PLEASE IF BUILTIN_RAM DOESN'T COVER THE ENTIRE (CURRENTLY)
-// // 16 BIT RANGE, I.E. ISN'T 32768, PLEASE SET THE FOLLOWING FLAG
-// `define NOT_FULL
-
/********** Internal **********/
`ifdef SYNTHESIS
diff --git a/system/fpga_config/OrangeCrab_r0.2.1/fpga_top.v b/system/fpga_config/OrangeCrab_r0.2.1/fpga_top.v
index 1b4afdc..88db6cb 100644
--- a/system/fpga_config/OrangeCrab_r0.2.1/fpga_top.v
+++ b/system/fpga_config/OrangeCrab_r0.2.1/fpga_top.v
@@ -18,10 +18,12 @@
along with this program. If not, see . */
`include "error_header.v"
+`ifdef OUTPUT_JSON_STATISTICS
+`include "config.v"
+`endif
module fpga_top(
input clk48,
-
input user_button,
// output reset_n,
@@ -29,23 +31,68 @@ module fpga_top(
output rgb_led0_g,
output rgb_led0_b,
+ output wire [15:0] ddram_a, // [15:13] are unused in litex as well, they just also route them through a trellis block
+ output wire [2:0] ddram_ba,
+ output wire ddram_cas_n,
+ output wire ddram_cke,
+ output wire ddram_clk_p,
+ output wire ddram_cs_n,
+ output wire [1:0] ddram_dm,
+ input wire [15:0] ddram_dq,
+ input wire [1:0] ddram_dqs_p,
+ output wire [1:0] ddram_gnd,
+ output wire ddram_odt,
+ output wire ddram_ras_n,
+ output wire ddram_reset_n,
+ output wire [5:0] ddram_vccio,
+ output wire ddram_we_n,
+
inout gpio_0,/*sda*/
output gpio_1 /*scl*/
);
+assign ddram_a[15:13] = 3'b0;
+assign ddram_vccio = 6'd63;
+assign ddram_gnd = 2'd0;
+
wire HALT;
wire [`ERROR_BITS-1:0]ERROR;
wire [19:0] address_bus;
wire [15:0] data_bus_read,data_bus_write;
wire rd,wr,BHE,IOMEM;
-wire CPU_SPEED=clk48;
-system system(
- /* MISC */ CPU_SPEED,reset
- /* MEMORY / IO */ ,address_bus,data_bus_read,data_bus_write,BHE,rd,wr,IOMEM,HALT,ERROR
+wire CPU_SPEED;
+
+processor p(
+ .clock(CPU_SPEED),
+ .reset(reset),
+ .HALT(HALT),
+ .ERROR(ERROR),
+ .external_address_bus(address_bus),
+ .external_data_bus_read(data_bus_read),
+ .external_data_bus_write(data_bus_write),
+ .wait_state(wait_state),
+ .read(rd),
+ .write(wr),
+ .BHE(BHE),
+ .IOMEM(IOMEM)
+`ifdef CALCULATE_IPC
+ /* STATISTICS */ ,.new_instruction(new_instruction)
+`endif
+`ifdef OUTPUT_JSON_STATISTICS
+ /* */ ,.L1_SIZE_STAT(L1_SIZE_STAT), .VALID_INSTRUCTION_STAT(VALID_INSTRUCTION_STAT), .jump_req_debug(jump_req_debug)
+`endif
);
+`ifdef CALCULATE_IPC
+wire new_instruction;
+`endif
+`ifdef OUTPUT_JSON_STATISTICS
+wire [`L1_CACHE_SIZE-1:0]L1_SIZE_STAT;
+wire VALID_INSTRUCTION_STAT;
+wire jump_req_debug;
+`endif
reg [2:0]rgb_led_color;
assign rgb_led0_r=rgb_led_color[0];
assign rgb_led0_g=rgb_led_color[1];
@@ -80,7 +127,7 @@ reg [1:0] state=0;
always @(posedge counter[15]) begin
if(user_button==0)
- state=2'b00;
+ state<=2'b00;
case (state)
2'b00:begin
reset<=0;
@@ -95,7 +142,6 @@ always @(posedge counter[15]) begin
endcase
end
-
//------------------------------------------//
// Cache to allow the slow display to have a
// chance to keep up with the relentless CPU
@@ -135,6 +181,189 @@ end
wire I2C_SPEED=counter[7];
+
+wire [15:0]boot_rom_data_bus_read;
+wire [15:0]boot_rom_data_bus_write;
+
+assign boot_rom_data_bus_write=data_bus_write;
+
+wire boot_rom_cs_n;
+
+doublemem #( .RAM_SIZE_IN_BYTES(2048) ) boot_rom
+ ( address_bus[10:0],boot_rom_data_bus_read,boot_rom_data_bus_write,rd,wr,BHE,boot_rom_cs_n,CPU_SPEED );
+
+/// Memory Map
+
+assign data_bus_read = ( IOMEM == 1 ) ? data_bus_read_IO : data_bus_read_MEM ;
+wire [15:0] data_bus_read_IO = ( address_bus[7:1] == 7'h10 ) ? LITEDRAM_STATUS_REGISTER : Wishbone_driver_data_bus_read;
+
+
+assign boot_rom_cs_n = !((IOMEM==0)&&(address_bus[15:12]==4'hF));
+
+wire [15:0] data_bus_read_MEM = (address_bus[15:12]==4'hF)?boot_rom_data_bus_read:data_bus_read_DDR3;
+
+wire DDR3_ram_cs = (IOMEM==0)&&(address_bus[15:12]!=4'hF);
+//
+// 0x20 | DDR STATUS BYTE1 |
+// 0x21 | DDR STATUS BYTE1 |
+// | |
+// - | -- |
+// | |
+// 0x30 | WISHBONE |
+// .. | .. |
+// 0x3F | WISHBONE |
+//
+assign wishbone_cs=!((IOMEM==1)&&(address_bus[7:4] == 4'h4));
+
+/// DDR3 Controller
+
+wire ddr3_init_done,ddr3_init_error,ddr3_pll_locked;
+
+wire [31:0] ddr3_read_data;
+wire [31:0] ddr3_write_data;
+
+reg [15:0]DDR3_data_bus_read;
+
+assign ddr3_write_data={16'd0,data_bus_write};
+
+wire [15:0]Wishbone_driver_data_bus_read;
+wire [15:0]Wishbone_driver_data_bus_write=data_bus_write;
+
+wire wishbone_cs;
+
+Wishbone_IO_driver Wishbone_IO_driver(
+ ///// GENERAL //////
+ .clock(CPU_SPEED),
+ .reset_n(reset),
+
+ ////// CPU INTERFACE ///////
+ .address(address_bus[3:1]),
+ .data_bus_in(Wishbone_driver_data_bus_write),
+ .data_bus_out(Wishbone_driver_data_bus_read),
+ .read_n(rd),
+ .write_n(wr),
+ .chip_select_n(wishbone_cs),
+
+ ////// WISHBONE INTERFACE /////
+ .wb_ctrl_ack(wb_ctrl_ack),
+ .wb_ctrl_adr(wb_ctrl_adr),
+ .wb_ctrl_cyc(wb_ctrl_cyc),
+ .wb_ctrl_err(wb_ctrl_err),
+ .wb_ctrl_sel(wb_ctrl_sel),
+ .wb_ctrl_stb(wb_ctrl_stb),
+ .wb_ctrl_we(wb_ctrl_we),
+ .wb_ctrl_bte(wb_ctrl_bte),
+ .wb_ctrl_cti(wb_ctrl_cti),
+ .wb_ctrl_dat_r(wb_ctrl_dat_r),
+ .wb_ctrl_dat_w(wb_ctrl_dat_w)
+);
+
+
+wire [15:0] LITEDRAM_STATUS_REGISTER = { 13'd0, ddr3_pll_locked ,ddr3_init_error, ddr3_init_done };
+wire [15:0] data_bus_read_DDR3;
+
+Wishbone_memory_driver Wishbone_memory_driver(
+ ///// GENERAL //////
+ .clock(CPU_SPEED),
+ .reset_n(reset),
+
+ ////// CPU INTERFACE ///////
+ .address(address_bus),
+ .data_bus_in(data_bus_write),
+ .data_bus_out(data_bus_read_DDR3),
+ .wait_state(wait_state),
+ .read_n(rd),
+ .write_n(wr),
+ .chip_select_n(DDR3_ram_cs&&ddr3_init_done),
+
+ ////// WISHBONE INTERFACE /////
+ .wb_mem_ack(wb_mem_ack),
+ .wb_mem_adr(wb_mem_adr),
+ .wb_mem_cyc(wb_mem_cyc),
+ .wb_mem_err(wb_mem_err),
+ .wb_mem_sel(wb_mem_sel),
+ .wb_mem_stb(wb_mem_stb),
+ .wb_mem_we(wb_mem_we),
+ .wb_mem_data_r(wb_mem_data_r),
+ .wb_mem_data_w(wb_mem_data_w)
+);
+
+wire wait_state;
+
+wire wb_ctrl_ack;
+wire [29:0] wb_ctrl_adr;
+wire [1:0] wb_ctrl_bte;
+wire [2:0] wb_ctrl_cti;
+wire wb_ctrl_cyc;
+wire [31:0] wb_ctrl_dat_r;
+wire [31:0] wb_ctrl_dat_w;
+wire wb_ctrl_err;
+wire [3:0] wb_ctrl_sel;
+wire wb_ctrl_stb;
+wire wb_ctrl_we;
+
+wire wb_mem_ack;
+wire [24:0] wb_mem_adr;
+wire wb_mem_cyc;
+wire [31:0] wb_mem_data_r;
+wire [31:0] wb_mem_data_w;
+wire wb_mem_err;
+wire [3:0] wb_mem_sel;
+wire wb_mem_stb;
+wire wb_mem_we;
+
+litedram_core DDR3_RAM_DRIVER(
+ ////// GENERAL ///////
+ .clk(clk48),
+ .user_clk(CPU_SPEED),
+ .rst(!reset),
+
+ ////// DDR3 INTERFACE //////
+ .ddram_a(ddram_a[12:0]), //also ignored on the litedram core
+ .ddram_ba(ddram_ba),
+ .ddram_cas_n(ddram_cas_n),
+ .ddram_cke(ddram_cke),
+ .ddram_clk_n(1'b0), // goes nowhere ...
+ .ddram_clk_p(ddram_clk_p),
+ .ddram_cs_n(ddram_cs_n),
+ .ddram_dm(ddram_dm),
+ .ddram_dq(ddram_dq),
+ .ddram_dqs_n(2'b00), // goes nowhere ...
+ .ddram_dqs_p(ddram_dqs_p),
+ .ddram_odt(ddram_odt),
+ .ddram_ras_n(ddram_ras_n),
+ .ddram_reset_n(ddram_reset_n),
+ .ddram_we_n(ddram_we_n),
+
+ /////// SYSTEM MEMORY INTERFACE ////////////////
+ .init_done(ddr3_init_done),
+ .init_error(ddr3_init_error),
+ .user_port_wishbone_0_ack(wb_mem_ack),
+ .user_port_wishbone_0_adr(wb_mem_adr),
+ .user_port_wishbone_0_cyc(wb_mem_cyc),
+ .user_port_wishbone_0_dat_r(wb_mem_data_r),
+ .user_port_wishbone_0_dat_w(wb_mem_data_w),
+ .user_port_wishbone_0_err(wb_mem_err),
+ .user_port_wishbone_0_sel(wb_mem_sel),
+ .user_port_wishbone_0_stb(wb_mem_stb),
+ .user_port_wishbone_0_we(wb_mem_we),
+ .pll_locked(ddr3_pll_locked),
+ //output wire user_rst,
+
+ /////// WISHBONE CONTROL INTERFACE ///////////
+ .wb_ctrl_ack(wb_ctrl_ack),
+ .wb_ctrl_adr(wb_ctrl_adr),
+ .wb_ctrl_cyc(wb_ctrl_cyc),
+ .wb_ctrl_err(wb_ctrl_err),
+ .wb_ctrl_sel(wb_ctrl_sel),
+ .wb_ctrl_stb(wb_ctrl_stb),
+ .wb_ctrl_we(wb_ctrl_we),
+ .wb_ctrl_bte(wb_ctrl_bte),
+ .wb_ctrl_cti(wb_ctrl_cti),
+ .wb_ctrl_dat_r(wb_ctrl_dat_r),
+ .wb_ctrl_dat_w(wb_ctrl_dat_w)
+);
+
// Display driver
wire ascii_data_ready;
diff --git a/system/memory.v b/system/memory.v
index cabbbef..b655a80 100644
--- a/system/memory.v
+++ b/system/memory.v
@@ -19,10 +19,24 @@
/* This warning is because we don't use the full address bus. */
/* verilator lint_off UNUSEDSIGNAL */
-module doublemem(input [19:0] address,output [15:0] cpu_read_data ,input [15:0] cpu_write_data,input rd,input wr,input BHE,input cs,input clock);
+module doublemem
+ #(
+ parameter RAM_SIZE_IN_BYTES,
+ parameter ADDRESS_WIDTH=$clog2(RAM_SIZE_IN_BYTES)
+ )
+ ( input [ ADDRESS_WIDTH-1 : 0 ] address,
+ output [15:0] cpu_read_data,
+ input [15:0] cpu_write_data,
+ input rd,
+ input wr,
+ input BHE,
+ input cs,
+ input clock
+ );
/* verilator lint_on UNUSEDSIGNAL */
-reg [15:0] memory [0:`BUILTIN_RAM];
+reg [15:0] memory [0:(RAM_SIZE_IN_BYTES/2)-1];
+
initial begin
`ifndef YOSYS
@@ -31,39 +45,26 @@ initial begin
$display("No boot code specified. Please add +BOOT_CODE= to your vvp args");
$finish;
end
- $readmemh(boot_code, memory,0,`BUILTIN_RAM-1);
+ $readmemh(boot_code, memory,0,32767);
`else
//TODO: don't have it hard coded
- $readmemh("../boot_code/brainfuck_compiled.txt", memory,0,`BUILTIN_RAM-1);
-`endif
-
-`ifdef NOT_FULL
- jump_mem[0]=16'hB800;
- jump_mem[1]=16'h01ff;
- jump_mem[2]=16'hE000;
+ $readmemh("../boot_code/bios.stxt", memory,0,(RAM_SIZE_IN_BYTES/2)-1); // 2KiB
`endif
end
-`ifndef NOT_FULL
-assign cpu_read_data[7:0] = !address[0:0] & !rd & !cs ? memory[address[16:1]][15:8] : 8'hz;
-assign cpu_read_data[15:8] = !BHE & !rd & !cs ? memory[address[16:1]][7:0] : 8'hz;
-`else
-reg[15:0] jump_mem [0:4'h7];
+assign cpu_read_data[7:0] = !address[0:0] & !rd & !cs ? memory[address[ADDRESS_WIDTH-1:1]][15:8] : 8'hz;
-assign cpu_read_data[7:0] = !address[0:0] & !rd & !cs ? (address[15:4]==12'b111111111111 ? jump_mem[address[3:1]][15:8]:memory[address[16:1]][15:8]) : 8'hz;
+assign cpu_read_data[15:8] = !BHE & !rd & !cs ? memory[address[ADDRESS_WIDTH-1:1]][ 7:0] : 8'hz;
-assign cpu_read_data[15:8] = !BHE & !rd & !cs ? (address[15:4]==12'b111111111111 ? jump_mem[address[3:1]][7:0]:memory[address[16:1]][7:0]) : 8'hz;
-
-`endif
always @(posedge clock) begin
if( cs == 0 && wr == 0) begin
if(BHE==0)
- memory[address[16:1]][7:0]<=cpu_write_data[15:8];
+ memory[address[ADDRESS_WIDTH-1:1]][7:0]<=cpu_write_data[15:8];
if(address[0]==0)
- memory[address[16:1]][15:8]<=cpu_write_data[7:0];
+ memory[address[ADDRESS_WIDTH-1:1]][15:8]<=cpu_write_data[7:0];
end
end
diff --git a/system/peripherals/Wishbone_IO_driver.v b/system/peripherals/Wishbone_IO_driver.v
new file mode 100644
index 0000000..42722ee
--- /dev/null
+++ b/system/peripherals/Wishbone_IO_driver.v
@@ -0,0 +1,127 @@
+/* Wishbone_driver.v - Implements a classic wishbone master
+
+ 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 . */
+
+module Wishbone_IO_driver (
+ input wire clock,
+ input wire reset_n,
+
+ input wire [2:0] address,
+ input wire [15:0] data_bus_in,
+ output reg [15:0] data_bus_out,
+ input read_n,
+ input write_n,
+ input chip_select_n,
+
+ input wire wb_ctrl_ack,
+ output wire [29:0] wb_ctrl_adr,
+ output wire [1:0] wb_ctrl_bte,
+ output wire [2:0] wb_ctrl_cti,
+ output wire wb_ctrl_cyc,
+ input wire [31:0] wb_ctrl_dat_r,
+ output wire [31:0] wb_ctrl_dat_w,
+ input wire wb_ctrl_err,
+ output wire [3:0] wb_ctrl_sel,
+ output wire wb_ctrl_stb,
+ output wire wb_ctrl_we
+);
+
+reg [13:0]WISHBONE_ADDR=14'd0;
+reg WISHBONE_ACTIVE_CYCLE=1'b0;
+wire WISHBONE_ERROR_IN;
+reg [3:0]WISHBONE_SELECT=4'd0;
+reg WISHBONE_VALID_TRANSFER=1'b0;
+reg WISHBONE_WRITE=1'b1;
+wire WISHBONE_ACK_IN;
+reg [31:0]WISHBONE_DATA_READ=32'd0;
+wire [31:0]WISHBONE_DATA_WRITE;
+
+assign WISHBONE_ACK_IN=wb_ctrl_ack;
+assign wb_ctrl_adr={16'd0,WISHBONE_ADDR};
+assign WISHBONE_ERROR_IN=wb_ctrl_err;
+assign wb_ctrl_sel=WISHBONE_SELECT;
+assign wb_ctrl_stb=WISHBONE_VALID_TRANSFER;
+assign wb_ctrl_cyc=WISHBONE_ACTIVE_CYCLE;
+assign wb_ctrl_we=WISHBONE_WRITE;
+assign wb_ctrl_bte=2'b00; // Burst Type Extension 00:Linear burst
+assign wb_ctrl_cti=3'b000; // Cycle Type Idenfier 000:Classic cycle
+assign WISHBONE_DATA_WRITE=wb_ctrl_dat_r;
+assign wb_ctrl_dat_w=WISHBONE_DATA_READ;
+
+reg [31:0]WISHBONE_READ_BUFFER;
+
+reg [1:0]just_transacted;
+
+reg [1:0]WISHBONE_STATUS;
+
+wire CYCLE_END=(WISHBONE_ACK_IN==1'b1);//||WISHBONE_ERROR_IN==1'b1);
+
+always @( posedge clock )begin
+ if(reset_n==0)begin
+ just_transacted<=2'b0;
+ end
+ if(just_transacted==2'd1&&CYCLE_END==1'b1)begin
+ WISHBONE_READ_BUFFER<=WISHBONE_DATA_WRITE;
+ end
+ if(chip_select_n==0 && write_n==0 )begin
+ case (address)
+ 3'h0: WISHBONE_DATA_READ[15:0] <=data_bus_in;
+ 3'h1: WISHBONE_DATA_READ[31:16]<=data_bus_in;
+ 3'h2: WISHBONE_ADDR[13:0]<=data_bus_in[13:0];
+ 3'h3: begin end
+ default: begin end
+ endcase
+
+ case (address)
+ 3'h3: begin
+ WISHBONE_ACTIVE_CYCLE<=1;
+ WISHBONE_VALID_TRANSFER<=1;
+ WISHBONE_SELECT<=4'hF;
+ end
+ default: begin end
+ endcase
+ if(address==3'h3)begin
+ WISHBONE_WRITE<=1'b1;//data_bus_in[0:0];
+ if(data_bus_in[0:0]==1'b1)begin //write req
+ just_transacted<=2'd2;
+ end else begin
+ just_transacted<=2'd1;
+ end
+ end
+ end else if(just_transacted!=2'd0&&CYCLE_END==1'b1)begin // In the unlikely senario that the CPU wants to write without having checked for the previous write
+ WISHBONE_STATUS[0:0]<=WISHBONE_ACK_IN;
+ WISHBONE_STATUS[1:1]<=WISHBONE_ERROR_IN;
+ WISHBONE_ACTIVE_CYCLE<=0;
+ WISHBONE_VALID_TRANSFER<=0;
+ just_transacted<=2'b0;
+ end
+
+ if ( chip_select_n==0 && read_n==0 )begin
+ case (address)
+ /* verilator lint_off BLKSEQ */
+ /* Makes icarus verilog work as expected, not too sure if it helps real hardware yet*/
+ 3'h0: data_bus_out = WISHBONE_READ_BUFFER[15:0];
+ 3'h1: data_bus_out = WISHBONE_READ_BUFFER[31:16];
+ 3'h2: data_bus_out = {13'd0,WISHBONE_STATUS,just_transacted==2'd0||CYCLE_END==1'b1}; //1:NOT BUSY 0:BUSY
+ default: data_bus_out = 16'h0;
+ /* verilator lint_on BLKSEQ */
+ endcase
+ end
+end
+
+endmodule
diff --git a/system/peripherals/Wishbone_memory_driver.v b/system/peripherals/Wishbone_memory_driver.v
new file mode 100644
index 0000000..adb1f45
--- /dev/null
+++ b/system/peripherals/Wishbone_memory_driver.v
@@ -0,0 +1,149 @@
+/* Wishbone_driver.v - Implements a classic wishbone master that maps directly in memory space
+
+ 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 . */
+
+module Wishbone_memory_driver (
+ input wire clock,
+ input wire reset_n,
+
+ input wire [19:0] address,
+ input wire [15:0] data_bus_in,
+ output reg [15:0] data_bus_out,
+ output reg wait_state,
+ input read_n,
+ input write_n,
+ input chip_select_n,
+
+ input wire wb_mem_ack,
+ output wire [24:0] wb_mem_adr,
+ output wire wb_mem_cyc,
+/* verilator lint_off UNUSEDSIGNAL */
+// I don't yet use the upper word
+ input wire [31:0] wb_mem_data_r,
+/* verilator lint_on UNUSEDSIGNAL */
+ output wire [31:0] wb_mem_data_w,
+ input wire wb_mem_err,
+ output wire [3:0] wb_mem_sel,
+ output wire wb_mem_stb,
+ output wire wb_mem_we
+);
+
+reg WISHBONE_ACTIVE_CYCLE=1'b0;
+/* verilator lint_off UNUSEDSIGNAL */
+wire WISHBONE_ERROR_IN;
+/* verilator lint_on UNUSEDSIGNAL */
+reg [3:0]WISHBONE_SELECT=4'd0;
+reg WISHBONE_VALID_TRANSFER=1'b0;
+reg WISHBONE_WRITE=1'b1;
+wire WISHBONE_ACK_IN;
+reg [31:0]WISHBONE_DATA_READ=32'd0;
+wire [15:0]WISHBONE_DATA_WRITE;
+
+assign WISHBONE_ACK_IN=wb_mem_ack;
+assign wb_mem_adr={5'd0,address};
+assign WISHBONE_ERROR_IN=wb_mem_err;
+assign wb_mem_sel=WISHBONE_SELECT;
+assign wb_mem_stb=WISHBONE_VALID_TRANSFER;
+assign wb_mem_cyc=WISHBONE_ACTIVE_CYCLE;
+assign wb_mem_we=WISHBONE_WRITE;
+assign WISHBONE_DATA_WRITE=wb_mem_data_r[15:0];
+assign wb_mem_data_w=WISHBONE_DATA_READ;
+
+wire CYCLE_END=(WISHBONE_ACK_IN==1'b1);//||WISHBONE_ERROR_IN==1'b1);
+
+reg [3:0] state;
+
+always @(*) begin
+ wait_state=0;
+ if(reset_n==1) begin
+ case(state)
+ 4'd0:begin
+ if( chip_select_n && ((!read_n)||(!write_n)) )begin
+ wait_state=1;
+ end else begin
+ wait_state=0;
+ end
+ end
+ 4'd1:begin
+ wait_state=1;
+ end
+ 4'd2:begin
+ wait_state=1;
+ end
+ 4'd3:begin
+ wait_state=1;
+ end
+ 4'd4:begin
+ wait_state=0;
+ end
+ default:begin
+ end
+ endcase
+ end else begin
+ wait_state=0;
+ end
+end
+
+always @(posedge clock)begin
+ if(reset_n==0)
+ state<=0;
+ else begin
+ case(state)
+ 4'd0:begin
+ if( chip_select_n && ((!read_n)||(!write_n)) )begin
+ state<=4'd1;
+ end
+ end
+ 4'd1:begin
+ WISHBONE_ACTIVE_CYCLE<=1;
+ WISHBONE_VALID_TRANSFER<=1;
+ WISHBONE_SELECT<=4'hF;
+ WISHBONE_WRITE<=read_n;
+ if(read_n)begin
+ state<=4'd2;
+ WISHBONE_DATA_READ<={16'h0,data_bus_in};
+ end else
+ state<=4'd3;
+ end
+ 4'd2:begin
+ if(CYCLE_END==1'b1)begin
+ state<=4'd4;
+ WISHBONE_ACTIVE_CYCLE<=0;
+ WISHBONE_VALID_TRANSFER<=0;
+ end
+ end
+ 4'd3:begin
+ if(CYCLE_END==1'b1)begin
+ data_bus_out<=WISHBONE_DATA_WRITE[15:0];
+ state<=4'd4;
+ WISHBONE_ACTIVE_CYCLE<=0;
+ WISHBONE_VALID_TRANSFER<=0;
+ end
+ end
+ 4'd4:begin
+ if(read_n&&write_n)
+ state<=4'd0;
+ end
+ default:begin
+ state<=4'd0;
+ end
+ endcase
+ end
+end
+
+endmodule
diff --git a/system/processor.v b/system/processor.v
index 6918c5c..7f8ddfc 100644
--- a/system/processor.v
+++ b/system/processor.v
@@ -32,7 +32,7 @@
module processor (
/* MISC */ input clock, input reset, output wire HALT,output [`ERROR_BITS-1:0] ERROR
- /* MEMORY / IO */ ,output [19:0] external_address_bus, input [15:0] external_data_bus_read, output [15:0] external_data_bus_write,output read, output write,output BHE,output IOMEM
+ /* MEMORY / IO */ ,output [19:0] external_address_bus, input [15:0] external_data_bus_read, output [15:0] external_data_bus_write, input wait_state, output read, output write,output BHE,output IOMEM
`ifdef CALCULATE_IPC
/* STATISTICS */ ,output wire new_instruction
@@ -111,6 +111,7 @@ BIU BIU(
/**************** OUTSIDE WORLD ****************/
/* */ ,external_address_bus
/* */ ,external_data_bus_read,external_data_bus_write,read,write,BHE,IOMEM
+ /* */ ,wait_state
/**************** OUTPUT TO DE ****************/
/* */ ,IF2DE_INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION
diff --git a/system/system.v b/system/system.v
index 6e69924..ab64ccc 100644
--- a/system/system.v
+++ b/system/system.v
@@ -37,10 +37,11 @@ wire [15:0]data_bus_read_CPU,data_bus_write_CPU;
assign data_bus_read_CPU=(IOMEM==0)?data_bus_read_RAM:data_bus_IO;
assign data_bus_write=data_bus_write_CPU;
+wire wait_state=1'b0;
processor p(
/* MISC */ clock,reset,HALT,ERROR
- /* MEMORY / IO */ ,address_bus,data_bus_read_CPU,data_bus_write_CPU,rd,wr,BHE,IOMEM
+ /* MEMORY / IO */ ,address_bus,data_bus_read_CPU,data_bus_write_CPU,wait_state,rd,wr,BHE,IOMEM
`ifdef CALCULATE_IPC
/* STATISTICS */ ,new_instruction
`endif
@@ -51,7 +52,7 @@ processor p(
wire [15:0] data_bus_read_RAM;
-doublemem sysmem(address_bus,data_bus_read_RAM,data_bus_write_CPU,rd,wr,BHE,IOMEM,clock);
+doublemem #(.RAM_SIZE_IN_BYTES(65536)) sysmem(address_bus[15:0],data_bus_read_RAM,data_bus_write_CPU,rd,wr,BHE,IOMEM,clock);
`ifdef OUTPUT_JSON_STATISTICS
string stats_name,version,commit;
diff --git a/tools/gen_litedram.sh b/tools/gen_litedram.sh
new file mode 100755
index 0000000..4beec7a
--- /dev/null
+++ b/tools/gen_litedram.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+set -eu
+
+SOURCE_CODE_URL=https://github.com/enjoy-digital/litedram/archive/refs/tags/2023.08.tar.gz
+SOURCE_MD5_SUM=afc2208c08e60994d126c445574960da
+
+if [ "$#" = 0 ] || echo "$1" | grep '^-' > /dev/null
+then
+ echo This scripts generates a verilog file from the Migen project litedram
+ echo It is currently hardcoded for the ECP5 PHY
+ echo The provided file system/external_ip/litedram_core_ecp5_phy.v is the output of this program *BUT MODIFIED*
+ echo
+ echo Usage:
+ echo \ \ \ "$0" \