Compare commits
No commits in common. "master" and "v0.2.0" have entirely different histories.
9
.gitignore
vendored
9
.gitignore
vendored
@ -6,18 +6,9 @@
|
||||
*.swp
|
||||
*.memdump
|
||||
*.json
|
||||
*.dfu
|
||||
*.bit
|
||||
*.fst.hier
|
||||
abc.history
|
||||
boot_code/*.bin
|
||||
boot_code/*.txt
|
||||
boot_code/*.stxt
|
||||
system/boot_code.bin
|
||||
system/boot_code.txt
|
||||
system/obj_dir/
|
||||
system/simplified_ucode.txt
|
||||
system/build/
|
||||
tools/*svg
|
||||
system/external_ip/litedram_core_ecp5_phy.v
|
||||
system/external_ip/litedram_core_ecp5_phy_sim.v
|
||||
|
61
Makefile
61
Makefile
@ -1,6 +1,6 @@
|
||||
# This file is part of the 9086 project.
|
||||
#
|
||||
# Copyright (c) 2024 Efthymios Kritikos
|
||||
# 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
|
||||
@ -21,8 +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 boot_code/bios.stxt boot_code/i2c_bootloader.stxt
|
||||
PRINT_PATH_PREFIX=.
|
||||
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}
|
||||
|
||||
NO_ASM=1
|
||||
include common.mk
|
||||
@ -30,63 +29,21 @@ include common.mk
|
||||
.PHONY: ${BOOTABLES}
|
||||
.PHONY: ${subst .txt,.bin,${BOOTABLES}}
|
||||
|
||||
${BOOTABLES} ${subst .stxt,.bin,${subst .txt,.bin,${BOOTABLES}}} :
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=boot_code/ -C boot_code $(subst boot_code/,,$@)
|
||||
${BOOTABLES} ${subst .txt,.bin,${BOOTABLES}} :
|
||||
${Q}make ${MAKEOPTS} -C boot_code $(subst boot_code/,,$@)
|
||||
|
||||
boot_code/%.txt:
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=boot_code/ -C boot_code $(subst boot_code/,,$@)
|
||||
${Q}make ${MAKEOPTS} -C boot_code $(subst boot_code/,,$@)
|
||||
|
||||
.PHONY:${SYSTEM_VVP}
|
||||
${SYSTEM_VVP}:
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system system.vvp
|
||||
${Q}make ${MAKEOPTS} -C system system.vvp
|
||||
|
||||
.PHONY:${VERILATOR_BIN}
|
||||
${VERILATOR_BIN}:
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system obj_dir/Vsystem
|
||||
${Q}make ${MAKEOPTS} -C system obj_dir/Vsystem
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system clean
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=boot_code/ -C boot_code clean
|
||||
|
||||
.PHONY: mrproper
|
||||
mrproper: clean
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system mrproper
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=boot_code/ -C boot_code mrproper
|
||||
|
||||
.PHONY: upload_bitstream
|
||||
upload_bitstream: boot_code/i2c_bootloader.stxt
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system upload_bitstream
|
||||
|
||||
.PHONY: upload_bootrom
|
||||
upload_bootrom: boot_code/brainfuck_mandelbrot.bin
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system upload_bootrom
|
||||
|
||||
|
||||
.PHONY: fpga_sim
|
||||
fpga_sim: boot_code/i2c_bootloader.stxt
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system fpga_sim
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Simulation targets:'
|
||||
@echo ' - No target will start a simulation with the default'
|
||||
@echo ' program loaded to memory'
|
||||
@echo ' boot_code/[name].run - Start a simulation and load memory with the'
|
||||
@echo ' assembled code from boot_code/[name].asm'
|
||||
@echo ' boot_code/[name].wave - like the above but write trace file and start'
|
||||
@echo ' gtkwave with it'
|
||||
@echo ' boot_code/[name].disas - assemble and show the disassembly of the binary'
|
||||
@echo ''
|
||||
@echo 'Synthesis targets:'
|
||||
@echo ' upload_bitstream - Build a bitstream for the board selected in'
|
||||
@echo ' common.mk and upload it if possible'
|
||||
@echo ' upload_bootrom - Build the rom file and upload it to an I2C rom'
|
||||
@echo ' Currently only the MiniPro programmer is supported'
|
||||
@echo ' fpga_sim - Simulate the SoC that gets build for the configured'
|
||||
@echo ' fpga board'
|
||||
@echo ''
|
||||
@echo 'Cleaning targets:'
|
||||
@echo ' clean - Delete all non-source files generated by the build'
|
||||
@echo ' system'
|
||||
@echo ' mrproper - clean + delete downloaded external source IP files'
|
||||
${Q}make ${MAKEOPTS} -C system clean
|
||||
${Q}make ${MAKEOPTS} -C boot_code clean
|
||||
|
53
README.md
53
README.md
@ -13,64 +13,26 @@ A CPU that aims to be binary compatible with the 8086 ISA, focused on optimisati
|
||||
* [X] Is pipelined
|
||||
* [ ] Is Out of Order
|
||||
* [ ] Is superscalar
|
||||
* [X] Has been successfully synthesized
|
||||
* [ ] Has a comprehensive testing framework
|
||||
* [ ] Has been successfully synthesized
|
||||
|
||||
### Simulating it
|
||||
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).
|
||||
This list shows the software needed and the versions used during development :
|
||||
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 12.0 OR **(preferred)** Verilator : 5.018
|
||||
* Icarus Verilog : version 12.0 OR **(preferred)** Verilator : 5.016
|
||||
* bin86 : 0.16.21
|
||||
* GNU Make : 4.4.1
|
||||
* xxd : 2023-10-25
|
||||
* xxd : 2022-01-14
|
||||
* POSIX coreutils : GNU coreutils 9.4
|
||||
|
||||
After that you can run `make` on the top level directory and it should build everything and start the simulation
|
||||
|
||||
### Synthesis and bitstream creation for FPGAs
|
||||
You need to set FPGA\_BOARD in [./common.mk](./common.mk) to the name of a directory inside [./system/fpga\_config/](system/fpga_config/). You should also check inside your board directory for config.mk for further board-specific configuration options like the model of I2C boot rom (if any). Then you can run `make upload_bitstream` in the top level directory and it should create the bitstream and upload it to the fpga. Depending on the board you might need to run `make upload_bootrom` to upload the boot code to an I2C eeprom.
|
||||
|
||||
These are the currently supported FPGA boards:
|
||||
|
||||
* OrangeCrab r0.2.1
|
||||
|
||||
This list shows the software needed and the versions used during development :
|
||||
|
||||
* yosys : 0.37
|
||||
* bin86 : 0.16.21
|
||||
* GNU Make : 4.4.1
|
||||
* xxd : 2023-10-25
|
||||
* POSIX coreutils : GNU coreutils 9.4
|
||||
|
||||
Additionally, for ECP5 FPGAs:
|
||||
|
||||
* prjtrellis : 1.4 ( database commit 4dda149b9e4f1753ebc8b011ece2fe794be1281a )
|
||||
* nextpnr : 0.6
|
||||
|
||||
Additionally, for FPGAs using the [foboot](https://github.com/im-tomu/foboot) bootloader
|
||||
|
||||
* dfu-util : 0.11
|
||||
|
||||
Additionally, for boards that require an I2C eeprom to boot from
|
||||
|
||||
* minipro : 0.6 - ( git commit a227bce77d1b592785558e0af58ae2b0b97d4a23 )
|
||||
|
||||
Additionally, if you need a DRAM/DDR controller, the project supports litedram but all the dependencies
|
||||
needed to build it are downloaded automatically by the appropriate script.
|
||||
|
||||
### High level design overview
|
||||
|
||||
<img width="700" style=" margin: 10px 0px 10px 10px;" alt="9086 logo" src="readme_files/9086_overview.svg">
|
||||
|
||||
### License and Copyright
|
||||
All parts of this project and files in this repository are licensed under the GNU General Public License version 3 or later
|
||||
|
||||
Efthymios Kritikos is the copyright owner for all files except the following:
|
||||
|
||||
| File | Copyright owner | Original license |
|
||||
| :--------------------------------------------------------: | :-------------: | :--------------: |
|
||||
| system/fpga\_config/OrangeCrab\_r0.2.1/pin\_constraint.pcf | Greg Davill | MIT |
|
||||
### License
|
||||
All parts of this project are licensed under the GNU General Public License version 3 or later
|
||||
|
||||
### Version names
|
||||
The version name consist of three numbers:
|
||||
@ -80,4 +42,3 @@ The version name consist of three numbers:
|
||||
1. Patch level
|
||||
|
||||
For example v1.3.2 aims to support 80186 code, is on the fourth milestone and has 2 bug fixes since the milestone was reached.
|
||||
A "-dev" suffix denotes that the code is in the process to become that version, so in-between that and the previous.
|
||||
|
@ -1,286 +0,0 @@
|
||||
litedram_init:
|
||||
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,#0x0700
|
||||
MOV AX,#0xAAAA
|
||||
MOV [DI],AX
|
||||
MOV AX,#0x6666
|
||||
MOV AX,[DI]
|
||||
CMP AX,#0xAAAA
|
||||
JNZ FAILED
|
||||
MOV BX,#MEMTEST_PASS
|
||||
CALL print
|
||||
RET
|
||||
|
||||
FAILED:
|
||||
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
|
||||
|
||||
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'
|
@ -1,39 +1,16 @@
|
||||
# This file is part of the 9086 project.
|
||||
#
|
||||
# Copyright (c) 2024 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/>.
|
||||
|
||||
|
||||
PRINT_PATH_PREFIX=./
|
||||
SOURCE_FULL=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
|
||||
SOURCE_SHORT=bios.asm i2c_bootloader.asm
|
||||
BINARIES=$(subst .asm,.txt,${SOURCE_FULL}) $(subst .asm,.stxt,${SOURCE_SHORT})
|
||||
SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm pipeline_ideal.asm fibonacci.asm gnome_sort.asm cache_fill_and_empty.asm
|
||||
BINARIES=$(subst .asm,.txt,${SOURCE})
|
||||
BUILD_FILES=${BINARIES}
|
||||
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||
BUILD_FILES+=$(subst .asm,.fst,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||
BUILD_FILES+=$(subst .asm,.bin,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||
BUILD_FILES+=$(subst .asm,.json,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})
|
||||
BUILD_FILES+=$(subst .asm,.fst,${SOURCE})
|
||||
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
|
||||
BUILD_FILES+=$(subst .asm,.json,${SOURCE})
|
||||
|
||||
all: ${BINARIES}
|
||||
|
||||
brainfuck_interpreted.bin: brainfuck_interpreter_v0.asm hello_9086.bf.asm dos_layer.asm
|
||||
brainfuck_compiled.bin: brainfuck_compiler_v1.asm hello_9086.bf.asm dos_layer.asm
|
||||
brainfuck_mandelbrot.bin: brainfuck_compiler_v1.asm mandelbrot.bf.asm dos_layer.asm
|
||||
colored_led.bin: dos_layer.asm
|
||||
bios.bin: LiteDram_init.asm brainfuck_compiler_v1.asm hello_9086.bf.asm dos_layer.asm
|
||||
i2c_bootloader.bin: LiteDram_init.asm
|
||||
|
||||
fibonacci.bin: helpers.asm
|
||||
gnome_sort.bin: helpers.asm
|
||||
@ -47,5 +24,3 @@ include ../common.mk
|
||||
clean:
|
||||
$(call QUIET_CLEAN,boot_code)
|
||||
${Q}rm -f $(BUILD_FILES) *.bf.asm
|
||||
|
||||
mrproper:
|
||||
|
@ -1,31 +0,0 @@
|
||||
.org 0xF800
|
||||
mov sp,#STACK
|
||||
call litedram_init
|
||||
call INIT_INT_VECT_TABLE
|
||||
INCLUDE brainfuck_compiler_v1.asm
|
||||
prog:
|
||||
INCLUDE hello_9086.bf.asm
|
||||
|
||||
INCLUDE dos_layer.asm
|
||||
include LiteDram_init.asm
|
||||
|
||||
print:
|
||||
mov al,[bx]
|
||||
cmp al,#0
|
||||
je print_exit
|
||||
out byte #0xA5
|
||||
inc bx
|
||||
jmp print
|
||||
print_exit:
|
||||
ret
|
||||
|
||||
.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
|
@ -1,22 +1,15 @@
|
||||
; Interrupt table and routines
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
org 0x100
|
||||
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
|
||||
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xF800
|
||||
JMP AX
|
||||
output_program:
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
||||
|
@ -2,7 +2,7 @@
|
||||
;
|
||||
; This file is part of the 9086 project.
|
||||
;
|
||||
; Copyright (c) 2024 Efthymios Kritikos
|
||||
; 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
|
||||
@ -17,9 +17,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/>.
|
||||
|
||||
; 0x0000-0x0100 int vector 0x0100-0x0700 data 0x0700-0xC000 program data
|
||||
|
||||
mov sp,#STACK_COMPILER
|
||||
mov sp,#STACK
|
||||
mov bx,#bootup_msg
|
||||
mov ah,#0x02
|
||||
print1:
|
||||
@ -29,27 +27,17 @@ inc bx
|
||||
cmp dl,#0x0A
|
||||
jne print1
|
||||
|
||||
MOV DI,#0x0200
|
||||
MOV AX,#0x0000
|
||||
MOV bl,#0x00
|
||||
CLEAR:
|
||||
STOSW
|
||||
INC BL
|
||||
JNZ CLEAR
|
||||
|
||||
mov bx,#compiling
|
||||
mov ah,#0x02
|
||||
print2:
|
||||
mov dl,[bx]
|
||||
cmp dl,#0
|
||||
je exit
|
||||
int #0x21
|
||||
inc bx
|
||||
jmp print2
|
||||
exit:
|
||||
cmp dl,#0
|
||||
jne print2
|
||||
|
||||
MOV SI,#prog
|
||||
MOV DI,#0x0700
|
||||
MOV DI,#output_program
|
||||
;CL: write concat CH: move concat
|
||||
MOV CX,#0
|
||||
JMP COMPILE ; Moving some functions above the main switch to make shot jumps work
|
||||
@ -158,9 +146,8 @@ jne print3
|
||||
|
||||
MOV AL,#0xF4 ; hlt
|
||||
MOV [DI],AL
|
||||
; From 0x100 its free but i'll do 0x200 in case it start writing earlier
|
||||
MOV BX,#0x0200
|
||||
MOV AX,#0x0700
|
||||
MOV BX,#DATA
|
||||
MOV AX,#output_program
|
||||
JMP AX
|
||||
|
||||
;;;;;;;;; . ;;;;;;;;;
|
||||
@ -261,19 +248,18 @@ 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
|
||||
|
||||
compiled: .ASCII '\rCompiled! \n'
|
||||
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_COMPILER: ; brainfuck_mandelbrot depends on stack being at the end
|
||||
compiling: .ASCII 'Compiling...\0'
|
||||
compiled: .ASCII '\rCompiled! \n'
|
||||
DATA: .BLKB 560
|
||||
.BLKB 200
|
||||
STACK:
|
||||
|
@ -1,16 +1,16 @@
|
||||
; Interrupt table and routines
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
ORG 0xF000
|
||||
ORG 0x100
|
||||
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,#0xF000
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
||||
|
@ -2,7 +2,7 @@
|
||||
;
|
||||
; This file is part of the 9086 project.
|
||||
;
|
||||
; Copyright (c) 2024 Efthymios Kritikos
|
||||
; 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
|
||||
|
@ -1,22 +1,14 @@
|
||||
;I got this down to 11428 bytes
|
||||
|
||||
org 0x100
|
||||
output_program:
|
||||
|
||||
org 0xC000
|
||||
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
|
||||
|
||||
; Interrupt table and routines
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
.ORG 0x100
|
||||
INCLUDE brainfuck_compiler_v1.asm
|
||||
|
||||
prog:
|
||||
INCLUDE mandelbrot.bf.asm
|
||||
|
||||
output_program:
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xC000
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
||||
|
BIN
boot_code/brainfuck_mandelbrot.fst.hier
Normal file
BIN
boot_code/brainfuck_mandelbrot.fst.hier
Normal file
Binary file not shown.
@ -1,65 +0,0 @@
|
||||
.org 0xE000
|
||||
mov sp,#STACK
|
||||
|
||||
MAIN_LOOP:
|
||||
MOV DL,#0xF0
|
||||
DELAY11:
|
||||
MOV AX,#0x0000
|
||||
DELAY1:
|
||||
INC AX
|
||||
JNZ DELAY1
|
||||
INC DL
|
||||
JNZ DELAY11
|
||||
|
||||
MOV AL,#0x01
|
||||
out byte #0xB0
|
||||
|
||||
MOV SI,#RESERVED
|
||||
MOV DI,#RESERVED
|
||||
MOV AL,#0x68 ; 'h'
|
||||
#STOSB
|
||||
#MOV AL,#0x00
|
||||
#MOV AL,[SI]
|
||||
|
||||
#MOV AH,#0x02
|
||||
#MOV DL,AL
|
||||
#INT #0x21
|
||||
out byte #0xA5
|
||||
|
||||
MOV AL,#0x65
|
||||
out byte #0xA5
|
||||
MOV AL,#0x6c
|
||||
out byte #0xA5
|
||||
MOV AL,#0x6c
|
||||
out byte #0xA5
|
||||
MOV AL,#0x6f
|
||||
out byte #0xA5
|
||||
MOV AL,#0x20
|
||||
out byte #0xA5
|
||||
|
||||
MOV DL,#0xF0
|
||||
DELAY21:
|
||||
MOV AX,#0x0000
|
||||
DELAY2:
|
||||
INC AX
|
||||
JNZ DELAY2
|
||||
INC DL
|
||||
JNZ DELAY21
|
||||
MOV AL,#0x00
|
||||
out byte #0xB0
|
||||
|
||||
MOV AX,#0xE000
|
||||
JMP AX
|
||||
|
||||
RESERVED: DB 0x48 ; 'H'
|
||||
.BLKB 100
|
||||
STACK:
|
||||
|
||||
#INCLUDE dos_layer.asm
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xE000
|
||||
JMP AX
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
@ -1,3 +1,7 @@
|
||||
.ORG 0x84 ; INT 21
|
||||
DW 0xFFFF ; Code Segment
|
||||
DW PRINT_INT_HANDLE ; Program Counter
|
||||
|
||||
PRINT_INT_HANDLE:
|
||||
push AX
|
||||
CMP AH,#0x02
|
||||
@ -10,15 +14,3 @@ 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
|
||||
|
@ -1,8 +1,8 @@
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
|
||||
org 0xF000
|
||||
org 0x100
|
||||
mov sp,#STACK
|
||||
call INIT_INT_VECT_TABLE
|
||||
|
||||
MOV AX,#0x1
|
||||
MOV BX,#0x1
|
||||
@ -26,7 +26,6 @@ MOV DL,#0x0a
|
||||
INT #0x21
|
||||
|
||||
hlt
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
|
||||
.BLKB 200
|
||||
@ -34,6 +33,6 @@ STACK:
|
||||
INCLUDE helpers.asm
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xF000
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
.org 0xF000
|
||||
.org 0x100
|
||||
mov sp,#STACK
|
||||
MOV SI,#DATA
|
||||
call INIT_INT_VECT_TABLE
|
||||
|
||||
GNOME_SORT:
|
||||
CMP SI,#DATA+23
|
||||
CMP SI,#DATA+31
|
||||
JZ GNOMED
|
||||
MOV AX,[SI]
|
||||
INC SI
|
||||
@ -29,7 +29,7 @@ PRINT_LOOP:
|
||||
MOV AL,[SI]
|
||||
call PRINT_0_8_HEX
|
||||
INC SI
|
||||
CMP SI,#DATA+24
|
||||
CMP SI,#DATA+32
|
||||
JNZ PRINT_LOOP
|
||||
|
||||
MOV AH,#0x02
|
||||
@ -37,11 +37,11 @@ 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
|
||||
DB 0xe9, 0xdb, 0x1f, 0x21, 0x44, 0x4f, 0x99, 0x09
|
||||
DB 0x2a, 0x23, 0x82, 0x4f, 0x52, 0xf1, 0xdc, 0x0b
|
||||
|
||||
.BLKB 200
|
||||
STACK:
|
||||
@ -49,8 +49,6 @@ STACK:
|
||||
INCLUDE helpers.asm
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xF000
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
||||
|
@ -1,187 +0,0 @@
|
||||
.org 0xF800
|
||||
mov sp,#STACK
|
||||
call litedram_init
|
||||
|
||||
|
||||
mov bx,#load_i2c_txt
|
||||
call print
|
||||
|
||||
;########### SET ROM ADDRESS ############
|
||||
mov al,#0x50
|
||||
outb #0x61
|
||||
|
||||
mov ax,#0x0000 ; I2C ADDRESS
|
||||
outw #0x62
|
||||
|
||||
mov al,#0x02 ; Write 16bit
|
||||
outb #0x63
|
||||
|
||||
mov al,#0x00
|
||||
outb #0x60
|
||||
|
||||
|
||||
wait_send:
|
||||
inb #0x62
|
||||
test al,#0x02
|
||||
jnz rom_fail
|
||||
test al,#0x01
|
||||
jnz wait_send
|
||||
|
||||
mov bx,#OK_loading_txt
|
||||
call print
|
||||
|
||||
jmp read_code
|
||||
|
||||
rom_fail:
|
||||
call rom_fail_print
|
||||
|
||||
;############ READ CODE ##################
|
||||
read_code:
|
||||
|
||||
mov bx,#0xEFFF
|
||||
mov di,#0x0000
|
||||
rom_read_loop:
|
||||
mov al,#0x07 ; Read, 8bit, ignore ack
|
||||
outb #0x63
|
||||
|
||||
mov al,#0x00
|
||||
outb #0x60
|
||||
|
||||
push bx
|
||||
cmp di,#0x1800
|
||||
jz print_10
|
||||
cmp di,#0x3000
|
||||
jz print_20
|
||||
cmp di,#0x4800
|
||||
jz print_30
|
||||
cmp di,#0x6000
|
||||
jz print_40
|
||||
cmp di,#0x7800
|
||||
jz print_50
|
||||
cmp di,#0x9000
|
||||
jz print_60
|
||||
cmp di,#0xA800
|
||||
jz print_70
|
||||
cmp di,#0xC000
|
||||
jz print_80
|
||||
cmp di,#0xD800
|
||||
jz print_90
|
||||
back:
|
||||
pop bx
|
||||
|
||||
wait_send2: inb #0x62
|
||||
test al,#0x01
|
||||
jnz wait_send2
|
||||
|
||||
inw #0x60
|
||||
STOSW
|
||||
|
||||
|
||||
dec bx
|
||||
jz rom_read_end
|
||||
dec bx
|
||||
jz rom_read_end
|
||||
jmp rom_read_loop
|
||||
|
||||
rom_read_end:
|
||||
|
||||
mov bx,#clear_code
|
||||
call print
|
||||
|
||||
MOV AX,#0xC000
|
||||
JMP AX
|
||||
|
||||
print_10:
|
||||
mov cx,#ten_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_20:
|
||||
mov cx,#twenty_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_30:
|
||||
mov cx,#thirty_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_40:
|
||||
mov cx,#forty_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_50:
|
||||
mov cx,#fifty_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_60:
|
||||
mov cx,#sixty_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_70:
|
||||
mov cx,#seventy_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_80:
|
||||
mov cx,#eighty_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_90:
|
||||
mov cx,#ninty_prc_txt
|
||||
call print_prc
|
||||
jmp back
|
||||
|
||||
print_prc:
|
||||
mov bx,#loading_rom_txt
|
||||
call print
|
||||
mov bx,cx
|
||||
call print
|
||||
ret
|
||||
|
||||
;#########################################
|
||||
include LiteDram_init.asm
|
||||
|
||||
rom_fail_print:
|
||||
mov bx,#rom_fail_txt
|
||||
call print
|
||||
hlt
|
||||
|
||||
print:
|
||||
mov al,[bx]
|
||||
cmp al,#0
|
||||
je print_exit
|
||||
out byte #0xA5
|
||||
inc bx
|
||||
jmp print
|
||||
print_exit:
|
||||
ret
|
||||
|
||||
.BLKB 18 ; Using the text as stack space for the compiled program
|
||||
STACK: ; brainfuck_mandelbrot depends on stack being at the end
|
||||
|
||||
load_i2c_txt: .ASCII 'Read I2C EEPROM:\0'
|
||||
OK_loading_txt: .ASCII 'OK\nLoading rom 0%\r\0'
|
||||
loading_rom_txt: .ASCII 'Loading rom \0'
|
||||
rom_fail_txt: .ASCII 'FAIL\nNo i2c rom at 0x50\0'
|
||||
ten_prc_txt: .ASCII '10%\r\0'
|
||||
twenty_prc_txt: .ASCII '20%\r\0'
|
||||
thirty_prc_txt: .ASCII '30%\r\0'
|
||||
forty_prc_txt: .ASCII '40%\r\0'
|
||||
fifty_prc_txt: .ASCII '50%\r\0'
|
||||
sixty_prc_txt: .ASCII '60%\r\0'
|
||||
seventy_prc_txt: .ASCII '70%\r\0'
|
||||
eighty_prc_txt: .ASCII '80%\r\0'
|
||||
ninty_prc_txt: .ASCII '90%\r\0'
|
||||
clear_code: DB 0x1B,0x5B,0x48,0x1B,0x5B,0x32,0x4a,0x00
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xF800
|
||||
JMP AX
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
@ -1,4 +1,4 @@
|
||||
org 0xF000
|
||||
org 0x100
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
@ -102,5 +102,5 @@ inc bx
|
||||
hlt
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xF000
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
||||
|
65
common.mk
65
common.mk
@ -1,59 +1,26 @@
|
||||
.PRECIOUS:${BOOT_CODE}
|
||||
|
||||
########## BUILD OPTIONS ##########
|
||||
|
||||
QUIET=1
|
||||
# QUIET: 1=clean, non-verbose output
|
||||
# 2=normal make output
|
||||
|
||||
####### SIMULATION OPTIONS ########
|
||||
|
||||
SIM=VERILATOR
|
||||
# SIM: VERILATOR: use Verilator
|
||||
# ICARUS: use Icarus Verilog
|
||||
|
||||
NUMACTL=#numactl -m 0 -C 0,1 --
|
||||
|
||||
######## SYNTHESIS OPTIONS ########
|
||||
|
||||
# BOARD: the options are the directories in system/fpga_config/.
|
||||
# Select the one you have
|
||||
FPGA_BOARD=OrangeCrab_r0.2.1
|
||||
|
||||
# If this options is set to 1, builds with different seeds will be
|
||||
# considered separate, in combination with the fact that this build
|
||||
# system by default is generating a new seed for each build, it means
|
||||
# that for each build a new set of files gets created in the build
|
||||
# directory with the seed number on the filename without overwriting
|
||||
# the old ones.
|
||||
BUILD_SEED_DIFFERENTIATION=0
|
||||
|
||||
VERSION="v0.3.0-dev"
|
||||
|
||||
# TODO: handle case where the source code is not part of a git repository
|
||||
COMMIT=$(shell if which git >/dev/null 2>/dev/null ;then git log --pretty=format:'%H' -1 |cat ;else echo git-not-installed; fi)
|
||||
VERSION="v0.2.0"
|
||||
COMMIT=$(shell git log --pretty=format:'%H' -1 |cat)
|
||||
|
||||
ifeq "${QUIET}" "1"
|
||||
QUIET_AS = @echo ' AS '${PRINT_PATH_PREFIX}$@;
|
||||
|
||||
QUIET_VVP = @echo ' VVP '${PRINT_PATH_PREFIX}$@;
|
||||
QUIET_IVERILOG = @echo ' IVERILOG '${PRINT_PATH_PREFIX}$@;
|
||||
|
||||
QUIET_VERILATOR = @echo ' VERILATOR '${PRINT_PATH_PREFIX}$@;
|
||||
QUIET_CC = @echo ' CC '${PRINT_PATH_PREFIX}$@;
|
||||
|
||||
QUIET_YOSYS = @echo ' YOSYS '${PRINT_PATH_PREFIX}$@;
|
||||
QUIET_NEXTPNR = @echo ' NEXTPNR '${PRINT_PATH_PREFIX}$@;
|
||||
QUIET_ECPPACK = @echo ' ECPPACK '${PRINT_PATH_PREFIX}$@;
|
||||
QUIET_DFU_SUFFIX = @echo ' DFU-SUFFIX '${PRINT_PATH_PREFIX}$@;
|
||||
QUIET_DFU_UTIL = @echo ' DFU-UTIL '${PRINT_PATH_PREFIX}$<;
|
||||
QUIET_MINIPRO = @echo ' MINIPRO '${PRINT_PATH_PREFIX}${ROM_FILE};
|
||||
|
||||
QUIET_DOWNLOAD = @echo ' DOWNLOAD '${PRINT_PATH_PREFIX}$@;
|
||||
|
||||
QUIET_CLEAN = @echo ' CLEAN '${PRINT_PATH_PREFIX};
|
||||
QUIET_MRPROPER = @echo ' MRPROPER '${PRINT_PATH_PREFIX};
|
||||
QUIET_VERILATOR_RUN = @printf ' %s %s\n' $(shell basename "$1") $2;
|
||||
QUIET_AS = @echo ' AS '$@;
|
||||
QUIET_CC = @echo ' CC '$@;
|
||||
QUIET_VVP = @echo ' VVP '$@;
|
||||
QUIET_IVERILOG = @echo ' IVERILOG '$@;
|
||||
QUIET_VERILATOR = @echo ' VERILATOR '$@;
|
||||
QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
|
||||
QUIET_VERILATOR_RUN = @printf ' %s %s\n' $1 $2;
|
||||
Q = @
|
||||
MAKEOPTS=--no-print-directory
|
||||
.SILENT:
|
||||
@ -68,20 +35,12 @@ 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
|
||||
%.txt:%.bin
|
||||
${Q}dd if=/dev/zero bs=1 count=65536 of="$(subst .bin,.stage,$<)" status=none
|
||||
${Q}dd if="$<" 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_short,$<)" status=none
|
||||
${Q}dd if="$<" of="$(subst .bin,.stage_short,$<)" conv=notrunc,nocreat status=none
|
||||
${Q}xxd -ps -c 2 "$(subst .bin,.stage_short,$<)" > "$@"
|
||||
${Q}rm "$(subst .bin,.stage_short,$<)"
|
||||
|
||||
|
||||
ifeq "${NO_ASM}" "0"
|
||||
%.bin:%.asm
|
||||
${QUIET_AS}
|
||||
|
1
readme_files/.~lock.9086_design1.ase#
Normal file
1
readme_files/.~lock.9086_design1.ase#
Normal file
@ -0,0 +1 @@
|
||||
,user,localhost,24.10.2023 00:59,file:///home/user/.config/libreoffice/4;
|
148
system/Makefile
148
system/Makefile
@ -1,6 +1,6 @@
|
||||
# This file is part of the 9086 project.
|
||||
#
|
||||
# Copyright (c) 2024 Efthymios Kritikos
|
||||
# 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
|
||||
@ -15,47 +15,19 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
TOP_LEVEL_SOURCE=system.v
|
||||
SOURCES=processor.v memory.v registers.v alu.v decoder.v general.v biu.v execute.v
|
||||
INCLUDES=exec_state_def.v alu_header.v config.v ucode_header.v error_header.v
|
||||
MICROCODE=ucode.txt
|
||||
SYSTEM_VVP=system.vvp
|
||||
PRINT_PATH_PREFIX=./
|
||||
BUILD_FILES_PREFIX=build/
|
||||
|
||||
BOOT_CODE=boot_code.txt
|
||||
VERILATOR_BIN=obj_dir/Vsystem
|
||||
VERILATOR_FPGA_BIN=/Vfpga_top
|
||||
NO_ASM=0
|
||||
include ../common.mk
|
||||
|
||||
$(shell mkdir -p $(BUILD_FILES_PREFIX))
|
||||
FPGA_SEED ::= $(shell seq 1 200|sort -R|head -n1)
|
||||
|
||||
ifeq "${BUILD_SEED_DIFFERENTIATION}" "1"
|
||||
BUILD_NAME=${FPGA_BOARD}_${FPGA_SEED}
|
||||
else
|
||||
BUILD_NAME=${FPGA_BOARD}
|
||||
endif
|
||||
|
||||
include fpga_config/${FPGA_BOARD}/config.mk
|
||||
|
||||
# Synthesis and bitstream creation for ECP5
|
||||
ifeq "${ECP5_DEVICE}" "25F"
|
||||
NEXTPNR_ECP5_DEV=--25k
|
||||
else ifeq "${ECP5_DEVICE}" "85F"
|
||||
NEXTPNR_ECP5_DEV=--85k
|
||||
else
|
||||
$(error invalid ECP5 device ${ECP5_DEVICE})
|
||||
endif
|
||||
|
||||
EVENT_SIM_TESTBENCH=testbench.v
|
||||
VERILATOR_TESTBENCH=testbench.cpp
|
||||
SIMULATION_TOP_LEVEL_SOURCE=system.v
|
||||
INCLUDES=exec_state_def.v alu_header.v config.v ucode_header.v error_header.v
|
||||
SYSTEM_VVP=system.vvp
|
||||
VERILATOR_BIN=obj_dir/Vsystem
|
||||
BOOT_CODE=boot_code.txt
|
||||
GTKWSAVE=../gtkwave_savefile.gtkw
|
||||
MICROCODE=ucode.txt
|
||||
|
||||
SIMULATED_SOURCES ::= ${SIMULATION_TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
|
||||
FPGA_SIM_SOURCES ::= fpga_config/${FPGA_BOARD}/fpga_top.v ${SOURCES} ${FPGA_SOC_SIM_SOURCES} ${INCLUDES}
|
||||
FPGA_SOURCES ::= fpga_config/${FPGA_BOARD}/fpga_top.v ${SOURCES} ${FPGA_SOC_SOURCES} ${INCLUDES}
|
||||
NO_ASM=0
|
||||
include ../common.mk
|
||||
|
||||
#build options
|
||||
VERILATOR_OPTS += --cc --exe
|
||||
@ -64,114 +36,26 @@ VERILATOR_OPTS += --cc --exe
|
||||
VERILATOR_OPTS += --trace-fst --threads 1 --autoflush
|
||||
|
||||
#linter options
|
||||
VERILATOR_OPTS += -Wall --Wno-DECLFILENAME
|
||||
VERILATOR_OPTS += -Wall --Wno-DECLFILENAME -Wno-SYNCASYNCNET -Wno-MULTIDRIVEN
|
||||
|
||||
#optimisation options
|
||||
VERILATOR_OPTS += -x-assign fast --x-initial fast
|
||||
#For testing use:
|
||||
#VERILATOR_OPTS += -x-assign unique --x-initial unique
|
||||
|
||||
|
||||
################################################################################
|
||||
#### SIMULATION RECIPES ####
|
||||
################################################################################
|
||||
|
||||
# COMPILING
|
||||
${SYSTEM_VVP} : ${SIMULATED_SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
|
||||
${QUIET_IVERILOG}
|
||||
${Q}iverilog -g2012 -D CALCULATE_IPC -D OUTPUT_JSON_STATISTICS -o "$@" ${SIMULATION_TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||
${Q}iverilog -g2012 -D CALCULATE_IPC -D OTUPUT_JSON_STATISTICS -o "$@" ${TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||
|
||||
${VERILATOR_BIN}: ${VERILATOR_BIN}.mk
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=${PRINT_PATH_PREFIX}obj_dir/ OPT_FAST="-O2 -march=native -mtune=native" -C obj_dir -f ../verilator_makefile Vsystem
|
||||
${Q}make ${MAKEOPTS} OPT_FAST="-O2 -march=native -mtune=native" -C obj_dir -f ../verilator_makefile Vsystem
|
||||
|
||||
${VERILATOR_BIN}.mk: ${VERILATOR_TESTBENCH} ${SIMULATED_SOURCES}
|
||||
${VERILATOR_BIN}.mk: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
|
||||
${QUIET_VERILATOR}
|
||||
mkdir -p ${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/
|
||||
rm -f ${VERILATOR_BIN}.mk # Verilator doesn't update this when just changing the testbench and the makefile breaks so we remove it to make sure
|
||||
${Q}verilator -DCALCULATE_IPC -DOUTPUT_JSON_STATISTICS ${VERILATOR_OPTS} $^
|
||||
|
||||
${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/${VERILATOR_FPGA_BIN}: ${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/${VERILATOR_FPGA_BIN}.mk
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=${PRINT_PATH_PREFIX}${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/ OPT_FAST="-O2 -march=native -mtune=native" -C "${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/" -f ../../verilator_makefile_fpga Vfpga_top
|
||||
|
||||
${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/${VERILATOR_FPGA_BIN}.mk: fpga_config/${FPGA_BOARD}/testbench.cpp ${FPGA_SIM_SOURCES}
|
||||
${QUIET_VERILATOR}
|
||||
mkdir -p "${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/" # Verilator doesn't update this when just changing the testbench and the makefile breaks so we remove it to make sure
|
||||
rm -f ${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/${VERILATOR_FPGA_BIN}.mk
|
||||
${Q}verilator -DCALCULATE_IPC -DOUTPUT_JSON_STATISTICS --Mdir ${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/ ${VERILATOR_OPTS} ../../fpga_config/${FPGA_BOARD}/testbench.cpp ${FPGA_SIM_SOURCES}
|
||||
|
||||
.PHONY: fpga_sim
|
||||
fpga_sim fpga_sim.fst: ../boot_code/i2c_bootloader.stxt ${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/${VERILATOR_FPGA_BIN} ${MICROCODE} simplified_ucode.txt
|
||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
||||
${Q} ${NUMACTL} "${BUILD_FILES_PREFIX}/sim_${FPGA_BOARD}/${VERILATOR_FPGA_BIN}" +VERSION=${VERSION} +WAVEFORM="fpga_sim.fst" +COMMIT=${COMMIT} +BOOT_CODE="../boot_code/i2c_bootloader.stxt" +MICROCODE="simplified_ucode.txt"
|
||||
|
||||
################################################################################
|
||||
#### FPGA/ASIC RECIPES ####
|
||||
################################################################################
|
||||
|
||||
simplified_ucode.txt:ucode.txt
|
||||
${Q}tr 'x' '0' < $^ | sed 's@//.*@@' | grep ^@ |sort | sed 's/.* .//;s/ $$//' | tr -d _ > $@
|
||||
|
||||
external_ip/litedram_core_ecp5_phy.v:
|
||||
${QUIET_DOWNLOAD}
|
||||
${Q}../tools/gen_litedram.sh -q "$@"
|
||||
|
||||
external_ip/litedram_core_ecp5_phy_sim.v:
|
||||
${QUIET_DOWNLOAD}
|
||||
${Q}../tools/gen_litedram.sh --simulation -q "$@"
|
||||
|
||||
#########################################
|
||||
## SYNTHESIS RECIPES
|
||||
|
||||
#TODO: we are relying on yosys to trim the input program txt file and hope its enough for the whole program...
|
||||
${BUILD_FILES_PREFIX}synth_ecp5_${FPGA_BOARD}.json: ${FPGA_SOURCES} ${FPGA_BOOTCODE} simplified_ucode.txt
|
||||
${QUIET_YOSYS}
|
||||
${Q} yosys -q -p 'read_verilog -defer -noautowire -sv '"${FPGA_SOURCES}; attrmap -tocase keep -imap keep="true" keep=1 -imap keep="false" keep=0 -remove keep=0; synth_ecp5 -json \"$@\" -abc9 -top fpga_top"
|
||||
|
||||
##########################################
|
||||
## PLACE AND ROUTE RECIPES
|
||||
|
||||
${BUILD_FILES_PREFIX}nextpnr-ecp5_${BUILD_NAME}.bit:${BUILD_FILES_PREFIX}synth_${FPGA_BOARD}.json
|
||||
${QUIET_NEXTPNR}
|
||||
${Q}printf '\e[1;30mNotice: nextpnr rng seed is : %s\e[0m\n' "${FPGA_SEED}"
|
||||
${Q} nextpnr-ecp5 --seed ${FPGA_SEED} --Werror -q --json $< --textcfg "$@_config_temp" ${NEXTPNR_ECP5_DEV} --package ${ECP5_PACKAGE} --speed ${ECP5_SPEED_GRADE} --lpf fpga_config/${FPGA_BOARD}/pin_constraint.pcf --report=${BUILD_FILES_PREFIX}nextpnr_report_${BUILD_NAME}.json
|
||||
${Q}../tools/parse_nextpnr_stats.sh --brief ${BUILD_FILES_PREFIX}nextpnr_report_${BUILD_NAME}.json
|
||||
${Q}mv "$@_config_temp" "$@_config" # nextpnr-ecp5 will still generate a file even if it fails breaking the assumptions of the build system.
|
||||
${QUIET_ECPPACK}
|
||||
${Q}ecppack --compress --freq 38.8 --input $@_config --bit $@
|
||||
|
||||
nextpnr-gui: ${BUILD_FILES_PREFIX}synth_${FPGA_BOARD}.json
|
||||
${QUIET_NEXTPNR}
|
||||
${Q} nextpnr-ecp5 --seed ${FPGA_SEED} --json $< ${NEXTPNR_ECP5_DEV} --package ${ECP5_PACKAGE} --speed ${ECP5_SPEED_GRADE} --lpf fpga_config/${FPGA_BOARD}/pin_constraint.pcf --gui
|
||||
|
||||
##########################################
|
||||
## BITSTREAM MODIFICATION FOR/AND UPLOADING
|
||||
|
||||
${BUILD_FILES_PREFIX}bitstream_${BUILD_NAME}.dfu:${BUILD_FILES_PREFIX}bitstream_${BUILD_NAME}.bit
|
||||
${QUIET_DFU_SUFFIX}
|
||||
${Q}cp "$<" "$<.tempdfu"
|
||||
@#From some testing, dfu-suffix does output errors to stderr so this should be fine
|
||||
${Q}dfu-suffix --vid 1209 --pid 5af0 --add "$<.tempdfu" > /dev/null
|
||||
${Q}mv "$<.tempdfu" "$@"
|
||||
|
||||
dfu_upload:${BUILD_FILES_PREFIX}bitstream_${BUILD_NAME}.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'
|
||||
|
||||
minipro_upload:
|
||||
${QUIET_MINIPRO}
|
||||
${Q}minipro -p ${ROM_PART_ID} -w ${ROM_FILE}
|
||||
|
||||
################################################################################
|
||||
#### CLEAN-UP ####
|
||||
################################################################################
|
||||
|
||||
${Q}verilator -DCALCULATE_IPC -DOTUPUT_JSON_STATISTICS ${VERILATOR_OPTS} $^
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(call QUIET_CLEAN,system)
|
||||
${Q}rm -rf ${SYSTEM_VVP} *.fst boot_code.txt boot_code.bin *memdump *memdumptxt obj_dir simplified_ucode.txt abc.history build
|
||||
|
||||
.PHONY: mrproper
|
||||
mrproper:
|
||||
$(call QUIET_MRPROPER,system)
|
||||
${Q}rm -f external_ip/litedram_core_ecp5_phy.v external_ip/litedram_core_ecp5_phy_sim.v
|
||||
${Q}rm -rf ${SYSTEM_VVP} *.fst boot_code.txt boot_code.bin *memdump *memdumptxt obj_dir *json
|
||||
|
10
system/alu.v
10
system/alu.v
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -47,10 +47,10 @@ always @ ( * ) begin
|
||||
`ALU_OP_ADD_SIGNED_B: {C_FLAG,OUT[7:0]}=A[7:0]+SIGNED_8B;
|
||||
`ALU_OP_SUB: {C_FLAG,OUT[7:0]}=A[7:0]-B[7:0];
|
||||
`ALU_OP_SUB_REVERSE: {C_FLAG,OUT[7:0]}=B[7:0]-A[7:0];
|
||||
`ALU_OP_AND: begin C_FLAG=0;OUT[7:0]=A[7:0]&B[7:0]; end
|
||||
`ALU_OP_OR: begin C_FLAG=0;OUT[7:0]=A[7:0]|B[7:0]; end
|
||||
`ALU_OP_XOR: begin C_FLAG=0;OUT[7:0]=A[7:0]^B[7:0]; end
|
||||
`ALU_OP_SHIFT_LEFT: begin C_FLAG=(A&16'h80)==16'h80;OUT[7:0]=A[7:0]<<B; end
|
||||
`ALU_OP_AND: begin C_FLAG=0;OUT=A&B; end
|
||||
`ALU_OP_OR: begin C_FLAG=0;OUT=A|B; end
|
||||
`ALU_OP_XOR: begin C_FLAG=0;OUT=A^B; end
|
||||
`ALU_OP_SHIFT_LEFT: begin C_FLAG=(A&16'h80)==16'h80;OUT=A<<B; end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
|
245
system/biu.v
245
system/biu.v
@ -3,7 +3,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -45,40 +45,39 @@ 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
|
||||
/* */ ,inout [15:0] external_data_bus,output reg read, output reg write,output reg BHE,output reg IOMEM
|
||||
|
||||
/**************** OUTPUT TO DE ****************/
|
||||
/* */ ,output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION
|
||||
/* */ ,output reg VALID_DATA
|
||||
/* */ ,output reg VALID_DATA, output reg DATA_DIR
|
||||
|
||||
/**************** INPUT FROM DE ****************/
|
||||
,input Wbit, input MEM_OR_IO, input valid_instruction_ack
|
||||
|
||||
/**************** INPUT FROM EX ****************/
|
||||
/* */ ,input jump_req, input write_request, input read_request
|
||||
/* */ ,input[15:0] ADDRESS_INPUT, input [15:0] DATA_EX_WRITE
|
||||
/* */ ,input[15:0] ADDRESS_INPUT
|
||||
|
||||
/**************** OUTPUT TO EX *****************/
|
||||
/* */ ,output [15:0] DATA_EX_READ
|
||||
/************ BIDIRECTIONAL WITH EX ************/
|
||||
/* */ ,inout [15:0] DATA
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
/***************** STATISTICS *****************/
|
||||
/* */ ,output wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE_STAT, output wire VALID_INSTRUCTION_STAT
|
||||
`endif
|
||||
|
||||
);
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
assign FIFO_SIZE_STAT = FIFO_SIZE;
|
||||
assign VALID_INSTRUCTION_STAT = ((Isit1==1) && (FIFO_SIZE!=0) && `EARLY_VALID_INSTRUCTION_) || ((fifoIsize==2) && (FIFO_SIZE > 1) && `EARLY_VALID_INSTRUCTION_) || ((fifoIsize==3) && (FIFO_SIZE > 2) && `EARLY_VALID_INSTRUCTION_) || (FIFO_SIZE>3);
|
||||
`endif
|
||||
|
||||
reg [15:0] data_bus_output_register;
|
||||
assign external_data_bus_write=data_bus_output_register; //TODO: should we rename?
|
||||
assign external_data_bus=read?data_bus_output_register:16'hz;
|
||||
|
||||
reg [15:0] DATA_OUT;
|
||||
assign DATA_EX_READ=DATA_OUT; //TODO should we rename?
|
||||
assign DATA=DATA_DIR ? 16'hz:DATA_OUT;
|
||||
|
||||
`define FIFO_SIZE_BYTES $rtoi($pow(2,`L1_CACHE_SIZE))
|
||||
|
||||
@ -90,6 +89,21 @@ wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE = FIFO_end-FIFO_start;
|
||||
reg [3:0] biu_state;
|
||||
reg sane;
|
||||
|
||||
always @(negedge reset) begin
|
||||
biu_state <= `BIU_HALT;
|
||||
write <= 1;
|
||||
sane <= 0;
|
||||
end
|
||||
always @(posedge reset) begin
|
||||
biu_state <= `BIU_RESET1;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
FIFO_start = `L1_CACHE_SIZE'b0;
|
||||
FIFO_end = `L1_CACHE_SIZE'b0;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
end
|
||||
|
||||
reg jump_req_latch;
|
||||
|
||||
reg func;
|
||||
reg [19:0]INSTRUCTION_ADDRESS;
|
||||
reg [19:0]DATA_ADDRESS;
|
||||
@ -97,25 +111,13 @@ reg [19:0]DATA_ADDRESS;
|
||||
assign external_address_bus= func ? INSTRUCTION_ADDRESS : DATA_ADDRESS ;
|
||||
|
||||
always @(posedge clock) begin
|
||||
if ( reset == 0 ) begin
|
||||
biu_state <= `BIU_HALT;
|
||||
write <= 1;
|
||||
sane <= 0;
|
||||
biu_state <= `BIU_RESET1;
|
||||
FIFO_start <= `L1_CACHE_SIZE'b0;
|
||||
FIFO_end <= `L1_CACHE_SIZE'b0;
|
||||
end else if ( jump_req ) begin
|
||||
FIFO_start <= FIFO_end ;
|
||||
INSTRUCTION_ADDRESS <= { 4'hF , ADDRESS_INPUT };
|
||||
if ( jump_req_latch ) begin
|
||||
INSTRUCTION_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
|
||||
INSTRUCTION_LOCATION <= ADDRESS_INPUT;
|
||||
func <= 1;
|
||||
jump_req_latch <= 0;
|
||||
if (biu_state==`BIU_READ)
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
end else if(valid_instruction_ack) begin
|
||||
FIFO_start <= FIFO_start + {{`L1_CACHE_SIZE-3{1'b0}},Isize};
|
||||
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {13'd0,Isize};
|
||||
end else if (wait_state==1)begin
|
||||
// nothing...
|
||||
end else begin
|
||||
case(biu_state)
|
||||
`BIU_HALT: begin
|
||||
@ -123,14 +125,18 @@ 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'hF , ADDRESS_INPUT };
|
||||
DATA_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
|
||||
DATA_DIR <= 1 ;
|
||||
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'hF,INSTRUCTION_LOCATION} ;
|
||||
FIFO_end<=FIFO_start;
|
||||
INSTRUCTION_ADDRESS <= {4'b0,INSTRUCTION_LOCATION} ;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
FIFO_end=FIFO_start;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
end else if ( read_request ) begin
|
||||
func<=0;
|
||||
DATA_ADDRESS <= { 4'hF , ADDRESS_INPUT };
|
||||
DATA_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
|
||||
DATA_DIR <= 0;
|
||||
IOMEM <= MEM_OR_IO;
|
||||
read <= 0;
|
||||
BHE <= 0;
|
||||
@ -155,17 +161,23 @@ always @(posedge clock) begin
|
||||
/*************** INSTRUCTION FIFO READ ***************/
|
||||
`BIU_READ: begin
|
||||
if(INSTRUCTION_ADDRESS[0:0]==0 && FIFO_SIZE<{{(`L1_CACHE_SIZE-1){1'b1}},1'b0})begin
|
||||
INPUT_FIFO[FIFO_end] <= external_data_bus_read[7:0];
|
||||
INPUT_FIFO[FIFO_end+`L1_CACHE_SIZE'd1] <= external_data_bus_read[15:8];
|
||||
FIFO_end <= FIFO_end+`L1_CACHE_SIZE'd2;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
INPUT_FIFO[FIFO_end] = external_data_bus[7:0];
|
||||
INPUT_FIFO[FIFO_end+`L1_CACHE_SIZE'd1] = external_data_bus[15:8];
|
||||
FIFO_end = FIFO_end+`L1_CACHE_SIZE'd2;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd2;
|
||||
end else if(INSTRUCTION_ADDRESS[0:0]==0)begin
|
||||
INPUT_FIFO[FIFO_end] <= external_data_bus_read[7:0];
|
||||
FIFO_end <= FIFO_end+`L1_CACHE_SIZE'd1;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
INPUT_FIFO[FIFO_end] = external_data_bus[7:0];
|
||||
FIFO_end = FIFO_end+`L1_CACHE_SIZE'd1;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
||||
end else begin
|
||||
INPUT_FIFO[FIFO_end] <= external_data_bus_read[15:8];
|
||||
FIFO_end <= FIFO_end+`L1_CACHE_SIZE'd1;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
INPUT_FIFO[FIFO_end] = external_data_bus[15:8];
|
||||
FIFO_end = FIFO_end+`L1_CACHE_SIZE'd1;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
||||
end
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
@ -173,12 +185,13 @@ always @(posedge clock) begin
|
||||
end
|
||||
|
||||
/*************** DATA WRITE ***************/
|
||||
//TODO TODO TODO flush fifo, self modifying code
|
||||
`BIU_PUT_UNALIGNED_16BIT_DATA:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Writing 16bit %04x at %04x",DATA_EX_WRITE,DATA_ADDRESS);
|
||||
$display("Writing 16bit %04x at %04x",DATA,DATA_ADDRESS);
|
||||
`endif
|
||||
BHE <= 0;
|
||||
data_bus_output_register <= {DATA_EX_WRITE[7:0],DATA_EX_WRITE[15:8]};
|
||||
data_bus_output_register <= {DATA[7:0],DATA[15:8]};
|
||||
write <= 0;
|
||||
biu_state <= `BIU_PUT_UNALIGNED_PREP_NEXT2;
|
||||
end
|
||||
@ -190,22 +203,22 @@ always @(posedge clock) begin
|
||||
end
|
||||
`BIU_PUT_ALIGNED_16BIT_DATA:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Writing 16bit %04x at %04x",DATA_EX_WRTIE,DATA_ADDRESS);
|
||||
$display("Writing 16bit %04x at %04x",DATA,DATA_ADDRESS);
|
||||
`endif
|
||||
data_bus_output_register <= {DATA_EX_WRITE[15:8],DATA_EX_WRITE[7:0]};
|
||||
data_bus_output_register <= {DATA[15:8],DATA[7:0]};
|
||||
write <= 0;
|
||||
biu_state <= `BIU_WRITE_RELEASE;
|
||||
end
|
||||
`BIU_PUT_BYTE:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Writing 8bit %02x at %04x",DATA_EX_WRITE[7:0],DATA_ADDRESS);
|
||||
$display("Writing 8bit %02x at %04x",DATA[7:0],DATA_ADDRESS);
|
||||
`endif
|
||||
if(ADDRESS_INPUT[0:0]==0) begin
|
||||
BHE <= 1;
|
||||
data_bus_output_register <= {8'b0,DATA_EX_WRITE[7:0]};
|
||||
data_bus_output_register <= {8'b0,DATA[7:0]};
|
||||
end else begin
|
||||
BHE <= 0;
|
||||
data_bus_output_register <= {DATA_EX_WRITE[7:0],8'b0};
|
||||
data_bus_output_register <= {DATA[7:0],8'b0};
|
||||
end
|
||||
write <= 0;
|
||||
biu_state <= `BIU_WRITE_RELEASE;
|
||||
@ -222,6 +235,7 @@ always @(posedge clock) begin
|
||||
|
||||
/*************** DATA READ ***************/
|
||||
`define finished_read \
|
||||
DATA_DIR <= 0; \
|
||||
if ( read_request == 0 ) begin \
|
||||
biu_state <= `BIU_NEXT_ACTION;\
|
||||
VALID_DATA <= 0;\
|
||||
@ -230,20 +244,20 @@ always @(posedge clock) begin
|
||||
`BIU_GET_ALIGNED_DATA:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
if(Wbit==1)
|
||||
$display("Reading 16bit %04x from %04x",external_data_bus_read,DATA_ADDRESS);
|
||||
$display("Reading 16bit %04x from %04x",external_data_bus,DATA_ADDRESS);
|
||||
else
|
||||
$display("Reading 8bit %02x from %04x",external_data_bus_read[7:0],DATA_ADDRESS);
|
||||
$display("Reading 8bit %02x from %04x",external_data_bus[7:0],DATA_ADDRESS);
|
||||
`endif
|
||||
DATA_OUT <= (Wbit==1)? external_data_bus_read : {8'b0,external_data_bus_read[7:0]} ;
|
||||
DATA_OUT <= (Wbit==1)? external_data_bus : {8'b0,external_data_bus[7:0]} ;
|
||||
read <=1;
|
||||
`finished_read
|
||||
end
|
||||
`BIU_GET_UNALIGNED_DATA:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
if(Wbit==0)
|
||||
$display("Reading 8bit %02x from %04x",external_data_bus_read[15:8],DATA_ADDRESS);
|
||||
$display("Reading 8bit %02x from %04x",external_data_bus[15:8],DATA_ADDRESS);
|
||||
`endif
|
||||
DATA_OUT[7:0] <= external_data_bus_read[15:8];
|
||||
DATA_OUT[7:0] <= external_data_bus[15:8];
|
||||
read <=1;
|
||||
if(Wbit==1) begin
|
||||
biu_state <= `BIU_GET_SECOND_BYTE;
|
||||
@ -258,9 +272,9 @@ always @(posedge clock) begin
|
||||
end
|
||||
`BIU_GET_SECOND_BYTE1:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Reading 16bit %02x from %04x",{external_data_bus_read[7:0],DATA_OUT[7:0]},DATA_ADDRESS-1);//read started a byte earlier
|
||||
$display("Reading 16bit %02x from %04x",{external_data_bus[7:0],DATA_OUT[7:0]},DATA_ADDRESS-1);//read started a byte earlier
|
||||
`endif
|
||||
DATA_OUT[15:8] <= external_data_bus_read[7:0];
|
||||
DATA_OUT[15:8] <= external_data_bus[7:0];
|
||||
`finished_read
|
||||
read <=1;
|
||||
end
|
||||
@ -271,12 +285,15 @@ always @(posedge clock) begin
|
||||
VALID_DATA <= 0;
|
||||
end
|
||||
`BIU_RESET2: begin
|
||||
FIFO_start <= `L1_CACHE_SIZE'b0;
|
||||
FIFO_end <= `L1_CACHE_SIZE'b0;
|
||||
/* verilator lint_off BLKSEQ */
|
||||
FIFO_start = `L1_CACHE_SIZE'b0;
|
||||
FIFO_end = `L1_CACHE_SIZE'b0;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
INSTRUCTION_ADDRESS <= 20'hFFFF0;
|
||||
INSTRUCTION_ADDRESS <= 20'h0FFF0;
|
||||
INSTRUCTION_LOCATION <= 16'hFFF0;
|
||||
VALID_DATA <= 0;
|
||||
DATA_DIR <= 0;
|
||||
sane<=1;
|
||||
end
|
||||
default: begin
|
||||
@ -286,39 +303,60 @@ always @(posedge clock) begin
|
||||
end
|
||||
end
|
||||
|
||||
/* update VALID_INSTRUCTION and INSTRUCTION */
|
||||
always @( posedge clock) begin
|
||||
wire [2:0] Isize;
|
||||
InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},Isize);
|
||||
|
||||
if(jump_req==1)begin
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end else if(sane==1) begin
|
||||
//if(VALID_INSTRUCTION == 1 ) begin
|
||||
// `ifdef DOUBLE_INSTRUCTION_LOAD
|
||||
// if(FIFO_SIZE>`L1_CACHE_SIZE'd3+{{`L1_CACHE_SIZE-3{1'b0}},Isize})begin
|
||||
// if((fifoIsize2==2) && (FIFO_SIZE > `L1_CACHE_SIZE'd1+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}))begin
|
||||
// VALID_INSTRUCTION <= 1;
|
||||
// INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||
// INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
// end else if((fifoIsize2==3) && (FIFO_SIZE > `L1_CACHE_SIZE'd2+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}))begin
|
||||
// VALID_INSTRUCTION <= 1;
|
||||
// INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||
// INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
// INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||
// end else if(FIFO_SIZE>`L1_CACHE_SIZE'd3+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize})begin
|
||||
// VALID_INSTRUCTION <= 1;
|
||||
// INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||
// INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
// INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||
// INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
||||
// end else
|
||||
// VALID_INSTRUCTION <= 0;
|
||||
// end else begin
|
||||
// VALID_INSTRUCTION <= 0;
|
||||
// end
|
||||
// `else
|
||||
// VALID_INSTRUCTION <= 0;
|
||||
// `endif
|
||||
//end else begin
|
||||
`ifdef INCLUDE_EARLY_CALC_CIRUIT
|
||||
wire [2:0] fifoIsize;
|
||||
wire Isit1;
|
||||
InstrSize fifoInstrSize({INPUT_FIFO[FIFO_start][7:0],INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1][5:3]},fifoIsize);
|
||||
Is1 Is1(INPUT_FIFO[FIFO_start][7:0],Isit1);
|
||||
`endif
|
||||
|
||||
`ifdef DOUBLE_INSTRUCTION_LOAD
|
||||
wire [2:0] fifoIsize2;
|
||||
InstrSize fifoInstrSize2(
|
||||
{ INPUT_FIFO[FIFO_start+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}][7:0], INPUT_FIFO[FIFO_start+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}+`L1_CACHE_SIZE'd1][5:3]}
|
||||
,fifoIsize2
|
||||
);
|
||||
`endif
|
||||
|
||||
always @( valid_instruction_ack ) begin
|
||||
/* verilator lint_off BLKSEQ */
|
||||
FIFO_start = FIFO_start + {{`L1_CACHE_SIZE-3{1'b0}},Isize};
|
||||
/* verilator lint_on BLKSEQ */
|
||||
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {13'd0,Isize};
|
||||
end
|
||||
|
||||
always @( FIFO_start or FIFO_end ) begin
|
||||
if(sane==1) begin
|
||||
if(VALID_INSTRUCTION == 1 ) begin
|
||||
`ifdef DOUBLE_INSTRUCTION_LOAD
|
||||
if(FIFO_SIZE>`L1_CACHE_SIZE'd3+{{`L1_CACHE_SIZE-3{1'b0}},Isize})begin
|
||||
if((fifoIsize2==2) && (FIFO_SIZE > `L1_CACHE_SIZE'd1+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}))begin
|
||||
VALID_INSTRUCTION <= 1;
|
||||
INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
end else if((fifoIsize2==3) && (FIFO_SIZE > `L1_CACHE_SIZE'd2+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}))begin
|
||||
VALID_INSTRUCTION <= 1;
|
||||
INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||
end else if(FIFO_SIZE>`L1_CACHE_SIZE'd3+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize})begin
|
||||
VALID_INSTRUCTION <= 1;
|
||||
INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||
INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
||||
end else
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end else begin
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end
|
||||
`else
|
||||
VALID_INSTRUCTION <= 0;
|
||||
`endif
|
||||
end else begin
|
||||
//$display("trig fifoIsize=%d %d/%d [%02x %02x]",fifoIsize,FIFO_start,FIFO_end,INPUT_FIFO[FIFO_start],INPUT_FIFO[FIFO_start+1]);
|
||||
`ifdef EARLY_VALID_INSTRUCTION
|
||||
if(FIFO_start==FIFO_end) begin
|
||||
@ -345,11 +383,10 @@ always @( posedge clock) begin
|
||||
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||
INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
||||
end else
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end
|
||||
`else
|
||||
if(FIFO_start==FIFO_end) begin
|
||||
/*TODO: Same as on the first statement on the other side of the `ifdef */
|
||||
/*TODO: Same as on the first statment on the other side of the `ifdef */
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end else if(FIFO_SIZE>`L1_CACHE_SIZE'd3)begin
|
||||
VALID_INSTRUCTION <= 1;
|
||||
@ -357,29 +394,19 @@ always @( posedge clock) begin
|
||||
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||
INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
||||
end else
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end
|
||||
`endif
|
||||
//end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire [2:0] Isize;
|
||||
InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},Isize);
|
||||
|
||||
`ifdef INCLUDE_EARLY_CALC_CIRCUIT
|
||||
wire [2:0] fifoIsize;
|
||||
wire Isit1;
|
||||
InstrSize fifoInstrSize({INPUT_FIFO[FIFO_start][7:0],INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1][5:3]},fifoIsize);
|
||||
Is1 Is1(INPUT_FIFO[FIFO_start][7:0],Isit1);
|
||||
`endif
|
||||
|
||||
`ifdef DOUBLE_INSTRUCTION_LOAD
|
||||
wire [2:0] fifoIsize2;
|
||||
InstrSize fifoInstrSize2(
|
||||
{ INPUT_FIFO[FIFO_start+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}][7:0], INPUT_FIFO[FIFO_start+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}+`L1_CACHE_SIZE'd1][5:3]}
|
||||
,fifoIsize2
|
||||
);
|
||||
`endif
|
||||
always @( posedge jump_req ) begin
|
||||
/* verilator lint_off BLKSEQ */
|
||||
FIFO_start = FIFO_end ;
|
||||
/* verilator lint_on BLKSEQ */
|
||||
jump_req_latch <= 1;
|
||||
DATA_DIR <= 1;
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -1,4 +1,8 @@
|
||||
.ORG 0xFF00
|
||||
.ORG 0x84 ; INT 21
|
||||
DW 0xFFFF ; Code Segment
|
||||
DW PRINT_INT_HANDLE ; Program Counter
|
||||
|
||||
.ORG 0x0100
|
||||
start:
|
||||
MOV SP,#STACK
|
||||
MOV AX,#0x0000
|
||||
@ -21,15 +25,16 @@ dec [si]
|
||||
dec cx
|
||||
cmp CX,#0x00
|
||||
MOV CH,#0x9A
|
||||
inw #0x20
|
||||
CMP AX,#0xABCD
|
||||
TEST CH,#0x70
|
||||
jz WAZZ
|
||||
mov al,#'0
|
||||
out byte #0xA5
|
||||
mov ah,#2
|
||||
mov dl,#'1
|
||||
int #0x21
|
||||
hlt
|
||||
WAZZ:
|
||||
mov al,#'1
|
||||
out byte #0xA5
|
||||
mov ah,#2
|
||||
mov dl,#'0
|
||||
int #0x21
|
||||
hlt
|
||||
TEST_:
|
||||
ADD AX,#0xDEAD
|
||||
@ -47,5 +52,5 @@ iret
|
||||
STACK:
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xFF00
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -25,7 +25,7 @@
|
||||
/** OUTPUT **/
|
||||
/* These are usually set at build time*/
|
||||
//`define CALCULATE_IPC
|
||||
//`define OUTPUT_JSON_STATISTICS
|
||||
//`define OTUPUT_JSON_STATISTICS
|
||||
|
||||
/** Optimisations **/
|
||||
|
||||
@ -34,10 +34,8 @@
|
||||
* for the maximum instruction size worth of bytes */
|
||||
`define EARLY_VALID_INSTRUCTION
|
||||
|
||||
/*********** CURRENTLY DOESN'T WORK *************/
|
||||
/* Enables the ability in BIU to pre-decode two instructions, one after the other in memory*/
|
||||
//`define DOUBLE_INSTRUCTION_LOAD
|
||||
/************************************************/
|
||||
`define DOUBLE_INSTRUCTION_LOAD
|
||||
|
||||
/* Size is in powers of two with minimal 3.
|
||||
* 3 : 8 Bytes
|
||||
@ -47,21 +45,10 @@
|
||||
`define L1_CACHE_SIZE 4
|
||||
|
||||
|
||||
// Use high impedance instead of some other undefined value
|
||||
// when a signal is invalid (for example a data port when a
|
||||
// memory is not selected). This could be used for debug
|
||||
//`define USE_HIGH_IMPEDANCE
|
||||
|
||||
/********** Internal **********/
|
||||
`ifdef SYNTHESIS
|
||||
`undef DEBUG_REG_WRITES
|
||||
`undef DEBUG_PC_ADDRESS
|
||||
`undef DEBUG_DATA_READ_WRITES
|
||||
`undef CALCULATE_IPC
|
||||
`undef OUTPUT_JSON_STATISTICS
|
||||
`endif
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
`define CALCULATE_IPC
|
||||
`endif
|
||||
|
||||
@ -71,12 +58,12 @@
|
||||
`endif
|
||||
|
||||
`ifdef EARLY_VALID_INSTRUCTION
|
||||
`define INCLUDE_EARLY_CALC_CIRCUIT
|
||||
`define INCLUDE_EARLY_CALC_CIRUIT
|
||||
`define EARLY_VALID_INSTRUCTION_ 1
|
||||
`else
|
||||
`define EARLY_VALID_INSTRUCTION_ 0
|
||||
`endif
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
`define INCLUDE_EARLY_CALC_CIRCUIT
|
||||
`define INCLUDE_EARLY_CALC_CIRUIT
|
||||
`endif
|
||||
|
495
system/decoder.v
495
system/decoder.v
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -62,9 +62,7 @@ module decoder(
|
||||
reg SIMPLE_MICRO; /* use simple decodings (=0) or microcode data (=1) */
|
||||
wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry;
|
||||
reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr;
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
wire DEPENDS_ON_PREVIOUS;
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
wire set_params;
|
||||
|
||||
wire MEM_OR_IO, HALT,Wbit,memio_address_select;
|
||||
@ -76,7 +74,7 @@ wire [`EXEC_STATE_BITS-1:0] next_state;
|
||||
wire [`ERROR_BITS-1:0] ERROR;
|
||||
|
||||
instruction_decode instruction_decode(
|
||||
/* INPUT */ IF2DE_INSTRUCTION,{8'h0,EX2DE_FLAGS}, clock
|
||||
/* INPUT */ IF2DE_INSTRUCTION,{8'h0,EX2DE_FLAGS}
|
||||
/* MICROCODE */ ,ucode_seq_addr_entry,SIMPLE_MICRO,ucode_seq_addr
|
||||
/* OUTPUT */ ,DEPENDS_ON_PREVIOUS, set_params, MEM_OR_IO,ERROR, HALT
|
||||
|
||||
@ -91,103 +89,129 @@ instruction_decode instruction_decode(
|
||||
/* */ ,reg_write_addr, reg_read_port2_addr, reg_read_port1_addr
|
||||
);
|
||||
|
||||
reg [`DE_STATE_BITS-1:0] de_state;
|
||||
|
||||
|
||||
always @(negedge reset) begin
|
||||
de_state <= `DE_HALT; //TODO: race condition ??
|
||||
`ifdef CALCULATE_IPC
|
||||
new_instruction<=0;
|
||||
`endif
|
||||
valid_exec_data<=0;
|
||||
instant_response <= 0;
|
||||
stalled_response <= 0;
|
||||
end
|
||||
|
||||
always @(posedge reset) begin
|
||||
de_state <= `DE_STATE_ENTRY;
|
||||
/* need early init */
|
||||
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
||||
SIMPLE_MICRO <= 0;
|
||||
owe_set_init <= 0;
|
||||
set_initial_values<=0;
|
||||
wait_exec<=0;
|
||||
first_ucode <= 0;
|
||||
HALT_LATCHED <= 0;
|
||||
ERROR_LATCHED <= `ERROR_BITS'h0;
|
||||
VALID_INSTRUCTION_ACK <= 0;
|
||||
end
|
||||
|
||||
wire [2:0] instr_end;
|
||||
InstrSize InstrSize({IF2DE_INSTRUCTION[31:24],IF2DE_INSTRUCTION[21:19]},instr_end);
|
||||
|
||||
reg owe_set_init;
|
||||
|
||||
reg [1:0] wait_;
|
||||
//TODO: Why do we need to make a local copy on a register for the code inside the always @(next_state) to read it?
|
||||
// For some reason the raw VALID_INSTRUCTION signal reads always 1 and it has something to do with the block
|
||||
// being triggered by next_exec
|
||||
reg VALID_INSTRUCTION_lc;
|
||||
always @(VALID_INSTRUCTION)begin VALID_INSTRUCTION_lc<=VALID_INSTRUCTION; end
|
||||
|
||||
always @(posedge clock)begin
|
||||
if(reset==0)begin
|
||||
`ifdef CALCULATE_IPC
|
||||
new_instruction<=0;
|
||||
`endif
|
||||
valid_exec_data<=0;
|
||||
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
||||
SIMPLE_MICRO <= 0;
|
||||
owe_set_init <= 0;
|
||||
set_initial_values<=0;
|
||||
first_ucode <= 0;
|
||||
HALT_LATCHED <= 0;
|
||||
ERROR_LATCHED <= `ERROR_BITS'h0;
|
||||
VALID_INSTRUCTION_ACK <= 0;
|
||||
wait_<=0;
|
||||
reg instant_response, stalled_response;
|
||||
reg wait_exec;
|
||||
|
||||
always @(next_exec) begin
|
||||
de_state<=`DE_STATE_ENTRY;
|
||||
if ( VALID_INSTRUCTION_lc == 1 && DEPENDS_ON_PREVIOUS == 0 && ucode_seq_addr_entry==`UCODE_NO_INSTRUCTION) begin
|
||||
instant_response <= !instant_response;
|
||||
end else begin
|
||||
if(wait_==2) begin
|
||||
//`define LATCH(VAR) VAR_LATCHED <= VAR; //TODO would this work?
|
||||
IN_MOD_LATCHED <= IN_MOD;
|
||||
OUT_MOD_LATCHED <= OUT_MOD;
|
||||
RM_LATCHED <= RM;
|
||||
MEM_OR_IO_LATCHED <= MEM_OR_IO;
|
||||
PARAM1_LATCHED <= PARAM1;
|
||||
PARAM2_LATCHED <= PARAM2;
|
||||
ALU_OP_LATCHED <= ALU_OP;
|
||||
in_alu_sel1_LATCHED <= in_alu_sel1;
|
||||
in_alu_sel2_LATCHED <= in_alu_sel2;
|
||||
reg_read_port1_addr_LATCHED <= reg_read_port1_addr;
|
||||
reg_read_port2_addr_LATCHED <= reg_read_port2_addr;
|
||||
reg_write_addr_LATCHED <= reg_write_addr;
|
||||
Wbit_LATCHED <= Wbit;
|
||||
ERROR_LATCHED <= ERROR;
|
||||
HALT_LATCHED <= HALT;
|
||||
next_state_LATCHED <= next_state;
|
||||
memio_address_select_LATCHED <= memio_address_select;
|
||||
|
||||
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;
|
||||
SIMPLE_MICRO <= 1;
|
||||
first_ucode <= 1;
|
||||
set_initial_values <= 1;
|
||||
valid_exec_data <= 0;
|
||||
wait_<=1;
|
||||
end else begin
|
||||
if(SIMPLE_MICRO==0||first_ucode==1||owe_set_init==1)begin
|
||||
first_ucode <= 0;
|
||||
/* This runs at the start of the execution of an 8086 instruction */
|
||||
`ifdef DEBUG_PC_ADDRESS
|
||||
$display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,IF2DE_INSTRUCTION);
|
||||
`endif
|
||||
`ifdef CALCULATE_IPC
|
||||
new_instruction <= !new_instruction;
|
||||
`endif
|
||||
owe_set_init<=0;
|
||||
ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end};
|
||||
VALID_INSTRUCTION_ACK <= 1;
|
||||
end
|
||||
if(set_params)begin
|
||||
set_initial_values <= 1;
|
||||
end
|
||||
/* This runs at the start of each execution cycle, with microcode this is more than once per 8086 instruction */
|
||||
valid_exec_data<=1;
|
||||
wait_<=1;
|
||||
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*/
|
||||
SIMPLE_MICRO <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else if(wait_!=0) begin
|
||||
set_initial_values <= 0;
|
||||
wait_<=0;
|
||||
VALID_INSTRUCTION_ACK<=0;
|
||||
end else if(next_exec==1'b1)begin
|
||||
if ( ( VALID_INSTRUCTION == 1 || SIMPLE_MICRO == 1 ) /*&& DEPENDS_ON_PREVIOUS == 0 && ucode_seq_addr_entry==`UCODE_NO_INSTRUCTION*/) begin
|
||||
wait_<=2;
|
||||
end else
|
||||
valid_exec_data<=0;
|
||||
end else
|
||||
valid_exec_data<=0;
|
||||
wait_exec<=0;
|
||||
end
|
||||
end
|
||||
|
||||
reg first_ucode;
|
||||
|
||||
always @(instant_response or stalled_response) begin
|
||||
//`define LATCH(VAR) VAR_LATCHED <= VAR; //TODO would this work?
|
||||
IN_MOD_LATCHED <= IN_MOD;
|
||||
OUT_MOD_LATCHED <= OUT_MOD;
|
||||
RM_LATCHED <= RM;
|
||||
MEM_OR_IO_LATCHED <= MEM_OR_IO;
|
||||
PARAM1_LATCHED <= PARAM1;
|
||||
PARAM2_LATCHED <= PARAM2;
|
||||
ALU_OP_LATCHED <= ALU_OP;
|
||||
in_alu_sel1_LATCHED <= in_alu_sel1;
|
||||
in_alu_sel2_LATCHED <= in_alu_sel2;
|
||||
reg_read_port1_addr_LATCHED <= reg_read_port1_addr;
|
||||
reg_read_port2_addr_LATCHED <= reg_read_port2_addr;
|
||||
reg_write_addr_LATCHED <= reg_write_addr;
|
||||
Wbit_LATCHED <= Wbit;
|
||||
ERROR_LATCHED <= ERROR;
|
||||
HALT_LATCHED <= HALT;
|
||||
next_state_LATCHED <= next_state;
|
||||
memio_address_select_LATCHED <= memio_address_select;
|
||||
|
||||
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;
|
||||
SIMPLE_MICRO <= 1;
|
||||
first_ucode <= 1;
|
||||
set_initial_values <= !set_initial_values;
|
||||
/*keep de_state the same and rerun decode this time with all the data from the microcode rom*/
|
||||
end else begin
|
||||
if(SIMPLE_MICRO==0||first_ucode==1||owe_set_init==1)begin
|
||||
first_ucode <= 0;
|
||||
/* This runs at the start of the execution of an 8086 instruction */
|
||||
`ifdef DEBUG_PC_ADDRESS
|
||||
$display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,IF2DE_INSTRUCTION);
|
||||
`endif
|
||||
`ifdef CALCULATE_IPC
|
||||
new_instruction <= !new_instruction;
|
||||
`endif
|
||||
owe_set_init<=0;
|
||||
ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end};
|
||||
VALID_INSTRUCTION_ACK <= !VALID_INSTRUCTION_ACK;
|
||||
end
|
||||
if(set_params)begin
|
||||
set_initial_values <= !set_initial_values;
|
||||
end
|
||||
/* This runs at the start of each execution cycle, with microcode this is more than once per 8086 instruction */
|
||||
valid_exec_data<=!valid_exec_data;
|
||||
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*/
|
||||
SIMPLE_MICRO <= 0;
|
||||
end
|
||||
end
|
||||
wait_exec<=1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clock) begin
|
||||
case(de_state)
|
||||
`DE_STATE_ENTRY:begin
|
||||
if ( ( VALID_INSTRUCTION==1 || SIMPLE_MICRO == 1 ) && wait_exec==0) begin
|
||||
stalled_response <= !stalled_response;
|
||||
end
|
||||
end
|
||||
`DE_HALT:begin
|
||||
end
|
||||
default:begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
@ -200,7 +224,6 @@ module microcode(
|
||||
);
|
||||
|
||||
initial begin
|
||||
`ifndef YOSYS
|
||||
string ucode_path;
|
||||
if($value$plusargs("MICROCODE=%s",ucode_path))begin
|
||||
$readmemb(ucode_path,ucode_rom,0,`UCODE_SIZE-1);
|
||||
@ -208,10 +231,6 @@ initial begin
|
||||
$display("Please supply microcode rom file as a runtime vvp argument +MICROCODE=<path>");
|
||||
$finish;
|
||||
end
|
||||
`else
|
||||
//TODO: don't have it hard coded
|
||||
$readmemb("simplified_ucode.txt",ucode_rom,0,`UCODE_SIZE-1);
|
||||
`endif
|
||||
end
|
||||
|
||||
reg [`UCODE_DATA_BITS-1:0] ucode_rom [ 0:`UCODE_SIZE-1 ];
|
||||
@ -221,9 +240,7 @@ assign DATA=ucode_rom[ADDR];
|
||||
endmodule
|
||||
|
||||
module instruction_decode(
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
/* INPUTS */ input wire [31:0] INSTRUCTION,input wire [15:0] FLAGS,input clock
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
/* INPUTS */ input wire [31:0] INSTRUCTION,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 reg DEPENDS_ON_PREVIOUS, output reg set_params,output reg MEM_OR_IO, output reg [`ERROR_BITS-1:0] ERROR, output reg HALT
|
||||
|
||||
@ -248,10 +265,16 @@ wire [`UCODE_DATA_BITS-1:0] ucode_data;
|
||||
|
||||
microcode ucode(seq_addr_input,ucode_data);
|
||||
|
||||
`define invalid_instruction next_state=`EXEC_WAIT;ERROR<=`ERR_UNIMPL_INSTRUCTION;HALT<=0;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;opcode_size=0;DEPENDS_ON_PREVIOUS<=0;
|
||||
`define unimpl_addressing_mode next_state=`EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;HALT<=0;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||
`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO<=0;
|
||||
`define normal_microcoded ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO<=0;
|
||||
`define invalid_instruction next_state=`EXEC_WAIT;ERROR<=`ERR_UNIMPL_INSTRUCTION;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||
`define unimpl_addressing_mode next_state=`EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||
|
||||
|
||||
//TODO: A possible optimisation for instruction with 8bit parameter and
|
||||
//opcode_size=0 would be to set PARAM1 here instead of sending execution over
|
||||
//to EXEC_DE_LOAD_8_PARAM
|
||||
|
||||
`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO=0;
|
||||
`define normal_microcoded ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO=0;
|
||||
|
||||
reg [1:0] PARAM_ACTION;
|
||||
`define NO_LOAD 2'b00
|
||||
@ -264,7 +287,7 @@ reg Sbit,opcode_size;
|
||||
// then branching off of that instead of the raw bits. otherwise the code
|
||||
// would be identical
|
||||
/* verilator lint_off BLKSEQ */
|
||||
always @( posedge clock ) begin
|
||||
always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
||||
set_params = 1;
|
||||
PARAM_ACTION = `NO_LOAD;
|
||||
Sbit=0;//TODO: If no Sbit we assume it's 0,right?
|
||||
@ -275,22 +298,21 @@ always @( posedge clock ) begin
|
||||
/* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/
|
||||
opcode_size=0;
|
||||
Wbit=INSTRUCTION[24:24];
|
||||
Sbit=0;
|
||||
IN_MOD=3'b011;
|
||||
in_alu_sel1=2'b00;
|
||||
in_alu_sel2=2'b01;
|
||||
OUT_MOD=3'b011;
|
||||
MEM_OR_IO<=0;
|
||||
reg_read_port2_addr<={Wbit,3'b000};
|
||||
reg_write_addr<={Wbit,3'b000};
|
||||
ALU_OP<=`ALU_OP_ADD;
|
||||
MEM_OR_IO=0;
|
||||
reg_read_port2_addr={Wbit,3'b000};
|
||||
reg_write_addr={Wbit,3'b000};
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
memio_address_select=0;
|
||||
if(Wbit)
|
||||
PARAM_ACTION=`LOAD_16;
|
||||
else
|
||||
PARAM_ACTION=`LOAD_8;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
11'b1000_00??_101, /* SUB */
|
||||
11'b1000_00??_000 : /* ADD */ begin
|
||||
@ -306,13 +328,13 @@ always @( posedge clock ) begin
|
||||
in_alu_sel1=2'b00;
|
||||
if(IN_MOD==3'b011)begin
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_write_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
reg_write_addr={Wbit,RM};
|
||||
end else begin
|
||||
in_alu_sel2=2'b00;
|
||||
end
|
||||
OUT_MOD=IN_MOD;
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
memio_address_select=0;
|
||||
case({Sbit,Wbit}) // TODO: Isn't this supposed to be just a LOAD_8?
|
||||
2'b00,2'b11:begin
|
||||
@ -326,15 +348,15 @@ always @( posedge clock ) begin
|
||||
end
|
||||
endcase
|
||||
case(INSTRUCTION[21:19])
|
||||
3'b000: ALU_OP<=`ALU_OP_ADD;
|
||||
3'b101: ALU_OP<=`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
|
||||
end
|
||||
endcase
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
11'b1000_00??_111 : begin
|
||||
/* CMP - compare Immediate with register / memory */
|
||||
@ -349,13 +371,13 @@ always @( posedge clock ) begin
|
||||
end
|
||||
in_alu_sel1=2'b00;
|
||||
OUT_MOD=3'b100;
|
||||
MEM_OR_IO<=0;
|
||||
ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||
MEM_OR_IO=0;
|
||||
ALU_OP=`ALU_OP_SUB_REVERSE;
|
||||
memio_address_select=0;
|
||||
if(IN_MOD==3'b011)begin
|
||||
/*compare register with param*/
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end else begin
|
||||
/*compare register indirect access
|
||||
@ -369,7 +391,7 @@ always @( posedge clock ) begin
|
||||
else
|
||||
PARAM_ACTION=`LOAD_8;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
11'b1011_????_??? : begin
|
||||
/* MOV - Move Immediate byte to register */
|
||||
@ -380,16 +402,16 @@ always @( posedge clock ) begin
|
||||
in_alu_sel1=2'b00;
|
||||
in_alu_sel2=2'b00;
|
||||
OUT_MOD=3'b011;
|
||||
MEM_OR_IO<=0;
|
||||
reg_write_addr<={Wbit,INSTRUCTION[26:24]};
|
||||
MEM_OR_IO=0;
|
||||
reg_write_addr={Wbit,INSTRUCTION[26:24]};
|
||||
if(Wbit)
|
||||
PARAM_ACTION=`LOAD_16;
|
||||
else
|
||||
PARAM_ACTION=`LOAD_8;
|
||||
PARAM2=0;
|
||||
ALU_OP<=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -400,15 +422,15 @@ always @( posedge clock ) begin
|
||||
RM=INSTRUCTION[18:16];
|
||||
Wbit=INSTRUCTION[24:24];
|
||||
in_alu_sel1=2'b00;
|
||||
PARAM1<=0;
|
||||
MEM_OR_IO<=0;
|
||||
PARAM1=0;
|
||||
MEM_OR_IO=0;
|
||||
if(INSTRUCTION[25:25] == 1)begin
|
||||
/* Mem/Reg to reg */
|
||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||
if(IN_MOD==3'b011)begin
|
||||
/*Reg to Reg*/
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end else begin
|
||||
/*Mem to Reg*/
|
||||
@ -416,7 +438,7 @@ always @( posedge clock ) begin
|
||||
next_state=`EXEC_MEMIO_READ;
|
||||
end
|
||||
OUT_MOD=3'b011;
|
||||
reg_write_addr<={Wbit,INSTRUCTION[21:19]};
|
||||
reg_write_addr={Wbit,INSTRUCTION[21:19]};
|
||||
end else begin
|
||||
/* Reg to Mem/Reg */
|
||||
IN_MOD=3'b011;
|
||||
@ -424,18 +446,18 @@ always @( posedge clock ) begin
|
||||
if(IN_MOD==3'b011)begin
|
||||
/*Reg to Reg*/
|
||||
in_alu_sel2=2'b01;
|
||||
reg_write_addr<={Wbit,RM};
|
||||
reg_write_addr={Wbit,RM};
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end else begin
|
||||
/*Reg to Mem*/
|
||||
in_alu_sel2=2'b00;
|
||||
next_state=`EXEC_DE_LOAD_REG_TO_PARAM;
|
||||
end
|
||||
reg_read_port2_addr<={Wbit,INSTRUCTION[21:19]};
|
||||
reg_read_port2_addr={Wbit,INSTRUCTION[21:19]};
|
||||
end
|
||||
ALU_OP<=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -449,17 +471,17 @@ always @( posedge clock ) begin
|
||||
in_alu_sel1=2'b01;
|
||||
in_alu_sel2=2'b00;
|
||||
OUT_MOD=3'b011;
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
IN_MOD=3'b011;
|
||||
PARAM2=1;
|
||||
reg_read_port1_addr<={1'b1,INSTRUCTION[26:24]};
|
||||
reg_write_addr<={1'b1,INSTRUCTION[26:24]};
|
||||
reg_read_port1_addr={1'b1,INSTRUCTION[26:24]};
|
||||
reg_write_addr={1'b1,INSTRUCTION[26:24]};
|
||||
if(INSTRUCTION[27:27]==0)
|
||||
ALU_OP<=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
else
|
||||
ALU_OP<=`ALU_OP_SUB;
|
||||
ALU_OP=`ALU_OP_SUB;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -474,41 +496,33 @@ always @( posedge clock ) begin
|
||||
RM=INSTRUCTION[18:16];
|
||||
in_alu_sel2=(IN_MOD==3'b011)? 2'b01 : 2'b00;
|
||||
in_alu_sel1=2'b00;/* number 1 */
|
||||
PARAM1<=16'd1;
|
||||
PARAM1=1;
|
||||
OUT_MOD=IN_MOD;
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
|
||||
/*in case IN_MOD=011 */
|
||||
reg_read_port2_addr<={1'b0,RM};
|
||||
reg_write_addr<={1'b0,RM};
|
||||
reg_read_port2_addr={1'b0,RM};
|
||||
reg_write_addr={1'b0,RM};
|
||||
|
||||
ALU_OP<=(INSTRUCTION[19:19]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
||||
ALU_OP=(INSTRUCTION[19:19]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
||||
if ( IN_MOD == 3'b011 )
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
else
|
||||
next_state=`EXEC_MEMIO_READ;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
11'b1111_0100_??? : begin
|
||||
/* HLT - Halt */
|
||||
/* 1 1 1 1 0 1 0 0 | */
|
||||
opcode_size=0;
|
||||
IN_MOD=3'b011;
|
||||
HALT<=1;
|
||||
ERROR<=`ERR_NO_ERROR;
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||
|
||||
opcode_size=0;
|
||||
Wbit=1;
|
||||
in_alu_sel1=2'b10;
|
||||
in_alu_sel2=2'b00;
|
||||
PARAM2=16'hFFFF;
|
||||
ALU_OP<=`ALU_OP_ADD_SIGNED_B;
|
||||
OUT_MOD=3'b101;
|
||||
MEM_OR_IO<=0;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
next_state=`EXEC_WAIT;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -523,17 +537,18 @@ always @( posedge clock ) begin
|
||||
IN_MOD=3'b011;
|
||||
in_alu_sel1=2'b00;
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,3'b000};
|
||||
reg_read_port2_addr={Wbit,3'b000};
|
||||
OUT_MOD=3'b100;
|
||||
ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||
MEM_OR_IO<=0;
|
||||
ALU_OP=`ALU_OP_SUB_REVERSE;
|
||||
MEM_OR_IO=0;
|
||||
if(Wbit==1)
|
||||
PARAM_ACTION=`LOAD_16;
|
||||
else begin
|
||||
PARAM_ACTION=`LOAD_8;
|
||||
//PARAM1[7:0]=INSTRUCTION[7:0]; TODO:needed?
|
||||
end
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -551,8 +566,8 @@ always @( posedge clock ) begin
|
||||
in_alu_sel1=2'b10;
|
||||
in_alu_sel2=2'b00;
|
||||
PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
||||
ALU_OP<=`ALU_OP_ADD_SIGNED_B;
|
||||
MEM_OR_IO<=0;
|
||||
ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
||||
MEM_OR_IO=0;
|
||||
OUT_MOD=3'b101;
|
||||
case(INSTRUCTION[27:25])
|
||||
3'b000: begin
|
||||
@ -562,7 +577,7 @@ always @( posedge clock ) begin
|
||||
else begin
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
3'b010: begin
|
||||
/* Jump on (not) Zero */
|
||||
@ -570,7 +585,7 @@ always @( posedge clock ) begin
|
||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||
else
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
3'b100: begin
|
||||
/* Jump on (not) Sign */
|
||||
@ -578,7 +593,7 @@ always @( posedge clock ) begin
|
||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||
else
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
3'b101: begin
|
||||
/* Jump on (not) Parity */
|
||||
@ -586,7 +601,7 @@ always @( posedge clock ) begin
|
||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||
else
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
3'b001: begin
|
||||
/* Jump on (not) Carry */
|
||||
@ -594,10 +609,10 @@ always @( posedge clock ) begin
|
||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||
else
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
default:begin
|
||||
`invalid_instruction /*We don't support that condition*/
|
||||
`invalid_instruction; /*We don't support that condition*/
|
||||
end
|
||||
endcase
|
||||
DEPENDS_ON_PREVIOUS<=1;
|
||||
@ -611,11 +626,11 @@ always @( posedge clock ) begin
|
||||
in_alu_sel1=2'b10;
|
||||
in_alu_sel2=2'b00;
|
||||
PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
||||
ALU_OP<=`ALU_OP_ADD_SIGNED_B;
|
||||
ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
||||
OUT_MOD=3'b101;
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -641,7 +656,7 @@ always @( posedge clock ) begin
|
||||
opcode_size=0;
|
||||
Wbit=1;
|
||||
Sbit=0;
|
||||
PARAM1<=2;
|
||||
PARAM1=2;
|
||||
seq_addr_entry<=`UCODE_RET_ENTRY;
|
||||
`normal_microcoded
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
@ -667,7 +682,7 @@ always @( posedge clock ) begin
|
||||
Wbit=1;
|
||||
Sbit=0;
|
||||
PARAM2=2;
|
||||
reg_read_port2_addr<={1'b1,INSTRUCTION[26:24]};
|
||||
reg_read_port2_addr={1'b1,INSTRUCTION[26:24]};
|
||||
seq_addr_entry<=`UCODE_PUSH_ENTRY;
|
||||
`normal_microcoded
|
||||
memio_address_select=0;
|
||||
@ -680,18 +695,18 @@ always @( posedge clock ) begin
|
||||
Wbit=INSTRUCTION[24:24];
|
||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||
RM={INSTRUCTION[18:16]};
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
if(Wbit==1)begin
|
||||
PARAM_ACTION=`LOAD_16;
|
||||
end else begin
|
||||
PARAM_ACTION=`LOAD_8;
|
||||
end
|
||||
in_alu_sel1=2'b00; /* PARAM1 */
|
||||
ALU_OP<=`ALU_OP_AND;
|
||||
ALU_OP=`ALU_OP_AND;
|
||||
case(IN_MOD)
|
||||
3'b011:begin
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end
|
||||
default:begin
|
||||
@ -700,7 +715,7 @@ always @( posedge clock ) begin
|
||||
end
|
||||
endcase
|
||||
OUT_MOD=3'b100;/*NULL*/
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -711,7 +726,7 @@ always @( posedge clock ) begin
|
||||
Wbit=INSTRUCTION[24:24];
|
||||
IN_MOD=3'b011;
|
||||
RM=3'b000;
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
if(Wbit==1)begin
|
||||
PARAM_ACTION=`LOAD_16;
|
||||
end else begin
|
||||
@ -719,11 +734,11 @@ always @( posedge clock ) begin
|
||||
end
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
in_alu_sel1=2'b00; /* PARAM1 */
|
||||
ALU_OP<=`ALU_OP_AND;
|
||||
ALU_OP=`ALU_OP_AND;
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
OUT_MOD=3'b100;/*NULL*/
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -733,8 +748,8 @@ always @( posedge clock ) begin
|
||||
opcode_size=0;
|
||||
Wbit=1;
|
||||
Sbit=0;
|
||||
PARAM1<=2;
|
||||
reg_write_addr<={1'b1,INSTRUCTION[26:24]};
|
||||
PARAM1=2;
|
||||
reg_write_addr={1'b1,INSTRUCTION[26:24]};
|
||||
seq_addr_entry<=`UCODE_POP_ENTRY;
|
||||
`normal_microcoded
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
@ -747,19 +762,19 @@ always @( posedge clock ) begin
|
||||
Wbit=1;
|
||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||
RM=INSTRUCTION[18:16];
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
in_alu_sel1=2'b11;
|
||||
if (IN_MOD==3'b011)begin
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end else begin
|
||||
in_alu_sel2=2'b00;
|
||||
next_state=`EXEC_MEMIO_READ;
|
||||
end
|
||||
ALU_OP<=`ALU_OP_ADD;
|
||||
ALU_OP=`ALU_OP_ADD;
|
||||
OUT_MOD=3'b101;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
end
|
||||
@ -770,7 +785,7 @@ always @( posedge clock ) begin
|
||||
opcode_size=1;
|
||||
in_alu_sel1=2'b00;
|
||||
in_alu_sel2=2'b11;
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
if(Wbit==1)begin
|
||||
PARAM_ACTION=`LOAD_16;
|
||||
end else begin
|
||||
@ -780,7 +795,7 @@ always @( posedge clock ) begin
|
||||
OUT_MOD={1'b0,INSTRUCTION[23:22]};
|
||||
IN_MOD=3'b011;
|
||||
RM=INSTRUCTION[18:16];
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
@ -811,17 +826,15 @@ always @( posedge clock ) begin
|
||||
opcode_size=0;
|
||||
in_alu_sel1=2'b00;
|
||||
in_alu_sel2=2'b11;
|
||||
reg_read_port1_addr<={Wbit,3'b000};
|
||||
reg_read_port1_addr={Wbit,3'b000};
|
||||
PARAM_ACTION=`LOAD_8;
|
||||
MEM_OR_IO=1;
|
||||
HALT <= 0;
|
||||
PARAM1<=0;
|
||||
PARAM1=0;
|
||||
OUT_MOD={3'b000};
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
IN_MOD=3'b011;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
`normal_instruction
|
||||
MEM_OR_IO<=1;
|
||||
ALU_OP<=`ALU_OP_ADD;
|
||||
end
|
||||
11'b1100_1111_???:begin
|
||||
/* IRET - Return from interrupt */
|
||||
@ -831,7 +844,7 @@ always @( posedge clock ) begin
|
||||
opcode_size=0;
|
||||
Wbit=1;
|
||||
Sbit=0;
|
||||
PARAM1<=2;
|
||||
PARAM1=2;
|
||||
seq_addr_entry<=`UCODE_RET_ENTRY;
|
||||
`normal_microcoded
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
@ -846,7 +859,7 @@ always @( posedge clock ) begin
|
||||
Wbit=INSTRUCTION[24:24];
|
||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||
RM={INSTRUCTION[18:16]};
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
if(Wbit==1)begin
|
||||
PARAM_ACTION=`LOAD_16;
|
||||
end else begin
|
||||
@ -854,15 +867,15 @@ always @( posedge clock ) begin
|
||||
end
|
||||
in_alu_sel1=2'b00; /* PARAM1 */
|
||||
case(INSTRUCTION[21:19])
|
||||
3'b100: ALU_OP<=`ALU_OP_AND;
|
||||
3'b001: ALU_OP<=`ALU_OP_OR;
|
||||
3'b100: ALU_OP=`ALU_OP_AND;
|
||||
3'b001: ALU_OP=`ALU_OP_OR;
|
||||
default:begin end
|
||||
endcase
|
||||
case(IN_MOD)
|
||||
3'b011:begin
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_write_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
reg_write_addr={Wbit,RM};
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end
|
||||
default:begin
|
||||
@ -873,7 +886,7 @@ always @( posedge clock ) begin
|
||||
OUT_MOD=IN_MOD;
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
memio_address_select=0;
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end
|
||||
11'b0000_00??_???,11'b0010_10??_???,11'b0011_10??_???:begin
|
||||
/* CMP - Compare Register/memory and register */
|
||||
@ -888,11 +901,11 @@ always @( posedge clock ) begin
|
||||
IN_MOD=3'b011;
|
||||
RM=INSTRUCTION[18:16];
|
||||
in_alu_sel1=2'b01;//constantly register
|
||||
reg_read_port1_addr<={Wbit,INSTRUCTION[21:19]};
|
||||
reg_read_port1_addr={Wbit,INSTRUCTION[21:19]};
|
||||
if(IN_MOD==3'b011)begin
|
||||
in_alu_sel2=2'b01;
|
||||
reg_read_port2_addr<={Wbit,RM};
|
||||
reg_write_addr<={Wbit,RM};
|
||||
reg_read_port2_addr={Wbit,RM};
|
||||
reg_write_addr={Wbit,RM};
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
end else begin
|
||||
in_alu_sel2=2'b00;
|
||||
@ -902,12 +915,12 @@ always @( posedge clock ) begin
|
||||
PARAM_ACTION=`LOAD_8;
|
||||
end
|
||||
end
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
memio_address_select=0;
|
||||
case (INSTRUCTION[29:26])
|
||||
4'b0000: ALU_OP<=`ALU_OP_ADD;
|
||||
4'b1010: ALU_OP<=`ALU_OP_SUB;
|
||||
4'b1110: ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||
4'b0000: ALU_OP=`ALU_OP_ADD;
|
||||
4'b1010: ALU_OP=`ALU_OP_SUB;
|
||||
4'b1110: ALU_OP=`ALU_OP_SUB_REVERSE;
|
||||
default: begin end
|
||||
endcase
|
||||
case (INSTRUCTION[29:26])
|
||||
@ -919,33 +932,11 @@ always @( posedge clock ) begin
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
next_state=`EXEC_WRITE_ENTRY;
|
||||
if(INSTRUCTION[25:25]==1'b0) begin
|
||||
`normal_instruction
|
||||
`normal_instruction;
|
||||
end else begin
|
||||
`unimpl_addressing_mode
|
||||
`unimpl_addressing_mode;
|
||||
end
|
||||
end
|
||||
11'b1110_010?_???:begin
|
||||
/* IN - Read from a defined port to AL or AX */
|
||||
/* | 1 1 1 0 0 1 0 W | DATA 8 | */
|
||||
memio_address_select=1;
|
||||
OUT_MOD=3'b011;
|
||||
Wbit=INSTRUCTION[24:24];
|
||||
opcode_size=0;
|
||||
in_alu_sel1=2'b00;
|
||||
in_alu_sel2=2'b00;
|
||||
PARAM2= {8'b0,INSTRUCTION[23:16]}; //TODO: this is a bit of a hack, i should've used PARAM_ACTION but it loads into PARAM1 and messes up my next_state
|
||||
PARAM1<=0;
|
||||
reg_write_addr<={Wbit,3'b000};
|
||||
reg_read_port1_addr<={Wbit,3'b000};
|
||||
DEPENDS_ON_PREVIOUS<=0;
|
||||
IN_MOD=3'b110;
|
||||
MEM_OR_IO<=1;
|
||||
HALT<=0;
|
||||
ERROR<=0;
|
||||
ALU_OP<=`ALU_OP_ADD;
|
||||
next_state=`EXEC_MEMIO_READ_SETADDR;
|
||||
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||
end
|
||||
default:begin
|
||||
`invalid_instruction
|
||||
end
|
||||
@ -964,52 +955,51 @@ always @( posedge clock ) begin
|
||||
default: begin end /*impossible*/
|
||||
endcase
|
||||
if(ucode_data[36:36]==0) /*Set reg write address*/
|
||||
reg_write_addr <= ucode_data[12:9 ];
|
||||
reg_write_addr = ucode_data[12:9 ];
|
||||
in_alu_sel1 = ucode_data[14:13];
|
||||
in_alu_sel2 = ucode_data[16:15];
|
||||
OUT_MOD = ucode_data[19:17];
|
||||
/*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_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;
|
||||
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 */
|
||||
reg_read_port1_addr<=ucode_data[26:23];
|
||||
reg_read_port1_addr=ucode_data[26:23];
|
||||
IN_MOD=ucode_data[29:27];
|
||||
if(ucode_data[35:35]==0) /* Set reg read port 1 address */
|
||||
reg_read_port2_addr<=ucode_data[33:30];
|
||||
reg_read_port2_addr=ucode_data[33:30];
|
||||
if(ucode_data[37:37]==1) /* Overwrite Wbit */
|
||||
Wbit=ucode_data[38:38];
|
||||
memio_address_select=ucode_data[39:39];
|
||||
MEM_OR_IO<=0;
|
||||
MEM_OR_IO=0;
|
||||
HALT <= 0;
|
||||
ERROR <= 0; //TODO probably, right?
|
||||
end
|
||||
|
||||
if(PARAM_ACTION==`LOAD_8)begin
|
||||
if(opcode_size==0)begin
|
||||
if({Sbit,Wbit}==2'b11)begin
|
||||
/*signed "16bit" read*/
|
||||
PARAM1 <= {{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
||||
PARAM1 = {{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
||||
end else begin
|
||||
//PARAM1[7:0] = INSTRUCTION[23:16];
|
||||
PARAM1 <= {8'b0,INSTRUCTION[23:16]};
|
||||
PARAM1 = {8'b0,INSTRUCTION[23:16]};
|
||||
end
|
||||
end else begin
|
||||
if({Sbit,Wbit}==2'b11)begin
|
||||
/*signed "16bit" read*/
|
||||
PARAM1 <= {{8{INSTRUCTION[15:15]}},INSTRUCTION[15:8]};
|
||||
PARAM1 = {{8{INSTRUCTION[15:15]}},INSTRUCTION[15:8]};
|
||||
end else begin
|
||||
//PARAM1[7:0] = INSTRUCTION[15:8];
|
||||
PARAM1 <= {8'b0,INSTRUCTION[15:8]};
|
||||
PARAM1 = {8'b0,INSTRUCTION[15:8]};
|
||||
end
|
||||
end
|
||||
case(IN_MOD)
|
||||
@ -1018,11 +1008,11 @@ always @( posedge clock ) begin
|
||||
endcase
|
||||
end else if (PARAM_ACTION == `LOAD_16) begin
|
||||
if(opcode_size==0)begin
|
||||
PARAM1[7:0] <= INSTRUCTION[23:16];
|
||||
PARAM1[15:8] <= INSTRUCTION[15:8];
|
||||
PARAM1[7:0] = INSTRUCTION[23:16];
|
||||
PARAM1[15:8] = INSTRUCTION[15:8];
|
||||
end else begin
|
||||
PARAM1[15:8] <= INSTRUCTION[7:0];
|
||||
PARAM1[7:0] <= INSTRUCTION[15:8];
|
||||
PARAM1[15:8] = INSTRUCTION[7:0];
|
||||
PARAM1[7:0] = INSTRUCTION[15:8];
|
||||
end
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: next_state = `EXEC_MEMIO_READ;
|
||||
@ -1039,7 +1029,7 @@ endmodule
|
||||
/* IN: {INSTRUCTION[31:24],INSTRUCTION[21:19]} */
|
||||
/* OUT: number in bytes */
|
||||
module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT );
|
||||
always @* begin
|
||||
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 */
|
||||
@ -1069,16 +1059,15 @@ module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT );
|
||||
11'b1010_100?_??? : VERDICT = 3'd2+{2'b0,IN[3:3]}; /* TEST - Bitwise AND affecting only flags */
|
||||
11'b0000_00??_??? : VERDICT = 3'd2; /* ADD - Reg/memory with register to either */
|
||||
11'b0010_10??_??? : VERDICT = 3'd2; /* SUB - Reg/memory with register to either */
|
||||
11'b0011_10??_??? : VERDICT = 3'd2; /* CMP - Compare Register/memory and register */
|
||||
11'b1110_010?_??? : VERDICT = 3'd2; /* IN - Read from a defined port to AL or AX */
|
||||
11'b0011_10??_??? : VERDICT = 3'd2; /* CMP - Compare Register/memory and register */
|
||||
default: VERDICT = 3'd7;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
||||
`ifdef INCLUDE_EARLY_CALC_CIRCUIT
|
||||
`ifdef INCLUDE_EARLY_CALC_CIRUIT
|
||||
module Is1 ( input [7:0] IN, output reg VERDICT );
|
||||
always @* begin
|
||||
always @( IN ) begin
|
||||
casez(IN)
|
||||
8'b0100_???? : VERDICT = 1; /* DEC - Decrement Register | INC - Increment Register */
|
||||
8'b1111_0100 : VERDICT = 1; /* HLT - Halt */
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -21,7 +21,6 @@
|
||||
`define EXEC_STATE_BITS 4
|
||||
|
||||
|
||||
//TODO: Please clean this up
|
||||
`define EXEC_WAIT 4'b1100
|
||||
|
||||
/*DECODE SATE*/
|
||||
|
422
system/execute.v
422
system/execute.v
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -42,10 +42,10 @@ module execute_unit (
|
||||
/* */ ,output reg biu_read_request, output reg biu_jump_req,output reg biu_write_request
|
||||
|
||||
/*************** INPUT FROM BIU ****************/
|
||||
/* */ ,input BIU_VALID_DATA,input [15:0] BIU_EX_DATA_READ
|
||||
/* */ ,input BIU_VALID_DATA, input biu_data_direction
|
||||
|
||||
/**************** OUTPUT TO BIU ****************/
|
||||
/* */ ,output [15:0] BIU_EX_DATA_WRITE
|
||||
/************ BIDIRECTIONAL WITH BIU ***********/
|
||||
/* */ ,inout [15:0] BIU_DATA
|
||||
|
||||
/***************** REGISTERS *****************/
|
||||
/* */ ,input [15:0] reg_read_port1_data ,input [15:0] reg_read_port2_data, output reg [3:0] reg_read_port1_addr
|
||||
@ -57,7 +57,7 @@ assign _ALU_O_ = ALU_O;
|
||||
reg [`EXEC_STATE_BITS-1:0] exec_state;
|
||||
reg [15:0] PARAM1,PARAM2;
|
||||
|
||||
assign BIU_EX_DATA_WRITE = memio_address_select ? reg_read_port1_data : ALU_O;
|
||||
assign BIU_DATA = biu_data_direction ? (memio_address_select ? reg_read_port1_data : ALU_O): 16'hz;
|
||||
|
||||
/*############ ALU / Execution units ################################################## */
|
||||
|
||||
@ -93,231 +93,233 @@ ALU ALU1(
|
||||
|
||||
/*############ Execute logic ########################################################## */
|
||||
|
||||
always @(valid_input) begin
|
||||
exec_state <= init_state;
|
||||
reg_write_we <= 1;
|
||||
biu_jump_req <= 0;
|
||||
use_exec_reg_addr <= 0;
|
||||
end
|
||||
|
||||
always @( set_initial_values) begin
|
||||
PARAM1 <= PARAM1_INIT;
|
||||
PARAM2 <= PARAM2_INIT;
|
||||
end
|
||||
|
||||
always @(negedge reset) begin
|
||||
exec_state <= `EXEC_WAIT;
|
||||
end
|
||||
|
||||
always @(posedge reset) begin
|
||||
exec_state <= `EXEC_RESET;
|
||||
next_exec <= 0;
|
||||
end
|
||||
|
||||
`define unimpl_addressing_mode exec_state <= `EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;
|
||||
|
||||
`define finished_instruction exec_state <= `EXEC_WAIT;next_exec<=1;
|
||||
`define finished_instruction next_exec<=!next_exec; exec_state <= `EXEC_WAIT;
|
||||
|
||||
always @(posedge clock) begin
|
||||
if ( !reset ) begin
|
||||
exec_state <= `EXEC_RESET;
|
||||
end else begin
|
||||
if ( set_initial_values )begin
|
||||
PARAM1 <= PARAM1_INIT;
|
||||
PARAM2 <= PARAM2_INIT;
|
||||
case (exec_state)
|
||||
`EXEC_RESET: begin
|
||||
biu_write_request <= 0;
|
||||
biu_read_request <= 0;
|
||||
biu_jump_req <= 0;
|
||||
reg_write_we <= 1;
|
||||
exec_state <= `EXEC_WAIT;
|
||||
next_exec <= 0;
|
||||
ERROR <= `ERR_NO_ERROR;
|
||||
end
|
||||
begin
|
||||
case (exec_state)
|
||||
`EXEC_RESET: begin
|
||||
biu_write_request <= 0;
|
||||
biu_read_request <= 0;
|
||||
biu_jump_req <= 0;
|
||||
reg_write_we <= 1;
|
||||
exec_state <= `EXEC_WAIT;
|
||||
ERROR <= `ERR_NO_ERROR;
|
||||
end
|
||||
`EXEC_WAIT:begin
|
||||
if(valid_input)begin
|
||||
exec_state <= init_state;
|
||||
next_exec<=0;
|
||||
end else begin
|
||||
next_exec<=1;
|
||||
end
|
||||
biu_jump_req <= 0;
|
||||
reg_write_we <= 1;
|
||||
use_exec_reg_addr <= 0;
|
||||
ERROR<=`ERR_NO_ERROR;
|
||||
end
|
||||
`EXEC_DE_LOAD_REG_TO_PARAM:begin
|
||||
PARAM2<=reg_read_port2_data;
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: exec_state <= `EXEC_MEMIO_READ;
|
||||
default: exec_state <= `EXEC_WRITE_ENTRY;
|
||||
endcase
|
||||
end
|
||||
`EXEC_MEMIO_READ:begin
|
||||
/*Decode MOD R/M, read the data and place it to PARAM1*/
|
||||
case (IN_MOD)
|
||||
3'b000,
|
||||
3'b001,
|
||||
3'b010:begin
|
||||
case (RM)
|
||||
3'b000:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b001:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b010:begin
|
||||
/*[BP]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b011:begin
|
||||
/*[BP]+[DI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b100:begin
|
||||
/*[SI]*/
|
||||
reg_read_port1_addr <= 4'b1110;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
3'b101:begin
|
||||
/*[DI]*/
|
||||
reg_read_port1_addr <= 4'b1111;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
3'b110:begin
|
||||
/*d16 */
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b111:begin
|
||||
/*[BX]*/
|
||||
reg_read_port1_addr <= 4'b1011;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
endcase
|
||||
if(IN_MOD!=3'b000)begin
|
||||
/*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/
|
||||
`unimpl_addressing_mode;
|
||||
end
|
||||
`EXEC_WAIT:begin
|
||||
reg_write_we <= 1;
|
||||
use_exec_reg_addr <= 0;
|
||||
ERROR<=`ERR_NO_ERROR;
|
||||
end
|
||||
`EXEC_DE_LOAD_REG_TO_PARAM:begin
|
||||
PARAM2<=reg_read_port2_data;
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: exec_state <= `EXEC_MEMIO_READ;
|
||||
default: exec_state <= `EXEC_WRITE_ENTRY;
|
||||
endcase
|
||||
end
|
||||
`EXEC_MEMIO_READ:begin
|
||||
/*Decode MOD R/M, read the data and place it to PARAM1*/
|
||||
case (IN_MOD)
|
||||
3'b000,
|
||||
3'b001,
|
||||
3'b010:begin
|
||||
case (RM)
|
||||
3'b000:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b110:begin /* SP Indirect read*/
|
||||
reg_read_port1_addr <= 4'b1100;
|
||||
3'b001:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b010:begin
|
||||
/*[BP]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b011:begin
|
||||
/*[BP]+[DI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b100:begin
|
||||
/*[SI]*/
|
||||
reg_read_port1_addr <= 4'b1110;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
default:begin
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`EXEC_MEMIO_READ_SETADDR:begin
|
||||
/* if memio_address_select == 0 ADDRESS: reg_read_port1_data DATA:ALU1_O */
|
||||
/* if memio_address_select == 1 ADDRESS: ALU1_O DATA: reg_read_port1_data */
|
||||
|
||||
if(memio_address_select==0)
|
||||
BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
|
||||
else
|
||||
BIU_ADDRESS_INPUT <= ALU_O;
|
||||
|
||||
if ( BIU_VALID_DATA == 1 ) begin
|
||||
exec_state <= `EXEC_WRITE_ENTRY;
|
||||
PARAM2 <= BIU_EX_DATA_READ;
|
||||
biu_read_request <= 0;
|
||||
end else begin
|
||||
biu_read_request <= 1;
|
||||
end
|
||||
end
|
||||
`EXEC_NEXT_INSTRUCTION:begin
|
||||
`finished_instruction
|
||||
/*necessary for biu to see we went on another state from decode to give us a new instruction*/
|
||||
end
|
||||
`EXEC_WRITE_ENTRY:begin
|
||||
EX2DE_FLAGS[7:0] <= ALU_FLAGS[7:0];
|
||||
case(OUT_MOD)
|
||||
3'b000,
|
||||
3'b001,
|
||||
3'b010 : begin
|
||||
if(memio_address_select==1)
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
else
|
||||
case (RM) /* Duplicate code with write... */
|
||||
3'b000:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b001:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b010:begin
|
||||
/*[BP]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b011:begin
|
||||
/*[BP]+[DI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b100:begin
|
||||
/*[SI]*/
|
||||
reg_read_port1_addr <= 4'b1110;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
end
|
||||
3'b101:begin
|
||||
/*[DI]*/
|
||||
reg_read_port1_addr <= 4'b1111;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
end
|
||||
3'b110:begin
|
||||
/*d16 */
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b111:begin
|
||||
/*[BX]*/
|
||||
reg_read_port1_addr <= 4'b1011;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
3'b011:begin
|
||||
reg_write_we <= 0;
|
||||
`finished_instruction
|
||||
end
|
||||
3'b100:begin /*No output*/
|
||||
`finished_instruction
|
||||
end
|
||||
3'b101:begin /* Program Counter*/
|
||||
BIU_ADDRESS_INPUT <= ALU_O[15:0];
|
||||
biu_jump_req <= 1;
|
||||
exec_state <= `EXEC_JUMP_RELEASE;
|
||||
end
|
||||
3'b110:begin /* SP Indirect write*/
|
||||
reg_read_port1_addr <= 4'b1100;
|
||||
3'b101:begin
|
||||
/*[DI]*/
|
||||
reg_read_port1_addr <= 4'b1111;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
3'b111:begin /* Write to PRAM1 (for microcode calculations) */
|
||||
PARAM1 <= ALU_O;
|
||||
`finished_instruction
|
||||
end
|
||||
default:begin
|
||||
3'b110:begin
|
||||
/*d16 */
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b111:begin
|
||||
/*[BX]*/
|
||||
reg_read_port1_addr <= 4'b1011;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`EXEC_JUMP_RELEASE:begin
|
||||
biu_jump_req <= 0;
|
||||
`finished_instruction
|
||||
end
|
||||
`EXEC_MEMIO_WRITE:begin
|
||||
/* if memio_address_select == 0 ADDRESS: reg_read_port1_data DATA:ALU1_O */
|
||||
/* if memio_address_select == 1 ADDRESS: ALU1_O DATA: reg_read_port1_data */
|
||||
|
||||
biu_write_request <= 1;
|
||||
|
||||
if(memio_address_select==0)
|
||||
BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
|
||||
else
|
||||
BIU_ADDRESS_INPUT <= ALU_O;
|
||||
|
||||
if (write == 0) begin //TODO: don't do it that way or better yet don't do it at all somehow
|
||||
biu_write_request <= 0;
|
||||
`finished_instruction
|
||||
if(IN_MOD!=3'b000)begin
|
||||
/*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/
|
||||
`unimpl_addressing_mode;
|
||||
end
|
||||
|
||||
end
|
||||
3'b110:begin /* SP Indirect read*/
|
||||
reg_read_port1_addr <= 4'b1100;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
default:begin
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
`EXEC_MEMIO_READ_SETADDR:begin
|
||||
if(memio_address_select==0)
|
||||
BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
|
||||
else
|
||||
BIU_ADDRESS_INPUT <= ALU_O;
|
||||
|
||||
if ( BIU_VALID_DATA == 1 ) begin
|
||||
exec_state <= `EXEC_WRITE_ENTRY;
|
||||
PARAM2 <= BIU_DATA;
|
||||
biu_read_request <= 0;
|
||||
end else begin
|
||||
biu_read_request <= 1;
|
||||
end
|
||||
end
|
||||
`EXEC_NEXT_INSTRUCTION:begin
|
||||
`finished_instruction
|
||||
/*necessary for biu to see we went on another state from decode to give us a new instruction*/
|
||||
end
|
||||
`EXEC_WRITE_ENTRY:begin
|
||||
EX2DE_FLAGS[7:0] <= ALU_FLAGS[7:0];
|
||||
case(OUT_MOD)
|
||||
3'b000,
|
||||
3'b001,
|
||||
3'b010 : begin
|
||||
if(memio_address_select==1)
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
else
|
||||
case (RM) /* Duplicate code with write... */
|
||||
3'b000:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b001:begin
|
||||
/*[BX]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b010:begin
|
||||
/*[BP]+[SI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b011:begin
|
||||
/*[BP]+[DI]*/
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b100:begin
|
||||
/*[SI]*/
|
||||
reg_read_port1_addr <= 4'b1110;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
end
|
||||
3'b101:begin
|
||||
/*[DI]*/
|
||||
reg_read_port1_addr <= 4'b1111;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
end
|
||||
3'b110:begin
|
||||
/*d16 */
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
3'b111:begin
|
||||
/*[BX]*/
|
||||
reg_read_port1_addr <= 4'b1011;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
3'b011:begin
|
||||
reg_write_we <= 0;
|
||||
`finished_instruction
|
||||
end
|
||||
3'b100:begin /*No output*/
|
||||
`finished_instruction
|
||||
end
|
||||
3'b101:begin /* Program Counter*/
|
||||
BIU_ADDRESS_INPUT <= ALU_O[15:0];
|
||||
biu_jump_req <= 1;
|
||||
exec_state <= `EXEC_JUMP_RELEASE;
|
||||
end
|
||||
3'b110:begin /* SP Indirect write*/
|
||||
reg_read_port1_addr <= 4'b1100;
|
||||
use_exec_reg_addr <= 1;
|
||||
exec_state <= `EXEC_MEMIO_WRITE;
|
||||
end
|
||||
3'b111:begin /* Write to PRAM1 (for microcode calculations) */
|
||||
PARAM1 <= ALU_O;
|
||||
`finished_instruction
|
||||
end
|
||||
default:begin
|
||||
`unimpl_addressing_mode
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`EXEC_JUMP_RELEASE:begin
|
||||
biu_jump_req <= 0;
|
||||
`finished_instruction
|
||||
end
|
||||
`EXEC_MEMIO_WRITE:begin
|
||||
/* if memio_address_select == 0 ADDRESS: reg_read_port1_data DATA:ALU1_O */
|
||||
/* if memio_address_select == 1 ADDRESS: ALU1_O DATA: reg_read_port1_data */
|
||||
|
||||
biu_write_request <= 1;
|
||||
|
||||
if(memio_address_select==0)
|
||||
BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
|
||||
else
|
||||
BIU_ADDRESS_INPUT <= ALU_O;
|
||||
|
||||
if (write == 0) begin //TODO: don't do it that was or better yet don't do it at all somehow
|
||||
biu_write_request <= 0;
|
||||
`finished_instruction
|
||||
end
|
||||
|
||||
end
|
||||
default:begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -1,39 +0,0 @@
|
||||
|
||||
#### ECP5 specific ####
|
||||
ECP5_DEVICE=25F
|
||||
# ECP5_DEVICE: 25F: Create bitstream for the LFE5U-25F
|
||||
# 85F: Create bitstream for the LFE5U-85F
|
||||
ECP5_PACKAGE=CSFBGA285
|
||||
# ECP5_PACKAGE: CSFBGA285: The one used in OrangeCrab
|
||||
|
||||
FPGA_FILE_EXT=dfu
|
||||
|
||||
#This is on the 8th postiion in the chip id, for example
|
||||
# LFE5U-25-7BG381I
|
||||
# ^---------- this would be a 7 speed grade
|
||||
#
|
||||
# 6 is the slowest and 8 is the fastest
|
||||
ECP5_SPEED_GRADE=8
|
||||
|
||||
ROM_PART_ID=24lc512
|
||||
|
||||
######## End of user configuration ########
|
||||
|
||||
#NOT USED OUTSIDE OF HERE
|
||||
FPGA_SOC_COMMON_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 peripherals/I2C_driver_multiplexer.v peripherals/CPU_to_I2C_driver_bridge.v
|
||||
|
||||
FPGA_SOC_SOURCES=${FPGA_SOC_COMMON_SOURCES} external_ip/litedram_core_ecp5_phy.v
|
||||
FPGA_SOC_SIM_SOURCES=${FPGA_SOC_COMMON_SOURCES} fpga_config/OrangeCrab_r0.2.1/verilator_config.vlt external_ip/litedram_core_ecp5_phy_sim.v
|
||||
|
||||
FPGA_BOOTCODE=../boot_code/i2c_bootloader.stxt
|
||||
|
||||
ROM_FILE=../boot_code/brainfuck_mandelbrot.bin
|
||||
|
||||
upload_bitstream: dfu_upload
|
||||
upload_bootrom: minipro_upload
|
||||
|
||||
${BUILD_FILES_PREFIX}bitstream_${BUILD_NAME}.bit:${BUILD_FILES_PREFIX}nextpnr-ecp5_${BUILD_NAME}.bit
|
||||
${Q}cp "$^" "$@"
|
||||
|
||||
${BUILD_FILES_PREFIX}synth_${FPGA_BOARD}.json:${BUILD_FILES_PREFIX}synth_ecp5_${FPGA_BOARD}.json
|
||||
${Q}cp "$^" "$@"
|
@ -1,630 +0,0 @@
|
||||
/* top.v - Implements FPGA and Board specific circuitry
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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/>. */
|
||||
|
||||
`include "error_header.v"
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`include "config.v"
|
||||
`endif
|
||||
|
||||
module fpga_top(
|
||||
input clk48,
|
||||
input user_button,
|
||||
// output reset_n,
|
||||
|
||||
output rgb_led0_r,
|
||||
output rgb_led0_g,
|
||||
output rgb_led0_b,
|
||||
|
||||
`ifdef SYNTHESIS
|
||||
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 i2c_sda,/*sda*/
|
||||
output i2c_scl /*scl*/
|
||||
`else
|
||||
output i2c_dir,
|
||||
output i2c_scl,
|
||||
input i2c_sda_in,
|
||||
output i2c_sda_out
|
||||
`endif
|
||||
);
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
string waveform_name;
|
||||
initial begin
|
||||
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
||||
$dumpfile(waveform_name);
|
||||
$dumpvars(0,p,cycles);
|
||||
end
|
||||
end
|
||||
//TODO: should there be some common file between all the fpga_tops and system.v for this stuff?
|
||||
always @(posedge clk48) begin
|
||||
if(HALT==1&&disp_cache_start==disp_cache_end)begin
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
reg sane;
|
||||
always @(posedge reset)begin sane<=1; end
|
||||
always @( ERROR ) begin
|
||||
if ( ERROR != `ERR_NO_ERROR && sane == 1 ) begin
|
||||
$display("PROCESSOR RUN INTO AN ERROR.");
|
||||
case (ERROR)
|
||||
default:begin
|
||||
end
|
||||
`ERR_UNIMPL_INSTRUCTION:begin
|
||||
$display("Unimplemented instruction");
|
||||
end
|
||||
`ERR_UNIMPL_ADDRESSING_MODE: begin
|
||||
$display("Unimplemented addressing mode");
|
||||
end
|
||||
endcase
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
`ifdef SYNTHESIS
|
||||
assign ddram_a[15:13] = 3'b0;
|
||||
assign ddram_vccio = 6'd63;
|
||||
assign ddram_gnd = 2'd0;
|
||||
`endif
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
`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
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
|
||||
reg [2:0]rgb_led_color;
|
||||
assign rgb_led0_r=rgb_led_color[0];
|
||||
assign rgb_led0_g=rgb_led_color[1];
|
||||
assign rgb_led0_b=rgb_led_color[2];
|
||||
|
||||
// A bit useless since if the cpu ERRORS out or HALTS it will continue executing anyway
|
||||
//always @(HALT or ERROR or user_button) begin
|
||||
// if (HALT==1) begin
|
||||
// /* yellow */
|
||||
// rgb_led_color<=3'b100;
|
||||
// end else if (ERROR != `ERROR_BITS'b0) begin
|
||||
// /* red */
|
||||
// rgb_led_color<=3'b110;
|
||||
// end else begin
|
||||
// /* green */
|
||||
// rgb_led_color<=3'b101;
|
||||
// end
|
||||
//end
|
||||
|
||||
// Create a 27 bit register
|
||||
reg [26:0] counter = 0;
|
||||
|
||||
// Every positive edge increment register by 1
|
||||
always @(posedge clk48) begin
|
||||
counter <= counter + 1;
|
||||
end
|
||||
|
||||
/*** RESET CIRCUIT ***/
|
||||
|
||||
reg reset=0;
|
||||
reg [1:0] state=0;
|
||||
|
||||
always @(posedge counter[15]) begin
|
||||
if(user_button==0)
|
||||
state<=2'b00;
|
||||
case (state)
|
||||
2'b00:begin
|
||||
reset<=0;
|
||||
state<=2'b01;
|
||||
end
|
||||
2'b01:begin
|
||||
reset<=1;
|
||||
state<=2'b10;
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
//------------------------------------------//
|
||||
// Cache to allow the slow display to have a
|
||||
// chance to keep up with the relentless CPU
|
||||
|
||||
reg [7:0] disp_cache_start=0;
|
||||
reg [7:0] disp_cache_end=0;
|
||||
reg [7:0] disp_write_cache [255:0];
|
||||
reg ascii_state=0;
|
||||
always @(posedge CPU_SPEED)begin
|
||||
|
||||
if(wr==0)begin
|
||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )begin
|
||||
disp_write_cache[disp_cache_end]<=data_bus_write[15:8];
|
||||
disp_cache_end<=disp_cache_end+8'd1;
|
||||
end else if(IOMEM==1'b1 && address_bus[7:0]==8'hB0 )begin
|
||||
if(data_bus_write[0:0]==1)
|
||||
rgb_led_color<=3'b000;
|
||||
else
|
||||
rgb_led_color<=3'b111;
|
||||
end
|
||||
end else if(ascii_state==1'b0)begin
|
||||
if(ascii_data_ready&disp_cache_start!=disp_cache_end)begin
|
||||
`ifndef SYNTHESIS
|
||||
$write("%s" ,disp_write_cache[disp_cache_start]); // TODO: maybe simulate the i2c lcd
|
||||
`endif
|
||||
ascii_data<=disp_write_cache[disp_cache_start];
|
||||
disp_cache_start<=disp_cache_start+8'd1;
|
||||
ascii_data_write_req<=1;
|
||||
ascii_state<=1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if(ascii_state==1'b1)begin
|
||||
if(!ascii_data_ready)begin
|
||||
ascii_data_write_req<=0;
|
||||
ascii_state<=1'b0;
|
||||
end
|
||||
end
|
||||
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 : ( (address_bus[7:4] == 4'h4) ? Wishbone_driver_data_bus_read:CPU_I2C_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));
|
||||
assign i2c_cs= !((IOMEM==1)&&(address_bus[7:4] == 4'h6));
|
||||
|
||||
assign wait_state_I2C=(i2c_cs==1'b0&&rd==1'b0)^i2c_cs_1d;
|
||||
|
||||
reg i2c_cs_1d;
|
||||
|
||||
always @(posedge CPU_SPEED)begin
|
||||
i2c_cs_1d<=(i2c_cs==1'b0&&rd==1'b0);
|
||||
end // TODO: Probably would need to so the same for the wishbone IO
|
||||
|
||||
wire wait_state_I2C;
|
||||
/// DDR3 Controller
|
||||
|
||||
wire ddr3_init_done,ddr3_init_error,ddr3_pll_locked;
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
wire user_rst;
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
`ifndef SYNTHESIS
|
||||
assign ddr3_pll_locked=1;
|
||||
wire sim_trace;
|
||||
assign sim_trace=0;//signal is not connected on litedram, not sure what was the idea behind it
|
||||
`endif
|
||||
|
||||
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),
|
||||
.BHE(BHE),
|
||||
.data_bus_in(data_bus_write),
|
||||
.data_bus_out(data_bus_read_DDR3),
|
||||
.wait_state(wait_state_WBIO),
|
||||
.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;
|
||||
assign wait_state=wait_state_WBIO||wait_state_I2C;
|
||||
wire wait_state_WBIO;
|
||||
|
||||
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),
|
||||
`ifdef SYNTHESIS
|
||||
.rst(!reset),
|
||||
.pll_locked(ddr3_pll_locked),
|
||||
`else
|
||||
.sim_trace(sim_trace),
|
||||
`endif
|
||||
|
||||
////// DDR3 INTERFACE //////
|
||||
`ifdef SYNTHESIS
|
||||
.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),
|
||||
`endif
|
||||
|
||||
/////// 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),
|
||||
.user_rst(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)
|
||||
);
|
||||
|
||||
wire [15:0]CPU_I2C_data_bus_read;
|
||||
wire i2c_cs;
|
||||
|
||||
wire [6:0] CPU_I2C_OUT_ADDRESS;
|
||||
wire CPU_I2C_OUT_BUSY,CPU_I2C_OUT_TRANSACT,CPU_I2C_DIR;
|
||||
wire [15:0]CPU_I2C_DATA_READ,CPU_I2C_DATA_WRITE;
|
||||
wire CPU_I2C_IGN_ACK;
|
||||
wire CPU_I2C_ERROR;
|
||||
|
||||
CPU_to_I2C_driver_bridge CPU_to_I2C_driver_bridge (
|
||||
.clock(CPU_SPEED),
|
||||
.reset_n(reset),
|
||||
|
||||
// CPU INTERFACE
|
||||
.address(address_bus[2:0]),
|
||||
.data_bus_in(data_bus_write),
|
||||
.data_bus_out(CPU_I2C_data_bus_read),
|
||||
.read_n(rd),
|
||||
.write_n(wr),
|
||||
.chip_select_n(i2c_cs),
|
||||
|
||||
// I2C DRIVER INTERFACE
|
||||
.OUT_ADDRESS(CPU_I2C_OUT_ADDRESS),
|
||||
.OUT_BUSY(CPU_I2C_OUT_BUSY),
|
||||
.OUT_TRANSACT(CPU_I2C_OUT_TRANSACT),
|
||||
.DIR(CPU_I2C_DIR),
|
||||
.OUT_I2C_DATA_READ(CPU_I2C_DATA_READ),
|
||||
.OUT_I2C_DATA_WRITE(CPU_I2C_DATA_WRITE),
|
||||
|
||||
.TRANS_WIDTH(CPU_I2C_TRANS_WIDTH),
|
||||
.OUT_IGN_ACK(CPU_I2C_IGN_ACK),
|
||||
.IN_ERROR(CPU_I2C_ERROR)
|
||||
);
|
||||
|
||||
// Display driver
|
||||
|
||||
wire ascii_data_ready;
|
||||
reg ascii_data_write_req=0;
|
||||
reg [7:0] ascii_data;
|
||||
ascii_to_HD44780_driver LCD_DRIVER(
|
||||
/* system */
|
||||
I2C_SPEED,
|
||||
1'b1,
|
||||
|
||||
/* Data Input */
|
||||
ascii_data_ready,
|
||||
ascii_data_write_req,
|
||||
ascii_data,
|
||||
|
||||
/* write circuitry */
|
||||
!pcf_busy,
|
||||
pcf_write_req,
|
||||
pcf_data,
|
||||
pcf_command_data
|
||||
);
|
||||
|
||||
// Port expander driver
|
||||
|
||||
wire pcf_write_req,pcf_command_data,pcf_busy;
|
||||
wire [3:0]pcf_data;
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
wire [7:0]DISP_I2C_DATA_WRITE;
|
||||
wire [15:0]DISP_I2C_DATA_READ;
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
wire DISP_I2C_BUSY,DISP_I2C_TRANSACT;
|
||||
wire [6:0] DISP_I2C_ADDRESS;
|
||||
assign DISP_I2C_ADDRESS=7'h27;
|
||||
wire DISP_DIR;
|
||||
|
||||
pcf8574_for_HD44780 PCF8574_driver(
|
||||
.clock(I2C_SPEED),
|
||||
|
||||
.pcf_write_req(pcf_write_req),
|
||||
.pcf_command_data(pcf_command_data),
|
||||
.pcf_data(pcf_data),
|
||||
|
||||
.pcf_busy(pcf_busy),
|
||||
.new_backlight(1'b0),
|
||||
.backlight_update(1'b0),
|
||||
|
||||
.DIR(DISP_DIR),
|
||||
.I2C_BUSY(DISP_I2C_BUSY),
|
||||
.I2C_TRANSACT(DISP_I2C_TRANSACT),
|
||||
|
||||
.i2c_data_write(DISP_I2C_DATA_WRITE)
|
||||
);
|
||||
|
||||
wire [6:0]MULT_TO_DRIV_I2C_ADDRESS;
|
||||
wire MULT_TO_DRIV_I2C_BUSY;
|
||||
wire MULT_TO_DRIV_I2C_TRANSACT;
|
||||
wire [15:0]MULT_TO_DRIV_DATA_WRITE, MULT_TO_DRIV_DATA_READ;
|
||||
wire MULT_TO_DRIV_DIR;
|
||||
wire CPU_I2C_TRANS_WIDTH;
|
||||
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
wire DISP_ERROR; //TODO: It would be ideal to acknoledge any warnings but it's not really too important
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
I2C_driver_multiplexer I2C_driver_multiplexer(
|
||||
.clock(I2C_SPEED),
|
||||
.reset_n(reset),
|
||||
|
||||
////// INPUT 1 ///////
|
||||
.IN1_ADDRESS(DISP_I2C_ADDRESS),
|
||||
.IN1_BUSY(DISP_I2C_BUSY),
|
||||
.IN1_DIR(DISP_DIR),
|
||||
.IN1_TRANSACT(DISP_I2C_TRANSACT),
|
||||
.IN1_I2C_DATA_READ(DISP_I2C_DATA_READ),
|
||||
.IN1_I2C_DATA_WRITE({8'h0,DISP_I2C_DATA_WRITE}),
|
||||
.IN1_TRANS_WIDTH(1'b0),
|
||||
.IN1_IGN_ACK(1'b0),
|
||||
.IN1_ERROR(DISP_ERROR),
|
||||
|
||||
////// INPUT 2 ///////
|
||||
.IN2_ADDRESS(CPU_I2C_OUT_ADDRESS),
|
||||
.IN2_BUSY(CPU_I2C_OUT_BUSY),
|
||||
.IN2_TRANSACT(CPU_I2C_OUT_TRANSACT),
|
||||
.IN2_DIR(CPU_I2C_DIR),
|
||||
.IN2_I2C_DATA_READ(CPU_I2C_DATA_READ),
|
||||
.IN2_I2C_DATA_WRITE(CPU_I2C_DATA_WRITE),
|
||||
.IN2_TRANS_WIDTH(CPU_I2C_TRANS_WIDTH),
|
||||
.IN2_IGN_ACK(CPU_I2C_IGN_ACK),
|
||||
.IN2_ERROR(CPU_I2C_ERROR),
|
||||
|
||||
////// OUTPUT ///////
|
||||
.OUT_ADDRESS(MULT_TO_DRIV_I2C_ADDRESS),
|
||||
.OUT_BUSY(MULT_TO_DRIV_I2C_BUSY),
|
||||
.OUT_TRANSACT(MULT_TO_DRIV_I2C_TRANSACT),
|
||||
.OUT_DIR(MULT_TO_DRIV_DIR),
|
||||
.OUT_I2C_DATA_WRITE(MULT_TO_DRIV_DATA_WRITE),
|
||||
.OUT_I2C_DATA_READ(MULT_TO_DRIV_DATA_READ),
|
||||
.OUT_TRANS_WIDTH(MULT_TO_DRIV_TRANS_WIDTH),
|
||||
.OUT_IGN_ACK(MULT_TO_DRIV_IGN_ACK),
|
||||
.OUT_ERROR(MULT_TO_DRIV_ERROR)
|
||||
);
|
||||
|
||||
// I2C driver
|
||||
|
||||
wire SDA_direction;
|
||||
wire SCL,SDA_input,SDA_output;
|
||||
wire MULT_TO_DRIV_TRANS_WIDTH;
|
||||
wire MULT_TO_DRIV_IGN_ACK;
|
||||
wire MULT_TO_DRIV_ERROR;
|
||||
|
||||
I2C_driver i2c_driver(
|
||||
.clock(I2C_SPEED),
|
||||
|
||||
.SDA_input(SDA_input),
|
||||
.SDA_output(SDA_output),
|
||||
.SDA_direction(SDA_direction),
|
||||
.SCL(SCL),
|
||||
|
||||
.address(MULT_TO_DRIV_I2C_ADDRESS),
|
||||
.I2C_BUSY(MULT_TO_DRIV_I2C_BUSY),
|
||||
.I2C_TRANSACT(MULT_TO_DRIV_I2C_TRANSACT),
|
||||
.DIR(MULT_TO_DRIV_DIR),
|
||||
.i2c_data_write(MULT_TO_DRIV_DATA_WRITE),
|
||||
.i2c_data_read(MULT_TO_DRIV_DATA_READ),
|
||||
|
||||
.transact_width(MULT_TO_DRIV_TRANS_WIDTH),
|
||||
.ignore_ack(MULT_TO_DRIV_IGN_ACK),
|
||||
|
||||
.error(MULT_TO_DRIV_ERROR)
|
||||
);
|
||||
|
||||
`ifdef SYNTHESIS
|
||||
|
||||
TRELLIS_IO #(
|
||||
// Parameters.
|
||||
.DIR ("BIDIR")
|
||||
) TRELLIS_IO_00 (
|
||||
// pin
|
||||
.B (i2c_sda),
|
||||
//input
|
||||
.I (1'd0),
|
||||
//Direction
|
||||
.T (~( SDA_direction & (~SDA_output) )),
|
||||
// Output
|
||||
.O (SDA_input)
|
||||
);
|
||||
|
||||
assign i2c_scl=SCL;
|
||||
|
||||
`else
|
||||
|
||||
assign i2c_dir=SDA_direction;
|
||||
assign i2c_scl=SCL;
|
||||
assign SDA_input=i2c_sda_in;
|
||||
assign i2c_sda_out=SDA_output;
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
@ -1,257 +0,0 @@
|
||||
LOCATE COMP "clk48" SITE "A9";
|
||||
IOBUF PORT "clk48" IO_TYPE=LVCMOS33;
|
||||
FREQUENCY PORT "clk48" 48.0 MHz;
|
||||
LOCATE COMP "ddram_a[0]" SITE "C4";
|
||||
IOBUF PORT "ddram_a[0]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[0]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[1]" SITE "D2";
|
||||
IOBUF PORT "ddram_a[1]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[1]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[2]" SITE "D3";
|
||||
IOBUF PORT "ddram_a[2]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[2]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[3]" SITE "A3";
|
||||
IOBUF PORT "ddram_a[3]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[3]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[4]" SITE "A4";
|
||||
IOBUF PORT "ddram_a[4]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[4]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[5]" SITE "D4";
|
||||
IOBUF PORT "ddram_a[5]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[5]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[6]" SITE "C3";
|
||||
IOBUF PORT "ddram_a[6]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[6]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[7]" SITE "B2";
|
||||
IOBUF PORT "ddram_a[7]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[7]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[8]" SITE "B1";
|
||||
IOBUF PORT "ddram_a[8]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[8]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[9]" SITE "D1";
|
||||
IOBUF PORT "ddram_a[9]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[9]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[10]" SITE "A7";
|
||||
IOBUF PORT "ddram_a[10]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[10]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[11]" SITE "C2";
|
||||
IOBUF PORT "ddram_a[11]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[11]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[12]" SITE "B6";
|
||||
IOBUF PORT "ddram_a[12]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[12]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[13]" SITE "C1";
|
||||
IOBUF PORT "ddram_a[13]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[13]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[14]" SITE "A2";
|
||||
IOBUF PORT "ddram_a[14]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[14]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_a[15]" SITE "C7";
|
||||
IOBUF PORT "ddram_a[15]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_a[15]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_ba[0]" SITE "D6";
|
||||
IOBUF PORT "ddram_ba[0]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_ba[0]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_ba[1]" SITE "B7";
|
||||
IOBUF PORT "ddram_ba[1]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_ba[1]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_ba[2]" SITE "A6";
|
||||
IOBUF PORT "ddram_ba[2]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_ba[2]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_ras_n" SITE "C12";
|
||||
IOBUF PORT "ddram_ras_n" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_ras_n" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_cas_n" SITE "D13";
|
||||
IOBUF PORT "ddram_cas_n" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_cas_n" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_we_n" SITE "B12";
|
||||
IOBUF PORT "ddram_we_n" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_we_n" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_cs_n" SITE "A12";
|
||||
IOBUF PORT "ddram_cs_n" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_cs_n" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_dm[0]" SITE "D16";
|
||||
IOBUF PORT "ddram_dm[0]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dm[0]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_dm[1]" SITE "G16";
|
||||
IOBUF PORT "ddram_dm[1]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dm[1]" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_dq[0]" SITE "C17";
|
||||
IOBUF PORT "ddram_dq[0]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[0]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[0]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[1]" SITE "D15";
|
||||
IOBUF PORT "ddram_dq[1]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[1]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[1]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[2]" SITE "B17";
|
||||
IOBUF PORT "ddram_dq[2]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[2]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[2]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[3]" SITE "C16";
|
||||
IOBUF PORT "ddram_dq[3]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[3]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[3]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[4]" SITE "A15";
|
||||
IOBUF PORT "ddram_dq[4]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[4]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[4]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[5]" SITE "B13";
|
||||
IOBUF PORT "ddram_dq[5]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[5]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[5]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[6]" SITE "A17";
|
||||
IOBUF PORT "ddram_dq[6]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[6]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[6]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[7]" SITE "A13";
|
||||
IOBUF PORT "ddram_dq[7]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[7]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[7]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[8]" SITE "F17";
|
||||
IOBUF PORT "ddram_dq[8]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[8]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[8]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[9]" SITE "F16";
|
||||
IOBUF PORT "ddram_dq[9]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[9]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[9]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[10]" SITE "G15";
|
||||
IOBUF PORT "ddram_dq[10]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[10]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[10]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[11]" SITE "F15";
|
||||
IOBUF PORT "ddram_dq[11]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[11]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[11]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[12]" SITE "J16";
|
||||
IOBUF PORT "ddram_dq[12]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[12]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[12]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[13]" SITE "C18";
|
||||
IOBUF PORT "ddram_dq[13]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[13]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[13]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[14]" SITE "H16";
|
||||
IOBUF PORT "ddram_dq[14]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[14]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[14]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dq[15]" SITE "F18";
|
||||
IOBUF PORT "ddram_dq[15]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dq[15]" IO_TYPE=SSTL135_I;
|
||||
IOBUF PORT "ddram_dq[15]" TERMINATION=OFF;
|
||||
LOCATE COMP "ddram_dqs_p[0]" SITE "B15";
|
||||
IOBUF PORT "ddram_dqs_p[0]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dqs_p[0]" IO_TYPE=SSTL135D_I;
|
||||
IOBUF PORT "ddram_dqs_p[0]" TERMINATION=OFF;
|
||||
IOBUF PORT "ddram_dqs_p[0]" DIFFRESISTOR=100;
|
||||
LOCATE COMP "ddram_dqs_p[1]" SITE "G18";
|
||||
IOBUF PORT "ddram_dqs_p[1]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_dqs_p[1]" IO_TYPE=SSTL135D_I;
|
||||
IOBUF PORT "ddram_dqs_p[1]" TERMINATION=OFF;
|
||||
IOBUF PORT "ddram_dqs_p[1]" DIFFRESISTOR=100;
|
||||
LOCATE COMP "ddram_clk_p" SITE "J18";
|
||||
IOBUF PORT "ddram_clk_p" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_clk_p" IO_TYPE=SSTL135D_I;
|
||||
LOCATE COMP "ddram_cke" SITE "D18";
|
||||
IOBUF PORT "ddram_cke" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_cke" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_odt" SITE "C13";
|
||||
IOBUF PORT "ddram_odt" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_odt" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_reset_n" SITE "L18";
|
||||
IOBUF PORT "ddram_reset_n" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_reset_n" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "ddram_vccio[0]" SITE "K16";
|
||||
IOBUF PORT "ddram_vccio[0]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_vccio[0]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "ddram_vccio[1]" SITE "D17";
|
||||
IOBUF PORT "ddram_vccio[1]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_vccio[1]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "ddram_vccio[2]" SITE "K15";
|
||||
IOBUF PORT "ddram_vccio[2]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_vccio[2]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "ddram_vccio[3]" SITE "K17";
|
||||
IOBUF PORT "ddram_vccio[3]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_vccio[3]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "ddram_vccio[4]" SITE "B18";
|
||||
IOBUF PORT "ddram_vccio[4]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_vccio[4]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "ddram_vccio[5]" SITE "C6";
|
||||
IOBUF PORT "ddram_vccio[5]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_vccio[5]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "ddram_gnd[0]" SITE "L15";
|
||||
IOBUF PORT "ddram_gnd[0]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_gnd[0]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "ddram_gnd[1]" SITE "L16";
|
||||
IOBUF PORT "ddram_gnd[1]" SLEWRATE=FAST;
|
||||
IOBUF PORT "ddram_gnd[1]" IO_TYPE=SSTL135_II;
|
||||
LOCATE COMP "rgb_led0_r" SITE "K4";
|
||||
IOBUF PORT "rgb_led0_r" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "rgb_led0_g" SITE "M3";
|
||||
IOBUF PORT "rgb_led0_g" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "rgb_led0_b" SITE "J3";
|
||||
IOBUF PORT "rgb_led0_b" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "gpio_0" SITE "N17";
|
||||
IOBUF PORT "gpio_0" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_0" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_1" SITE "M18";
|
||||
IOBUF PORT "gpio_1" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_1" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_5" SITE "B10";
|
||||
IOBUF PORT "gpio_5" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_5" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_6" SITE "B9";
|
||||
IOBUF PORT "gpio_6" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_6" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_9" SITE "C8";
|
||||
IOBUF PORT "gpio_9" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_9" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_10" SITE "B8";
|
||||
IOBUF PORT "gpio_10" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_10" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_11" SITE "A8";
|
||||
IOBUF PORT "gpio_11" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_11" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_12" SITE "H2";
|
||||
IOBUF PORT "gpio_12" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_12" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_13" SITE "J2";
|
||||
IOBUF PORT "gpio_13" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_13" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_a0" SITE "L4";
|
||||
IOBUF PORT "gpio_a0" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_a0" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_a1" SITE "N3";
|
||||
IOBUF PORT "gpio_a1" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_a1" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_a2" SITE "N4";
|
||||
IOBUF PORT "gpio_a2" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_a2" PULLMODE=DOWN;
|
||||
LOCATE COMP "gpio_a3" SITE "H4";
|
||||
IOBUF PORT "gpio_a3" IO_TYPE=LVCMOS33;
|
||||
IOBUF PORT "gpio_a3" PULLMODE=DOWN;
|
||||
LOCATE COMP "user_button" SITE "J17";
|
||||
IOBUF PORT "user_button" IO_TYPE=SSTL135_I;
|
||||
LOCATE COMP "reset_n" SITE "V17";
|
||||
IOBUF PORT "reset_n" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "spiflash4x_cs_n" SITE "U17";
|
||||
IOBUF PORT "spiflash4x_cs_n" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "spiflash4x_dq[0]" SITE "U18";
|
||||
IOBUF PORT "spiflash4x_dq[0]" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "spiflash4x_dq[1]" SITE "T18";
|
||||
IOBUF PORT "spiflash4x_dq[1]" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "spiflash4x_dq[2]" SITE "R18";
|
||||
IOBUF PORT "spiflash4x_dq[2]" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "spiflash4x_dq[3]" SITE "N18";
|
||||
IOBUF PORT "spiflash4x_dq[3]" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "usb_d_p" SITE "N1";
|
||||
IOBUF PORT "usb_d_p" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "usb_d_n" SITE "M2";
|
||||
IOBUF PORT "usb_d_n" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "usb_pullup" SITE "N2";
|
||||
IOBUF PORT "usb_pullup" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "i2c_sda" SITE "C10";
|
||||
IOBUF PORT "i2c_sda" IO_TYPE=LVCMOS33;
|
||||
LOCATE COMP "i2c_scl" SITE "C9";
|
||||
IOBUF PORT "i2c_scl" IO_TYPE=LVCMOS33;
|
@ -1,55 +0,0 @@
|
||||
#include "Vfpga_top.h"
|
||||
#include "verilated.h"
|
||||
#include "stdio.h"
|
||||
|
||||
Vfpga_top *system_state;
|
||||
VerilatedContext* contextp;
|
||||
|
||||
/*In hz */
|
||||
#define CPU_SPEED 1000
|
||||
|
||||
#define timeinc CPU_SPEED*1000000/2
|
||||
|
||||
void tick() {
|
||||
system_state->clk48 = 1;
|
||||
contextp->timeInc(timeinc);
|
||||
system_state->eval();
|
||||
system_state->clk48 = 0;
|
||||
contextp->timeInc(timeinc);
|
||||
system_state->eval();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
contextp = new VerilatedContext;
|
||||
|
||||
// Set debug level, 0 is off, 9 is highest presently used
|
||||
// May be overridden by commandArgs argument parsing
|
||||
contextp->debug(0);
|
||||
|
||||
// Verilator must compute traced signals
|
||||
contextp->traceEverOn(true);
|
||||
|
||||
contextp->commandArgs(argc, argv);
|
||||
system_state = new Vfpga_top{contextp};
|
||||
system_state->user_button=1;
|
||||
system_state->i2c_sda_in=0;
|
||||
|
||||
//system_state->reset=1;
|
||||
tick();
|
||||
//system_state->reset=0;
|
||||
tick();
|
||||
tick();
|
||||
//system_state->reset=1;
|
||||
|
||||
// Simulate until $finish
|
||||
while(!contextp->gotFinish()){
|
||||
tick();
|
||||
}
|
||||
|
||||
system_state->final();
|
||||
|
||||
delete system_state;
|
||||
delete contextp;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
`verilator_config
|
||||
lint_off -rule COMBDLY -file "external_ip/litedram_core_ecp5_phy_sim.v"
|
||||
lint_off -rule CASEINCOMPLETE -file "external_ip/litedram_core_ecp5_phy_sim.v"
|
||||
lint_off -rule UNUSEDSIGNAL -file "external_ip/litedram_core_ecp5_phy_sim.v"
|
||||
lint_off -rule WIDTHEXPAND -file "external_ip/litedram_core_ecp5_phy_sim.v"
|
||||
lint_off -rule WIDTHTRUNC -file "external_ip/litedram_core_ecp5_phy_sim.v"
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -19,55 +19,30 @@
|
||||
|
||||
/* This warning is because we don't use the full address bus. */
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
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
|
||||
);
|
||||
module doublemem(input [19:0] address,inout wire [15:0] data ,input rd,input wr,input BHE,input cs);
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
reg [15:0] memory [0:(RAM_SIZE_IN_BYTES/2)-1];
|
||||
|
||||
reg [15:0] memory [0:32768];
|
||||
|
||||
initial begin
|
||||
`ifndef YOSYS
|
||||
string boot_code;
|
||||
if(!$value$plusargs("BOOT_CODE=%s",boot_code))begin
|
||||
$display("No boot code specified. Please add +BOOT_CODE=<path> to your vvp args");
|
||||
$finish;
|
||||
end
|
||||
$readmemh(boot_code, memory,0,(RAM_SIZE_IN_BYTES/2)-1);
|
||||
`else
|
||||
//TODO: don't have it hard coded
|
||||
$readmemh("../boot_code/i2c_bootloader.stxt", memory,0,(RAM_SIZE_IN_BYTES/2)-1); // 2KiB
|
||||
`endif
|
||||
$readmemh(boot_code, memory,0,32767);
|
||||
end
|
||||
|
||||
assign data[7:0] = !address[0:0] & !rd & !cs ? memory[address[16:1]][15:8] : 8'hz;
|
||||
|
||||
`ifdef USE_HIGH_IMPEDANCE
|
||||
assign cpu_read_data[7:0] = !address[0:0] & !rd & !cs ? memory[address[ADDRESS_WIDTH-1:1]][15:8] : `16'hz;
|
||||
assign cpu_read_data[15:8] = !BHE & !rd & !cs ? memory[address[ADDRESS_WIDTH-1:1]][ 7:0] : `16'hz;
|
||||
`else
|
||||
assign cpu_read_data[7:0] = memory[address[ADDRESS_WIDTH-1:1]][15:8];
|
||||
assign cpu_read_data[15:8] = memory[address[ADDRESS_WIDTH-1:1]][ 7:0];
|
||||
`endif
|
||||
assign data[15:8] = !BHE & !rd & !cs ? memory[address[16:1]][7:0] : 8'hz;
|
||||
|
||||
|
||||
always @(posedge clock) begin
|
||||
if( cs == 0 && wr == 0) begin
|
||||
always @(negedge wr) begin
|
||||
if( cs == 0 ) begin
|
||||
if(BHE==0)
|
||||
memory[address[ADDRESS_WIDTH-1:1]][7:0]<=cpu_write_data[15:8];
|
||||
memory[address[16:1]][7:0]<=data[15:8];
|
||||
if(address[0]==0)
|
||||
memory[address[ADDRESS_WIDTH-1:1]][15:8]<=cpu_write_data[7:0];
|
||||
memory[address[16:1]][15:8]<=data[7:0];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,93 +0,0 @@
|
||||
/* CPU_to_I2C_driver_bridge - Implements CPU interface for the I2C_driver
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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 CPU_to_I2C_driver_bridge (
|
||||
input wire clock,
|
||||
input wire reset_n,
|
||||
|
||||
// CPU INTERFACE
|
||||
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,
|
||||
|
||||
// I2C DRIVER INTERFACE
|
||||
output wire [6:0] OUT_ADDRESS,
|
||||
input wire OUT_BUSY,
|
||||
output reg OUT_TRANSACT,
|
||||
output reg DIR,
|
||||
input wire [15:0] OUT_I2C_DATA_READ,
|
||||
output reg [15:0] OUT_I2C_DATA_WRITE,
|
||||
|
||||
output reg TRANS_WIDTH,
|
||||
output reg OUT_IGN_ACK,
|
||||
|
||||
input IN_ERROR
|
||||
);
|
||||
|
||||
//assign data_bus_out=((address==3'h0)&&chip_select_n==1'b0&&read_n==1'b0)? 16'h0043 : 16'h0000;
|
||||
//assign data_bus_out= (chip_select_n==1'b0&&read_n==1'b0) ? 16'h0043 : 16'h0000;
|
||||
//assign data_bus_out= (1) ? 16'h0043 : 16'h0000;
|
||||
|
||||
reg [6:0] ADDRESS_REG=7'b1111111;
|
||||
|
||||
assign OUT_ADDRESS=ADDRESS_REG;
|
||||
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
reg [15:0]READ_DATA=16'h0;
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
reg WAIT;
|
||||
always @( posedge clock )begin
|
||||
if ( reset_n==0 ) begin
|
||||
WAIT<=0;
|
||||
OUT_TRANSACT<=0;
|
||||
end
|
||||
if ( WAIT==1'b1 && OUT_BUSY==1'b1 )begin
|
||||
WAIT<=1'b0;
|
||||
OUT_TRANSACT<=0;
|
||||
READ_DATA<=OUT_I2C_DATA_READ;
|
||||
end
|
||||
if ( chip_select_n==0 && read_n==0 )begin
|
||||
case (address)
|
||||
3'h0: data_bus_out <= {OUT_I2C_DATA_READ};
|
||||
3'h2: data_bus_out <= {14'd0,IN_ERROR,OUT_BUSY|WAIT};
|
||||
default: data_bus_out <= 16'h0;
|
||||
endcase
|
||||
end
|
||||
if ( chip_select_n==0 && write_n==0 && address==3'd3 ) begin
|
||||
OUT_TRANSACT<=1;
|
||||
WAIT<=1;
|
||||
end
|
||||
if ( chip_select_n==0 && write_n==0 && address==3'd3 ) begin
|
||||
DIR<=data_bus_in[8:8];
|
||||
TRANS_WIDTH<=data_bus_in[9:9];
|
||||
OUT_IGN_ACK<=data_bus_in[10:10];
|
||||
end
|
||||
if ( chip_select_n==0 && write_n==0 && address==3'd1 ) begin
|
||||
ADDRESS_REG <= data_bus_in[14:8];
|
||||
end
|
||||
if ( chip_select_n==0 && write_n==0 && address==3'd2 ) begin
|
||||
OUT_I2C_DATA_WRITE <= data_bus_in[15:0];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,346 +0,0 @@
|
||||
/* I2C_driver.v - Implements an I2C interface
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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 I2C_driver (
|
||||
input wire clock,
|
||||
input wire SDA_input,
|
||||
output reg SDA_output,
|
||||
output reg SDA_direction, //1:output 0:input
|
||||
output reg SCL,
|
||||
|
||||
input wire [6:0] address,
|
||||
output reg I2C_BUSY=0,
|
||||
input wire I2C_TRANSACT,
|
||||
input wire DIR,
|
||||
input wire [15:0] i2c_data_write,
|
||||
input wire transact_width, /* 0=byte 1=word */
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
input wire ignore_ack,
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
output reg [15:0] i2c_data_read=16'h4141,
|
||||
|
||||
output reg error=0
|
||||
);
|
||||
|
||||
//assign i2c_data_read=16'h0042;
|
||||
|
||||
reg DIR_latched;
|
||||
|
||||
reg [5:0] i2c_state = 6'b100100;
|
||||
|
||||
reg [3:0] data_bit_counter;
|
||||
reg [15:0] data_internal;
|
||||
reg [6:0]address_internal;
|
||||
|
||||
reg trans_width_latch;
|
||||
|
||||
always @(posedge clock) begin
|
||||
case (i2c_state)
|
||||
/***** start sequence ******/
|
||||
6'b000000:begin
|
||||
SDA_direction<=1;
|
||||
SDA_output<=1;
|
||||
SCL<=1;
|
||||
i2c_state<=6'b000001;
|
||||
end
|
||||
6'b000001:begin
|
||||
SDA_output<=0;
|
||||
SCL<=1;
|
||||
i2c_state<=6'b000010;
|
||||
end
|
||||
6'b000010:begin
|
||||
SDA_output<=0;
|
||||
SCL<=0;
|
||||
i2c_state<=6'b000011;
|
||||
data_bit_counter<=0;
|
||||
end
|
||||
/****** Set address ********/
|
||||
6'b000011:begin
|
||||
SCL<=0;
|
||||
i2c_state<=6'b000100;
|
||||
end
|
||||
6'b000100:begin
|
||||
SCL<=0;
|
||||
SDA_output<=address_internal[6:6];
|
||||
address_internal[6:0]<={address_internal[5:0],1'b0};
|
||||
data_bit_counter<=data_bit_counter+1;
|
||||
i2c_state<=6'b000101;
|
||||
end
|
||||
6'b000101:begin
|
||||
SCL<=1;
|
||||
i2c_state<=6'b000110;
|
||||
end
|
||||
6'b000110:begin
|
||||
SCL<=1;
|
||||
if(data_bit_counter==4'd7)
|
||||
i2c_state<=6'b000111;
|
||||
else
|
||||
i2c_state<=6'b000011;
|
||||
end
|
||||
/****** Read/Write *********/
|
||||
6'b000111:begin
|
||||
SCL<=0;
|
||||
i2c_state<=6'b001000;
|
||||
end
|
||||
6'b001000:begin
|
||||
SCL<=0;
|
||||
SDA_output<=DIR_latched;/*Write=0 Read=1*/
|
||||
i2c_state<=6'b001001;
|
||||
end
|
||||
6'b001001:begin
|
||||
SCL<=1;
|
||||
i2c_state<=6'b001010;
|
||||
end
|
||||
6'b001010:begin
|
||||
SCL<=1;
|
||||
i2c_state<=6'b001011;
|
||||
end
|
||||
/****** Acknowledge ********/
|
||||
6'b001011:begin
|
||||
SCL<=0;
|
||||
SDA_direction<=0;
|
||||
i2c_state<=6'b001100;
|
||||
end
|
||||
6'b001100:begin
|
||||
SCL<=0;
|
||||
i2c_state<=6'b001101;
|
||||
end
|
||||
6'b001101:begin
|
||||
SCL<=1;
|
||||
i2c_state<=6'b001110;
|
||||
end
|
||||
6'b001110:begin
|
||||
SCL<=1;
|
||||
if (SDA_input==1)begin
|
||||
error<=1'b1;
|
||||
i2c_state<=6'b100100;
|
||||
end
|
||||
i2c_state<=6'b001111;
|
||||
data_bit_counter<=0;
|
||||
end
|
||||
/****** separator ********/
|
||||
6'b001111:begin
|
||||
SCL<=0;
|
||||
SDA_output<=0;
|
||||
i2c_state<=6'b010000;
|
||||
end
|
||||
6'b010000:begin
|
||||
SCL<=0;
|
||||
i2c_state<=6'b010001;
|
||||
end
|
||||
6'b010001:begin
|
||||
SCL<=0;
|
||||
SDA_output<=1;
|
||||
i2c_state<=6'b010010;
|
||||
end
|
||||
6'b010010:begin
|
||||
SCL<=0;
|
||||
SDA_output<=1;
|
||||
i2c_state<=6'b010011;
|
||||
end
|
||||
6'b010011:begin
|
||||
SCL<=0;
|
||||
SDA_output<=0;
|
||||
i2c_state<=6'b010100;
|
||||
end
|
||||
/****** Send data ********/
|
||||
6'b010100:begin
|
||||
if(DIR_latched==1'b1)begin
|
||||
SDA_direction<=0;
|
||||
end else begin
|
||||
SDA_direction<=1;
|
||||
end
|
||||
SCL<=0;
|
||||
i2c_state<=6'b010101;
|
||||
end
|
||||
6'b010101:begin
|
||||
SCL<=0;
|
||||
if(DIR_latched==1'b0)begin
|
||||
SDA_output<=data_internal[7:7];
|
||||
data_internal[7:0]<={data_internal[6:0],1'b0};
|
||||
end
|
||||
data_bit_counter<=data_bit_counter+1;
|
||||
i2c_state<=6'b010110;
|
||||
end
|
||||
6'b010110:begin
|
||||
SCL<=1;
|
||||
if(DIR_latched==1'b1)begin
|
||||
i2c_data_read[15:0]<={8'h0,i2c_data_read[6:0],SDA_input};
|
||||
end
|
||||
i2c_state<=6'b010111;
|
||||
end
|
||||
6'b010111:begin
|
||||
SCL<=1;
|
||||
if(data_bit_counter==4'd8)begin
|
||||
i2c_state<=6'b011000;
|
||||
end else begin
|
||||
i2c_state<=6'b010100;
|
||||
end
|
||||
end
|
||||
/****** Acknowledge ********/
|
||||
6'b011000:begin
|
||||
// Note: If we read we want to send an ack,
|
||||
// If we write we want to read an ack so it's reversed here
|
||||
if(DIR_latched==1'b1)begin
|
||||
SDA_direction<=1;
|
||||
end else begin
|
||||
SDA_direction<=0;
|
||||
end
|
||||
SCL<=0;
|
||||
i2c_state<=6'b011001;
|
||||
end
|
||||
6'b011001:begin
|
||||
SCL<=0;
|
||||
if(DIR_latched==1'b1)begin
|
||||
SDA_output<=1'b0;
|
||||
end
|
||||
i2c_state<=6'b011010;
|
||||
end
|
||||
6'b011010:begin
|
||||
SCL<=1;
|
||||
i2c_state<=6'b011011;
|
||||
end
|
||||
6'b011011:begin
|
||||
SCL<=1;
|
||||
if (SDA_input==1 && DIR_latched==1'b0)begin
|
||||
error<=1'b1;
|
||||
end
|
||||
if(trans_width_latch==1'b1)begin
|
||||
i2c_state<=6'b100101;
|
||||
data_bit_counter<=4'd0;
|
||||
end else
|
||||
i2c_state<=6'b011100;
|
||||
end
|
||||
/****** Send data (16bit) ********/
|
||||
6'b100101:begin
|
||||
SCL<=0;
|
||||
if(DIR_latched==1'b1)begin
|
||||
SDA_direction<=0;
|
||||
end else begin
|
||||
SDA_direction<=1;
|
||||
end
|
||||
i2c_state<=6'b100110;
|
||||
end
|
||||
6'b100110:begin
|
||||
SCL<=0;
|
||||
if(DIR_latched==1'b0)begin
|
||||
SDA_output<=data_internal[15:15];
|
||||
data_internal[15:8]<={data_internal[14:8],1'b0};
|
||||
end
|
||||
data_bit_counter<=data_bit_counter+1;
|
||||
i2c_state<=6'b100111;
|
||||
end
|
||||
6'b100111:begin
|
||||
SCL<=1;
|
||||
if(DIR_latched==1'b1)begin
|
||||
i2c_data_read[15:0]<={i2c_data_read[14:8],SDA_input,i2c_data_read[7:0]};
|
||||
end
|
||||
i2c_state<=6'b101000;
|
||||
end
|
||||
6'b101000:begin
|
||||
SCL<=1;
|
||||
if(data_bit_counter==4'd8)begin
|
||||
i2c_state<=6'b101001;
|
||||
end else
|
||||
i2c_state<=6'b100101;
|
||||
end
|
||||
/****** Acknowledge (16bit) ********/
|
||||
6'b101001:begin
|
||||
SDA_direction<=0;
|
||||
SCL<=0;
|
||||
i2c_state<=6'b101010;
|
||||
end
|
||||
6'b101010:begin
|
||||
SCL<=0;
|
||||
i2c_state<=6'b101011;
|
||||
end
|
||||
6'b101011:begin
|
||||
SCL<=1;
|
||||
i2c_state<=6'b101100;
|
||||
end
|
||||
6'b101100:begin
|
||||
SCL<=1;
|
||||
if ( SDA_input==1 && DIR_latched==1'b0 ) begin
|
||||
error<=1'b1;
|
||||
end
|
||||
i2c_state<=6'b011100;
|
||||
SDA_direction<=1;
|
||||
end
|
||||
/****** separator ********/
|
||||
6'b011100:begin
|
||||
SCL<=0;
|
||||
SDA_output<=0;
|
||||
i2c_state<=6'b011101;
|
||||
end
|
||||
6'b011101:begin
|
||||
SCL<=0;
|
||||
i2c_state<=6'b011110;
|
||||
end
|
||||
6'b011110:begin
|
||||
SCL<=0;
|
||||
SDA_output<=1;
|
||||
i2c_state<=6'b011111;
|
||||
end
|
||||
6'b011111:begin
|
||||
SCL<=0;
|
||||
SDA_output<=1;
|
||||
i2c_state<=6'b100000;
|
||||
end
|
||||
6'b100000:begin
|
||||
SCL<=0;
|
||||
SDA_output<=0;
|
||||
i2c_state<=6'b100001;
|
||||
end
|
||||
/****** stop bit *******/
|
||||
6'b100001:begin
|
||||
SCL<=1;
|
||||
SDA_output<=0;
|
||||
i2c_state<=6'b100010;
|
||||
end
|
||||
6'b100010:begin
|
||||
SCL<=1;
|
||||
SDA_output<=1;
|
||||
i2c_state<=6'b100011;
|
||||
end
|
||||
6'b100011:begin
|
||||
SCL<=1;
|
||||
SDA_output<=1;
|
||||
i2c_state<=6'b100100;
|
||||
I2C_BUSY<=0;
|
||||
end
|
||||
6'b100100:begin
|
||||
if(I2C_TRANSACT==1)begin
|
||||
I2C_BUSY<=1;
|
||||
i2c_state<=0;
|
||||
data_internal<=i2c_data_write;
|
||||
address_internal<=address;
|
||||
trans_width_latch<=transact_width;
|
||||
DIR_latched<=DIR;
|
||||
error<=1'b0;
|
||||
end
|
||||
end
|
||||
default:begin
|
||||
SCL<=0;
|
||||
SDA_output<=0;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,123 +0,0 @@
|
||||
/* I2C_driver_multiplexer.v - Implements a multiplexer for the SoC side of I2C_driver.v
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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 I2C_driver_multiplexer (
|
||||
input wire clock,
|
||||
input wire reset_n,
|
||||
|
||||
////// INPUT 1 ///////
|
||||
input wire [6:0] IN1_ADDRESS,
|
||||
output reg IN1_BUSY,
|
||||
input wire IN1_TRANSACT,
|
||||
input wire IN1_DIR,
|
||||
output reg [15:0] IN1_I2C_DATA_READ,
|
||||
input wire [15:0] IN1_I2C_DATA_WRITE,
|
||||
input IN1_TRANS_WIDTH,
|
||||
input IN1_IGN_ACK,
|
||||
output reg IN1_ERROR,
|
||||
|
||||
////// INPUT 2 ///////
|
||||
input wire [6:0] IN2_ADDRESS,
|
||||
output reg IN2_BUSY,
|
||||
input wire IN2_TRANSACT,
|
||||
input wire IN2_DIR,
|
||||
output reg [15:0] IN2_I2C_DATA_READ,
|
||||
input wire [15:0] IN2_I2C_DATA_WRITE,
|
||||
input IN2_TRANS_WIDTH,
|
||||
input IN2_IGN_ACK,
|
||||
output reg IN2_ERROR,
|
||||
|
||||
////// OUTPUT ///////
|
||||
output wire [6:0] OUT_ADDRESS,
|
||||
input wire OUT_BUSY,
|
||||
output reg OUT_TRANSACT,
|
||||
output wire OUT_DIR,
|
||||
input wire [15:0] OUT_I2C_DATA_READ,
|
||||
output wire [15:0] OUT_I2C_DATA_WRITE,
|
||||
output OUT_TRANS_WIDTH,
|
||||
output wire OUT_IGN_ACK,
|
||||
input wire OUT_ERROR
|
||||
);
|
||||
|
||||
reg select;
|
||||
|
||||
assign OUT_TRANS_WIDTH = select ? IN1_TRANS_WIDTH : IN2_TRANS_WIDTH;
|
||||
assign OUT_I2C_DATA_WRITE = select ? IN1_I2C_DATA_WRITE : IN2_I2C_DATA_WRITE;
|
||||
assign OUT_ADDRESS = select ? IN1_ADDRESS : IN2_ADDRESS;
|
||||
assign OUT_IGN_ACK = select ? IN1_IGN_ACK : IN2_IGN_ACK;
|
||||
assign OUT_DIR= select ? IN1_DIR : IN2_DIR;
|
||||
|
||||
reg [1:0] STATE;
|
||||
reg SERVICED;
|
||||
|
||||
always @(posedge clock)begin
|
||||
if(reset_n==1'b0)begin
|
||||
OUT_TRANSACT<=0;
|
||||
IN1_BUSY<=0;
|
||||
IN2_BUSY<=0;
|
||||
STATE<=2'd0;
|
||||
end else begin
|
||||
case(STATE)
|
||||
2'd0:begin
|
||||
if(IN1_TRANSACT&&OUT_BUSY==1'b0)begin
|
||||
select<=1'b1;
|
||||
OUT_TRANSACT<=1;
|
||||
STATE<=2'd1;
|
||||
SERVICED<=1'b0;
|
||||
end else if(IN2_TRANSACT&&OUT_BUSY==1'b0)begin
|
||||
select<=1'b0;
|
||||
OUT_TRANSACT<=1;
|
||||
IN1_BUSY<=1;
|
||||
STATE<=2'd1;
|
||||
SERVICED<=1'b1;
|
||||
end
|
||||
if(OUT_BUSY==1'b0)begin
|
||||
IN1_BUSY<=0;
|
||||
IN2_BUSY<=0;
|
||||
end
|
||||
end
|
||||
2'd1:begin
|
||||
if(OUT_BUSY==1'b1)begin
|
||||
STATE<=2'd0;
|
||||
OUT_TRANSACT<=0;
|
||||
end
|
||||
if(SERVICED==1'b0)begin
|
||||
IN1_BUSY<=1;
|
||||
end else begin
|
||||
IN2_BUSY<=1;
|
||||
end
|
||||
end
|
||||
default:begin
|
||||
STATE<=2'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always @(negedge OUT_BUSY)begin
|
||||
if(select)begin
|
||||
IN1_I2C_DATA_READ<=OUT_I2C_DATA_READ;
|
||||
IN1_ERROR<=OUT_ERROR;
|
||||
end else begin
|
||||
IN2_I2C_DATA_READ<=OUT_I2C_DATA_READ;
|
||||
IN2_ERROR<=OUT_ERROR;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,127 +0,0 @@
|
||||
/* Wishbone_driver.v - Implements a classic wishbone master
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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 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 scenario 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
|
@ -1,73 +0,0 @@
|
||||
/* Wishbone_driver.v - Implements a classic wishbone master that maps directly in memory space
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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 Wishbone_memory_driver (
|
||||
input wire clock,
|
||||
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
input wire reset_n,
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
input wire [19:0] address,
|
||||
input wire [15:0] data_bus_in,
|
||||
output reg [15:0] data_bus_out,
|
||||
output wire wait_state,
|
||||
input read_n,
|
||||
input write_n,
|
||||
input chip_select_n,
|
||||
input BHE,
|
||||
|
||||
input wire wb_mem_ack,
|
||||
output wire [24:0] wb_mem_adr,
|
||||
output reg 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,
|
||||
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
input wire wb_mem_err,
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
output wire [3:0] wb_mem_sel,
|
||||
output reg wb_mem_stb,
|
||||
output wire wb_mem_we
|
||||
);
|
||||
|
||||
assign wb_mem_adr={6'd0,address[19:1]};
|
||||
assign wb_mem_sel={2'b11,!BHE,!address[0]};
|
||||
|
||||
always @(posedge clock)begin
|
||||
wb_mem_cyc<=( (!read_n||!write_n)^(wb_mem_ack) )&(!chip_select_n);
|
||||
wb_mem_stb<=( (!read_n||!write_n)^(wb_mem_ack) )&(!chip_select_n);
|
||||
end
|
||||
|
||||
always @(posedge wb_mem_ack)begin
|
||||
data_bus_out<=wb_mem_data_r[15:0];
|
||||
end
|
||||
assign wb_mem_data_w={16'd0,data_bus_in};
|
||||
|
||||
assign wait_state=( (!read_n||!write_n)^(wb_mem_ack) )&(!chip_select_n);
|
||||
|
||||
assign wb_mem_we=read_n;
|
||||
|
||||
endmodule
|
@ -1,348 +0,0 @@
|
||||
/* ascii_to_HD44780_driver.v - driver that takes in ascii and outputs control
|
||||
sequences for an HD44780 display
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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 ascii_to_HD44780_driver (
|
||||
/* system */
|
||||
input wire clock,
|
||||
input wire rst_n,
|
||||
|
||||
/* Data Input */
|
||||
output reg in_data_ready=0,
|
||||
input data_write_req,
|
||||
input [7:0] in_ascii_data,
|
||||
|
||||
/* write circuitry */
|
||||
input wire done_writing,
|
||||
output reg write_req=0,
|
||||
output reg [3:0] data,
|
||||
output reg cmd_data=0
|
||||
);
|
||||
|
||||
initial begin
|
||||
init_cmd_data[ 0] = 4'h3;
|
||||
init_cmd_data[ 1] = 4'h3;
|
||||
init_cmd_data[ 2] = 4'h3;
|
||||
init_cmd_data[ 3] = 4'h2;
|
||||
init_cmd_data[ 4] = 4'h2; //0x28
|
||||
init_cmd_data[ 5] = 4'h8;
|
||||
init_cmd_data[ 6] = 4'h0; //0x07
|
||||
init_cmd_data[ 7] = 4'h7;
|
||||
init_cmd_data[ 8] = 4'h0; //0x0F
|
||||
init_cmd_data[ 9] = 4'hF;
|
||||
init_cmd_data[10] = 4'h0; //0x01
|
||||
init_cmd_data[11] = 4'h1;
|
||||
init_cmd_data[12] = 4'h0; //0x06
|
||||
init_cmd_data[13] = 4'h6;
|
||||
init_cmd_data[14] = 4'h0; // 0x02
|
||||
init_cmd_data[15] = 4'h2;
|
||||
end
|
||||
|
||||
reg [4:0] init_seq=0;
|
||||
|
||||
reg [3:0] init_cmd_data [15:0];
|
||||
|
||||
reg [7:0]print_data;
|
||||
|
||||
reg [1:0]line=0;
|
||||
reg [5:0]col=0;
|
||||
|
||||
reg [7:0] driver_state =0;
|
||||
|
||||
reg next_line;
|
||||
|
||||
reg [7:0]clear_count;
|
||||
|
||||
always @(posedge clock) begin
|
||||
if(rst_n==0)begin
|
||||
in_data_ready<=0;
|
||||
write_req<=1'b0;
|
||||
init_seq<=5'd0;
|
||||
cmd_data<=1'b0;
|
||||
line<=0;
|
||||
col<=0;
|
||||
driver_state<=0;
|
||||
end else begin
|
||||
case(driver_state)
|
||||
8'd0:begin
|
||||
if(init_seq!=5'd16)begin
|
||||
/** Initialise display **/
|
||||
data<=init_cmd_data[init_seq[3:0]];
|
||||
cmd_data<=1'b0;
|
||||
in_data_ready<=0;
|
||||
if(!done_writing)begin
|
||||
init_seq<=init_seq+5'd1;
|
||||
driver_state<=8'd12;
|
||||
write_req<=1'b0;
|
||||
end else begin
|
||||
write_req<=1'b1;
|
||||
end
|
||||
end else if(col==6'd20)begin
|
||||
/** Check if we run out of screen **/
|
||||
driver_state<=8'd6;
|
||||
cmd_data<=1'b0;
|
||||
next_line<=1;
|
||||
end else if(data_write_req==1)begin
|
||||
if(in_ascii_data==8'h0A)begin // '\n'
|
||||
driver_state<=8'd6;
|
||||
cmd_data<=1'b0;
|
||||
next_line<=1;
|
||||
end else if(in_ascii_data==8'h0D)begin // '\r'
|
||||
driver_state<=8'd6;
|
||||
cmd_data<=1'b0;
|
||||
next_line<=0;
|
||||
end else if(in_ascii_data==8'h1b)begin // '\e'
|
||||
driver_state<=8'd13;
|
||||
cmd_data<=1'b1;
|
||||
in_data_ready<=0;
|
||||
end else begin
|
||||
if (in_ascii_data[7:5]==3'b000||in_ascii_data[7:7]==1'b1)
|
||||
if(in_ascii_data==8'h00)
|
||||
print_data<=8'h23;
|
||||
else
|
||||
print_data<=8'h3F;
|
||||
else
|
||||
print_data<=in_ascii_data;
|
||||
cmd_data<=1'b1;
|
||||
driver_state<=8'd9;
|
||||
end
|
||||
in_data_ready<=0;
|
||||
end else begin
|
||||
in_data_ready<=1;
|
||||
end
|
||||
end
|
||||
8'd6:begin
|
||||
if(next_line)begin
|
||||
case(line)
|
||||
2'd0: data<=4'hC;
|
||||
2'd1: data<=4'h9;
|
||||
2'd2: data<=4'hD;
|
||||
2'd3: data<=4'hD;
|
||||
endcase
|
||||
end else begin
|
||||
case(line)
|
||||
2'd0: data<=4'h8;
|
||||
2'd1: data<=4'hC;
|
||||
2'd2: data<=4'h9;
|
||||
2'd3: data<=4'hD;
|
||||
endcase
|
||||
end
|
||||
if(done_writing==0)begin
|
||||
driver_state<=8'd7;
|
||||
write_req<=1'b0;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd7:begin
|
||||
if(done_writing==1)
|
||||
driver_state<=8'd8;
|
||||
end
|
||||
8'd8:begin
|
||||
if(next_line)begin
|
||||
case(line)
|
||||
2'd0: begin data<=4'h0; end
|
||||
2'd1: begin data<=4'h4; end
|
||||
2'd2: begin data<=4'h4; end
|
||||
2'd3: begin data<=4'h4; end
|
||||
endcase
|
||||
end else begin
|
||||
case(line)
|
||||
2'd0: begin data<=4'h0; end
|
||||
2'd1: begin data<=4'h0; end
|
||||
2'd2: begin data<=4'h4; end
|
||||
2'd3: begin data<=4'h4; end
|
||||
endcase
|
||||
end
|
||||
if(!done_writing)begin
|
||||
driver_state<=8'd12;
|
||||
col<=0;
|
||||
write_req<=1'b0;
|
||||
if(next_line)begin
|
||||
case(line)
|
||||
2'd0: begin line<=1; end
|
||||
2'd1: begin line<=2; end
|
||||
2'd2: begin line<=3; end
|
||||
2'd3: begin line<=3; end
|
||||
endcase
|
||||
end
|
||||
write_req<=1'b0;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd9:begin
|
||||
data<=print_data[7:4];
|
||||
if(!done_writing)begin
|
||||
driver_state<=8'd10;
|
||||
write_req<=1'b0;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd10:begin
|
||||
if(done_writing==1)
|
||||
driver_state<=8'd11;
|
||||
end
|
||||
8'd11:begin
|
||||
data<=print_data[3:0];
|
||||
if(!done_writing)begin
|
||||
driver_state<=8'd12;
|
||||
write_req<=1'b0;
|
||||
col<=col+1;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd12:begin
|
||||
if(done_writing)
|
||||
driver_state<=8'd0;
|
||||
end
|
||||
8'd13:begin // Escape sequence start
|
||||
if(data_write_req==1'b0)begin
|
||||
driver_state<=8'd14;
|
||||
in_data_ready<=1;
|
||||
end
|
||||
end
|
||||
8'd14:begin
|
||||
if(data_write_req==1'b1)begin
|
||||
in_data_ready<=1'b0;
|
||||
case(in_ascii_data[7:0])
|
||||
8'h5b:begin// '['
|
||||
driver_state<=8'd16;
|
||||
end
|
||||
default:begin
|
||||
driver_state<=8'd15;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
8'd15:begin
|
||||
if(data_write_req==1'b0)begin
|
||||
driver_state<=8'd0;
|
||||
end
|
||||
end
|
||||
8'd16:begin // Second part of escape sequency
|
||||
if(data_write_req==1'b0)begin
|
||||
in_data_ready<=1'b1;
|
||||
driver_state<=8'd17;
|
||||
end
|
||||
end
|
||||
8'd17:begin
|
||||
if(data_write_req==1'b1)begin
|
||||
driver_state<=8'd17;
|
||||
in_data_ready<=1'b0;
|
||||
case(in_ascii_data[7:0])
|
||||
8'h48:begin// 'H'
|
||||
driver_state<=8'd25;
|
||||
cmd_data<=1'b0;
|
||||
clear_count<=8'd80;
|
||||
end
|
||||
8'h32:begin// '2'
|
||||
driver_state<=8'd23;
|
||||
end
|
||||
default: begin
|
||||
driver_state<=8'd15;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
8'd18:begin
|
||||
data<=4'h2;
|
||||
if(!done_writing)begin
|
||||
driver_state<=8'd19;
|
||||
write_req<=1'b0;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd19:begin
|
||||
if(done_writing==1)
|
||||
driver_state<=8'd20;
|
||||
end
|
||||
8'd20:begin
|
||||
data<=4'h0;
|
||||
if(!done_writing)begin
|
||||
driver_state<=8'd21;
|
||||
write_req<=1'b0;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd21:begin
|
||||
if(done_writing)begin
|
||||
driver_state<=8'd22;
|
||||
clear_count<=clear_count-8'd1;
|
||||
end
|
||||
end
|
||||
8'd22:begin
|
||||
if(clear_count==8'd0)begin
|
||||
driver_state<=8'd0;
|
||||
end else begin
|
||||
driver_state<=8'd18;
|
||||
end
|
||||
end
|
||||
8'd23:begin
|
||||
if(data_write_req==1'b0)begin
|
||||
in_data_ready<=1'b1;
|
||||
driver_state<=8'd24;
|
||||
end
|
||||
end
|
||||
8'd24:begin
|
||||
if(data_write_req==1'b1)begin
|
||||
driver_state<=8'd17;
|
||||
in_data_ready<=1'b0;
|
||||
case(in_ascii_data[7:0])
|
||||
8'h4a:begin// 'J'
|
||||
driver_state<=8'd18;
|
||||
clear_count<=8'd80;
|
||||
end
|
||||
default:begin
|
||||
driver_state<=8'd0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
8'd25:begin
|
||||
data<=4'h8;
|
||||
if(!done_writing)begin
|
||||
driver_state<=8'd26;
|
||||
write_req<=1'b0;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd26:begin
|
||||
if(done_writing==1)
|
||||
driver_state<=8'd27;
|
||||
end
|
||||
8'd27:begin
|
||||
data<=4'h0;
|
||||
if(!done_writing)begin
|
||||
driver_state<=8'd28;
|
||||
write_req<=1'b0;
|
||||
end else
|
||||
write_req<=1'b1;
|
||||
end
|
||||
8'd28:begin
|
||||
if(done_writing)begin
|
||||
driver_state<=8'd0;
|
||||
col<=0;
|
||||
line<=0;
|
||||
end
|
||||
end
|
||||
default: begin driver_state<=0; end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,126 +0,0 @@
|
||||
/* pcf8574_for_HD44780.v - takes in control sequences for an HD44780 display
|
||||
and outputs data that control a pcf8574 connected to a HD44780 in a standard
|
||||
manner over i2c
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 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 pcf8574_for_HD44780(
|
||||
input wire clock,
|
||||
|
||||
input wire pcf_write_req,
|
||||
input wire pcf_command_data,
|
||||
input wire [3:0]pcf_data,
|
||||
output reg pcf_busy=0,
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
input new_backlight,
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
input backlight_update,
|
||||
|
||||
input I2C_BUSY,
|
||||
output reg I2C_TRANSACT=0,
|
||||
output reg DIR=0,
|
||||
|
||||
output reg [7:0]i2c_data_write
|
||||
);
|
||||
|
||||
reg backlight=1;
|
||||
reg backlight_latch=0;
|
||||
reg [3:0]pcf_state=0;
|
||||
|
||||
always @(posedge clock) begin
|
||||
// [ D7 , D6 , D5 , D4 , BACKLIGHT , EN , WRITE , COMMAND/DATA ]
|
||||
if(backlight_update)
|
||||
backlight_latch<=1;
|
||||
case(pcf_state)
|
||||
4'b0000: begin /*Idle*/
|
||||
if(pcf_write_req&&I2C_BUSY==0)begin
|
||||
pcf_state<=4'b0001;
|
||||
I2C_TRANSACT<=0;
|
||||
pcf_busy<=1;
|
||||
end else if(backlight_latch&&I2C_BUSY==0)begin
|
||||
pcf_state<=4'b1111;
|
||||
I2C_TRANSACT<=0;
|
||||
pcf_busy<=1;
|
||||
end
|
||||
end
|
||||
4'b0001: begin
|
||||
if(I2C_BUSY==0)begin
|
||||
i2c_data_write<={pcf_data[3:0],backlight,1'b0,1'b0,pcf_command_data};
|
||||
I2C_TRANSACT<=1;
|
||||
backlight_latch<=0;
|
||||
pcf_state<=4'b0010;
|
||||
end
|
||||
end
|
||||
4'b0010:begin
|
||||
if(I2C_BUSY==1)begin
|
||||
I2C_TRANSACT<=0;
|
||||
pcf_state<=4'b0011;
|
||||
end
|
||||
end
|
||||
4'b0011: begin
|
||||
if(I2C_BUSY==0)begin
|
||||
i2c_data_write<={pcf_data[3:0],backlight,1'b1,1'b0,pcf_command_data};
|
||||
I2C_TRANSACT<=1;
|
||||
backlight_latch<=0;
|
||||
pcf_state<=4'b0100;
|
||||
end
|
||||
end
|
||||
4'b0100:begin
|
||||
if(I2C_BUSY==1)begin
|
||||
I2C_TRANSACT<=0;
|
||||
pcf_state<=4'b0101;
|
||||
end
|
||||
end
|
||||
4'b0101: begin
|
||||
if(I2C_BUSY==0)begin
|
||||
i2c_data_write<={pcf_data[3:0],backlight,1'b0,1'b0,pcf_command_data};
|
||||
I2C_TRANSACT<=1;
|
||||
pcf_state<=4'b0110;
|
||||
end
|
||||
end
|
||||
4'b0110: begin
|
||||
if(I2C_BUSY==1)begin
|
||||
I2C_TRANSACT<=0;
|
||||
pcf_state<=4'b0111;
|
||||
end
|
||||
end
|
||||
4'b0111:begin
|
||||
if(I2C_BUSY==0)begin
|
||||
pcf_state<=4'b0000;
|
||||
pcf_busy<=1'b0;
|
||||
end
|
||||
end
|
||||
4'b1111:begin
|
||||
if(I2C_BUSY==1)begin
|
||||
pcf_state<=4'b0000;
|
||||
I2C_TRANSACT<=1'b0;
|
||||
pcf_busy<=1'b0;
|
||||
end else begin
|
||||
i2c_data_write<={4'b0,backlight,1'b0,1'b0,1'b0};
|
||||
backlight_latch<=0;
|
||||
I2C_TRANSACT<=1'b1;
|
||||
pcf_busy<=1'b1;
|
||||
end
|
||||
end
|
||||
default:begin
|
||||
pcf_state<=0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -20,7 +20,6 @@
|
||||
`include "exec_state_def.v"
|
||||
`include "alu_header.v"
|
||||
`include "config.v"
|
||||
`include "error_header.v"
|
||||
|
||||
//HALT: active high
|
||||
//IOMEM: 1=IO 0=MEM
|
||||
@ -32,19 +31,19 @@
|
||||
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, input wait_state, output read, output write,output BHE,output IOMEM
|
||||
/* MEMORY / IO */ ,output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
/* STATISTICS */ ,output wire new_instruction
|
||||
`endif
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
/* */ ,output wire [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT, output wire VALID_INSTRUCTION_STAT, output wire jump_req_debug
|
||||
`endif
|
||||
|
||||
);
|
||||
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
assign jump_req_debug=biu_jump_req;
|
||||
`endif
|
||||
|
||||
@ -85,10 +84,10 @@ execute_unit execute_unit (
|
||||
/* */ ,biu_read_request, biu_jump_req, biu_write_request
|
||||
|
||||
/*************** INPUT FROM BIU ****************/
|
||||
/* */ ,BIU_VALID_DATA,BIU_EX_DATA_READ
|
||||
/* */ ,BIU_VALID_DATA, BIU_DATA_DIR
|
||||
|
||||
/**************** OUTPUT TO BIU ****************/
|
||||
/* */ ,BIU_EX_DATA_WRITE
|
||||
/************ BIDIRECTIONAL WITH BIU ***********/
|
||||
/* */ ,BIU_DATA
|
||||
|
||||
/***************** REGISTERS *****************/
|
||||
/* */ ,reg_read_port1_data, reg_read_port2_data, EXEC_reg_read_port1_addr
|
||||
@ -99,10 +98,11 @@ execute_unit execute_unit (
|
||||
/*############ Bus Interface Unit ############################################### */
|
||||
|
||||
wire [15:0] INSTRUCTION_LOCATION;
|
||||
wire [15:0] BIU_EX_DATA_READ,BIU_EX_DATA_WRITE;
|
||||
wire [15:0] BIU_DATA;
|
||||
wire [31:0] IF2DE_INSTRUCTION;
|
||||
wire BIU_VALID_DATA;
|
||||
wire VALID_INSTRUCTION;
|
||||
wire BIU_DATA_DIR;
|
||||
|
||||
BIU BIU(
|
||||
/***************** GENERAL *****************/
|
||||
@ -110,24 +110,23 @@ BIU BIU(
|
||||
|
||||
/**************** OUTSIDE WORLD ****************/
|
||||
/* */ ,external_address_bus
|
||||
/* */ ,external_data_bus_read,external_data_bus_write,read,write,BHE,IOMEM
|
||||
/* */ ,wait_state
|
||||
/* */ ,external_data_bus,read,write,BHE,IOMEM
|
||||
|
||||
/**************** OUTPUT TO DE ****************/
|
||||
/* */ ,IF2DE_INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION
|
||||
/* */ ,BIU_VALID_DATA
|
||||
/* */ ,BIU_VALID_DATA,BIU_DATA_DIR
|
||||
|
||||
/**************** INPUT FROM DE ****************/
|
||||
,Wbit,MEM_OR_IO,VALID_INSTRUCTION_ACK
|
||||
|
||||
/**************** INPUT FROM EX ****************/
|
||||
/* */ ,biu_jump_req,biu_write_request,biu_read_request
|
||||
/* */ ,BIU_ADDRESS_INPUT,BIU_EX_DATA_WRITE
|
||||
/* */ ,BIU_ADDRESS_INPUT
|
||||
|
||||
/***************** OUTPUT TO EX ****************/
|
||||
/* */ ,BIU_EX_DATA_READ
|
||||
/************ BIDIRECTIONAL WITH EX ************/
|
||||
/* */ ,BIU_DATA
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
/***************** STATISTICS *****************/
|
||||
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT
|
||||
`endif
|
||||
@ -189,14 +188,13 @@ assign reg_read_port1_addr = use_exec_reg_addr ? EXEC_reg_read_port1_addr : DE_r
|
||||
wire [15:0] reg_read_port1_data, reg_read_port2_data;
|
||||
|
||||
register_file register_file(
|
||||
/* WRITE */ .write_port1_addr(reg_write_addr), //TODO: should this come from exec instead?
|
||||
/* 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),
|
||||
/* GENERAL */ .clock(clock)
|
||||
/* */ .read_port2_data(reg_read_port2_data)
|
||||
);
|
||||
|
||||
/*############################################################################### */
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -21,8 +21,7 @@
|
||||
|
||||
/* Register address format:
|
||||
* [W-bit] [ 3-bit address] */
|
||||
module register_file (write_port1_addr,write_port1_data,write_port1_we,read_port1_addr,read_port1_data,read_port2_addr,read_port2_data,clock);
|
||||
input clock;
|
||||
module register_file (write_port1_addr,write_port1_data,write_port1_we,read_port1_addr,read_port1_data,read_port2_addr,read_port2_data);
|
||||
input [3:0] write_port1_addr;
|
||||
input [3:0] read_port1_addr;
|
||||
input [3:0] read_port2_addr;
|
||||
@ -33,11 +32,11 @@ input write_port1_we;
|
||||
|
||||
reg [15:0] registers [7:0];
|
||||
|
||||
assign read_port1_data[15:8] = read_port1_addr[3:3] ? registers[read_port1_addr[2:0]][15:8] : 8'h0 ;
|
||||
assign read_port1_data[15:8] = read_port1_addr[3:3] ? registers[read_port1_addr[2:0]][15:8] : 8'hz ;
|
||||
assign read_port1_data[7:0] = ( read_port1_addr[3:3] ? registers[read_port1_addr[2:0]][7:0] :
|
||||
( read_port1_addr[2:2] ? registers[ {1'b0,read_port1_addr[1:0]} ][15:8] : registers[ {1'b0,read_port1_addr[1:0]} ][7:0] ) );
|
||||
|
||||
assign read_port2_data[15:8] = read_port2_addr[3:3] ? registers[read_port2_addr[2:0]][15:8] : 8'h0 ;
|
||||
assign read_port2_data[15:8] = read_port2_addr[3:3] ? registers[read_port2_addr[2:0]][15:8] : 8'hz ;
|
||||
assign read_port2_data[7:0] = ( read_port2_addr[3:3] ? registers[read_port2_addr[2:0]][7:0] :
|
||||
( read_port2_addr[2:2] ? registers[ {1'b0,read_port2_addr[1:0]} ][15:8] : registers[ {1'b0,read_port2_addr[1:0]} ][7:0] ) );
|
||||
|
||||
@ -49,48 +48,47 @@ assign read_port2_data[7:0] = ( read_port2_addr[3:3] ? registers[read_port2_addr
|
||||
wire write_Wbit;
|
||||
assign write_Wbit=write_port1_addr[3:3];
|
||||
|
||||
always @(posedge clock) begin
|
||||
if(write_port1_we==0)begin
|
||||
if(write_Wbit==1)begin
|
||||
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
|
||||
registers[write_port1_addr[2:0]] <= write_port1_data;
|
||||
always @(negedge write_port1_we) begin
|
||||
if(write_Wbit==1)begin
|
||||
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
|
||||
registers[write_port1_addr[2:0]] <= write_port1_data;
|
||||
end else begin
|
||||
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
|
||||
if(write_port1_addr[2:2]==1)begin
|
||||
/* Byte */
|
||||
registers[ {1'b0,write_port1_addr[1:0]} ][15:8] <= write_port1_data[7:0];
|
||||
end else begin
|
||||
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
|
||||
if(write_port1_addr[2:2]==1)begin
|
||||
/* Byte */
|
||||
registers[ {1'b0,write_port1_addr[1:0]} ][15:8] <= write_port1_data[7:0];
|
||||
end else begin
|
||||
/* Byte */
|
||||
registers[ {1'b0,write_port1_addr[1:0]} ][7:0] <= write_port1_data[7:0];
|
||||
end
|
||||
/* Byte */
|
||||
registers[ {1'b0,write_port1_addr[1:0]} ][7:0] <= write_port1_data[7:0];
|
||||
end
|
||||
`ifdef DEBUG_REG_WRITES
|
||||
// Icarus Verilog really doesn't like non-blocking assignments
|
||||
// here
|
||||
/* verilator lint_off BLKSEQ */
|
||||
if(write_port1_addr[3:2]==2'b11)begin
|
||||
case(write_port1_addr[1:0])
|
||||
2'b00: debug_name="sp";
|
||||
2'b01: debug_name="bp";
|
||||
2'b10: debug_name="si";
|
||||
2'b11: debug_name="di";
|
||||
endcase
|
||||
end else begin
|
||||
case(write_port1_addr[1:0])
|
||||
2'b00: debug_name="ax";
|
||||
2'b01: debug_name="cx";
|
||||
2'b10: debug_name="dx";
|
||||
2'b11: debug_name="bx";
|
||||
endcase
|
||||
end
|
||||
/* verilator lint_on BLKSEQ */
|
||||
if (write_Wbit)
|
||||
debug_address<=write_port1_addr[2:0];
|
||||
else
|
||||
debug_address<={1'b0,write_port1_addr[1:0]};
|
||||
|
||||
`endif
|
||||
end
|
||||
`ifdef DEBUG_REG_WRITES
|
||||
// Icarus Verilog really doesn't like non-blocking assignments
|
||||
// here
|
||||
/* verilator lint_off BLKSEQ */
|
||||
if(write_port1_addr[3:2]==2'b11)begin
|
||||
case(write_port1_addr[1:0])
|
||||
2'b00: debug_name="sp";
|
||||
2'b01: debug_name="bp";
|
||||
2'b10: debug_name="si";
|
||||
2'b11: debug_name="di";
|
||||
endcase
|
||||
end else begin
|
||||
case(write_port1_addr[1:0])
|
||||
2'b00: debug_name="ax";
|
||||
2'b01: debug_name="cx";
|
||||
2'b10: debug_name="dx";
|
||||
2'b11: debug_name="bx";
|
||||
endcase
|
||||
end
|
||||
/* verilator lint_on BLKSEQ */
|
||||
if (write_Wbit)
|
||||
debug_address<=write_port1_addr[2:0];
|
||||
else
|
||||
debug_address<={1'b0,write_port1_addr[1:0]};
|
||||
|
||||
`endif
|
||||
|
||||
end
|
||||
|
||||
`ifdef DEBUG_REG_WRITES
|
||||
|
231
system/system.v
231
system/system.v
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -22,66 +22,52 @@
|
||||
`include "config.v"
|
||||
|
||||
|
||||
module system ( input clock,input reset, output [19:0]address_bus, output [15:0]data_bus_write ,output BHE, output rd, output wr, output IOMEM, output HALT, output [`ERROR_BITS-1:0] ERROR);
|
||||
module system ( input clock,input reset, output [19:0]address_bus, inout [15:0]data_bus,output BHE, output rd, output wr, output IOMEM, output HALT, output [`ERROR_BITS-1:0] ERROR);
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
wire new_instruction;
|
||||
`endif
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
wire unsigned [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT;
|
||||
wire VALID_INSTRUCTION_STAT,jump_req;
|
||||
`endif
|
||||
|
||||
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,wait_state,rd,wr,BHE,IOMEM
|
||||
/* MEMORY / IO */ ,address_bus,data_bus,rd,wr,BHE,IOMEM
|
||||
`ifdef CALCULATE_IPC
|
||||
/* STATISTICS */ ,new_instruction
|
||||
`endif
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT, jump_req
|
||||
`endif
|
||||
);
|
||||
|
||||
wire [15:0] data_bus_read_RAM;
|
||||
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
||||
|
||||
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
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
string stats_name,version,commit;
|
||||
integer json_file_descriptor;
|
||||
`endif
|
||||
|
||||
`ifndef YOSYS
|
||||
string waveform_name;
|
||||
`endif
|
||||
|
||||
initial begin
|
||||
`ifndef SYNTHESIS
|
||||
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
||||
$dumpfile(waveform_name);
|
||||
$dumpvars(0,p,cycles);
|
||||
end
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
if(!$value$plusargs("VERSION=%s",version)) version="unkown";
|
||||
if(!$value$plusargs("COMMIT=%s",commit)) commit="unkown";
|
||||
if($value$plusargs("STATS=%s",stats_name))begin
|
||||
json_file_descriptor=$fopen(stats_name,"w");
|
||||
$fdisplay(json_file_descriptor,"{\n\"L1_size\":%0d,\n\"9086 verison\":\"%s\",\n\"latest commit\":\"%s\",\n\"Cycles\":[",$rtoi($pow(2,`L1_CACHE_SIZE)),version,commit);
|
||||
first_json_cycle = 1;
|
||||
end else
|
||||
json_file_descriptor=0;
|
||||
`endif
|
||||
sane=0;
|
||||
finish=0;
|
||||
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
||||
$dumpfile(waveform_name);
|
||||
$dumpvars(0,p,cycles);
|
||||
end
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
if(!$value$plusargs("VERSION=%s",version)) version="unkown";
|
||||
if(!$value$plusargs("COMMIT=%s",commit)) commit="unkown";
|
||||
if($value$plusargs("STATS=%s",stats_name))begin
|
||||
json_file_descriptor=$fopen(stats_name,"w");
|
||||
$fdisplay(json_file_descriptor,"{\n\"L1_size\":%0d,\n\"9086 verison\":\"%s\",\n\"latest commit\":\"%s\",\n\"Cycles\":[",$rtoi($pow(2,`L1_CACHE_SIZE)),version,commit);
|
||||
first_json_cycle = 1;
|
||||
end else
|
||||
json_file_descriptor=0;
|
||||
`endif
|
||||
sane=0;
|
||||
finish=0;
|
||||
end
|
||||
|
||||
//integer killswitch=0;
|
||||
@ -95,7 +81,7 @@ end
|
||||
// end
|
||||
//end
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
reg first_json_cycle;
|
||||
always @(negedge clock)begin
|
||||
if(finish < 2 && json_file_descriptor!=0 && sane)begin
|
||||
@ -105,127 +91,96 @@ always @(negedge clock)begin
|
||||
end
|
||||
`endif
|
||||
|
||||
reg [15:0]data_bus_IO;
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
always @(negedge wr) begin
|
||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )begin
|
||||
$write("%s" ,data_bus_write[15:8]);
|
||||
end else if(IOMEM==1'b1 && address_bus[7:0]==8'hB0 )begin
|
||||
if(data_bus_write[0:0]==1)
|
||||
$display("\x1b[7mLed turned on\x1b[m\n");
|
||||
else
|
||||
$display("\x1b[7mLed turned off\x1b[m\n");
|
||||
end
|
||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
|
||||
$write("%s" ,data_bus[15:8]);
|
||||
end
|
||||
always @(negedge rd) begin
|
||||
if(IOMEM==1'b1 && address_bus[7:1]==7'h10 )begin // 0xABCD on address 0x20
|
||||
data_bus_IO<=16'hABCD;
|
||||
end else begin
|
||||
data_bus_IO<=16'h0000;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
reg [128:0] instruction_count;
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
always @(new_instruction) begin
|
||||
instruction_count<=instruction_count+1;
|
||||
end
|
||||
`endif
|
||||
|
||||
reg [1:0] finish;
|
||||
string memdump_name;
|
||||
always @(posedge HALT) begin
|
||||
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||
$writememh(memdump_name, sysmem.memory,0,32767);
|
||||
end
|
||||
finish<=2'd1;
|
||||
end
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
reg [128:0] instruction_count_temp;
|
||||
`endif
|
||||
always @(posedge clock) begin
|
||||
/* Allow some clock cycles for the waveform*/
|
||||
case(finish)
|
||||
2'd0: begin end
|
||||
2'd1: begin
|
||||
finish <= 2;
|
||||
/* instruction_count gets updated at the sme time as HALT is pulled so wait a clock cycle to get an accurate reading*/
|
||||
$display("\x1b[7mProcessor halted.\nCycles run for : %0d\x1b[m",cycles);
|
||||
`ifdef CALCULATE_IPC
|
||||
/* verilator lint_off REALCVT */
|
||||
$display("\x1b[7mInstr. per cycle : %f\x1b[m", $itor(instruction_count) / $itor(cycles) );
|
||||
/* verilator lint_on REALCVT */
|
||||
`endif
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
instruction_count_temp <= instruction_count;
|
||||
`endif
|
||||
end
|
||||
2'd2: begin
|
||||
finish <= 3;
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
if(json_file_descriptor!=0)
|
||||
$fdisplay(json_file_descriptor,"],\n\"Total Cycles\":%0d,\n\"Instructions run\":%0d\n}",cycles-1,instruction_count_temp);
|
||||
`endif
|
||||
end
|
||||
2'd3: $finish;
|
||||
endcase
|
||||
end
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
reg [128:0] instruction_count_temp;
|
||||
`endif
|
||||
|
||||
string memdump_name;
|
||||
|
||||
always @(posedge HALT) begin
|
||||
always @(posedge reset)begin
|
||||
sane<=1;
|
||||
end
|
||||
reg sane;
|
||||
always @( ERROR ) begin
|
||||
if ( ERROR != `ERR_NO_ERROR && sane == 1 ) begin
|
||||
$display("PROCESSOR RUN INTO AN ERROR.");
|
||||
case (ERROR)
|
||||
default:begin
|
||||
end
|
||||
`ERR_UNIMPL_INSTRUCTION:begin
|
||||
$display("Unimplemented instruction");
|
||||
end
|
||||
`ERR_UNIMPL_ADDRESSING_MODE: begin
|
||||
$display("Unimplemented addressing mode");
|
||||
end
|
||||
endcase
|
||||
$display("Cycles run for: %0d",cycles-1);
|
||||
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||
$writememh(memdump_name, sysmem.memory,0,32767);
|
||||
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
||||
end
|
||||
finish<=2'd1;
|
||||
end
|
||||
end
|
||||
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
reg [1:0] finish;
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
reg [128:0] cycles;
|
||||
|
||||
reg sane;
|
||||
reg [128:0] cycles;
|
||||
|
||||
always @(posedge reset)begin
|
||||
sane<=1;
|
||||
always @(negedge clock)begin
|
||||
if(reset==1)
|
||||
cycles<=cycles+1;
|
||||
else begin
|
||||
cycles<=0;
|
||||
`ifdef OTUPUT_JSON_STATISTICS
|
||||
instruction_count <= 0;
|
||||
`endif
|
||||
end
|
||||
|
||||
always @(posedge clock) begin
|
||||
/* Allow some clock cycles for the waveform*/
|
||||
case(finish)
|
||||
2'd0: begin end
|
||||
2'd1: begin
|
||||
finish <= 2;
|
||||
/* instruction_count gets updated at the sme time as HALT is pulled so wait a clock cycle to get an accurate reading*/
|
||||
$display("\x1b[7mProcessor halted.\nCycles run for : %0d\x1b[m",cycles);
|
||||
`ifdef CALCULATE_IPC
|
||||
$display("\x1b[7mInstr. per cycle : %f\x1b[m", $itor(instruction_count) / $itor(cycles) );
|
||||
`endif
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
instruction_count_temp <= instruction_count;
|
||||
`endif
|
||||
end
|
||||
2'd2: begin
|
||||
finish <= 3;
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
if(json_file_descriptor!=0)
|
||||
$fdisplay(json_file_descriptor,"],\n\"Total Cycles\":%0d,\n\"Instructions run\":%0d\n}",cycles-1,instruction_count_temp);
|
||||
`endif
|
||||
$finish;
|
||||
end
|
||||
2'd3: begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @( ERROR ) begin
|
||||
if ( ERROR != `ERR_NO_ERROR && sane == 1 ) begin
|
||||
$display("PROCESSOR RUN INTO AN ERROR.");
|
||||
case (ERROR)
|
||||
default:begin
|
||||
end
|
||||
`ERR_UNIMPL_INSTRUCTION:begin
|
||||
$display("Unimplemented instruction");
|
||||
end
|
||||
`ERR_UNIMPL_ADDRESSING_MODE: begin
|
||||
$display("Unimplemented addressing mode");
|
||||
end
|
||||
endcase
|
||||
$display("Cycles run for: %0d",cycles-1);
|
||||
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
||||
end
|
||||
finish<=2'd1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(negedge clock)begin
|
||||
if(reset==1)
|
||||
cycles<=cycles+1;
|
||||
else begin
|
||||
cycles<=0;
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
instruction_count <= 0;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -36,7 +36,6 @@ int main(int argc, char** argv) {
|
||||
tick();
|
||||
system_state->reset=0;
|
||||
tick();
|
||||
tick();
|
||||
system_state->reset=1;
|
||||
|
||||
// Simulate until $finish
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
@ -25,7 +25,7 @@ wire clock;
|
||||
reg reset;
|
||||
reg clk_enable;
|
||||
wire [19:0]address_bus;
|
||||
wire [15:0]data_bus_write;
|
||||
wire [15:0]data_bus;
|
||||
wire rd,wr,HALT;
|
||||
wire [2:0] ERROR;
|
||||
wire IOMEM;
|
||||
@ -33,7 +33,7 @@ wire IOMEM;
|
||||
system system( .clock(clock),
|
||||
.reset(reset),
|
||||
.address_bus(address_bus),
|
||||
.data_bus_write(data_bus_write),
|
||||
.data_bus(data_bus),
|
||||
.rd(rd),
|
||||
.wr(wr),
|
||||
.HALT(HALT),
|
||||
@ -49,26 +49,22 @@ initial begin
|
||||
do_reset = 0;
|
||||
end
|
||||
|
||||
reg [2:0]do_reset;
|
||||
reg [1:0]do_reset;
|
||||
|
||||
always @(posedge clock) begin
|
||||
case(do_reset)
|
||||
3'd0:begin
|
||||
2'd0:begin
|
||||
do_reset<=1;
|
||||
end
|
||||
3'd1:begin
|
||||
2'd1:begin
|
||||
do_reset<=2;
|
||||
reset <= 0;
|
||||
end
|
||||
3'd2:begin
|
||||
2'd2:begin
|
||||
do_reset<=3;
|
||||
reset <= 0;
|
||||
end
|
||||
3'd3:begin
|
||||
do_reset<=4;
|
||||
reset <= 1;
|
||||
end
|
||||
3'd4:begin
|
||||
2'd3:begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2024 Efthymios Kritikos
|
||||
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
|
||||
|
@ -1,21 +0,0 @@
|
||||
# This file is basically to make verilator compilation look pretty.
|
||||
# If the project doesn't compile it might be because verilator handles compilation
|
||||
# differently and this patch doesn't work anymore. In such case remove everything
|
||||
# except the include Vfpga_top.mk line and try again.
|
||||
VM_DEFAULT_RULES=0
|
||||
|
||||
include Vfpga_top.mk
|
||||
|
||||
include ../../../common.mk
|
||||
|
||||
%.o: %.cpp
|
||||
${QUIET_CC}
|
||||
${Q}$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
||||
|
||||
$(VK_SLOW_OBJS): %.o: %.cpp
|
||||
${QUIET_CC}
|
||||
${Q}$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
||||
|
||||
$(VK_GLOBAL_OBJS): %.o: %.cpp
|
||||
${QUIET_CC}
|
||||
${Q}$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_GLOBAL) -c -o $@ $<
|
@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# docker_build_tests.sh - Tests the build process on various distributions with docker
|
||||
#
|
||||
# Copyright (c) 2024 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/>.
|
||||
#
|
||||
set -eu
|
||||
|
||||
PROJDIRNAME=$(basename $(realpath "$(dirname "$0")"/..))
|
||||
cd $(realpath "$(dirname "$0")"/../..)
|
||||
|
||||
FAILED=0
|
||||
|
||||
do_test(){
|
||||
case "$1" in
|
||||
"debian:stable"|"debian:latest")
|
||||
SYSTEM_UPDATE="apt-get update ;apt-get -y install make bin86 xxd verilator g++ libz-dev"
|
||||
;;
|
||||
"ubuntu:latest")
|
||||
SYSTEM_UPDATE="apt-get update ;apt-get -y install make bin86 xxd verilator g++ libz-dev libfindbin-libs-perl"
|
||||
;;
|
||||
"fedora:latest")
|
||||
SYSTEM_UPDATE="dnf install -y make verilator dev86 g++ zlib-devel xxd"
|
||||
;;
|
||||
"archlinux:latest")
|
||||
SYSTEM_UPDATE="pacman --noconfirm -Sy make verilator xxd bin86 gcc python"
|
||||
;;
|
||||
esac
|
||||
if tar c "$PROJDIRNAME" | docker run -i "$1" bash -c 'set -eu;tar x ;'"$SYSTEM_UPDATE"'; cd 9086; make mrproper; if [ "$(make -j boot_code/gnome_sort.run| tail -n5|head -n 1)" = "06 09 17 18 1F 21 33 37 3A 3F 44 4F 51 51 54 5D 8B 99 A5 AE DB DF E9 EE " ];then echo pass;else echo failed check; exit 1;fi ' > /dev/null 2>/dev/null
|
||||
then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ubuntu:latest has a version of verilator that is too old.
|
||||
for i in debian:stable debian:latest fedora:latest archlinux:latest
|
||||
do
|
||||
printf 'Testing with docker image %s \t: ' "$i" |expand -t 44
|
||||
if ! do_test "$i"
|
||||
then
|
||||
FAILED=1
|
||||
printf '\e[1;31mFailed\e[0m\n'
|
||||
else
|
||||
printf '\e[1;32mPassed\e[0m\n'
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$FAILED" = 1 ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
@ -1,246 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# gen_litedram.sh - Downloads and generates the litedram verilog source code for a specific phy or for simulation
|
||||
#
|
||||
# Copyright (c) 2024 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/>.
|
||||
#
|
||||
set -eu
|
||||
|
||||
SOURCE_CODE_URL=https://github.com/enjoy-digital/litedram/archive/refs/tags/2023.08.tar.gz
|
||||
SOURCE_MD5_SUM=afc2208c08e60994d126c445574960da
|
||||
PYTHON_APPIMAGE_URL=https://github.com/niess/python-appimage/releases/download/python3.9/python3.9.18-cp39-cp39-manylinux_2_28_x86_64.AppImage
|
||||
PYTHON_APPIMAGE_SUM=8c383ade3ace416cf508d5f458b30149
|
||||
|
||||
OUTPUT_ECP5_1_WISHBONE_MD5=c775ddb23fd97211f3ace40d6e8c2a5f
|
||||
OUTPUT_ECP5_1_WISHBONE_SIM_MD5=06d0b073d06937312b425767c1895c6c
|
||||
|
||||
|
||||
help(){
|
||||
echo This scripts generates a verilog file from the litedram project
|
||||
echo It is currently hardcoded for the ECP5 PHY
|
||||
echo
|
||||
echo Usage:
|
||||
echo \ \ \ "$0" \<output verilog file\>
|
||||
}
|
||||
|
||||
STOP_PARSING=0
|
||||
OUT_FILE=""
|
||||
QUIET=0
|
||||
FORCE=0
|
||||
SIMULATION=0
|
||||
while [ $# -gt 0 ]; do
|
||||
if [ "$STOP_PARSING" = "1" ]
|
||||
then
|
||||
echo arguments after --
|
||||
help
|
||||
exit 1
|
||||
fi
|
||||
case $1 in
|
||||
-q|--quiet)
|
||||
QUIET="$1"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
shift
|
||||
;;
|
||||
-s|--simulation)
|
||||
SIMULATION=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
if ! [ $# -gt 1 ]
|
||||
then
|
||||
echo No file after --
|
||||
help
|
||||
exit 1
|
||||
fi
|
||||
if [ "$OUT_FILE" ]
|
||||
then
|
||||
echo Error two output files given
|
||||
exit 1
|
||||
fi
|
||||
OUT_FILE=$2
|
||||
STOP_PARSING=1
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option $1"
|
||||
help
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
if [ "$OUT_FILE" ]
|
||||
then
|
||||
echo Error two output files given
|
||||
exit 1
|
||||
fi
|
||||
OUT_FILE=$1
|
||||
shift # past argument
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$OUT_FILE" = "" ]
|
||||
then
|
||||
echo Error: No output file provided
|
||||
help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
trap 'rm -rf -- "$TEMP_DIR"' EXIT
|
||||
CUR_DIR=$(pwd)
|
||||
|
||||
if ! echo "$OUT_FILE" | grep '^/' > /dev/null
|
||||
then
|
||||
OUT_FILE="${CUR_DIR}/${OUT_FILE}"
|
||||
fi
|
||||
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
if [ "$QUIET" = 0 ];then
|
||||
echo Downloading litedram source code...
|
||||
fi
|
||||
wget --output-document=source.tar.gz --quiet "$SOURCE_CODE_URL"
|
||||
|
||||
|
||||
if [ "$(md5sum source.tar.gz)" != "${SOURCE_MD5_SUM} source.tar.gz" ]
|
||||
then
|
||||
echo Downloaded litedram source downloaded doesn\'t match md5 sum
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$QUIET" = 0 ];then
|
||||
echo Downloading python appimage...
|
||||
fi
|
||||
wget --output-document=python.AppImage --quiet "$PYTHON_APPIMAGE_URL"
|
||||
|
||||
if [ "$(md5sum python.AppImage)" != "${PYTHON_APPIMAGE_SUM} python.AppImage" ]
|
||||
then
|
||||
echo Downloaded python appimage source doesn\'t match md5 sum
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod a+x python.AppImage
|
||||
|
||||
./python.AppImage --appimage-extract >/dev/null
|
||||
|
||||
PYTHON=$(realpath squashfs-root/AppRun)
|
||||
|
||||
mkdir python_modules
|
||||
PYTHON_MODULES=$(realpath python_modules)
|
||||
|
||||
######### This is a patch ############
|
||||
# It's because litedram needs modules
|
||||
# it doesn't really use for --sim and
|
||||
# pip doesn't currently have some
|
||||
wget --quiet https://github.com/enjoy-digital/litescope/archive/refs/tags/2023.08.tar.gz
|
||||
tar xf 2023.08.tar.gz
|
||||
mv litescope-2023.08/litescope/ "${PYTHON_MODULES}"
|
||||
rm -r litescope-2023.08 2023.08.tar.gz
|
||||
######################################
|
||||
|
||||
|
||||
if [ "$QUIET" = 0 ];then
|
||||
echo extracting the source...
|
||||
fi
|
||||
tar xvf source.tar.gz > source_dir
|
||||
|
||||
SOURCE_DIR=$(head -n 1 source_dir)
|
||||
rm source_dir
|
||||
|
||||
if [ "$QUIET" = 0 ];then
|
||||
echo patching the source...
|
||||
fi
|
||||
#Generate the following text by running this: (diff -Naur /dev/null examples/orangecrab_9086.yml | gzip -9 | base64 | tr -d '\n';echo)
|
||||
echo H4sIAAAAAAACA61US2+bQBA+179ihC+JMA4Pg4mlSo7sOLFaJ5bjHKqqQguMYxRg6QJ2UJX/3lkwUeKop3oOy2pmvm/niaZpcBHi7iIt4/iLqZuWZpiaboJhj6zhaGD13aFOYthDUOWlo6oq4AtLshjzCy5Y+oSBYL53qbtOv0rekVhguCNzONKtvnM5HNqubtoHkvEYNL2ng2r0LAPG4476p6MCdOEGUxQsBu2/RfIplFkUoDKi6/fZtf2omfZMcxc3pmtPlB69N1veXEHj1a8RQVZKdxLljqdITh+kC5PlIxRVhnCGL7DDFxHlwa4HOQo6JeS85kkwkV7EpUynK+szz3R1taiJOmoTauLle5YpQIi1KOnlJp4k9EKMWSUNJLqMeg5ljsAg5nvYsbhEKDiwHY9CEMhCiHGHcZQ+NdRdWN7+OEFF36qah4IlXsLDMsamWMpiPTC+OYOF4chMu/BQp9e45MA3UGwRfM5ECFzAw702nS8Wn8i81Cc+s3dUqrsy8VFIFr8qEJ4EL7P8HZiG8LmBAhj/Bku397BsWx1aTarrydKmRlGlmgTWssUEqgeEtG0pZwJ/l5gGFZyklFGalYUXxM/ehojrcAYuOnWTpQmCmAfPsHl79efkfrW6nqx/NYlU+UcwgDOQcNmCKi8w+URwRq2RGPgKB/T5EWmURkchgdmSzsl2TNmWZsIFwummTE6+X242KGgBsmJLkRhO77A8UtGOVcCThKUhNM5tNI+0kbDkosjhFNHQwgkvk3QUR/2zIuU+yrc+rbyny+08aEnfbn5rb3a5NoWsYN4+Cut8LPNgeK2/8nzt/AU14UE3kwUAAA== | base64 -d | gzip -d > 00-add_orangecrab_config.patch
|
||||
|
||||
cd "$SOURCE_DIR"
|
||||
|
||||
patch -s -p0 < ../00-add_orangecrab_config.patch > /dev/null
|
||||
|
||||
|
||||
if [ "$QUIET" = 0 ];then
|
||||
echo Downloading required python modules...
|
||||
fi
|
||||
|
||||
if ! "$PYTHON" -m pip install --target "$PYTHON_MODULES" install "pyaml==23.9.7" "migen==0.9.2" "litex==2023.08" "litedram==2023.8" "liteeth==2022.12" "liteiclink==2022.12" "pythondata_misc_tapcfg" > "$TEMP_DIR/build_log" 2> "$TEMP_DIR/build_log"
|
||||
then
|
||||
echo ERROR: Failed download python modules
|
||||
cat "$TEMP_DIR/build_log"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ./setup.py build > "$TEMP_DIR/build_log" 2> "$TEMP_DIR/build_log"
|
||||
then
|
||||
echo ERROR: Failed to run setup.py
|
||||
cat "$TEMP_DIR/build_log"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd build/lib/litedram/
|
||||
|
||||
GEN_OPTIONS=""
|
||||
|
||||
if [ $SIMULATION = 1 ]
|
||||
then
|
||||
GEN_OPTIONS="$GEN_OPTIONS --sim"
|
||||
fi
|
||||
|
||||
if ! PYTHONPATH=$PYTHON_MODULES "$PYTHON" gen.py $GEN_OPTIONS ../../../examples/orangecrab_9086.yml --no-compile-software > "$TEMP_DIR/build_log" 2> "$TEMP_DIR/build_log"
|
||||
then
|
||||
echo ERROR: Failed to run gen.py
|
||||
cat "$TEMP_DIR/build_log"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$QUIET" = 0 ];then
|
||||
echo patching source file...
|
||||
fi
|
||||
|
||||
if [ "$SIMULATION" = 0 ]
|
||||
then
|
||||
#This is just for some yosys warnings...
|
||||
echo H4sIAAAAAAACA82T326CMBTG73mKc7XBECnKAHUkvMeyNEdatZE/hiLEzPnsa5nL4pYh3izrTduc3/d9Jyet4ziw3IuMuWuseYsVdzNRc1ZhTtOy4uMGJmQydTzPmYRAgrkfzEk4noYzEgZh5INN1DJs2waX8cYt9lkG3yWRUo1nj5FPvMALzpIkASci/nQUgt3tASSJASilWBfw+tmFboKylaA7j7YVwxpH8LNGzrU3iC+roqh5tcKU01bXF/8igOYot30pHaCjzFNfGG25tTCcvw4EzFo8SEjMBwuWfC0KA/S6UKabspRqyxltMBNMwlMM0T0jiyHwM3nRvHlBLbHY5phuRMHJFwt3YJpXwB0eshIZFVJfleK39BaLWh+k1dmehhpXKLXgNIxOUVrWDbyauuKP/V1jWotG/WFlbRzhholUHBnEcb+7hj6GMti3rRR51bijVM+Weljv0yEXHY0EAAA= | base64 -d | gzip -d | patch -s -p0
|
||||
CHECK_MD5SUM=$OUTPUT_ECP5_1_WISHBONE_MD5
|
||||
else
|
||||
echo H4sIAAAAAAACA7WPOQ7CMBREe59ievPjPVvlC3AGMLGFIpkEZeP6pKBCoguvmPLNDBHhtvY5intY0itMSeR+SXEKj0s3TqnYAGipDSlNsoIqW2laVxWNaXTZWKfB5Q7jnEPEtIlhzRk/+BLZ1srCVLYuldPVR+Q9SJlTDb6ng/cMQtChMEbXpX+kuQs5QQ0zBNRzZsTo8Kp9PM5jXHP6x483iNz1Tr8BAAA= | base64 -d | gzip -d | patch -s -p0
|
||||
CHECK_MD5SUM=$OUTPUT_ECP5_1_WISHBONE_SIM_MD5
|
||||
fi
|
||||
|
||||
if ! [ "$(sed 's@//.*@@' build/gateware/litedram_core.v | md5sum )" = "$CHECK_MD5SUM -" ]
|
||||
then
|
||||
if [ "$FORCE" = 0 ]
|
||||
then
|
||||
echo ERROR: File was successfully built but the md5sum doesn\'t match the one used in development.
|
||||
echo You can ignore this error by passing the --force flag
|
||||
exit 1
|
||||
else
|
||||
echo WARNING: File was successfully built but the md5sum doesn\'t match the one used in development.
|
||||
fi
|
||||
fi
|
||||
|
||||
cp build/gateware/litedram_core.v "$OUT_FILE"
|
||||
|
||||
if [ "$QUIET" = 0 ];then
|
||||
echo File built correctly!
|
||||
fi
|
@ -1,70 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# parse_nextpnr_stats.sh - Reads a nextpnr json report file and generates some basic statistics about the design
|
||||
#
|
||||
# Copyright (c) 2024 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/>.
|
||||
#
|
||||
set -eu
|
||||
|
||||
if ! which jq &> /dev/null
|
||||
then
|
||||
echo to get statistics, please install jq
|
||||
exit 0
|
||||
fi
|
||||
|
||||
REPORT_TYPE=brief
|
||||
|
||||
if [ $# == 0 ]
|
||||
then
|
||||
echo $0' [report type] <report json file>'
|
||||
exit 1
|
||||
elif [ $# == 2 ]
|
||||
then
|
||||
case "$1" in
|
||||
"--brief")
|
||||
REPORT_TYPE=brief
|
||||
;;
|
||||
*)
|
||||
echo unknown parameter "\"$1\""
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
REPORT=$2
|
||||
else
|
||||
REPORT=$1
|
||||
fi
|
||||
|
||||
if ! [ -e "$REPORT" ]
|
||||
then
|
||||
echo file "\"${REPORT}\"" doesn\'t exist!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LUT_AVAIL=$(jq '.utilization.TRELLIS_COMB.available' "$REPORT" )
|
||||
LUT_USED=$(jq '.utilization.TRELLIS_COMB.used' "$REPORT" )
|
||||
FF_AVAIL=$(jq '.utilization.TRELLIS_FF.available' "$REPORT" )
|
||||
FF_USED=$(jq '.utilization.TRELLIS_FF.used' "$REPORT" )
|
||||
FREQ_GOT=$(jq '.fmax."$glbnet$CPU_SPEED".achieved' "$REPORT" |grep -o '..\..')
|
||||
FREQ_MAX=$(jq '.fmax."$glbnet$CPU_SPEED".constraint' "$REPORT" |grep -o '..\..')
|
||||
|
||||
if [ "$REPORT_TYPE" == "brief" ]
|
||||
then
|
||||
printf '\e[1;30m'
|
||||
echo Luts $LUT_USED/$LUT_AVAIL \($(echo "($LUT_USED*100)/$LUT_AVAIL"|bc -l|grep -o '^.*\..')%\)
|
||||
echo Flip Flops $FF_USED/$FF_AVAIL \($(echo "($FF_USED*100)/$FF_AVAIL"|bc -l|grep -o '^.*\..')%\)
|
||||
echo Max CPU freq $FREQ_GOT/$FREQ_MAX
|
||||
printf '\e[0m'
|
||||
fi
|
@ -1,29 +1,11 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# plot.sh - Parses the runtime simulation json data and plots them to an svg file
|
||||
#
|
||||
# Copyright (c) 2024 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/>.
|
||||
#
|
||||
set -euf
|
||||
|
||||
print_help(){
|
||||
echo "$0 <json data file> <function> <output filename>"
|
||||
echo " Possible functions:"
|
||||
echo " cache_time : graph of cache utilisation in bytes over time in clock cycles"
|
||||
echo " cache_util_freq : graph of the likelihood of the cache for each utilisation"
|
||||
echo " cache_util_freq : graph of the likelyhood of the cache for each utilisation"
|
||||
}
|
||||
|
||||
if [ "$#" != 3 ] || ! [ -e "$1" ]
|
||||
|
Loading…
Reference in New Issue
Block a user