Compare commits
115 Commits
Author | SHA1 | Date | |
---|---|---|---|
fde181aa66 | |||
c527a053a6 | |||
aac55f7038 | |||
a8c29aff9b | |||
be402aa8f7 | |||
1966ab78b4 | |||
1d9be44c5a | |||
8281c9a21f | |||
3e66336456 | |||
65dfd21ef0 | |||
94bc6eba39 | |||
8544764612 | |||
bc1dcacfc0 | |||
533f346f9b | |||
48249e8051 | |||
b1108e375d | |||
df5b9c13ea | |||
05343864da | |||
c1e597feba | |||
8edafd70cf | |||
dc7c4e95f2 | |||
acc0581124 | |||
2fcc521f12 | |||
dd1080b42c | |||
dd50114c07 | |||
26210be950 | |||
8fb6dadf48 | |||
0eecfdcf40 | |||
8c921380bc | |||
374b1946e9 | |||
63ea29e399 | |||
f1dc9d8a59 | |||
f07e0e7c1f | |||
17638d5cbd | |||
aedefddb5d | |||
29bc2e6d96 | |||
98d30a1813 | |||
09ccce5f30 | |||
0ca1da81b1 | |||
2c8e8a9d9c | |||
189b037bdf | |||
618c3102d8 | |||
7d2cb5672f | |||
e06c0eeaa0 | |||
fa62b07c14 | |||
f471b305d8 | |||
4c130a8d63 | |||
09b3d51015 | |||
863af26422 | |||
a88c420ca5 | |||
e0dc7bae07 | |||
1a1634c673 | |||
4767a7addc | |||
01dcbfa7a1 | |||
30ffa1b00c | |||
5ebd53b11c | |||
ae16c79b0a | |||
9947517693 | |||
4a5df9c74e | |||
aa9b7c0a50 | |||
df2975fa09 | |||
c7ddf3fa9e | |||
694f708a32 | |||
934e2f5a36 | |||
08aac5c7b6 | |||
601397b7f0 | |||
43f3e16ca4 | |||
36bf8f9c7a | |||
5feee9de57 | |||
85512d5ace | |||
b2972c9938 | |||
3ec90b1843 | |||
557d160be6 | |||
3a63e916f5 | |||
49335a2c2f | |||
8a62b89a13 | |||
cfed0b4117 | |||
4c28f98797 | |||
d151435ac1 | |||
ced03c48d6 | |||
8d3b54b812 | |||
42c319d55d | |||
a693b87e96 | |||
af63ef1d68 | |||
d2a98c02ff | |||
79d598fc64 | |||
0bf00df07c | |||
35a5a9ada2 | |||
6c146098ee | |||
e74d73ed58 | |||
3dd2ff59ea | |||
021dd06e9a | |||
64f5da82b0 | |||
1b510e4781 | |||
7db70d79ff | |||
90f63b525d | |||
30c3deca37 | |||
53e9d371d7 | |||
f914d1ec8f | |||
aca3357cda | |||
97912b1a29 | |||
bfa576e2a0 | |||
07d2a80b2e | |||
df342467c7 | |||
00aa828ddc | |||
fe0426a77b | |||
7151d5634f | |||
539fb8416b | |||
a8ab6b2dc7 | |||
7724e5f383 | |||
e4ef199b83 | |||
7e612bb701 | |||
c854818d6d | |||
b7bfbd4e33 | |||
da51dd6da7 |
10
.gitignore
vendored
10
.gitignore
vendored
@ -6,8 +6,18 @@
|
||||
*.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) 2023 Efthymios Kritikos
|
||||
# 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
|
||||
@ -21,7 +21,8 @@ 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} boot_code/fibonacci.txt boot_code/gnome_sort.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=.
|
||||
|
||||
NO_ASM=1
|
||||
include common.mk
|
||||
@ -29,21 +30,63 @@ include common.mk
|
||||
.PHONY: ${BOOTABLES}
|
||||
.PHONY: ${subst .txt,.bin,${BOOTABLES}}
|
||||
|
||||
${BOOTABLES} ${subst .txt,.bin,${BOOTABLES}} :
|
||||
${Q}make ${MAKEOPTS} -C boot_code $(subst boot_code/,,$@)
|
||||
${BOOTABLES} ${subst .stxt,.bin,${subst .txt,.bin,${BOOTABLES}}} :
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=boot_code/ -C boot_code $(subst boot_code/,,$@)
|
||||
|
||||
boot_code/%.txt:
|
||||
${Q}make ${MAKEOPTS} -C boot_code $(subst boot_code/,,$@)
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=boot_code/ -C boot_code $(subst boot_code/,,$@)
|
||||
|
||||
.PHONY:${SYSTEM_VVP}
|
||||
${SYSTEM_VVP}:
|
||||
${Q}make ${MAKEOPTS} -C system system.vvp
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system system.vvp
|
||||
|
||||
.PHONY:${VERILATOR_BIN}
|
||||
${VERILATOR_BIN}:
|
||||
${Q}make ${MAKEOPTS} -C system obj_dir/Vsystem
|
||||
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system obj_dir/Vsystem
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
${Q}make ${MAKEOPTS} -C system clean
|
||||
${Q}make ${MAKEOPTS} -C boot_code 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'
|
||||
|
60
README.md
60
README.md
@ -1,7 +1,7 @@
|
||||
<img width="186" height="70" style=" margin: 10px 0px 10px 10px;" alt="9086 logo" src="readme_files/9086_design1.svg">
|
||||
|
||||
|
||||
A CPU that aims to be binary compatible with the 8086 and with as many optimisations as possible
|
||||
A CPU that aims to be binary compatible with the 8086 ISA, focused on optimisation and flexibility.
|
||||
|
||||
### Progress
|
||||
|
||||
@ -10,28 +10,67 @@ A CPU that aims to be binary compatible with the 8086 and with as many optimisat
|
||||
* [X] Is Turing complete
|
||||
* [ ] Can boot up MS-DOS / FreeDOS
|
||||
* [ ] Is completely binary compatible
|
||||
* [ ] Is pipelined
|
||||
* [X] Is pipelined
|
||||
* [ ] Is Out of Order
|
||||
* [ ] Is superscalar
|
||||
* [ ] Has been successfully synthesized
|
||||
* [X] Has been successfully synthesized
|
||||
* [ ] Has a comprehensive testing framework
|
||||
|
||||
### 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)
|
||||
Specifically this list shows the software needed and the versions used during development (other versions should work as well)
|
||||
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 :
|
||||
|
||||
* Icarus Verilog : version 11.0 OR **(preferred)** Verilator : 5.006
|
||||
* Icarus Verilog : version 12.0 OR **(preferred)** Verilator : 5.018
|
||||
* bin86 : 0.16.21
|
||||
* GNU Make : 4.4.1
|
||||
* xxd : 2022-01-14
|
||||
* POSIX coreutils : GNU coreutils 9.1
|
||||
* xxd : 2023-10-25
|
||||
* 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
|
||||
All parts of this project are licensed under the GNU General Public License version 3 or later
|
||||
### 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 |
|
||||
|
||||
### Version names
|
||||
The version name consist of three numbers:
|
||||
@ -41,3 +80,4 @@ 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.
|
||||
|
286
boot_code/LiteDram_init.asm
Normal file
286
boot_code/LiteDram_init.asm
Normal file
@ -0,0 +1,286 @@
|
||||
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,16 +1,39 @@
|
||||
SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm fibonacci.asm gnome_sort.asm
|
||||
BINARIES=$(subst .asm,.txt,${SOURCE})
|
||||
# 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})
|
||||
BUILD_FILES=${BINARIES}
|
||||
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})
|
||||
BUILD_FILES+=$(subst .asm,.fst,${SOURCE})
|
||||
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
|
||||
BUILD_FILES+=$(subst .asm,.json,${SOURCE})
|
||||
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})
|
||||
|
||||
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
|
||||
@ -24,3 +47,5 @@ include ../common.mk
|
||||
clean:
|
||||
$(call QUIET_CLEAN,boot_code)
|
||||
${Q}rm -f $(BUILD_FILES) *.bf.asm
|
||||
|
||||
mrproper:
|
||||
|
31
boot_code/bios.asm
Normal file
31
boot_code/bios.asm
Normal file
@ -0,0 +1,31 @@
|
||||
.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,15 +1,22 @@
|
||||
; Interrupt table and routines
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
org 0x100
|
||||
INCLUDE brainfuck_compiler_v1.asm
|
||||
output_program:
|
||||
|
||||
org 0xF800
|
||||
mov sp,#SMALL_STACK
|
||||
call INIT_INT_VECT_TABLE
|
||||
INCLUDE brainfuck_compiler_v1.asm
|
||||
SMALL_STACK:
|
||||
|
||||
INCLUDE dos_layer.asm
|
||||
prog:
|
||||
INCLUDE hello_9086.bf.asm
|
||||
|
||||
|
||||
output_program:
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
MOV AX,#0xF800
|
||||
JMP AX
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
||||
|
@ -2,7 +2,7 @@
|
||||
;
|
||||
; This file is part of the 9086 project.
|
||||
;
|
||||
; Copyright (c) 2023 Efthymios Kritikos
|
||||
; 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
|
||||
@ -17,7 +17,9 @@
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
mov sp,#STACK
|
||||
; 0x0000-0x0100 int vector 0x0100-0x0700 data 0x0700-0xC000 program data
|
||||
|
||||
mov sp,#STACK_COMPILER
|
||||
mov bx,#bootup_msg
|
||||
mov ah,#0x02
|
||||
print1:
|
||||
@ -27,17 +29,27 @@ 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
|
||||
cmp dl,#0
|
||||
jne print2
|
||||
jmp print2
|
||||
exit:
|
||||
|
||||
MOV SI,#prog
|
||||
MOV DI,#output_program
|
||||
MOV DI,#0x0700
|
||||
;CL: write concat CH: move concat
|
||||
MOV CX,#0
|
||||
JMP COMPILE ; Moving some functions above the main switch to make shot jumps work
|
||||
@ -146,8 +158,9 @@ jne print3
|
||||
|
||||
MOV AL,#0xF4 ; hlt
|
||||
MOV [DI],AL
|
||||
MOV BX,#DATA
|
||||
MOV AX,#output_program
|
||||
; From 0x100 its free but i'll do 0x200 in case it start writing earlier
|
||||
MOV BX,#0x0200
|
||||
MOV AX,#0x0700
|
||||
JMP AX
|
||||
|
||||
;;;;;;;;; . ;;;;;;;;;
|
||||
@ -248,18 +261,19 @@ MOV AL,#0x43 ; inc %bx
|
||||
STOSB
|
||||
JMP MOVES_FLUSHED
|
||||
|
||||
|
||||
MOVES_ONE_LEFT:
|
||||
MOV AL,#0x4b ; dec %bx
|
||||
STOSB
|
||||
JMP MOVES_FLUSHED
|
||||
|
||||
|
||||
MOVES_FLUSHED:
|
||||
MOV CH,#0
|
||||
RET
|
||||
|
||||
bootup_msg: .ASCII 'Native 8086 brainfuck compiler v1\n'
|
||||
compiling: .ASCII 'Compiling...\0'
|
||||
compiled: .ASCII '\rCompiled! \n'
|
||||
DATA: .BLKB 560
|
||||
.BLKB 200
|
||||
STACK:
|
||||
compiling: .ASCII 'Compiling...\0'
|
||||
bootup_msg: .ASCII 'Native 8086 brainfuck compiler v1\n'
|
||||
.BLKB 6 ; Using the text as stack space for the compiled program
|
||||
STACK_COMPILER: ; brainfuck_mandelbrot depends on stack being at the end
|
||||
|
@ -1,16 +1,16 @@
|
||||
; Interrupt table and routines
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
ORG 0x100
|
||||
ORG 0xF000
|
||||
mov sp,#STACK
|
||||
call INIT_INT_VECT_TABLE
|
||||
INCLUDE brainfuck_interpreter_v0.asm
|
||||
|
||||
.BLKB 200
|
||||
STACK:
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
prog:
|
||||
INCLUDE hello_9086.bf.asm
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
MOV AX,#0xF000
|
||||
JMP AX
|
||||
|
@ -2,7 +2,7 @@
|
||||
;
|
||||
; This file is part of the 9086 project.
|
||||
;
|
||||
; Copyright (c) 2023 Efthymios Kritikos
|
||||
; 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
|
||||
|
@ -1,14 +1,22 @@
|
||||
; Interrupt table and routines
|
||||
INCLUDE dos_layer.asm
|
||||
;I got this down to 11428 bytes
|
||||
|
||||
.ORG 0x100
|
||||
org 0x100
|
||||
output_program:
|
||||
|
||||
org 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
|
||||
|
||||
INCLUDE dos_layer.asm
|
||||
prog:
|
||||
INCLUDE mandelbrot.bf.asm
|
||||
|
||||
output_program:
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
MOV AX,#0xC000
|
||||
JMP AX
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
||||
|
33
boot_code/cache_fill_and_empty.asm
Normal file
33
boot_code/cache_fill_and_empty.asm
Normal file
@ -0,0 +1,33 @@
|
||||
.ORG 0x0100
|
||||
MOV DI,#0x2000
|
||||
STOS
|
||||
STOS
|
||||
STOS
|
||||
STOS
|
||||
STOS
|
||||
STOS
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
MOV CX,#0x0000
|
||||
HLT
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
JMP AX
|
65
boot_code/colored_led.asm
Normal file
65
boot_code/colored_led.asm
Normal file
@ -0,0 +1,65 @@
|
||||
.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,7 +1,3 @@
|
||||
.ORG 0x84 ; INT 21
|
||||
DW 0xFFFF ; Code Segment
|
||||
DW PRINT_INT_HANDLE ; Program Counter
|
||||
|
||||
PRINT_INT_HANDLE:
|
||||
push AX
|
||||
CMP AH,#0x02
|
||||
@ -14,3 +10,15 @@ MOV AL,DL
|
||||
out byte #0xA5
|
||||
POP AX
|
||||
iret
|
||||
|
||||
INIT_INT_VECT_TABLE:
|
||||
push AX
|
||||
push DI
|
||||
MOV DI,#0x0084
|
||||
MOV AX,#0xFFFF
|
||||
STOSW
|
||||
MOV AX,#PRINT_INT_HANDLE
|
||||
STOSW
|
||||
POP DI
|
||||
POP AX
|
||||
RET
|
||||
|
@ -1,8 +1,8 @@
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
|
||||
org 0x100
|
||||
org 0xF000
|
||||
mov sp,#STACK
|
||||
call INIT_INT_VECT_TABLE
|
||||
|
||||
MOV AX,#0x1
|
||||
MOV BX,#0x1
|
||||
@ -26,6 +26,7 @@ MOV DL,#0x0a
|
||||
INT #0x21
|
||||
|
||||
hlt
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
|
||||
.BLKB 200
|
||||
@ -33,6 +34,6 @@ STACK:
|
||||
INCLUDE helpers.asm
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
MOV AX,#0xF000
|
||||
JMP AX
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
INCLUDE dos_layer.asm
|
||||
|
||||
.org 0x100
|
||||
.org 0xF000
|
||||
mov sp,#STACK
|
||||
MOV SI,#DATA
|
||||
call INIT_INT_VECT_TABLE
|
||||
|
||||
GNOME_SORT:
|
||||
CMP SI,#DATA+31
|
||||
CMP SI,#DATA+23
|
||||
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+32
|
||||
CMP SI,#DATA+24
|
||||
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,6 +49,8 @@ STACK:
|
||||
INCLUDE helpers.asm
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
MOV AX,#0xF000
|
||||
JMP AX
|
||||
|
||||
.ORG 0xFFFF
|
||||
DB 0x00 ;Make sure a full 64KiB image
|
||||
|
187
boot_code/i2c_bootloader.asm
Normal file
187
boot_code/i2c_bootloader.asm
Normal file
@ -0,0 +1,187 @@
|
||||
.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
|
106
boot_code/pipeline_ideal.asm
Normal file
106
boot_code/pipeline_ideal.asm
Normal file
@ -0,0 +1,106 @@
|
||||
org 0xF000
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
inc ax
|
||||
inc bx
|
||||
hlt
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0xF000
|
||||
JMP AX
|
78
common.mk
78
common.mk
@ -1,24 +1,59 @@
|
||||
.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)
|
||||
|
||||
ifeq "${QUIET}" "1"
|
||||
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;
|
||||
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;
|
||||
Q = @
|
||||
MAKEOPTS=--no-print-directory
|
||||
.SILENT:
|
||||
@ -32,13 +67,20 @@ run: $(subst .txt,.run,${BOOT_CODE})
|
||||
wave: $(subst .txt,.wave,${BOOT_CODE})
|
||||
disas: $(subst .txt,.disas,${BOOT_CODE})
|
||||
|
||||
# Assembling code
|
||||
%.stxt: %.bin
|
||||
${Q}dd if=/dev/zero bs=1 count=2048 of="$(subst .bin,.stage,$<)" status=none
|
||||
${Q}dd if="$<" bs=1 skip=63488 of="$(subst .bin,.stage,$<)" conv=notrunc,nocreat status=none
|
||||
${Q}xxd -ps -c 2 "$(subst .bin,.stage,$<)" > "$@"
|
||||
${Q}rm "$(subst .bin,.stage,$<)"
|
||||
|
||||
# Assembling code
|
||||
%.txt:%.bin
|
||||
${Q}dd if=/dev/zero bs=1 count=65536 of="$(subst .bin,.stage,$<)" status=none
|
||||
${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,$<)"
|
||||
${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
|
||||
@ -50,31 +92,29 @@ endif
|
||||
ifeq "${SIM}" "ICARUS"
|
||||
%.fst %.memdump: %.txt ${SYSTEM_VVP} ${MICROCODE}
|
||||
${QUIET_VVP}
|
||||
${Q}vvp "${SYSTEM_VVP}" -fst +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.fst,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
|
||||
${Q}vvp "${SYSTEM_VVP}" -fst +VERSION=${VERSION} +COMMIT=${COMMIT} +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.fst,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
|
||||
${Q}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
|
||||
${Q}rm "$(subst .txt,.memdumptxt,$<)"
|
||||
|
||||
%.run: %.txt ${SYSTEM_VVP} ${MICROCODE}
|
||||
${QUIET_VVP}
|
||||
${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
|
||||
${Q}vvp -i "${SYSTEM_VVP}" +VERSION=${VERSION} +COMMIT=${COMMIT} +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
%.json: %.txt ${SYSTEM_VVP} ${MICROCODE}
|
||||
${QUIET_VVP}
|
||||
${Q}vvp -i "${SYSTEM_VVP}" +STATS="$@" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
${Q}vvp -i "${SYSTEM_VVP}" +VERSION=${VERSION} +COMMIT=${COMMIT} +STATS="$@" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
else ifeq "${SIM}" "VERILATOR"
|
||||
%.fst %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
||||
${Q}"${VERILATOR_BIN}" +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.fst,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
|
||||
${Q}"${VERILATOR_BIN}" +VERSION=${VERSION} +COMMIT=${COMMIT} +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.fst,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
|
||||
${Q}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
|
||||
${Q}rm "$(subst .txt,.memdumptxt,$<)"
|
||||
|
||||
%.json: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
||||
${Q} ${NUMACTL} "${VERILATOR_BIN}" +STATS=$@ +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
|
||||
${Q} ${NUMACTL} "${VERILATOR_BIN}" +VERSION=${VERSION} +COMMIT=${COMMIT} +STATS=$@ +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
%.run: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
||||
${Q} ${NUMACTL} "${VERILATOR_BIN}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
${Q} ${NUMACTL} "${VERILATOR_BIN}" +VERSION=${VERSION} +COMMIT=${COMMIT} +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||
endif
|
||||
|
||||
%.disas: %.bin
|
||||
|
@ -1,43 +1,74 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.111 (w)1999-2020 BSI
|
||||
[*] Thu Mar 9 04:20:33 2023
|
||||
[*] Wed May 31 20:14:37 2023
|
||||
[*]
|
||||
[dumpfile] "/home/user/9086/system/boot_code.fst"
|
||||
[dumpfile_mtime] "Thu Mar 9 04:18:18 2023"
|
||||
[dumpfile_size] 8510
|
||||
[dumpfile_mtime] "Wed May 31 20:14:23 2023"
|
||||
[dumpfile_size] 4718
|
||||
[savefile] "/home/user/9086/gtkwave_savefile.gtkw"
|
||||
[timestart] 198700000000
|
||||
[size] 1236 1017
|
||||
[timestart] 500000000
|
||||
[size] 1044 1003
|
||||
[pos] -1 -1
|
||||
*-34.595051 280500000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
*-32.495049 38460000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] TOP.
|
||||
[treeopen] TOP.system.
|
||||
[sst_width] 221
|
||||
[signals_width] 293
|
||||
[treeopen] TOP.system.p.
|
||||
[treeopen] TOP.system.p.BIU.
|
||||
[treeopen] TOP.system.p.decoder.
|
||||
[treeopen] TOP.system.p.execute_unit.
|
||||
[sst_width] 263
|
||||
[signals_width] 231
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 312
|
||||
[sst_vpaned_height] 298
|
||||
@28
|
||||
TOP.system.clock
|
||||
TOP.system.reset
|
||||
TOP.system.p.state[5:0]
|
||||
@22
|
||||
TOP.system.p.ucode_seq_addr[4:0]
|
||||
TOP.system.address_bus[19:0]
|
||||
TOP.system.data_bus[15:0]
|
||||
TOP.system.p.CIR[15:0]
|
||||
TOP.system.p.PARAM1[15:0]
|
||||
TOP.system.p.PARAM2[15:0]
|
||||
@28
|
||||
TOP.system.p.read
|
||||
TOP.system.p.write
|
||||
@29
|
||||
TOP.system.IOMEM
|
||||
@22
|
||||
TOP.system.p.ALU_1A[15:0]
|
||||
TOP.system.p.ALU_1B[15:0]
|
||||
TOP.system.p.ALU_1O[15:0]
|
||||
@200
|
||||
-
|
||||
@28
|
||||
TOP.system.p.ERROR
|
||||
TOP.system.p.BIU.VALID_INSTRUCTION
|
||||
TOP.system.p.valid_exec_data
|
||||
TOP.system.p.execute_unit.next_exec
|
||||
@23
|
||||
TOP.system.p.IF2DE_INSTRUCTION[31:0]
|
||||
@22
|
||||
TOP.system.p.BIU.biu_state[3:0]
|
||||
@28
|
||||
TOP.system.p.execute_unit.exec_state[3:0]
|
||||
TOP.system.p.BIU.write_request
|
||||
TOP.system.p.BIU.read_request
|
||||
TOP.system.p.execute_unit.biu_jump_req
|
||||
@200
|
||||
-
|
||||
@28
|
||||
TOP.system.p.ERROR[2:0]
|
||||
TOP.system.IOMEM
|
||||
TOP.system.p.HALT
|
||||
@22
|
||||
TOP.system.p.BIU.INSTRUCTION[31:0]
|
||||
TOP.system.p.BIU.FIFO_end[3:0]
|
||||
TOP.system.p.BIU.FIFO_start[3:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[0][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[1][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[2][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[3][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[4][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[5][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[6][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[7][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[8][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[9][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[10][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[11][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[12][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[13][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[14][7:0]
|
||||
TOP.system.p.BIU.INPUT_FIFO[15][7:0]
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
Binary file not shown.
@ -1,12 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 112 42" shape-rendering="crispEdges">
|
||||
<path stroke="#346524" d="M0 0h5M9 0h3M16 0h3M23 0h3M30 0h3M37 0h3M44 0h17M65 0h3M72 0h3M79 0h3M86 0h10M100 0h6M110 0h2M0 1h5M9 1h3M16 1h3M23 1h3M30 1h3M37 1h3M44 1h4M57 1h4M65 1h3M72 1h3M79 1h3M86 1h10M100 1h6M110 1h2M0 2h5M9 2h3M16 2h3M23 2h3M30 2h3M37 2h3M44 2h3M58 2h3M65 2h3M72 2h3M79 2h3M86 2h3M93 2h3M100 2h6M110 2h2M0 3h5M9 3h3M16 3h3M23 3h3M30 3h3M37 3h3M44 3h3M58 3h3M65 3h3M72 3h3M79 3h3M86 3h3M93 3h3M100 3h6M110 3h2M0 4h2M103 4h3M110 4h2M0 5h2M110 5h2M0 6h2M110 6h2M0 7h2M110 7h2M0 8h2M109 8h3M0 9h2M103 9h9M0 10h2M103 10h9M0 11h2M0 12h2M0 13h2M0 14h2M0 15h2M103 15h9M0 16h2M103 16h9M0 17h2M0 18h2M0 19h3M0 20h3M0 21h3M103 21h9M0 22h3M103 22h9M0 23h3M0 24h2M0 25h2M0 26h2M0 27h2M103 27h9M0 28h2M103 28h9M0 29h2M0 30h2M0 31h2M0 32h2M0 33h2M103 33h9M0 34h2M103 34h9M0 35h2M103 35h9M0 36h2M103 36h3M110 36h2M0 37h2M103 37h2M111 37h1M0 38h2M111 38h1M0 39h5M9 39h3M16 39h3M23 39h3M30 39h3M37 39h3M44 39h3M51 39h3M58 39h3M65 39h3M72 39h3M79 39h3M86 39h3M93 39h3M111 39h1M0 40h5M9 40h3M16 40h3M23 40h3M30 40h3M37 40h3M44 40h3M51 40h3M58 40h3M65 40h3M72 40h3M79 40h3M86 40h3M93 40h3M111 40h1M0 41h5M9 41h88M110 41h2" />
|
||||
<path stroke="#6daa2c" d="M5 0h4M12 0h4M19 0h4M26 0h4M33 0h4M40 0h4M61 0h4M68 0h4M75 0h4M82 0h4M96 0h4M106 0h4M5 1h4M12 1h4M19 1h4M26 1h4M33 1h4M40 1h4M48 1h9M61 1h4M68 1h4M75 1h4M82 1h4M96 1h4M106 1h4M51 2h3M106 2h4M51 3h3M106 3h4M106 4h4M103 5h7M103 6h7M103 7h7M103 8h6M103 11h9M103 12h9M103 13h9M103 14h9M103 17h9M103 18h9M103 19h9M103 20h9M103 23h9M103 24h9M103 25h9M103 26h9M103 29h9M103 30h9M103 31h9M103 32h9M106 36h4M105 37h2M109 37h2M103 38h3M110 38h1M100 39h6M110 39h1M100 40h7M109 40h2M5 41h4M97 41h13" />
|
||||
<path stroke="#deeed6" d="M5 2h4M12 2h4M19 2h4M26 2h4M33 2h4M40 2h4M47 2h4M54 2h4M61 2h4M68 2h4M75 2h4M82 2h4M89 2h4M96 2h4M5 3h4M12 3h4M19 3h4M26 3h4M33 3h4M40 3h4M47 3h4M54 3h4M61 3h4M68 3h4M75 3h4M82 3h4M89 3h4M96 3h4M5 39h4M12 39h4M19 39h4M26 39h4M33 39h4M40 39h4M47 39h4M54 39h4M61 39h4M68 39h4M75 39h4M82 39h4M89 39h4M96 39h4M5 40h4M12 40h4M19 40h4M26 40h4M33 40h4M40 40h4M47 40h4M54 40h4M61 40h4M68 40h4M75 40h4M82 40h4M89 40h4M96 40h4" />
|
||||
<path stroke="#4e4a4e" d="M2 4h101M2 5h1M102 5h1M2 6h1M102 6h1M2 7h1M102 7h1M2 8h1M102 8h1M2 9h1M102 9h1M2 10h1M102 10h1M2 11h1M102 11h1M2 12h1M102 12h1M2 13h1M102 13h1M2 14h1M102 14h1M2 15h1M102 15h1M2 16h1M102 16h1M2 17h1M93 17h3M102 17h1M2 18h3M91 18h2M96 18h2M102 18h1M5 19h1M91 19h1M97 19h1M102 19h1M6 20h1M90 20h1M98 20h1M102 20h1M6 21h1M90 21h1M98 21h1M102 21h1M90 22h1M102 22h1M102 23h1M102 24h1M2 25h1M102 25h1M2 26h1M102 26h1M2 27h1M102 27h1M2 28h1M102 28h1M2 29h1M102 29h1M2 30h1M102 30h1M2 31h1M102 31h1M2 32h1M5 32h3M102 32h1M2 33h1M4 33h1M8 33h1M102 33h1M2 34h1M4 34h1M8 34h1M102 34h1M2 35h1M102 35h1M2 36h1M102 36h1M2 37h1M102 37h1M2 38h101" />
|
||||
<path stroke="#756f75" d="M3 5h99M3 6h99M3 7h99M3 8h15M29 8h7M47 8h7M65 8h7M85 8h17M3 9h14M30 9h5M48 9h5M66 9h5M85 9h17M3 10h13M31 10h3M49 10h3M67 10h3M84 10h18M3 11h13M31 11h3M49 11h3M67 11h3M83 11h19M3 12h13M19 12h9M31 12h3M37 12h8M49 12h3M56 12h7M67 12h3M74 12h28M3 13h13M19 13h9M31 13h3M37 13h7M49 13h3M55 13h9M67 13h3M73 13h29M3 14h13M19 14h9M31 14h3M37 14h7M49 14h3M55 14h9M67 14h3M73 14h29M3 15h13M19 15h9M31 15h3M37 15h6M49 15h3M55 15h9M67 15h3M73 15h29M3 16h13M19 16h9M31 16h3M37 16h6M49 16h3M55 16h9M67 16h3M73 16h29M3 17h13M19 17h9M31 17h3M37 17h5M45 17h1M49 17h3M55 17h9M67 17h3M73 17h20M96 17h6M5 18h11M19 18h9M31 18h3M37 18h5M45 18h1M49 18h3M55 18h9M67 18h3M73 18h18M93 18h3M98 18h4M3 19h2M6 19h10M19 19h9M31 19h3M37 19h4M44 19h2M49 19h3M55 19h9M67 19h3M73 19h18M92 19h5M98 19h4M3 20h3M7 20h9M31 20h3M37 20h4M44 20h2M49 20h4M55 20h9M66 20h4M83 20h7M91 20h7M99 20h3M3 21h3M7 21h9M31 21h3M37 21h3M43 21h3M49 21h4M66 21h4M84 21h6M91 21h7M99 21h3M3 22h3M7 22h10M31 22h3M37 22h3M43 22h3M49 22h5M65 22h5M84 22h6M91 22h7M99 22h3M3 23h2M6 23h12M31 23h3M37 23h2M42 23h4M49 23h4M66 23h4M85 23h6M92 23h5M98 23h4M5 24h23M31 24h3M37 24h2M42 24h4M49 24h3M67 24h3M74 24h7M85 24h6M93 24h3M98 24h4M3 25h25M31 25h3M37 25h1M41 25h5M49 25h3M55 25h9M67 25h3M73 25h9M85 25h8M96 25h6M3 26h25M31 26h3M37 26h1M41 26h5M49 26h3M55 26h9M67 26h3M73 26h9M85 26h17M3 27h25M31 27h3M40 27h6M49 27h3M55 27h9M67 27h3M73 27h9M85 27h17M3 28h25M31 28h3M40 28h6M49 28h3M55 28h9M67 28h3M73 28h9M85 28h17M3 29h25M31 29h3M39 29h7M49 29h3M55 29h9M67 29h3M73 29h9M85 29h17M3 30h25M31 30h3M39 30h7M49 30h3M55 30h9M67 30h3M73 30h9M85 30h17M3 31h25M31 31h3M38 31h8M49 31h3M56 31h7M67 31h3M74 31h7M85 31h17M3 32h2M8 32h10M31 32h3M49 32h3M67 32h3M85 32h17M3 33h1M5 33h3M9 33h8M31 33h3M49 33h3M67 33h4M84 33h18M3 34h1M5 34h3M9 34h7M31 34h4M48 34h5M66 34h6M83 34h19M3 35h1M5 35h3M9 35h7M30 35h6M47 35h7M65 35h8M82 35h20M3 36h2M8 36h94M3 37h99" />
|
||||
<path stroke="#d1cdd1" d="M18 8h11M36 8h11M54 8h1M17 9h13M35 9h13M53 9h1M16 10h15M34 10h15M52 10h1M16 11h3M28 11h3M34 11h3M45 11h4M16 12h3M28 12h3M34 12h3M45 12h4M16 13h3M28 13h3M34 13h3M44 13h5M16 14h3M28 14h3M34 14h3M44 14h5M16 15h3M28 15h3M34 15h3M43 15h6M16 16h3M28 16h3M34 16h3M43 16h2M46 16h3M16 17h3M28 17h3M34 17h3M42 17h3M46 17h3M16 18h3M28 18h3M34 18h3M42 18h2M46 18h3M16 19h3M28 19h3M34 19h3M41 19h3M46 19h2M16 20h15M34 20h3M41 20h2M46 20h1M17 21h14M34 21h3M40 21h3M46 21h1M18 22h13M34 22h3M40 22h2M28 23h3M34 23h3M39 23h3M28 24h3M34 24h3M39 24h2M28 25h3M34 25h3M38 25h3M28 26h3M34 26h3M38 26h2M28 27h3M34 27h6M28 28h3M34 28h5M28 29h3M34 29h5M28 30h3M34 30h4M28 31h3M34 31h4M18 32h13M34 32h3M18 33h13M35 33h2M18 34h12M56 34h2M81 34h1" />
|
||||
<path stroke="#dfd7df" d="M55 8h10M72 8h13M54 9h12M71 9h13M53 10h14M70 10h13M52 11h4M63 11h4M70 11h4M52 12h3M64 12h3M70 12h3M52 13h3M64 13h3M70 13h3M52 14h3M64 14h3M70 14h3M52 15h3M64 15h3M70 15h3M52 16h3M64 16h3M70 16h3M52 17h3M64 17h3M70 17h3M52 18h3M64 18h3M70 18h3M48 19h1M52 19h3M64 19h3M70 19h3M47 20h2M53 20h2M64 20h2M70 20h13M47 21h2M54 21h11M70 21h14M46 22h3M54 22h11M70 22h14M46 23h3M53 23h13M70 23h4M81 23h4M46 24h3M52 24h3M64 24h3M70 24h3M82 24h3M46 25h3M52 25h3M64 25h3M70 25h3M82 25h3M46 26h3M52 26h3M64 26h3M70 26h3M82 26h3M46 27h3M52 27h3M64 27h3M70 27h3M82 27h3M46 28h3M52 28h3M64 28h3M70 28h3M82 28h3M46 29h3M52 29h3M64 29h3M70 29h3M82 29h3M46 30h3M52 30h3M64 30h3M70 30h3M82 30h3M46 31h3M52 31h4M63 31h4M70 31h4M81 31h4M37 32h12M52 32h15M71 32h13M17 33h1M37 33h11M53 33h13M72 33h11M16 34h2M36 34h11M54 34h2M58 34h7M73 34h8" />
|
||||
<path stroke="#9f9a9f" d="M84 9h1M83 10h1M19 11h9M37 11h8M56 11h7M74 11h9M55 12h1M63 12h1M73 12h1M45 16h1M44 18h1M43 20h1M16 21h1M53 21h1M65 21h1M17 22h1M42 22h1M18 23h10M74 23h7M41 24h1M55 24h9M73 24h1M81 24h1M40 26h1M39 28h1M38 30h1M70 32h1M84 32h1M34 33h1M48 33h1M52 33h1M66 33h1M71 33h1M83 33h1M30 34h1M35 34h1M47 34h1M53 34h1M65 34h1M72 34h1M82 34h1M16 35h14M36 35h11M54 35h11M73 35h9" />
|
||||
<path stroke="#8595a1" d="M6 22h1M98 22h1M5 23h1M91 23h1M97 23h1M2 24h3M91 24h2M96 24h2M93 25h3M4 35h1M8 35h1M5 36h3" />
|
||||
<path stroke="#dad45e" d="M107 37h2M106 38h4M106 39h4M107 40h2" />
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 116 43" shape-rendering="crispEdges">
|
||||
<path stroke="#6daa2c" d="M0 0h4M10 0h4M17 0h4M24 0h4M31 0h5M39 0h4M46 0h4M68 0h4M75 0h4M82 0h4M89 0h4M102 0h6M114 0h2M0 1h4M10 1h4M17 1h4M24 1h4M31 1h5M39 1h4M46 1h4M54 1h10M68 1h4M75 1h4M82 1h4M89 1h4M102 1h6M114 1h2M0 2h4M35 2h1M57 2h3M64 2h1M71 2h1M114 2h2M0 3h4M35 3h1M57 3h3M64 3h1M71 3h1M114 3h2M0 4h4M114 4h2M0 5h4M110 5h6M0 6h4M110 6h6M0 7h4M110 7h6M0 8h4M110 8h6M0 9h6M0 10h6M0 11h6M110 11h6M0 12h6M110 12h6M110 13h6M110 14h6M0 15h6M0 16h6M0 17h6M110 17h6M0 18h6M110 18h6M0 19h2M110 19h6M0 20h2M110 20h6M0 21h2M1 22h2M2 23h1M110 23h6M2 24h1M110 24h6M1 25h2M110 25h6M0 26h2M110 26h6M5 28h1M0 29h2M5 29h1M110 29h6M1 30h2M5 30h1M110 30h6M2 31h1M5 31h1M110 31h6M2 32h1M5 32h1M110 32h6M1 33h2M5 33h1M0 34h3M5 34h1M0 35h3M5 35h1M0 36h3M5 36h1M114 36h2M0 37h3M5 37h1M113 37h2M0 38h3M5 38h1M110 38h4M0 39h3M5 39h3M23 39h1M28 39h3M35 39h1M107 39h7M0 40h3M5 40h3M23 40h1M28 40h3M35 40h1M107 40h8M0 41h2M5 41h3M10 41h4M17 41h4M24 41h11M38 41h5M46 41h4M53 41h4M67 41h4M74 41h5M82 41h4M89 41h4M96 41h4M104 41h12M10 42h4M17 42h4M38 42h5M46 42h4M53 42h4M67 42h4M74 42h5M82 42h4M88 42h6M96 42h4" />
|
||||
<path stroke="#346524" d="M4 0h6M14 0h3M21 0h3M28 0h3M36 0h3M43 0h3M50 0h18M72 0h3M79 0h3M86 0h3M93 0h9M108 0h6M4 1h6M14 1h3M21 1h3M28 1h3M36 1h3M43 1h3M50 1h4M64 1h4M72 1h3M79 1h3M86 1h3M93 1h9M108 1h6M4 2h6M14 2h3M21 2h3M28 2h3M36 2h2M43 2h3M50 2h3M65 2h2M72 2h2M79 2h3M86 2h3M93 2h3M100 2h3M107 2h7M4 3h6M14 3h3M21 3h3M28 3h3M36 3h2M43 3h3M50 3h3M65 3h2M72 3h2M79 3h3M86 3h3M93 3h3M100 3h3M107 3h7M4 4h2M110 4h4M4 5h2M4 6h2M4 7h2M4 8h2M110 9h6M110 10h6M0 13h6M0 14h6M110 15h6M110 16h6M2 19h6M2 20h6M2 21h6M110 21h6M3 22h5M110 22h6M3 23h5M3 24h3M3 25h3M2 26h4M0 27h6M110 27h6M0 28h5M110 28h6M2 29h3M3 30h2M3 31h2M3 32h2M3 33h2M110 33h6M3 34h2M110 34h6M3 35h2M110 35h6M3 36h2M110 36h4M3 37h2M110 37h3M3 38h2M3 39h2M8 39h2M14 39h3M21 39h2M36 39h2M43 39h3M50 39h3M57 39h3M64 39h3M71 39h3M79 39h3M86 39h3M93 39h3M100 39h3M3 40h2M8 40h2M14 40h3M21 40h2M36 40h2M43 40h3M50 40h3M57 40h3M64 40h3M71 40h3M79 40h3M86 40h3M93 40h3M100 40h3M2 41h3M8 41h2M14 41h3M21 41h3M35 41h3M43 41h3M50 41h3M57 41h10M71 41h3M79 41h3M86 41h3M93 41h3M100 41h4M0 42h10M14 42h3M21 42h17M43 42h3M50 42h3M57 42h10M71 42h3M79 42h3M86 42h2M94 42h2M100 42h16" />
|
||||
<path stroke="#deeed6" d="M10 2h4M17 2h4M24 2h4M31 2h4M38 2h5M46 2h4M53 2h4M60 2h4M67 2h4M74 2h5M82 2h4M89 2h4M96 2h4M103 2h4M10 3h4M17 3h4M24 3h4M31 3h4M38 3h5M46 3h4M53 3h4M60 3h4M67 3h4M74 3h5M82 3h4M89 3h4M96 3h4M103 3h4M10 39h4M17 39h4M24 39h4M31 39h4M38 39h5M46 39h4M53 39h4M60 39h4M67 39h4M74 39h5M82 39h4M89 39h4M96 39h4M103 39h4M10 40h4M17 40h4M24 40h4M31 40h4M38 40h5M46 40h4M53 40h4M60 40h4M67 40h4M74 40h5M82 40h4M89 40h4M96 40h4M103 40h4" />
|
||||
<path stroke="#4e4a4e" d="M6 4h104M6 5h2M109 5h1M6 6h2M109 6h1M6 7h2M109 7h1M6 8h2M109 8h1M6 9h2M109 9h1M6 10h2M109 10h1M6 11h2M109 11h1M6 12h2M109 12h1M6 13h2M109 13h1M6 14h2M109 14h1M6 15h2M109 15h1M6 16h2M109 16h1M6 17h2M100 17h3M109 17h1M6 18h4M98 18h2M103 18h2M109 18h1M10 19h1M98 19h1M104 19h1M109 19h1M11 20h1M97 20h1M105 20h1M109 20h1M11 21h1M97 21h1M105 21h1M109 21h1M97 22h1M109 22h1M109 23h1M109 24h1M6 25h2M109 25h1M6 26h2M109 26h1M6 27h2M109 27h1M6 28h2M109 28h1M6 29h2M109 29h1M6 30h2M109 30h1M6 31h2M109 31h1M6 32h2M10 32h3M109 32h1M6 33h2M9 33h1M13 33h1M109 33h1M6 34h2M9 34h1M13 34h1M109 34h1M6 35h2M109 35h1M6 36h2M109 36h1M6 37h2M109 37h1M6 38h104" />
|
||||
<path stroke="#756f75" d="M8 5h101M8 6h101M8 7h101M8 8h16M35 8h7M53 8h8M72 8h7M92 8h17M8 9h15M36 9h5M54 9h6M73 9h5M92 9h17M8 10h13M37 10h3M55 10h4M74 10h3M91 10h18M8 11h13M37 11h3M55 11h4M74 11h3M90 11h19M8 12h13M25 12h9M37 12h3M43 12h8M55 12h4M63 12h7M74 12h3M81 12h28M8 13h13M25 13h9M37 13h3M43 13h7M55 13h4M62 13h9M74 13h3M80 13h29M8 14h13M25 14h9M37 14h3M43 14h7M55 14h4M62 14h9M74 14h3M80 14h29M8 15h13M25 15h9M37 15h3M43 15h6M55 15h4M62 15h9M74 15h3M80 15h29M8 16h13M25 16h9M37 16h3M43 16h6M55 16h4M62 16h9M74 16h3M80 16h29M8 17h13M25 17h9M37 17h3M43 17h5M51 17h1M55 17h4M62 17h9M74 17h3M80 17h20M103 17h6M10 18h11M25 18h9M37 18h3M43 18h5M51 18h1M55 18h4M62 18h9M74 18h3M80 18h18M100 18h3M105 18h4M8 19h2M11 19h10M25 19h9M37 19h3M43 19h4M50 19h2M55 19h4M62 19h9M74 19h3M80 19h18M99 19h5M105 19h4M8 20h3M12 20h9M37 20h3M43 20h4M50 20h2M55 20h5M62 20h9M73 20h4M90 20h7M98 20h7M106 20h3M8 21h3M12 21h9M37 21h3M43 21h3M49 21h3M55 21h5M73 21h4M91 21h6M98 21h7M106 21h3M8 22h3M12 22h11M37 22h3M43 22h3M49 22h3M55 22h6M72 22h5M91 22h6M98 22h7M106 22h3M8 23h2M11 23h13M37 23h3M43 23h2M48 23h4M55 23h5M73 23h4M92 23h6M99 23h5M105 23h4M10 24h24M37 24h3M43 24h2M48 24h4M55 24h4M74 24h3M81 24h7M92 24h6M100 24h3M105 24h4M8 25h26M37 25h3M43 25h1M47 25h5M55 25h4M62 25h9M74 25h3M80 25h9M92 25h8M103 25h6M8 26h26M37 26h3M43 26h1M47 26h5M55 26h4M62 26h9M74 26h3M80 26h9M92 26h17M8 27h26M37 27h3M46 27h6M55 27h4M62 27h9M74 27h3M80 27h9M92 27h17M8 28h26M37 28h3M46 28h6M55 28h4M62 28h9M74 28h3M80 28h9M92 28h17M8 29h26M37 29h3M45 29h7M55 29h4M62 29h9M74 29h3M80 29h9M92 29h17M8 30h26M37 30h3M45 30h7M55 30h4M62 30h9M74 30h3M80 30h9M92 30h17M8 31h26M37 31h3M44 31h8M55 31h4M63 31h7M74 31h3M81 31h7M92 31h17M8 32h2M13 32h11M37 32h3M55 32h4M74 32h3M92 32h17M8 33h1M10 33h3M14 33h9M37 33h3M55 33h4M74 33h4M91 33h18M8 34h1M10 34h3M14 34h7M37 34h4M54 34h6M73 34h6M90 34h19M8 35h1M10 35h3M14 35h7M36 35h6M53 35h8M72 35h8M89 35h20M8 36h2M13 36h96M8 37h101" />
|
||||
<path stroke="#d1cdd1" d="M24 8h11M42 8h11M61 8h1M23 9h13M41 9h13M60 9h1M21 10h16M40 10h15M59 10h1M21 11h4M34 11h3M40 11h3M51 11h4M21 12h4M34 12h3M40 12h3M51 12h4M21 13h4M34 13h3M40 13h3M50 13h5M21 14h4M34 14h3M40 14h3M50 14h5M21 15h4M34 15h3M40 15h3M49 15h6M21 16h4M34 16h3M40 16h3M49 16h2M52 16h3M21 17h4M34 17h3M40 17h3M48 17h3M52 17h3M21 18h4M34 18h3M40 18h3M48 18h2M52 18h3M21 19h4M34 19h3M40 19h3M47 19h3M52 19h2M21 20h16M40 20h3M47 20h2M52 20h1M23 21h14M40 21h3M46 21h3M52 21h1M24 22h13M40 22h3M46 22h2M34 23h3M40 23h3M45 23h3M34 24h3M40 24h3M45 24h2M34 25h3M40 25h3M44 25h3M34 26h3M40 26h3M44 26h2M34 27h3M40 27h6M34 28h3M40 28h5M34 29h3M40 29h5M34 30h3M40 30h4M34 31h3M40 31h4M24 32h13M40 32h3M24 33h13M41 33h2M24 34h12M63 34h2M88 34h1" />
|
||||
<path stroke="#dfd7df" d="M62 8h10M79 8h13M61 9h12M78 9h13M60 10h14M77 10h13M59 11h4M70 11h4M77 11h4M59 12h3M71 12h3M77 12h3M59 13h3M71 13h3M77 13h3M59 14h3M71 14h3M77 14h3M59 15h3M71 15h3M77 15h3M59 16h3M71 16h3M77 16h3M59 17h3M71 17h3M77 17h3M59 18h3M71 18h3M77 18h3M54 19h1M59 19h3M71 19h3M77 19h3M53 20h2M60 20h2M71 20h2M77 20h13M53 21h2M61 21h11M77 21h14M52 22h3M61 22h11M77 22h14M52 23h3M60 23h13M77 23h4M88 23h4M52 24h3M59 24h3M71 24h3M77 24h3M89 24h3M52 25h3M59 25h3M71 25h3M77 25h3M89 25h3M52 26h3M59 26h3M71 26h3M77 26h3M89 26h3M52 27h3M59 27h3M71 27h3M77 27h3M89 27h3M52 28h3M59 28h3M71 28h3M77 28h3M89 28h3M52 29h3M59 29h3M71 29h3M77 29h3M89 29h3M52 30h3M59 30h3M71 30h3M77 30h3M89 30h3M52 31h3M59 31h4M70 31h4M77 31h4M88 31h4M43 32h12M59 32h15M78 32h13M23 33h1M43 33h11M60 33h13M79 33h11M21 34h3M42 34h11M61 34h2M65 34h7M80 34h8" />
|
||||
<path stroke="#9f9a9f" d="M91 9h1M90 10h1M25 11h9M43 11h8M63 11h7M81 11h9M62 12h1M70 12h1M80 12h1M51 16h1M50 18h1M49 20h1M21 21h2M60 21h1M72 21h1M23 22h1M48 22h1M24 23h10M81 23h7M47 24h1M62 24h9M80 24h1M88 24h1M46 26h1M45 28h1M44 30h1M77 32h1M91 32h1M40 33h1M54 33h1M59 33h1M73 33h1M78 33h1M90 33h1M36 34h1M41 34h1M53 34h1M60 34h1M72 34h1M79 34h1M89 34h1M21 35h15M42 35h11M61 35h11M80 35h9" />
|
||||
<path stroke="#dad45e" d="M0 22h1M0 23h2M0 24h2M0 25h1M0 30h1M0 31h2M0 32h2M0 33h1M115 37h1M114 38h2M114 39h2M115 40h1" />
|
||||
<path stroke="#8595a1" d="M11 22h1M105 22h1M10 23h1M98 23h1M104 23h1M6 24h4M98 24h2M103 24h2M100 25h3M9 35h1M13 35h1M10 36h3" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 61 KiB |
152
system/Makefile
152
system/Makefile
@ -1,6 +1,6 @@
|
||||
# This file is part of the 9086 project.
|
||||
#
|
||||
# Copyright (c) 2023 Efthymios Kritikos
|
||||
# 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
|
||||
@ -15,20 +15,48 @@
|
||||
# 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
|
||||
EVENT_SIM_TESTBENCH=testbench.v
|
||||
VERILATOR_TESTBENCH=testbench.cpp
|
||||
INCLUDES=proc_state_def.v alu_header.v config.v ucode_header.v
|
||||
SYSTEM_VVP=system.vvp
|
||||
VERILATOR_BIN=obj_dir/Vsystem
|
||||
BOOT_CODE=boot_code.txt
|
||||
GTKWSAVE=../gtkwave_savefile.gtkw
|
||||
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
|
||||
GTKWSAVE=../gtkwave_savefile.gtkw
|
||||
|
||||
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}
|
||||
|
||||
#build options
|
||||
VERILATOR_OPTS += --cc --exe
|
||||
|
||||
@ -36,26 +64,114 @@ VERILATOR_OPTS += --cc --exe
|
||||
VERILATOR_OPTS += --trace-fst --threads 1 --autoflush
|
||||
|
||||
#linter options
|
||||
VERILATOR_OPTS += -Wall --Wno-DECLFILENAME -Wno-SYNCASYNCNET -Wno-MULTIDRIVEN
|
||||
VERILATOR_OPTS += -Wall --Wno-DECLFILENAME
|
||||
|
||||
#optimisation options
|
||||
VERILATOR_OPTS += -x-assign fast --x-initial fast
|
||||
#For testing use:
|
||||
#VERILATOR_OPTS=-x-assign unique --x-initial unique
|
||||
#VERILATOR_OPTS += -x-assign unique --x-initial unique
|
||||
|
||||
|
||||
################################################################################
|
||||
#### SIMULATION RECIPES ####
|
||||
################################################################################
|
||||
|
||||
# COMPILING
|
||||
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
|
||||
${SYSTEM_VVP} : ${SIMULATED_SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||
${QUIET_IVERILOG}
|
||||
${Q}iverilog -g2012 -o "$@" ${TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||
${Q}iverilog -g2012 -D CALCULATE_IPC -D OUTPUT_JSON_STATISTICS -o "$@" ${SIMULATION_TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||
|
||||
${VERILATOR_BIN}: ${VERILATOR_BIN}.mk
|
||||
${Q}make ${MAKEOPTS} OPT_FAST="-O2 -march=native -mtune=native" -C obj_dir -f ../verilator_makefile Vsystem
|
||||
${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
|
||||
|
||||
${VERILATOR_BIN}.mk: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
|
||||
${VERILATOR_BIN}.mk: ${VERILATOR_TESTBENCH} ${SIMULATED_SOURCES}
|
||||
${QUIET_VERILATOR}
|
||||
${Q}verilator ${VERILATOR_OPTS} $^
|
||||
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 ####
|
||||
################################################################################
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(call QUIET_CLEAN,system)
|
||||
${Q}rm -rf ${SYSTEM_VVP} *.fst boot_code.txt boot_code.bin *memdump *memdumptxt obj_dir
|
||||
${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
|
||||
|
10
system/alu.v
10
system/alu.v
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
@ -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=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
|
||||
`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
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
|
385
system/biu.v
Normal file
385
system/biu.v
Normal file
@ -0,0 +1,385 @@
|
||||
/* biu.v - implementation of the 9086 bus interface unit. The logic that
|
||||
controls all external bus functions
|
||||
|
||||
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 "config.v"
|
||||
|
||||
`define BIU_HALT 4'b0000
|
||||
`define BIU_NEXT_ACTION 4'b0001
|
||||
`define BIU_READ 4'b0010
|
||||
`define BIU_RESET1 4'b0011
|
||||
`define BIU_RESET2 4'b1111
|
||||
|
||||
`define BIU_PUT_BYTE 4'b0100
|
||||
`define BIU_PUT_UNALIGNED_16BIT_DATA 4'b0101
|
||||
`define BIU_PUT_ALIGNED_16BIT_DATA 4'b0110
|
||||
`define BIU_PUT_UNALIGNED_PREP_NEXT2 4'b1000
|
||||
`define BIU_WRITE_EXIT 4'b1001
|
||||
`define BIU_WRITE_RELEASE 4'b1010
|
||||
|
||||
`define BIU_GET_ALIGNED_DATA 4'b1011
|
||||
`define BIU_GET_UNALIGNED_DATA 4'b1100
|
||||
`define BIU_GET_SECOND_BYTE 4'b1101
|
||||
`define BIU_GET_SECOND_BYTE1 4'b1110
|
||||
|
||||
module BIU (
|
||||
|
||||
/***************** GENERAL *****************/
|
||||
/* */ input clock, input reset
|
||||
|
||||
/**************** OUTSIDE WORLD ****************/
|
||||
/* */ ,output wire [19:0] external_address_bus
|
||||
/* */ ,input [15:0] external_data_bus_read,output [15:0] external_data_bus_write,output reg read, output reg write,output reg BHE,output reg IOMEM
|
||||
/* */ ,input wait_state
|
||||
|
||||
/**************** OUTPUT TO DE ****************/
|
||||
/* */ ,output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION
|
||||
/* */ ,output reg VALID_DATA
|
||||
|
||||
/**************** 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
|
||||
|
||||
/**************** OUTPUT TO EX *****************/
|
||||
/* */ ,output [15:0] DATA_EX_READ
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
/***************** STATISTICS *****************/
|
||||
/* */ ,output wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE_STAT, output wire VALID_INSTRUCTION_STAT
|
||||
`endif
|
||||
|
||||
);
|
||||
|
||||
`ifdef OUTPUT_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?
|
||||
|
||||
reg [15:0] DATA_OUT;
|
||||
assign DATA_EX_READ=DATA_OUT; //TODO should we rename?
|
||||
|
||||
`define FIFO_SIZE_BYTES $rtoi($pow(2,`L1_CACHE_SIZE))
|
||||
|
||||
reg [7:0] INPUT_FIFO [`FIFO_SIZE_BYTES-1:0];
|
||||
reg [`L1_CACHE_SIZE-1:0] FIFO_start; /*inclusive*/
|
||||
reg [`L1_CACHE_SIZE-1:0] FIFO_end; /*exclusive*/
|
||||
wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE = FIFO_end-FIFO_start;
|
||||
|
||||
reg [3:0] biu_state;
|
||||
reg sane;
|
||||
|
||||
reg func;
|
||||
reg [19:0]INSTRUCTION_ADDRESS;
|
||||
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 };
|
||||
INSTRUCTION_LOCATION <= ADDRESS_INPUT;
|
||||
func <= 1;
|
||||
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
|
||||
end
|
||||
`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 };
|
||||
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;
|
||||
end else if ( read_request ) begin
|
||||
func<=0;
|
||||
DATA_ADDRESS <= { 4'hF , ADDRESS_INPUT };
|
||||
IOMEM <= MEM_OR_IO;
|
||||
read <= 0;
|
||||
BHE <= 0;
|
||||
biu_state <= (ADDRESS_INPUT[0:0])?`BIU_GET_UNALIGNED_DATA:`BIU_GET_ALIGNED_DATA;
|
||||
end else begin
|
||||
if ( FIFO_SIZE!={`L1_CACHE_SIZE{1'b1}} ) begin
|
||||
func<=1;
|
||||
biu_state <= `BIU_READ;
|
||||
write <= 1;
|
||||
read <= 0;
|
||||
IOMEM <= 0;
|
||||
BHE <= 0;
|
||||
end else begin
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
/*************** 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;
|
||||
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;
|
||||
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;
|
||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
||||
end
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
read<=1;
|
||||
end
|
||||
|
||||
/*************** DATA WRITE ***************/
|
||||
`BIU_PUT_UNALIGNED_16BIT_DATA:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Writing 16bit %04x at %04x",DATA_EX_WRITE,DATA_ADDRESS);
|
||||
`endif
|
||||
BHE <= 0;
|
||||
data_bus_output_register <= {DATA_EX_WRITE[7:0],DATA_EX_WRITE[15:8]};
|
||||
write <= 0;
|
||||
biu_state <= `BIU_PUT_UNALIGNED_PREP_NEXT2;
|
||||
end
|
||||
`BIU_PUT_UNALIGNED_PREP_NEXT2:begin
|
||||
write <= 1;
|
||||
DATA_ADDRESS <= DATA_ADDRESS+20'd1;
|
||||
BHE <= 1;
|
||||
biu_state <= `BIU_WRITE_EXIT;
|
||||
end
|
||||
`BIU_PUT_ALIGNED_16BIT_DATA:begin
|
||||
`ifdef DEBUG_DATA_READ_WRITES
|
||||
$display("Writing 16bit %04x at %04x",DATA_EX_WRTIE,DATA_ADDRESS);
|
||||
`endif
|
||||
data_bus_output_register <= {DATA_EX_WRITE[15:8],DATA_EX_WRITE[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);
|
||||
`endif
|
||||
if(ADDRESS_INPUT[0:0]==0) begin
|
||||
BHE <= 1;
|
||||
data_bus_output_register <= {8'b0,DATA_EX_WRITE[7:0]};
|
||||
end else begin
|
||||
BHE <= 0;
|
||||
data_bus_output_register <= {DATA_EX_WRITE[7:0],8'b0};
|
||||
end
|
||||
write <= 0;
|
||||
biu_state <= `BIU_WRITE_RELEASE;
|
||||
end
|
||||
`BIU_WRITE_EXIT:begin
|
||||
write <= 0;
|
||||
biu_state <= `BIU_WRITE_RELEASE;
|
||||
end
|
||||
`BIU_WRITE_RELEASE:begin
|
||||
write <= 1;
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
end
|
||||
|
||||
|
||||
/*************** DATA READ ***************/
|
||||
`define finished_read \
|
||||
if ( read_request == 0 ) begin \
|
||||
biu_state <= `BIU_NEXT_ACTION;\
|
||||
VALID_DATA <= 0;\
|
||||
end else \
|
||||
VALID_DATA <= 1;
|
||||
`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);
|
||||
else
|
||||
$display("Reading 8bit %02x from %04x",external_data_bus_read[7:0],DATA_ADDRESS);
|
||||
`endif
|
||||
DATA_OUT <= (Wbit==1)? external_data_bus_read : {8'b0,external_data_bus_read[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);
|
||||
`endif
|
||||
DATA_OUT[7:0] <= external_data_bus_read[15:8];
|
||||
read <=1;
|
||||
if(Wbit==1) begin
|
||||
biu_state <= `BIU_GET_SECOND_BYTE;
|
||||
end else begin
|
||||
`finished_read
|
||||
end
|
||||
end
|
||||
`BIU_GET_SECOND_BYTE:begin
|
||||
DATA_ADDRESS <= DATA_ADDRESS+20'd1;
|
||||
biu_state <= `BIU_GET_SECOND_BYTE1;
|
||||
read <=0;
|
||||
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
|
||||
`endif
|
||||
DATA_OUT[15:8] <= external_data_bus_read[7:0];
|
||||
`finished_read
|
||||
read <=1;
|
||||
end
|
||||
|
||||
/*************** HOUSE KEEPING ***************/
|
||||
`BIU_RESET1: begin
|
||||
biu_state <= `BIU_RESET2;
|
||||
VALID_DATA <= 0;
|
||||
end
|
||||
`BIU_RESET2: begin
|
||||
FIFO_start <= `L1_CACHE_SIZE'b0;
|
||||
FIFO_end <= `L1_CACHE_SIZE'b0;
|
||||
biu_state <= `BIU_NEXT_ACTION;
|
||||
INSTRUCTION_ADDRESS <= 20'hFFFF0;
|
||||
INSTRUCTION_LOCATION <= 16'hFFF0;
|
||||
VALID_DATA <= 0;
|
||||
sane<=1;
|
||||
end
|
||||
default: begin
|
||||
biu_state <= `BIU_NEXT_ACTION;/*Should be unreachable*/
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
/* update VALID_INSTRUCTION and INSTRUCTION */
|
||||
always @( posedge clock) begin
|
||||
|
||||
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
|
||||
//$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
|
||||
/*TODO: I would use FIFO_SIZE==0 here or better yet add an else at the
|
||||
end but since FIFO_start and FIFO_end are updated in a blocking
|
||||
manner it seems that the assign statement updating FIFO_SIZE
|
||||
doesn't work. PLEASE CLEAN UP THIS MESS */
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end else if((Isit1==1) && (FIFO_SIZE!=0))begin
|
||||
VALID_INSTRUCTION <= 1;
|
||||
INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||
end else if((fifoIsize==2) && (FIFO_SIZE > `L1_CACHE_SIZE'd1))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((fifoIsize==3) && (FIFO_SIZE > `L1_CACHE_SIZE'd2))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)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;
|
||||
`else
|
||||
if(FIFO_start==FIFO_end) begin
|
||||
/*TODO: Same as on the first statement on the other side of the `ifdef */
|
||||
VALID_INSTRUCTION <= 0;
|
||||
end else if(FIFO_SIZE>`L1_CACHE_SIZE'd3)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;
|
||||
`endif
|
||||
//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
|
||||
|
||||
endmodule
|
@ -1,8 +1,4 @@
|
||||
.ORG 0x84 ; INT 21
|
||||
DW 0xFFFF ; Code Segment
|
||||
DW PRINT_INT_HANDLE ; Program Counter
|
||||
|
||||
.ORG 0x0100
|
||||
.ORG 0xFF00
|
||||
start:
|
||||
MOV SP,#STACK
|
||||
MOV AX,#0x0000
|
||||
@ -25,16 +21,15 @@ dec [si]
|
||||
dec cx
|
||||
cmp CX,#0x00
|
||||
MOV CH,#0x9A
|
||||
TEST CH,#0x70
|
||||
inw #0x20
|
||||
CMP AX,#0xABCD
|
||||
jz WAZZ
|
||||
mov ah,#2
|
||||
mov dl,#'1
|
||||
int #0x21
|
||||
mov al,#'0
|
||||
out byte #0xA5
|
||||
hlt
|
||||
WAZZ:
|
||||
mov ah,#2
|
||||
mov dl,#'0
|
||||
int #0x21
|
||||
mov al,#'1
|
||||
out byte #0xA5
|
||||
hlt
|
||||
TEST_:
|
||||
ADD AX,#0xDEAD
|
||||
@ -52,5 +47,5 @@ iret
|
||||
STACK:
|
||||
|
||||
.ORG 0xFFF0
|
||||
MOV AX,#0x0100
|
||||
MOV AX,#0xFF00
|
||||
JMP AX
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
@ -17,16 +17,66 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
//Runtime Verbosity
|
||||
/** Runtime Verbosity **/
|
||||
//`define DEBUG_REG_WRITES
|
||||
//`define DEBUG_PC_ADDRESS
|
||||
//`define DEBUG_MEMORY_WRITES
|
||||
//`define DEBUG_DATA_READ_WRITES
|
||||
|
||||
`define CALCULATE_IPC
|
||||
`define OUTPUT_JSON_STATISTICS
|
||||
/** OUTPUT **/
|
||||
/* These are usually set at build time*/
|
||||
//`define CALCULATE_IPC
|
||||
//`define OUTPUT_JSON_STATISTICS
|
||||
|
||||
/** Optimisations **/
|
||||
|
||||
/* Enables the ability to check if an instruction in the input
|
||||
* buffer is completed and mark it ready instead of always waiting
|
||||
* 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
|
||||
/************************************************/
|
||||
|
||||
/* Size is in powers of two with minimal 3.
|
||||
* 3 : 8 Bytes
|
||||
* 4 : 16 Bytes
|
||||
* 5 : 32 Bytes
|
||||
* . : ... */
|
||||
`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
|
||||
`define CALCULATE_IPC
|
||||
`endif
|
||||
|
||||
`ifdef DOUBLE_INSTRUCTION_LOAD
|
||||
/*Needed for DOUBLE_INSTRUCTION_LOAD*/
|
||||
`define EARLY_VALID_INSTRUCTION
|
||||
`endif
|
||||
|
||||
`ifdef EARLY_VALID_INSTRUCTION
|
||||
`define INCLUDE_EARLY_CALC_CIRCUIT
|
||||
`define EARLY_VALID_INSTRUCTION_ 1
|
||||
`else
|
||||
`define EARLY_VALID_INSTRUCTION_ 0
|
||||
`endif
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
`define INCLUDE_EARLY_CALC_CIRCUIT
|
||||
`endif
|
||||
|
1016
system/decoder.v
1016
system/decoder.v
File diff suppressed because it is too large
Load Diff
4
system/error_header.v
Normal file
4
system/error_header.v
Normal file
@ -0,0 +1,4 @@
|
||||
`define ERROR_BITS 3
|
||||
`define ERR_NO_ERROR 3'b000
|
||||
`define ERR_UNIMPL_INSTRUCTION 3'b001
|
||||
`define ERR_UNIMPL_ADDRESSING_MODE 3'b010
|
46
system/exec_state_def.v
Normal file
46
system/exec_state_def.v
Normal file
@ -0,0 +1,46 @@
|
||||
/* exec_state_def.v - Definitions of the states in the main state machine
|
||||
of the 9086 CPU.
|
||||
|
||||
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/>. */
|
||||
|
||||
`define EXEC_STATE_BITS 4
|
||||
|
||||
|
||||
//TODO: Please clean this up
|
||||
`define EXEC_WAIT 4'b1100
|
||||
|
||||
/*DECODE SATE*/
|
||||
`define EXEC_DE_LOAD_REG_TO_PARAM 4'b0011
|
||||
|
||||
/*MEM/IO READ*/
|
||||
`define EXEC_MEMIO_READ 4'b0101
|
||||
`define EXEC_MEMIO_READ_SETADDR 4'b0110
|
||||
|
||||
/*EXECUTE STATE*/
|
||||
`define EXEC_WRITE_ENTRY 4'b1000
|
||||
|
||||
/*MEM/IO WRITE*/
|
||||
`define EXEC_MEMIO_WRITE 4'b0111
|
||||
|
||||
`define EXEC_NEXT_INSTRUCTION 4'b1001
|
||||
|
||||
`define EXEC_NEXT_MICROCODE 4'b1010
|
||||
|
||||
`define EXEC_RESET 4'b1011
|
||||
|
||||
`define EXEC_JUMP_RELEASE 4'b1101
|
324
system/execute.v
Normal file
324
system/execute.v
Normal file
@ -0,0 +1,324 @@
|
||||
/* execute.v - Implements the instruction execution logic
|
||||
|
||||
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 "exec_state_def.v"
|
||||
`include "alu_header.v"
|
||||
`include "error_header.v"
|
||||
|
||||
module execute_unit (
|
||||
/***************** GENERAL *****************/
|
||||
/* */ input clock, input reset, input write /*TODO: REMOVE!!*/, output reg [`ERROR_BITS-1:0] ERROR
|
||||
|
||||
/*************** INPUT FROM DE ***************/
|
||||
/* SYNC SIGNALS */ ,input valid_input,input set_initial_values
|
||||
/* INSTR. PARAMS */ ,input Wbit ,input [2:0] IN_MOD, input [2:0] OUT_MOD, input [2:0] RM
|
||||
/* DATA */ ,input [15:0] PARAM1_INIT, input [15:0] PARAM2_INIT, input [15:0] ProgCount
|
||||
/* STATE CONTROL */ ,input [`EXEC_STATE_BITS-1:0] init_state
|
||||
/* ALU CONTROL */ ,input [1:0] in_alu_sel1, input [1:0] in_alu_sel2, input [`ALU_OP_BITS-1:0] ALU_OP, output [15:0] _ALU_O_
|
||||
/* OTHER */ ,input memio_address_select
|
||||
|
||||
/**************** OUTPUT TO DE ****************/
|
||||
/* SYNC SIGNALS */ ,output reg next_exec
|
||||
/* FLAGS */ ,output reg [7:0] EX2DE_FLAGS
|
||||
|
||||
/**************** OUTPUT TO BIU ****************/
|
||||
/* */ ,output reg [15:0] BIU_ADDRESS_INPUT
|
||||
/* */ ,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
|
||||
|
||||
/**************** OUTPUT TO BIU ****************/
|
||||
/* */ ,output [15:0] BIU_EX_DATA_WRITE
|
||||
|
||||
/***************** REGISTERS *****************/
|
||||
/* */ ,input [15:0] reg_read_port1_data ,input [15:0] reg_read_port2_data, output reg [3:0] reg_read_port1_addr
|
||||
/* */ ,output reg use_exec_reg_addr, output reg reg_write_we
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
/*############ ALU / Execution units ################################################## */
|
||||
|
||||
mux4 #(.WIDTH(16)) MUX16_1A(
|
||||
/*0*/ PARAM1,
|
||||
/*1*/ reg_read_port1_data,
|
||||
/*2*/ ProgCount[15:0],
|
||||
/*3*/ 16'd0, /*0 Constant*/
|
||||
in_alu_sel1,
|
||||
ALU_A);
|
||||
|
||||
mux4 #(.WIDTH(16)) MUX16_1B(
|
||||
/*0*/ PARAM2,
|
||||
/*1*/ reg_read_port2_data,
|
||||
/*2*/ ProgCount[15:0],
|
||||
/*3*/ 16'd0, /*0 Constant*/
|
||||
in_alu_sel2,
|
||||
ALU_B);
|
||||
|
||||
wire [15:0] ALU_A;
|
||||
wire [15:0] ALU_B;
|
||||
wire [15:0] ALU_O;
|
||||
wire [7:0] ALU_FLAGS;
|
||||
|
||||
ALU ALU1(
|
||||
/* INPUT 1 */ .A(ALU_A),
|
||||
/* INPUT 2 */ .B(ALU_B),
|
||||
/* OUTPUT */ .OUT(ALU_O),
|
||||
/* OPERATION */ .op(ALU_OP),
|
||||
/* FLAGS */ .FLAGS(ALU_FLAGS),
|
||||
/* Wbit */ .Wbit(Wbit)
|
||||
);
|
||||
|
||||
/*############ Execute logic ########################################################## */
|
||||
|
||||
`define unimpl_addressing_mode exec_state <= `EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;
|
||||
|
||||
`define finished_instruction exec_state <= `EXEC_WAIT;next_exec<=1;
|
||||
|
||||
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;
|
||||
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
|
||||
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
|
||||
`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;
|
||||
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 way or better yet don't do it at all somehow
|
||||
biu_write_request <= 0;
|
||||
`finished_instruction
|
||||
end
|
||||
|
||||
end
|
||||
default:begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
`undef unimpl_addressing_mode
|
0
system/external_ip/.keep
Normal file
0
system/external_ip/.keep
Normal file
39
system/fpga_config/OrangeCrab_r0.2.1/config.mk
Normal file
39
system/fpga_config/OrangeCrab_r0.2.1/config.mk
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
#### 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 "$^" "$@"
|
630
system/fpga_config/OrangeCrab_r0.2.1/fpga_top.v
Normal file
630
system/fpga_config/OrangeCrab_r0.2.1/fpga_top.v
Normal file
@ -0,0 +1,630 @@
|
||||
/* 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
|
257
system/fpga_config/OrangeCrab_r0.2.1/pin_constraint.pcf
Normal file
257
system/fpga_config/OrangeCrab_r0.2.1/pin_constraint.pcf
Normal file
@ -0,0 +1,257 @@
|
||||
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;
|
55
system/fpga_config/OrangeCrab_r0.2.1/testbench.cpp
Normal file
55
system/fpga_config/OrangeCrab_r0.2.1/testbench.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#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;
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
`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) 2023 Efthymios Kritikos
|
||||
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
@ -19,29 +19,56 @@
|
||||
|
||||
/* This warning is because we don't use the full address bus. */
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
module doublemem(input [19:0] address,inout wire [15:0] data ,input rd,input wr,input BHE,input cs);
|
||||
module doublemem
|
||||
#(
|
||||
parameter RAM_SIZE_IN_BYTES,
|
||||
parameter ADDRESS_WIDTH=$clog2(RAM_SIZE_IN_BYTES)
|
||||
)
|
||||
( input [ ADDRESS_WIDTH-1 : 0 ] address,
|
||||
output [15:0] cpu_read_data,
|
||||
input [15:0] cpu_write_data,
|
||||
input rd,
|
||||
input wr,
|
||||
input BHE,
|
||||
input cs,
|
||||
input clock
|
||||
);
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
|
||||
reg [15:0] memory [0:32768];
|
||||
reg [15:0] memory [0:(RAM_SIZE_IN_BYTES/2)-1];
|
||||
|
||||
|
||||
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,32767);
|
||||
$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
|
||||
end
|
||||
|
||||
assign data[7:0] = !address[0:0] & !rd & !cs ? memory[address[16:1]][15:8] : 8'hz;
|
||||
|
||||
assign data[15:8] = !BHE & !rd & !cs ? memory[address[16:1]][7:0] : 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
|
||||
|
||||
always @(negedge wr) begin
|
||||
|
||||
always @(posedge clock) begin
|
||||
if( cs == 0 && wr == 0) begin
|
||||
if(BHE==0)
|
||||
memory[address[16:1]][7:0]<=data[15:8];
|
||||
memory[address[ADDRESS_WIDTH-1:1]][7:0]<=cpu_write_data[15:8];
|
||||
if(address[0]==0)
|
||||
memory[address[16:1]][15:8]<=data[7:0];
|
||||
memory[address[ADDRESS_WIDTH-1:1]][15:8]<=cpu_write_data[7:0];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
93
system/peripherals/CPU_to_I2C_driver_bridge.v
Normal file
93
system/peripherals/CPU_to_I2C_driver_bridge.v
Normal file
@ -0,0 +1,93 @@
|
||||
/* 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
|
346
system/peripherals/I2C_driver.v
Normal file
346
system/peripherals/I2C_driver.v
Normal file
@ -0,0 +1,346 @@
|
||||
/* 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
|
123
system/peripherals/I2C_driver_multiplexer.v
Normal file
123
system/peripherals/I2C_driver_multiplexer.v
Normal file
@ -0,0 +1,123 @@
|
||||
/* 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
|
127
system/peripherals/Wishbone_IO_driver.v
Normal file
127
system/peripherals/Wishbone_IO_driver.v
Normal file
@ -0,0 +1,127 @@
|
||||
/* 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
|
73
system/peripherals/Wishbone_memory_driver.v
Normal file
73
system/peripherals/Wishbone_memory_driver.v
Normal file
@ -0,0 +1,73 @@
|
||||
/* 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
|
348
system/peripherals/ascii_to_HD44780_driver.v
Normal file
348
system/peripherals/ascii_to_HD44780_driver.v
Normal file
@ -0,0 +1,348 @@
|
||||
/* 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
|
126
system/peripherals/pcf8574_for_HD44780.v
Normal file
126
system/peripherals/pcf8574_for_HD44780.v
Normal file
@ -0,0 +1,126 @@
|
||||
/* 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
|
@ -1,63 +0,0 @@
|
||||
/* proc_state_def.v - Definitions of the states in the main state machine
|
||||
of the 9086 CPU.
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
`define PROC_STATE_BITS 6
|
||||
|
||||
|
||||
`define PROC_HALT_STATE 6'b000000
|
||||
|
||||
/*INSTRUCTION FETCH STATE*/
|
||||
`define PROC_IF_STATE_ENTRY 6'b000001
|
||||
`define PROC_IF_WRITE_CIR 6'b000010
|
||||
`define PROC_IF_STATE_EXTRA_FETCH_SET 6'b000011
|
||||
`define PROC_IF_STATE_EXTRA_FETCH 6'b000100
|
||||
|
||||
|
||||
/*DECODE SATE*/
|
||||
`define PROC_DE_STATE_ENTRY 6'b001000
|
||||
`define PROC_DE_LOAD_16_PARAM 6'b001001
|
||||
`define PROC_DE_LOAD_16_EXTRA_FETCH_SET 6'b001010
|
||||
`define PROC_DE_LOAD_16_EXTRA_FETCH 6'b001011
|
||||
`define PROC_DE_LOAD_REG_TO_PARAM 6'b001100
|
||||
|
||||
/*MEM/IO READ*/
|
||||
`define PROC_MEMIO_READ 6'b010000
|
||||
`define PROC_MEMIO_READ_SETADDR 6'b010001
|
||||
`define PROC_MEMIO_GET_ALIGNED_DATA 6'b010010 /* :) */
|
||||
`define PROC_MEMIO_GET_UNALIGNED_DATA 6'b010011 /* :( */
|
||||
`define PROC_MEMIO_GET_SECOND_BYTE 6'b010100
|
||||
`define PROC_MEMIO_GET_SECOND_BYTE1 6'b010101
|
||||
`define PROC_DE_LOAD_8_PARAM 6'b010110
|
||||
|
||||
/*EXECUTE STATE*/
|
||||
`define PROC_EX_STATE_ENTRY 6'b100000
|
||||
|
||||
/*MEM/IO WRITE*/
|
||||
`define PROC_MEMIO_WRITE 6'b101000
|
||||
`define PROC_MEMIO_PUT_ALIGNED_16BIT_DATA 6'b101001
|
||||
`define PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA 6'b101010
|
||||
`define PROC_MEMIO_PUT_BYTE 6'b101011
|
||||
`define PROC_MEMIO_WRITE_EXIT 6'b101101
|
||||
`define PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT 6'b101111
|
||||
`define PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2 6'b110010
|
||||
|
||||
`define PROC_NEXT_MICROCODE 6'b111000
|
||||
|
||||
`define PROC_RESET 6'b111100
|
@ -1,8 +1,8 @@
|
||||
/* processor.v - implementation of most functions of the 9086 processor
|
||||
/* processor.v - Connects the different modules comprising the processor
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
@ -17,644 +17,189 @@
|
||||
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 "proc_state_def.v"
|
||||
`include "exec_state_def.v"
|
||||
`include "alu_header.v"
|
||||
`include "config.v"
|
||||
`include "ucode_header.v"
|
||||
`include "error_header.v"
|
||||
|
||||
//HALT: active high
|
||||
//ERROR: active high
|
||||
//IOMEM: 1=IO 0=MEM
|
||||
//BHE: active low
|
||||
//write: active low
|
||||
//read: active low
|
||||
//reset: active low
|
||||
|
||||
module processor (
|
||||
/* MISC */ input clock, input reset, output reg HALT,output reg ERROR
|
||||
/* MEMORY / IO */ ,output reg [19:0] external_address_bus, inout [15:0] external_data_bus,output reg read, output reg write,output reg BHE,output reg IOMEM
|
||||
|
||||
/* 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
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
/* STATISTICS */ ,output reg new_instruction
|
||||
/* STATISTICS */ ,output wire new_instruction
|
||||
`endif
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
/* */ , output reg jump_debug
|
||||
/* */ ,output wire [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT, output wire VALID_INSTRUCTION_STAT, output wire jump_req_debug
|
||||
`endif
|
||||
|
||||
);
|
||||
|
||||
|
||||
/*if we don't read, output the register to have the bus stable by the write falling edge*/
|
||||
reg [15:0] data_bus_output_register;
|
||||
assign external_data_bus=read?data_bus_output_register:16'hz;
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
assign jump_req_debug=biu_jump_req;
|
||||
`endif
|
||||
|
||||
/*** Global Definitions ***/
|
||||
/* If there is an error either from the decoder or execution unit set it to ERROR */
|
||||
assign ERROR=(DE_ERROR!=`ERR_NO_ERROR)?DE_ERROR:(EXEC_ERROR!=`ERR_NO_ERROR)?EXEC_ERROR:`ERR_NO_ERROR;
|
||||
|
||||
|
||||
/*############ Execution Unit ################################################### */
|
||||
|
||||
wire [`ERROR_BITS-1:0] EXEC_ERROR;
|
||||
|
||||
wire biu_read_request,biu_jump_req,biu_write_request,use_exec_reg_addr;
|
||||
wire [3:0] EXEC_reg_read_port1_addr;
|
||||
wire [15:0] ALU_O;
|
||||
wire [7:0] EX2DE_FLAGS;
|
||||
wire [15:0] BIU_ADDRESS_INPUT;
|
||||
wire reg_write_we;
|
||||
wire next_exec;
|
||||
|
||||
execute_unit execute_unit (
|
||||
/***************** GENERAL *****************/
|
||||
/* */ clock, reset, write, EXEC_ERROR
|
||||
|
||||
/*************** INPUT FROM DE ***************/
|
||||
/* SYNC SIGNALS */ ,valid_exec_data,set_initial_values
|
||||
/* INSTR. PARAMS */ ,Wbit, IN_MOD, OUT_MOD, RM
|
||||
/* DATA */ ,PARAM1_INIT,PARAM2_INIT,ProgCount
|
||||
/* STATE CONTROL */ ,next_state
|
||||
/* ALU CONTROL */ ,in_alu_sel1, in_alu_sel2, ALU_OP, ALU_O
|
||||
/* OTHER */ ,memio_address_select
|
||||
|
||||
/**************** OUTPUT TO DE ****************/
|
||||
/* SYNC SIGNALS */ ,next_exec
|
||||
/* FLAGS */ ,EX2DE_FLAGS
|
||||
|
||||
/**************** OUTPUT TO BIU ****************/
|
||||
/* */ ,BIU_ADDRESS_INPUT
|
||||
/* */ ,biu_read_request, biu_jump_req, biu_write_request
|
||||
|
||||
/*************** INPUT FROM BIU ****************/
|
||||
/* */ ,BIU_VALID_DATA,BIU_EX_DATA_READ
|
||||
|
||||
/**************** OUTPUT TO BIU ****************/
|
||||
/* */ ,BIU_EX_DATA_WRITE
|
||||
|
||||
/***************** REGISTERS *****************/
|
||||
/* */ ,reg_read_port1_data, reg_read_port2_data, EXEC_reg_read_port1_addr
|
||||
/* */ ,use_exec_reg_addr, reg_write_we
|
||||
|
||||
);
|
||||
|
||||
/*############ Bus Interface Unit ############################################### */
|
||||
|
||||
wire [15:0] INSTRUCTION_LOCATION;
|
||||
wire [15:0] BIU_EX_DATA_READ,BIU_EX_DATA_WRITE;
|
||||
wire [31:0] IF2DE_INSTRUCTION;
|
||||
wire BIU_VALID_DATA;
|
||||
wire VALID_INSTRUCTION;
|
||||
|
||||
BIU BIU(
|
||||
/***************** GENERAL *****************/
|
||||
/* */ clock,reset
|
||||
|
||||
/**************** OUTSIDE WORLD ****************/
|
||||
/* */ ,external_address_bus
|
||||
/* */ ,external_data_bus_read,external_data_bus_write,read,write,BHE,IOMEM
|
||||
/* */ ,wait_state
|
||||
|
||||
/**************** OUTPUT TO DE ****************/
|
||||
/* */ ,IF2DE_INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION
|
||||
/* */ ,BIU_VALID_DATA
|
||||
|
||||
/**************** 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
|
||||
|
||||
/***************** OUTPUT TO EX ****************/
|
||||
/* */ ,BIU_EX_DATA_READ
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
/***************** STATISTICS *****************/
|
||||
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT
|
||||
`endif
|
||||
|
||||
);
|
||||
|
||||
reg [`PROC_STATE_BITS-1:0] state;
|
||||
|
||||
/*############ Decoder ########################################################## */
|
||||
wire Wbit, Sbit, opcode_size;
|
||||
wire [`PROC_STATE_BITS-1:0] next_state;
|
||||
wire [2:0]RM;
|
||||
wire [15:0]DE_PARAM1;// Input param1 form decoder to alu
|
||||
wire [15:0]DE_PARAM2;
|
||||
wire DE_ERROR,DE_HALT;
|
||||
wire [3:0]DE_reg_read_port1_addr,DE_reg_write_addr,DE_reg_read_port2_addr;
|
||||
wire [11:0]DE_REGISTER_CONTROL;
|
||||
wire [2:0]INSTRUCTION_INFO;
|
||||
wire [1:0]DECODER_SIGNALS;
|
||||
wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry;
|
||||
|
||||
reg SIMPLE_MICRO; /* output simple decodings (=0) or microcode data (=1) */
|
||||
wire [2:0] DE_instruction_size;
|
||||
reg instruction_size_init;
|
||||
wire [2:0] instruction_size;
|
||||
assign instruction_size = instruction_size_init ? 3'b010 : DE_instruction_size;
|
||||
wire memio_address_select;
|
||||
wire MEM_OR_IO;
|
||||
|
||||
wire [`ERROR_BITS-1:0] DE_ERROR;
|
||||
wire valid_exec_data, set_initial_values, Wbit;
|
||||
wire memio_address_select, MEM_OR_IO, VALID_INSTRUCTION_ACK;
|
||||
wire [1:0] in_alu_sel1, in_alu_sel2;
|
||||
wire [2:0] IN_MOD,OUT_MOD, RM;
|
||||
wire [3:0] DE_reg_read_port1_addr,DE_reg_read_port2_addr, reg_write_addr;
|
||||
wire [15:0] PARAM1_INIT, PARAM2_INIT, ProgCount;
|
||||
wire [`ALU_OP_BITS-1:0] ALU_OP;
|
||||
wire [`EXEC_STATE_BITS-1:0] next_state;
|
||||
|
||||
decoder decoder(
|
||||
.CIR(CIR),
|
||||
.FLAGS(FLAGS),
|
||||
.INSTRUCTION_INFO(INSTRUCTION_INFO),
|
||||
.DECODER_SIGNALS(DECODER_SIGNALS),
|
||||
.next_state(next_state),
|
||||
.IN_MOD(IN_MOD),
|
||||
.RM(RM),
|
||||
.PARAM1(DE_PARAM1),
|
||||
.PARAM2(DE_PARAM2),
|
||||
.in_alu1_sel1(in_alu1_sel1),
|
||||
.in_alu1_sel2(in_alu1_sel2),
|
||||
.OUT_MOD(OUT_MOD),
|
||||
.REGISTER_FILE_CONTROL(DE_REGISTER_CONTROL),
|
||||
.ALU_1OP(ALU_1OP),
|
||||
.seq_addr_entry(ucode_seq_addr_entry),
|
||||
.SIMPLE_MICRO(SIMPLE_MICRO),
|
||||
.seq_addr_input(ucode_seq_addr),
|
||||
.instruction_size(DE_instruction_size),
|
||||
.memio_address_select(memio_address_select),
|
||||
.MEM_OR_IO(MEM_OR_IO)
|
||||
/***************** GENERAL *****************/
|
||||
/* Input from sys. */ clock, reset
|
||||
/* Output to sys. */ ,MEM_OR_IO, DE_ERROR, HALT
|
||||
|
||||
/*************** INPUT FROM IF ***************/
|
||||
/* */ ,IF2DE_INSTRUCTION, VALID_INSTRUCTION
|
||||
/* */ ,INSTRUCTION_LOCATION
|
||||
|
||||
/*************** OUTPUT TO IF ***************/
|
||||
/* */ ,VALID_INSTRUCTION_ACK
|
||||
|
||||
/*************** INPUT FROM EX ***************/
|
||||
/* */ ,EX2DE_FLAGS[7:0], next_exec
|
||||
|
||||
/*************** OUTPUT TO DE ***************/
|
||||
/* SYNC SIGNALS */ ,set_initial_values, valid_exec_data
|
||||
/* INSTR. PARAMS */ ,Wbit, IN_MOD, OUT_MOD, RM
|
||||
/* DATA */ ,PARAM1_INIT, PARAM2_INIT, ProgCount
|
||||
/* STATE CONTROL */ ,next_state
|
||||
/* ALU CONTROL */ ,in_alu_sel1, in_alu_sel2, ALU_OP
|
||||
/* OTHER */ ,memio_address_select
|
||||
|
||||
/************* OUTPUT TO REGISTERS ************/
|
||||
/* */ , reg_write_addr,DE_reg_read_port2_addr, DE_reg_read_port1_addr
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
/* STATISTICS */ , new_instruction
|
||||
`endif
|
||||
|
||||
);
|
||||
|
||||
assign Wbit=INSTRUCTION_INFO[2:2];
|
||||
assign Sbit=INSTRUCTION_INFO[1:1];
|
||||
assign opcode_size=INSTRUCTION_INFO[0:0];
|
||||
/*############ Registers ######################################################## */
|
||||
|
||||
assign DE_reg_write_addr=DE_REGISTER_CONTROL[11:8];
|
||||
assign DE_reg_read_port1_addr=DE_REGISTER_CONTROL[7:4];
|
||||
assign DE_reg_read_port2_addr=DE_REGISTER_CONTROL[3:0];
|
||||
|
||||
assign DE_HALT=DECODER_SIGNALS[0:0];
|
||||
assign DE_ERROR=DECODER_SIGNALS[1:1];
|
||||
wire [3:0] reg_read_port1_addr;
|
||||
assign reg_read_port1_addr = use_exec_reg_addr ? EXEC_reg_read_port1_addr : DE_reg_read_port1_addr;
|
||||
|
||||
reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr;
|
||||
wire [15:0] reg_read_port1_data, reg_read_port2_data;
|
||||
|
||||
/*############ REGISTERS ########################################################## */
|
||||
|
||||
reg [15:0] CIR;
|
||||
reg [15:0] PARAM1;
|
||||
reg [15:0] PARAM2;
|
||||
|
||||
// verilator lint_off UNDRIVEN
|
||||
reg [15:0] FLAGS;
|
||||
// verilator lint_on UNDRIVEN
|
||||
|
||||
//Architectural Register file
|
||||
reg [3:0] reg_write_addr;
|
||||
wire [15:0] reg_write_data;
|
||||
reg reg_write_we;
|
||||
reg [3:0] reg_read_port1_addr;
|
||||
reg [15:0] reg_read_port1_data;
|
||||
reg [3:0] reg_read_port2_addr;
|
||||
reg [15:0] reg_read_port2_data;
|
||||
reg [1:0] reg_write_in_sel;
|
||||
mux4 #(.WIDTH(16)) REG_FILE_WRITE_IN_MUX(
|
||||
ALU_1O,
|
||||
16'hz,
|
||||
16'hz,
|
||||
16'hz,
|
||||
reg_write_in_sel,
|
||||
reg_write_data);
|
||||
register_file register_file(
|
||||
.write_port1_addr(reg_write_addr),
|
||||
.write_port1_data(reg_write_data),
|
||||
.write_port1_we(reg_write_we),
|
||||
.read_port1_addr(reg_read_port1_addr),
|
||||
.read_port1_data(reg_read_port1_data),
|
||||
.read_port2_addr(reg_read_port2_addr),
|
||||
.read_port2_data(reg_read_port2_data)
|
||||
/* WRITE */ .write_port1_addr(reg_write_addr), //TODO: should this come from exec instead?
|
||||
/* */ .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)
|
||||
);
|
||||
|
||||
reg [15:0] ProgCount;
|
||||
|
||||
/*############ ALU / Execution units ########################################################## */
|
||||
// ALU 1
|
||||
reg [1:0] in_alu1_sel1;
|
||||
reg [1:0] in_alu1_sel2;
|
||||
/* OUT_MOD : { EXTRA_FUNCTIONS_BIT[0:0], MOD_OR_EXTRA_FUNCTION[1:0] } */
|
||||
reg [2:0] IN_MOD;
|
||||
reg [2:0] OUT_MOD;
|
||||
|
||||
mux4 #(.WIDTH(16)) MUX16_1A(
|
||||
/*0*/ PARAM1,
|
||||
/*1*/ reg_read_port1_data,
|
||||
/*2*/ ProgCount[15:0],
|
||||
/*3*/ 16'd0, /*0 Constant*/
|
||||
in_alu1_sel1,
|
||||
ALU_1A);
|
||||
|
||||
mux4 #(.WIDTH(16)) MUX16_1B(
|
||||
/*0*/ PARAM2,
|
||||
/*1*/ reg_read_port2_data,
|
||||
/*2*/ ProgCount[15:0],
|
||||
/*3*/ 16'd0, /*0 Constant*/
|
||||
in_alu1_sel2,
|
||||
ALU_1B);
|
||||
|
||||
wire [15:0] ALU_1A;
|
||||
wire [15:0] ALU_1B;
|
||||
wire [15:0] ALU_1O;
|
||||
reg [`ALU_OP_BITS-1:0]ALU_1OP;
|
||||
wire [7:0] ALU_1FLAGS;
|
||||
ALU ALU1(
|
||||
.A(ALU_1A),
|
||||
.B(ALU_1B),
|
||||
.OUT(ALU_1O),
|
||||
.op(ALU_1OP),
|
||||
.FLAGS(ALU_1FLAGS),
|
||||
.Wbit(Wbit)
|
||||
);
|
||||
|
||||
/*############ Processor state machine ########################################################## */
|
||||
|
||||
/*** RESET LOGIC ***/
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
always @(negedge reset) begin
|
||||
state <= `PROC_HALT_STATE; //TODO: race condition ??
|
||||
end
|
||||
always @(posedge reset) begin
|
||||
state <= `PROC_RESET;
|
||||
end
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
|
||||
/*** Processor stages ***/
|
||||
`define invalid_instruction state <= `PROC_IF_STATE_ENTRY;ERROR <= 1;
|
||||
|
||||
always @(posedge clock) begin
|
||||
case(state)
|
||||
`PROC_RESET:begin
|
||||
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
||||
ProgCount <= 'hFFF0;//TODO: Implement Segmentation and set to zero
|
||||
HALT <= 0;
|
||||
ERROR <= 0;
|
||||
SIMPLE_MICRO <= 0;
|
||||
reg_write_we <= 1;
|
||||
instruction_size_init <= 1;
|
||||
state <= `PROC_IF_STATE_ENTRY;
|
||||
`ifdef CALCULATE_IPC
|
||||
new_instruction <= 0;
|
||||
`endif
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
jump_debug <= 0;
|
||||
`endif
|
||||
end
|
||||
`PROC_HALT_STATE:begin
|
||||
end
|
||||
`PROC_IF_STATE_ENTRY:begin
|
||||
BHE <= 0;
|
||||
external_address_bus <= {4'b0,ProgCount};
|
||||
IOMEM <= 0;
|
||||
read <= 0;
|
||||
write <= 1;
|
||||
reg_write_we <= 1;
|
||||
state <= `PROC_IF_WRITE_CIR;
|
||||
reg_write_in_sel <= 2'b00;
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
jump_debug <= 0;
|
||||
`endif
|
||||
end
|
||||
`PROC_IF_WRITE_CIR:begin
|
||||
`ifdef DEBUG_PC_ADDRESS
|
||||
/* Weird (possible bug) where even though the
|
||||
* testbench stop the clock after ERROR gets
|
||||
* raised the logic for the rising edge still
|
||||
* gets triggered printing this debug message. */
|
||||
if(ERROR!=1)begin
|
||||
if(instruction_size==1)
|
||||
$display("Fetched instruction at %0x",ProgCount - 1);
|
||||
else
|
||||
$display("Fetched instruction at %0x",ProgCount - 0);
|
||||
end
|
||||
`endif
|
||||
`ifdef CALCULATE_IPC
|
||||
new_instruction <= !new_instruction;
|
||||
`endif
|
||||
/*I built the entire decode stage with CIR
|
||||
* being big endian so just convert it here*/
|
||||
|
||||
if(instruction_size==1)begin
|
||||
/*Half on CIR half on this address */
|
||||
state <= `PROC_DE_STATE_ENTRY;
|
||||
if(ProgCount[0:0]==1)begin
|
||||
CIR <= {CIR[7:0],external_data_bus[15:8]};
|
||||
end else begin
|
||||
CIR <= {CIR[7:0],external_data_bus[7:0]};
|
||||
end
|
||||
ProgCount <= ProgCount+1;
|
||||
end else begin
|
||||
if(ProgCount[0:0]==1)begin
|
||||
/* Half on this address half on the next*/
|
||||
ProgCount <= ProgCount+1;
|
||||
CIR[15:8] <= external_data_bus[15:8];
|
||||
state <= `PROC_IF_STATE_EXTRA_FETCH_SET;
|
||||
end else begin
|
||||
/* Both on this address! */
|
||||
ProgCount <= ProgCount+2;
|
||||
CIR <= {external_data_bus[7:0],external_data_bus[15:8]};
|
||||
state <= `PROC_DE_STATE_ENTRY;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
`PROC_IF_STATE_EXTRA_FETCH_SET:begin
|
||||
external_address_bus <= {4'b0,ProgCount};
|
||||
BHE <= 0;
|
||||
state <= `PROC_IF_STATE_EXTRA_FETCH;
|
||||
end
|
||||
`PROC_IF_STATE_EXTRA_FETCH:begin
|
||||
CIR[7:0] <= external_data_bus[7:0];
|
||||
ProgCount <= ProgCount+1;
|
||||
state <= `PROC_DE_STATE_ENTRY;
|
||||
end
|
||||
`PROC_DE_STATE_ENTRY:begin
|
||||
external_address_bus <= {4'b0,ProgCount};
|
||||
if(SIMPLE_MICRO==0)begin
|
||||
/*This flag is set at reset and jump because
|
||||
* at IF we need to know the size of the
|
||||
* previous instruction (specifically if it was
|
||||
* a single byte and the value would be
|
||||
* incorrect in both cases. So when it gets
|
||||
* set reset it only at the start of the next
|
||||
* 8086 instruction */
|
||||
instruction_size_init <= 0;
|
||||
|
||||
/* We cannot set these directly within
|
||||
* microcode so don't overwrite useful values
|
||||
* each time the next microcode is executed.
|
||||
* Note this still allows to set initial values
|
||||
* at the start of the microcode */
|
||||
PARAM1 <= DE_PARAM1;
|
||||
PARAM2 <= DE_PARAM2;
|
||||
end
|
||||
ERROR <= DE_ERROR;
|
||||
HALT <= DE_HALT;
|
||||
reg_read_port1_addr <= DE_reg_read_port1_addr;
|
||||
reg_read_port2_addr <= DE_reg_read_port2_addr;
|
||||
reg_write_addr <= DE_reg_write_addr;
|
||||
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;
|
||||
/*keep state the same and rerun decode this time with all the data from the microcode rom*/
|
||||
end else begin
|
||||
state <= next_state;
|
||||
end
|
||||
end
|
||||
`PROC_DE_LOAD_REG_TO_PARAM:begin
|
||||
PARAM2<=reg_read_port2_data;
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||
default: state <= `PROC_EX_STATE_ENTRY;
|
||||
endcase
|
||||
end
|
||||
`PROC_DE_LOAD_8_PARAM:begin
|
||||
if(opcode_size==0)begin
|
||||
if({Sbit,Wbit}==2'b11)begin
|
||||
/*signed "16bit" read*/
|
||||
PARAM1 <= {{8{CIR[7:7]}},CIR[7:0]};
|
||||
end else begin
|
||||
PARAM1[7:0] <= CIR[7:0];
|
||||
end
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||
default: state <= `PROC_EX_STATE_ENTRY;
|
||||
endcase
|
||||
end else begin
|
||||
if(ProgCount[0:0]==1)begin
|
||||
if({Sbit,Wbit}==2'b11)begin
|
||||
/*signed "16bit" read*/
|
||||
PARAM1 <= {{8{external_data_bus[15:15]}},external_data_bus[15:8]};
|
||||
end else begin
|
||||
PARAM1[7:0] <= external_data_bus[15:8];
|
||||
end
|
||||
end else begin
|
||||
if({Sbit,Wbit}==2'b11)begin
|
||||
/*signed "16bit" read*/
|
||||
PARAM1 <= {{8{external_data_bus[7:7]}},external_data_bus[7:0]};
|
||||
end else begin
|
||||
PARAM1[7:0] <= external_data_bus[7:0];
|
||||
end
|
||||
end
|
||||
ProgCount <= ProgCount+1;
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||
default: state <= `PROC_EX_STATE_ENTRY;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
`PROC_DE_LOAD_16_PARAM:begin
|
||||
if(opcode_size==0)begin
|
||||
PARAM1[7:0] <= CIR[7:0];
|
||||
if(ProgCount[0:0]==1)begin
|
||||
PARAM1[15:8] <= external_data_bus[15:8];
|
||||
end else begin
|
||||
PARAM1[15:8] <= external_data_bus[7:0];
|
||||
end
|
||||
ProgCount <= ProgCount+1;
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||
default: state <= `PROC_EX_STATE_ENTRY;
|
||||
endcase
|
||||
end else begin
|
||||
if(ProgCount[0:0]==1)begin
|
||||
ProgCount <= ProgCount+1;
|
||||
PARAM1[7:0] <= external_data_bus[15:8];
|
||||
state <= `PROC_DE_LOAD_16_EXTRA_FETCH_SET;
|
||||
end else begin
|
||||
PARAM1 <= external_data_bus;
|
||||
ProgCount <= ProgCount+2;
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||
default: state <= `PROC_EX_STATE_ENTRY;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
`PROC_DE_LOAD_16_EXTRA_FETCH_SET:begin
|
||||
external_address_bus <= {4'b0,ProgCount};
|
||||
state <= `PROC_DE_LOAD_16_EXTRA_FETCH;
|
||||
end
|
||||
`PROC_DE_LOAD_16_EXTRA_FETCH:begin
|
||||
ProgCount <= ProgCount+1;
|
||||
PARAM1[15:8] <= external_data_bus[7:0];
|
||||
case(IN_MOD)
|
||||
3'b000,3'b001,3'b010: state <= `PROC_MEMIO_READ;
|
||||
default: state <= `PROC_EX_STATE_ENTRY;
|
||||
endcase
|
||||
end
|
||||
`PROC_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]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b001:begin
|
||||
/*[BX]+[SI]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b010:begin
|
||||
/*[BP]+[SI]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b011:begin
|
||||
/*[BP]+[DI]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b100:begin
|
||||
/*[SI]*/
|
||||
reg_read_port1_addr <= 4'b1110;
|
||||
state <= `PROC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
3'b101:begin
|
||||
/*[DI]*/
|
||||
reg_read_port1_addr <= 4'b1111;
|
||||
state <= `PROC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
3'b110:begin
|
||||
/*d16 */
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b111:begin
|
||||
/*[BX]*/
|
||||
reg_read_port1_addr <= 4'b1011;
|
||||
state <= `PROC_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 ....*/
|
||||
`invalid_instruction;
|
||||
end
|
||||
end
|
||||
3'b110:begin /* SP Indirect read*/
|
||||
reg_read_port1_addr <= 4'b1100;
|
||||
state <= `PROC_MEMIO_READ_SETADDR;
|
||||
end
|
||||
default:begin
|
||||
`invalid_instruction
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`PROC_MEMIO_READ_SETADDR:begin
|
||||
if(memio_address_select==0)
|
||||
external_address_bus <= {4'b0,reg_read_port1_data[15:0]};
|
||||
else
|
||||
external_address_bus <= {4'b0,ALU_1O};
|
||||
state <= (memio_address_select?ALU_1O[0:0]:reg_read_port1_data[0:0])?`PROC_MEMIO_GET_UNALIGNED_DATA:`PROC_MEMIO_GET_ALIGNED_DATA;
|
||||
end
|
||||
`PROC_MEMIO_GET_ALIGNED_DATA:begin
|
||||
PARAM2 <= (Wbit==1)? external_data_bus : {8'b0,external_data_bus[7:0]} ;
|
||||
state <= `PROC_EX_STATE_ENTRY;
|
||||
end
|
||||
`PROC_MEMIO_GET_UNALIGNED_DATA:begin
|
||||
PARAM2 <= {8'b0,external_data_bus[15:8]};
|
||||
if(Wbit==1) begin
|
||||
state <= `PROC_MEMIO_GET_SECOND_BYTE;
|
||||
end else begin
|
||||
state <= `PROC_EX_STATE_ENTRY;
|
||||
end
|
||||
end
|
||||
`PROC_MEMIO_GET_SECOND_BYTE:begin
|
||||
external_address_bus <= external_address_bus+1;
|
||||
state <= `PROC_MEMIO_GET_SECOND_BYTE1;
|
||||
end
|
||||
`PROC_MEMIO_GET_SECOND_BYTE1:begin
|
||||
PARAM2[15:8] <= external_data_bus[7:0];
|
||||
state <= `PROC_EX_STATE_ENTRY;
|
||||
end
|
||||
`PROC_EX_STATE_ENTRY:begin
|
||||
external_address_bus <= {4'b0,ProgCount};
|
||||
FLAGS[7:0] <= ALU_1FLAGS[7:0];
|
||||
case(OUT_MOD)
|
||||
3'b000,
|
||||
3'b001,
|
||||
3'b010 : begin
|
||||
if(memio_address_select==1)
|
||||
state <= `PROC_MEMIO_WRITE;
|
||||
else
|
||||
case (RM) /* Duplicate code with write... */
|
||||
3'b000:begin
|
||||
/*[BX]+[SI]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b001:begin
|
||||
/*[BX]+[SI]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b010:begin
|
||||
/*[BP]+[SI]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b011:begin
|
||||
/*[BP]+[DI]*/
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b100:begin
|
||||
/*[SI]*/
|
||||
reg_read_port1_addr <= 4'b1110;
|
||||
state <= `PROC_MEMIO_WRITE;
|
||||
end
|
||||
3'b101:begin
|
||||
/*[DI]*/
|
||||
reg_read_port1_addr <= 4'b1111;
|
||||
state <= `PROC_MEMIO_WRITE;
|
||||
end
|
||||
3'b110:begin
|
||||
/*d16 */
|
||||
`invalid_instruction
|
||||
end
|
||||
3'b111:begin
|
||||
/*[BX]*/
|
||||
reg_read_port1_addr <= 4'b1011;
|
||||
state <= `PROC_MEMIO_WRITE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
3'b011:begin
|
||||
reg_write_we <= 0;
|
||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||
state <= `PROC_IF_STATE_ENTRY;
|
||||
else
|
||||
state <= `PROC_NEXT_MICROCODE;
|
||||
end
|
||||
3'b100:begin /*No output*/
|
||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||
state <= `PROC_IF_STATE_ENTRY;
|
||||
else
|
||||
state <= `PROC_NEXT_MICROCODE;
|
||||
end
|
||||
3'b101:begin /* Program Counter*/
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
jump_debug <= 1;
|
||||
`endif
|
||||
ProgCount <= ALU_1O[15:0];
|
||||
instruction_size_init <= 1;
|
||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||
state <= `PROC_IF_STATE_ENTRY;
|
||||
else
|
||||
state <= `PROC_NEXT_MICROCODE;
|
||||
end
|
||||
3'b110:begin /* SP Indirect write*/
|
||||
reg_read_port1_addr <= 4'b1100;
|
||||
state <= `PROC_MEMIO_WRITE;
|
||||
end
|
||||
3'b111:begin /* Write to PRAM1 (for microcode calculations) */
|
||||
PARAM1 <= ALU_1O;
|
||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||
state <= `PROC_IF_STATE_ENTRY;
|
||||
else
|
||||
state <= `PROC_NEXT_MICROCODE;
|
||||
end
|
||||
default:begin
|
||||
`invalid_instruction
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`PROC_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 */
|
||||
`ifdef DEBUG_MEMORY_WRITES
|
||||
$display("Writing at %04x , %04x",reg_read_port1_data,ALU_1O);
|
||||
`endif
|
||||
if(memio_address_select==0)
|
||||
external_address_bus <= {4'b0,reg_read_port1_data[15:0]};
|
||||
else
|
||||
external_address_bus <= {4'b0,ALU_1O};
|
||||
|
||||
IOMEM <= MEM_OR_IO;
|
||||
state <= (Wbit==0) ? `PROC_MEMIO_PUT_BYTE : (reg_read_port1_data[0:0]?`PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA:`PROC_MEMIO_PUT_ALIGNED_16BIT_DATA) ;
|
||||
end
|
||||
`PROC_MEMIO_PUT_UNALIGNED_16BIT_DATA:begin
|
||||
read <= 1;
|
||||
BHE <= 0;
|
||||
if(memio_address_select==0)
|
||||
data_bus_output_register <= {ALU_1O[7:0],ALU_1O[15:8]};
|
||||
else
|
||||
data_bus_output_register <= {reg_read_port1_data[7:0],reg_read_port1_data[15:8]};
|
||||
state <= `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT;
|
||||
end
|
||||
`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT:begin
|
||||
write <= 0;
|
||||
state <= `PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2;
|
||||
end
|
||||
`PROC_MEMIO_PUT_UNALIGNED_PREP_NEXT2:begin
|
||||
write <= 1;
|
||||
external_address_bus <= external_address_bus+1;
|
||||
BHE <= 1;
|
||||
state <= `PROC_MEMIO_WRITE_EXIT;
|
||||
end
|
||||
`PROC_MEMIO_PUT_ALIGNED_16BIT_DATA:begin
|
||||
read <= 1;
|
||||
data_bus_output_register <= {ALU_1O[15:8],ALU_1O[7:0]};
|
||||
state <= `PROC_MEMIO_WRITE_EXIT;
|
||||
end
|
||||
`PROC_MEMIO_PUT_BYTE:begin
|
||||
read <= 1;
|
||||
state <= `PROC_MEMIO_WRITE_EXIT;
|
||||
if((memio_address_select?ALU_1O[0:0]:reg_read_port1_data[0:0])==0) begin
|
||||
BHE <= 1;
|
||||
if(memio_address_select==0)
|
||||
data_bus_output_register <= {8'b0,ALU_1O[7:0]};
|
||||
else
|
||||
data_bus_output_register <= {8'b0,reg_read_port1_data[7:0]};
|
||||
end else begin
|
||||
BHE <= 0;
|
||||
if(memio_address_select==0)
|
||||
data_bus_output_register <= {ALU_1O[7:0],8'b0};
|
||||
else
|
||||
data_bus_output_register <= {reg_read_port1_data[7:0],8'b0};
|
||||
end
|
||||
end
|
||||
`PROC_MEMIO_WRITE_EXIT:begin
|
||||
write <= 0;
|
||||
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
|
||||
state <= `PROC_IF_STATE_ENTRY;
|
||||
else
|
||||
state <= `PROC_NEXT_MICROCODE;
|
||||
end
|
||||
`PROC_NEXT_MICROCODE:begin
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
jump_debug <= 0;
|
||||
`endif
|
||||
read <= 0;
|
||||
write <= 1; // maybe we are coming from MEMIO_WRITE
|
||||
BHE <= 0;
|
||||
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;
|
||||
state <= `PROC_IF_STATE_ENTRY;
|
||||
end else begin
|
||||
state <= `PROC_DE_STATE_ENTRY;
|
||||
end
|
||||
reg_write_we <= 1;
|
||||
end
|
||||
default:begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`undef invalid_instruction
|
||||
/*############################################################################### */
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
@ -21,7 +21,8 @@
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
input [3:0] write_port1_addr;
|
||||
input [3:0] read_port1_addr;
|
||||
input [3:0] read_port2_addr;
|
||||
@ -32,22 +33,24 @@ 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'hz ;
|
||||
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[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'hz ;
|
||||
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[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] ) );
|
||||
|
||||
`ifdef DEBUG_REG_WRITES
|
||||
string debug_name;
|
||||
reg [2:0] debug_address;
|
||||
`endif
|
||||
|
||||
wire write_Wbit;
|
||||
assign write_Wbit=write_port1_addr[3:3];
|
||||
|
||||
always @(negedge write_port1_we) begin
|
||||
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;
|
||||
@ -81,18 +84,19 @@ always @(negedge write_port1_we) begin
|
||||
endcase
|
||||
end
|
||||
/* verilator lint_on BLKSEQ */
|
||||
`endif
|
||||
if (write_Wbit)
|
||||
debug_address<=write_port1_addr[2:0];
|
||||
else
|
||||
debug_address<={1'b0,write_port1_addr[1:0]};
|
||||
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef DEBUG_REG_WRITES
|
||||
always @(posedge write_port1_we) begin
|
||||
if ( debug_name != "" ) /*At the start this triggers for some reason */
|
||||
if (write_Wbit)begin
|
||||
$display("register %%%s update to $0x%04x",debug_name,registers[write_port1_addr[2:0]]);
|
||||
end else begin
|
||||
$display("register %%%s update to $0x%04x",debug_name,registers[{1'b0,write_port1_addr[1:0]}]);
|
||||
end
|
||||
$display("register %%%s update to $0x%04x",debug_name,registers[debug_address]);
|
||||
end
|
||||
`endif
|
||||
|
||||
|
136
system/system.v
136
system/system.v
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
@ -18,77 +18,134 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
`timescale 1ns/1ps
|
||||
`include "error_header.v"
|
||||
`include "config.v"
|
||||
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
`ifdef CALCULATE_IPC
|
||||
wire new_instruction;
|
||||
`endif
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
wire jump;
|
||||
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,rd,wr,BHE,IOMEM
|
||||
/* MEMORY / IO */ ,address_bus,data_bus_read_CPU,data_bus_write_CPU,wait_state,rd,wr,BHE,IOMEM
|
||||
`ifdef CALCULATE_IPC
|
||||
/* STATISTICS */ ,new_instruction
|
||||
`endif
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
/* */ , jump
|
||||
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT, jump_req
|
||||
`endif
|
||||
);
|
||||
|
||||
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
||||
wire [15:0] data_bus_read_RAM;
|
||||
|
||||
doublemem #(.RAM_SIZE_IN_BYTES(65536)) sysmem(address_bus[15:0],data_bus_read_RAM,data_bus_write_CPU,rd,wr,BHE,IOMEM,clock);
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
string stats_name;
|
||||
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);
|
||||
$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\":0,\n\"Cycles\":[");
|
||||
$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;
|
||||
`endif
|
||||
end
|
||||
|
||||
//integer killswitch=0;
|
||||
//always @(posedge clock) begin
|
||||
// killswitch <= killswitch +1;
|
||||
// if( killswitch == 20000 )begin
|
||||
// if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||
// $writememh(memdump_name, system.sysmem.memory,0,32767);
|
||||
// end
|
||||
// $finish;
|
||||
// end
|
||||
//end
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
reg first_json_cycle;
|
||||
always @(negedge clock)begin
|
||||
if(HALT==0 && json_file_descriptor!=0)begin
|
||||
$fdisplay(json_file_descriptor,"%s{\"C\":%0d,\"JMP\":%0d}",first_json_cycle?"":",",cycles,jump);
|
||||
if(finish < 2 && json_file_descriptor!=0 && sane)begin
|
||||
$fdisplay(json_file_descriptor,"%s{\"C\":%0d,\"L1\":%0d,\"VDI\":%0d,\"JMP\":%0d}",first_json_cycle?"":",",cycles,L1_SIZE_STAT,VALID_INSTRUCTION_STAT,jump_req);
|
||||
first_json_cycle <= 0;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
reg [15:0]data_bus_IO;
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
always @(negedge wr) begin
|
||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
|
||||
$write("%s" ,data_bus[15:8]);
|
||||
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
|
||||
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;
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
reg [128:0] instruction_count_temp;
|
||||
`endif
|
||||
|
||||
string memdump_name;
|
||||
|
||||
always @(posedge HALT) begin
|
||||
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||
$writememh(memdump_name, sysmem.memory,0,32767);
|
||||
@ -96,46 +153,79 @@ always @(posedge HALT) begin
|
||||
finish<=2'd1;
|
||||
end
|
||||
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
reg [1:0] finish;
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
|
||||
reg sane;
|
||||
reg [128:0] cycles;
|
||||
|
||||
always @(posedge reset)begin
|
||||
sane<=1;
|
||||
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
|
||||
if(json_file_descriptor!=0)
|
||||
$fdisplay(json_file_descriptor,"],\n\"Total Cycles\":%0d,\n\"Instructions run\":%0d\n}",cycles,instruction_count);
|
||||
instruction_count_temp <= instruction_count;
|
||||
`endif
|
||||
end
|
||||
2'd2: finish <= 3;
|
||||
2'd3: $finish;
|
||||
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 @(posedge ERROR) begin
|
||||
$display("PROCESSOR RUN INTO AN ERROR.\nCycles run for: %d",cycles-1);
|
||||
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
|
||||
|
||||
reg [128:0] cycles=0;
|
||||
end
|
||||
|
||||
always @(negedge clock)begin
|
||||
if(reset==1)
|
||||
cycles<=cycles+1;
|
||||
else begin
|
||||
cycles<=0;
|
||||
`ifdef CALCULATE_IPC
|
||||
`ifdef OUTPUT_JSON_STATISTICS
|
||||
instruction_count <= 0;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -36,6 +36,7 @@ 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) 2023 Efthymios Kritikos
|
||||
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
|
||||
@ -25,15 +25,15 @@ wire clock;
|
||||
reg reset;
|
||||
reg clk_enable;
|
||||
wire [19:0]address_bus;
|
||||
wire [15:0]data_bus;
|
||||
wire [15:0]data_bus_write;
|
||||
wire rd,wr,HALT;
|
||||
wire ERROR;
|
||||
wire [2:0] ERROR;
|
||||
wire IOMEM;
|
||||
|
||||
system system( .clock(clock),
|
||||
.reset(reset),
|
||||
.address_bus(address_bus),
|
||||
.data_bus(data_bus),
|
||||
.data_bus_write(data_bus_write),
|
||||
.rd(rd),
|
||||
.wr(wr),
|
||||
.HALT(HALT),
|
||||
@ -47,25 +47,28 @@ string memdump_name;
|
||||
initial begin
|
||||
clk_enable = 1;
|
||||
do_reset = 0;
|
||||
reset<=1;
|
||||
end
|
||||
|
||||
reg [1:0]do_reset;
|
||||
reg [2:0]do_reset;
|
||||
|
||||
always @(posedge clock) begin
|
||||
case(do_reset)
|
||||
2'd0:begin
|
||||
3'd0:begin
|
||||
do_reset<=1;
|
||||
end
|
||||
2'd1:begin
|
||||
3'd1:begin
|
||||
do_reset<=2;
|
||||
reset <= 0;
|
||||
end
|
||||
2'd2:begin
|
||||
3'd2:begin
|
||||
do_reset<=3;
|
||||
reset <= 0;
|
||||
end
|
||||
3'd3:begin
|
||||
do_reset<=4;
|
||||
reset <= 1;
|
||||
end
|
||||
2'd3:begin
|
||||
3'd4:begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file is part of the 9086 project.
|
||||
|
||||
Copyright (c) 2023 Efthymios Kritikos
|
||||
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
|
||||
|
21
system/verilator_makefile_fpga
Normal file
21
system/verilator_makefile_fpga
Normal file
@ -0,0 +1,21 @@
|
||||
# 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 $@ $<
|
66
tools/docker_build_tests.sh
Executable file
66
tools/docker_build_tests.sh
Executable file
@ -0,0 +1,66 @@
|
||||
#!/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
|
246
tools/gen_litedram.sh
Executable file
246
tools/gen_litedram.sh
Executable file
@ -0,0 +1,246 @@
|
||||
#!/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
|
70
tools/parse_nextpnr_stats.sh
Executable file
70
tools/parse_nextpnr_stats.sh
Executable file
@ -0,0 +1,70 @@
|
||||
#!/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
|
92
tools/plot.sh
Executable file
92
tools/plot.sh
Executable file
@ -0,0 +1,92 @@
|
||||
#!/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"
|
||||
}
|
||||
|
||||
if [ "$#" != 3 ] || ! [ -e "$1" ]
|
||||
then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CSV_FILE=$(mktemp)
|
||||
IN=$1
|
||||
OUT=$3
|
||||
|
||||
jq -r '.Cycles[]| [.C,.L1,.VDI,.JMP]|@csv' -- "$IN" > "$CSV_FILE"
|
||||
|
||||
BASE_GNUPLOT_OPTIONS="set datafile separator ',';set term svg;set output \"${OUT}\";"
|
||||
|
||||
parse_cache_size(){
|
||||
CACHE_SIZE=$(jq -r .L1_size -- "$IN")
|
||||
}
|
||||
|
||||
parse_total_cycles(){
|
||||
TOTAL_CYCLES=$(jq -r .\"Total\ Cycles\" -- "$IN")
|
||||
}
|
||||
|
||||
case "$2" in
|
||||
"cache_time")
|
||||
parse_cache_size
|
||||
parse_total_cycles
|
||||
gnuplot -e "${BASE_GNUPLOT_OPTIONS}\
|
||||
set term svg name \"Cache_time\";\
|
||||
set xlabel \"Clock cycles\";\
|
||||
set ylabel \"Cache utilisation (bytes)\";\
|
||||
set offsets 0, 0, 3, 1;\
|
||||
set ytics 0,1,$((CACHE_SIZE-1));\
|
||||
set xtics 0,$((TOTAL_CYCLES/15)),${TOTAL_CYCLES};\
|
||||
unset colorbox;\
|
||||
set ytics add (\"Valid\" -1);\
|
||||
set grid ytics;\
|
||||
set yrange [-2:${CACHE_SIZE}];\
|
||||
set xrange [-10:${TOTAL_CYCLES}+9];\
|
||||
set palette model RGB defined ( 0 'red', 1 'green', 2 'dark-khaki' );\
|
||||
plot\
|
||||
'${CSV_FILE}' using 1:(-2):(0):("'$'"4*100):(2) with vectors nohead palette notitle,\
|
||||
'${CSV_FILE}' using 1:2 with histeps notitle ls 1,\
|
||||
'${CSV_FILE}' using 1:(-0.75):(0):(-0.5):3 with vectors nohead palette notitle \
|
||||
"
|
||||
|
||||
;;
|
||||
"cache_util_freq")
|
||||
parse_cache_size
|
||||
gnuplot -e "${BASE_GNUPLOT_OPTIONS}\
|
||||
set term svg name \"cache_util_freq\";\
|
||||
set xlabel \"Utilisation (bytes)\";\
|
||||
set ylabel \"Occurrences\";\
|
||||
set boxwidth 0.5;\
|
||||
set style fill solid 0.4;\
|
||||
set xtics 0,1,$((CACHE_SIZE-1));\
|
||||
set offsets 1, 2, 0, 0;\
|
||||
plot '${CSV_FILE}' using 2:(1) smooth frequency with boxes notitle"
|
||||
|
||||
;;
|
||||
*)
|
||||
print_help;
|
||||
exit 1
|
||||
;;
|
||||
esac
|
Loading…
Reference in New Issue
Block a user