Compare commits
69 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 |
9
.gitignore
vendored
9
.gitignore
vendored
@ -6,9 +6,18 @@
|
|||||||
*.swp
|
*.swp
|
||||||
*.memdump
|
*.memdump
|
||||||
*.json
|
*.json
|
||||||
|
*.dfu
|
||||||
|
*.bit
|
||||||
|
*.fst.hier
|
||||||
|
abc.history
|
||||||
boot_code/*.bin
|
boot_code/*.bin
|
||||||
boot_code/*.txt
|
boot_code/*.txt
|
||||||
|
boot_code/*.stxt
|
||||||
system/boot_code.bin
|
system/boot_code.bin
|
||||||
system/boot_code.txt
|
system/boot_code.txt
|
||||||
system/obj_dir/
|
system/obj_dir/
|
||||||
|
system/simplified_ucode.txt
|
||||||
|
system/build/
|
||||||
tools/*svg
|
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.
|
# 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
|
# 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
|
# 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
|
BOOT_CODE=boot_code/brainfuck_mandelbrot.txt
|
||||||
GTKWSAVE=./gtkwave_savefile.gtkw
|
GTKWSAVE=./gtkwave_savefile.gtkw
|
||||||
MICROCODE=system/ucode.txt
|
MICROCODE=system/ucode.txt
|
||||||
BOOTABLES=boot_code/brainfuck_compiled.txt boot_code/brainfuck_interpreted.txt boot_code/pipeline_ideal.txt boot_code/fibonacci.txt boot_code/gnome_sort.txt boot_code/cache_fill_and_empty.txt ${BOOT_CODE}
|
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
|
NO_ASM=1
|
||||||
include common.mk
|
include common.mk
|
||||||
@ -29,21 +30,63 @@ include common.mk
|
|||||||
.PHONY: ${BOOTABLES}
|
.PHONY: ${BOOTABLES}
|
||||||
.PHONY: ${subst .txt,.bin,${BOOTABLES}}
|
.PHONY: ${subst .txt,.bin,${BOOTABLES}}
|
||||||
|
|
||||||
${BOOTABLES} ${subst .txt,.bin,${BOOTABLES}} :
|
${BOOTABLES} ${subst .stxt,.bin,${subst .txt,.bin,${BOOTABLES}}} :
|
||||||
${Q}make ${MAKEOPTS} -C boot_code $(subst boot_code/,,$@)
|
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=boot_code/ -C boot_code $(subst boot_code/,,$@)
|
||||||
|
|
||||||
boot_code/%.txt:
|
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}
|
.PHONY:${SYSTEM_VVP}
|
||||||
${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}
|
.PHONY:${VERILATOR_BIN}
|
||||||
${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
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
${Q}make ${MAKEOPTS} -C system clean
|
${Q}make ${MAKEOPTS} PRINT_PATH_PREFIX=system/ -C system clean
|
||||||
${Q}make ${MAKEOPTS} -C boot_code 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'
|
||||||
|
53
README.md
53
README.md
@ -13,26 +13,64 @@ A CPU that aims to be binary compatible with the 8086 ISA, focused on optimisati
|
|||||||
* [X] Is pipelined
|
* [X] Is pipelined
|
||||||
* [ ] Is Out of Order
|
* [ ] Is Out of Order
|
||||||
* [ ] Is superscalar
|
* [ ] Is superscalar
|
||||||
* [ ] Has been successfully synthesized
|
* [X] Has been successfully synthesized
|
||||||
|
* [ ] Has a comprehensive testing framework
|
||||||
|
|
||||||
### Simulating it
|
### 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)
|
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)
|
This list shows the software needed and the versions used during development :
|
||||||
|
|
||||||
* Icarus Verilog : version 12.0 OR **(preferred)** Verilator : 5.016
|
* Icarus Verilog : version 12.0 OR **(preferred)** Verilator : 5.018
|
||||||
* bin86 : 0.16.21
|
* bin86 : 0.16.21
|
||||||
* GNU Make : 4.4.1
|
* GNU Make : 4.4.1
|
||||||
* xxd : 2022-01-14
|
* xxd : 2023-10-25
|
||||||
* POSIX coreutils : GNU coreutils 9.4
|
* 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
|
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
|
### High level design overview
|
||||||
|
|
||||||
<img width="700" style=" margin: 10px 0px 10px 10px;" alt="9086 logo" src="readme_files/9086_overview.svg">
|
<img width="700" style=" margin: 10px 0px 10px 10px;" alt="9086 logo" src="readme_files/9086_overview.svg">
|
||||||
|
|
||||||
### License
|
### License and Copyright
|
||||||
All parts of this project are licensed under the GNU General Public License version 3 or later
|
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
|
### Version names
|
||||||
The version name consist of three numbers:
|
The version name consist of three numbers:
|
||||||
@ -42,3 +80,4 @@ The version name consist of three numbers:
|
|||||||
1. Patch level
|
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.
|
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 pipeline_ideal.asm fibonacci.asm gnome_sort.asm cache_fill_and_empty.asm
|
# This file is part of the 9086 project.
|
||||||
BINARIES=$(subst .asm,.txt,${SOURCE})
|
#
|
||||||
|
# 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=${BINARIES}
|
||||||
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||||
BUILD_FILES+=$(subst .asm,.fst,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.fst,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||||
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.bin,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||||
BUILD_FILES+=$(subst .asm,.json,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.json,${SOURCE_FULL} ${SOURCE_SHORT})
|
||||||
|
|
||||||
all: ${BINARIES}
|
all: ${BINARIES}
|
||||||
|
|
||||||
brainfuck_interpreted.bin: brainfuck_interpreter_v0.asm hello_9086.bf.asm dos_layer.asm
|
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_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
|
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
|
fibonacci.bin: helpers.asm
|
||||||
gnome_sort.bin: helpers.asm
|
gnome_sort.bin: helpers.asm
|
||||||
@ -24,3 +47,5 @@ include ../common.mk
|
|||||||
clean:
|
clean:
|
||||||
$(call QUIET_CLEAN,boot_code)
|
$(call QUIET_CLEAN,boot_code)
|
||||||
${Q}rm -f $(BUILD_FILES) *.bf.asm
|
${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
|
; Interrupt table and routines
|
||||||
INCLUDE dos_layer.asm
|
|
||||||
|
|
||||||
org 0x100
|
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:
|
prog:
|
||||||
INCLUDE hello_9086.bf.asm
|
INCLUDE hello_9086.bf.asm
|
||||||
|
|
||||||
|
|
||||||
output_program:
|
|
||||||
|
|
||||||
.ORG 0xFFF0
|
.ORG 0xFFF0
|
||||||
MOV AX,#0x0100
|
MOV AX,#0xF800
|
||||||
JMP AX
|
JMP AX
|
||||||
|
|
||||||
|
.ORG 0xFFFF
|
||||||
|
DB 0x00 ;Make sure a full 64KiB image
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
;
|
;
|
||||||
; This file is part of the 9086 project.
|
; 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
|
; 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
|
; 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
|
; You should have received a copy of the GNU General Public License
|
||||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
; 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 bx,#bootup_msg
|
||||||
mov ah,#0x02
|
mov ah,#0x02
|
||||||
print1:
|
print1:
|
||||||
@ -27,17 +29,27 @@ inc bx
|
|||||||
cmp dl,#0x0A
|
cmp dl,#0x0A
|
||||||
jne print1
|
jne print1
|
||||||
|
|
||||||
|
MOV DI,#0x0200
|
||||||
|
MOV AX,#0x0000
|
||||||
|
MOV bl,#0x00
|
||||||
|
CLEAR:
|
||||||
|
STOSW
|
||||||
|
INC BL
|
||||||
|
JNZ CLEAR
|
||||||
|
|
||||||
mov bx,#compiling
|
mov bx,#compiling
|
||||||
mov ah,#0x02
|
mov ah,#0x02
|
||||||
print2:
|
print2:
|
||||||
mov dl,[bx]
|
mov dl,[bx]
|
||||||
|
cmp dl,#0
|
||||||
|
je exit
|
||||||
int #0x21
|
int #0x21
|
||||||
inc bx
|
inc bx
|
||||||
cmp dl,#0
|
jmp print2
|
||||||
jne print2
|
exit:
|
||||||
|
|
||||||
MOV SI,#prog
|
MOV SI,#prog
|
||||||
MOV DI,#output_program
|
MOV DI,#0x0700
|
||||||
;CL: write concat CH: move concat
|
;CL: write concat CH: move concat
|
||||||
MOV CX,#0
|
MOV CX,#0
|
||||||
JMP COMPILE ; Moving some functions above the main switch to make shot jumps work
|
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 AL,#0xF4 ; hlt
|
||||||
MOV [DI],AL
|
MOV [DI],AL
|
||||||
MOV BX,#DATA
|
; From 0x100 its free but i'll do 0x200 in case it start writing earlier
|
||||||
MOV AX,#output_program
|
MOV BX,#0x0200
|
||||||
|
MOV AX,#0x0700
|
||||||
JMP AX
|
JMP AX
|
||||||
|
|
||||||
;;;;;;;;; . ;;;;;;;;;
|
;;;;;;;;; . ;;;;;;;;;
|
||||||
@ -248,18 +261,19 @@ MOV AL,#0x43 ; inc %bx
|
|||||||
STOSB
|
STOSB
|
||||||
JMP MOVES_FLUSHED
|
JMP MOVES_FLUSHED
|
||||||
|
|
||||||
|
|
||||||
MOVES_ONE_LEFT:
|
MOVES_ONE_LEFT:
|
||||||
MOV AL,#0x4b ; dec %bx
|
MOV AL,#0x4b ; dec %bx
|
||||||
STOSB
|
STOSB
|
||||||
JMP MOVES_FLUSHED
|
JMP MOVES_FLUSHED
|
||||||
|
|
||||||
|
|
||||||
MOVES_FLUSHED:
|
MOVES_FLUSHED:
|
||||||
MOV CH,#0
|
MOV CH,#0
|
||||||
RET
|
RET
|
||||||
|
|
||||||
bootup_msg: .ASCII 'Native 8086 brainfuck compiler v1\n'
|
|
||||||
compiling: .ASCII 'Compiling...\0'
|
|
||||||
compiled: .ASCII '\rCompiled! \n'
|
compiled: .ASCII '\rCompiled! \n'
|
||||||
DATA: .BLKB 560
|
compiling: .ASCII 'Compiling...\0'
|
||||||
.BLKB 200
|
bootup_msg: .ASCII 'Native 8086 brainfuck compiler v1\n'
|
||||||
STACK:
|
.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
|
mov sp,#STACK
|
||||||
|
call INIT_INT_VECT_TABLE
|
||||||
INCLUDE brainfuck_interpreter_v0.asm
|
INCLUDE brainfuck_interpreter_v0.asm
|
||||||
|
|
||||||
.BLKB 200
|
.BLKB 200
|
||||||
STACK:
|
STACK:
|
||||||
|
INCLUDE dos_layer.asm
|
||||||
|
|
||||||
prog:
|
prog:
|
||||||
INCLUDE hello_9086.bf.asm
|
INCLUDE hello_9086.bf.asm
|
||||||
|
|
||||||
.ORG 0xFFF0
|
.ORG 0xFFF0
|
||||||
MOV AX,#0x0100
|
MOV AX,#0xF000
|
||||||
JMP AX
|
JMP AX
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
;
|
;
|
||||||
; This file is part of the 9086 project.
|
; 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
|
; 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
|
; it under the terms of the GNU General Public License as published by
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
; Interrupt table and routines
|
;I got this down to 11428 bytes
|
||||||
INCLUDE dos_layer.asm
|
|
||||||
|
|
||||||
.ORG 0x100
|
org 0x100
|
||||||
|
output_program:
|
||||||
|
|
||||||
|
org 0xC000
|
||||||
|
mov sp,#SMALL_STACK
|
||||||
|
call INIT_INT_VECT_TABLE
|
||||||
INCLUDE brainfuck_compiler_v1.asm
|
INCLUDE brainfuck_compiler_v1.asm
|
||||||
|
SMALL_STACK:;Stack of compiler is at the end of file
|
||||||
|
|
||||||
|
INCLUDE dos_layer.asm
|
||||||
prog:
|
prog:
|
||||||
INCLUDE mandelbrot.bf.asm
|
INCLUDE mandelbrot.bf.asm
|
||||||
|
|
||||||
output_program:
|
|
||||||
|
|
||||||
.ORG 0xFFF0
|
.ORG 0xFFF0
|
||||||
MOV AX,#0x0100
|
MOV AX,#0xC000
|
||||||
JMP AX
|
JMP AX
|
||||||
|
|
||||||
|
.ORG 0xFFFF
|
||||||
|
DB 0x00 ;Make sure a full 64KiB image
|
||||||
|
Binary file not shown.
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:
|
PRINT_INT_HANDLE:
|
||||||
push AX
|
push AX
|
||||||
CMP AH,#0x02
|
CMP AH,#0x02
|
||||||
@ -14,3 +10,15 @@ MOV AL,DL
|
|||||||
out byte #0xA5
|
out byte #0xA5
|
||||||
POP AX
|
POP AX
|
||||||
iret
|
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
|
mov sp,#STACK
|
||||||
|
call INIT_INT_VECT_TABLE
|
||||||
|
|
||||||
MOV AX,#0x1
|
MOV AX,#0x1
|
||||||
MOV BX,#0x1
|
MOV BX,#0x1
|
||||||
@ -26,6 +26,7 @@ MOV DL,#0x0a
|
|||||||
INT #0x21
|
INT #0x21
|
||||||
|
|
||||||
hlt
|
hlt
|
||||||
|
INCLUDE dos_layer.asm
|
||||||
|
|
||||||
|
|
||||||
.BLKB 200
|
.BLKB 200
|
||||||
@ -33,6 +34,6 @@ STACK:
|
|||||||
INCLUDE helpers.asm
|
INCLUDE helpers.asm
|
||||||
|
|
||||||
.ORG 0xFFF0
|
.ORG 0xFFF0
|
||||||
MOV AX,#0x0100
|
MOV AX,#0xF000
|
||||||
JMP AX
|
JMP AX
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
INCLUDE dos_layer.asm
|
|
||||||
|
|
||||||
.org 0x100
|
.org 0xF000
|
||||||
mov sp,#STACK
|
mov sp,#STACK
|
||||||
MOV SI,#DATA
|
MOV SI,#DATA
|
||||||
|
call INIT_INT_VECT_TABLE
|
||||||
|
|
||||||
GNOME_SORT:
|
GNOME_SORT:
|
||||||
CMP SI,#DATA+31
|
CMP SI,#DATA+23
|
||||||
JZ GNOMED
|
JZ GNOMED
|
||||||
MOV AX,[SI]
|
MOV AX,[SI]
|
||||||
INC SI
|
INC SI
|
||||||
@ -29,7 +29,7 @@ PRINT_LOOP:
|
|||||||
MOV AL,[SI]
|
MOV AL,[SI]
|
||||||
call PRINT_0_8_HEX
|
call PRINT_0_8_HEX
|
||||||
INC SI
|
INC SI
|
||||||
CMP SI,#DATA+32
|
CMP SI,#DATA+24
|
||||||
JNZ PRINT_LOOP
|
JNZ PRINT_LOOP
|
||||||
|
|
||||||
MOV AH,#0x02
|
MOV AH,#0x02
|
||||||
@ -37,11 +37,11 @@ MOV DL,#0x0a
|
|||||||
INT #0x21
|
INT #0x21
|
||||||
|
|
||||||
hlt
|
hlt
|
||||||
|
INCLUDE dos_layer.asm
|
||||||
|
|
||||||
DATA: DB 0x51, 0x17, 0x37, 0x5d, 0x06, 0x3f, 0x51, 0x8b
|
DATA: DB 0x51, 0x17, 0x37, 0x5d, 0x06, 0x3f, 0x51, 0x8b
|
||||||
DB 0xa5, 0x33, 0x54, 0xdf, 0xae, 0xee, 0x3a, 0x18
|
DB 0xa5, 0x33, 0x54, 0xdf, 0xae, 0xee, 0x3a, 0x18
|
||||||
DB 0xe9, 0xdb, 0x1f, 0x21, 0x44, 0x4f, 0x99, 0x09
|
DB 0xe9, 0xdb, 0x1f, 0x21, 0x44, 0x4f, 0x99, 0x09
|
||||||
DB 0x2a, 0x23, 0x82, 0x4f, 0x52, 0xf1, 0xdc, 0x0b
|
|
||||||
|
|
||||||
.BLKB 200
|
.BLKB 200
|
||||||
STACK:
|
STACK:
|
||||||
@ -49,6 +49,8 @@ STACK:
|
|||||||
INCLUDE helpers.asm
|
INCLUDE helpers.asm
|
||||||
|
|
||||||
.ORG 0xFFF0
|
.ORG 0xFFF0
|
||||||
MOV AX,#0x0100
|
MOV AX,#0xF000
|
||||||
JMP AX
|
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
|
@ -1,4 +1,4 @@
|
|||||||
org 0x100
|
org 0xF000
|
||||||
inc ax
|
inc ax
|
||||||
inc bx
|
inc bx
|
||||||
inc ax
|
inc ax
|
||||||
@ -102,5 +102,5 @@ inc bx
|
|||||||
hlt
|
hlt
|
||||||
|
|
||||||
.ORG 0xFFF0
|
.ORG 0xFFF0
|
||||||
MOV AX,#0x0100
|
MOV AX,#0xF000
|
||||||
JMP AX
|
JMP AX
|
||||||
|
65
common.mk
65
common.mk
@ -1,26 +1,59 @@
|
|||||||
.PRECIOUS:${BOOT_CODE}
|
.PRECIOUS:${BOOT_CODE}
|
||||||
|
|
||||||
|
########## BUILD OPTIONS ##########
|
||||||
|
|
||||||
QUIET=1
|
QUIET=1
|
||||||
# QUIET: 1=clean, non-verbose output
|
# QUIET: 1=clean, non-verbose output
|
||||||
# 2=normal make output
|
# 2=normal make output
|
||||||
|
|
||||||
|
####### SIMULATION OPTIONS ########
|
||||||
|
|
||||||
SIM=VERILATOR
|
SIM=VERILATOR
|
||||||
# SIM: VERILATOR: use Verilator
|
# SIM: VERILATOR: use Verilator
|
||||||
# ICARUS: use Icarus Verilog
|
# ICARUS: use Icarus Verilog
|
||||||
|
|
||||||
NUMACTL=#numactl -m 0 -C 0,1 --
|
NUMACTL=#numactl -m 0 -C 0,1 --
|
||||||
|
|
||||||
VERSION="v0.2.0"
|
######## SYNTHESIS OPTIONS ########
|
||||||
COMMIT=$(shell git log --pretty=format:'%H' -1 |cat)
|
|
||||||
|
# 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"
|
ifeq "${QUIET}" "1"
|
||||||
QUIET_AS = @echo ' AS '$@;
|
QUIET_AS = @echo ' AS '${PRINT_PATH_PREFIX}$@;
|
||||||
QUIET_CC = @echo ' CC '$@;
|
|
||||||
QUIET_VVP = @echo ' VVP '$@;
|
QUIET_VVP = @echo ' VVP '${PRINT_PATH_PREFIX}$@;
|
||||||
QUIET_IVERILOG = @echo ' IVERILOG '$@;
|
QUIET_IVERILOG = @echo ' IVERILOG '${PRINT_PATH_PREFIX}$@;
|
||||||
QUIET_VERILATOR = @echo ' VERILATOR '$@;
|
|
||||||
QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
|
QUIET_VERILATOR = @echo ' VERILATOR '${PRINT_PATH_PREFIX}$@;
|
||||||
QUIET_VERILATOR_RUN = @printf ' %s %s\n' $1 $2;
|
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 = @
|
Q = @
|
||||||
MAKEOPTS=--no-print-directory
|
MAKEOPTS=--no-print-directory
|
||||||
.SILENT:
|
.SILENT:
|
||||||
@ -35,12 +68,20 @@ wave: $(subst .txt,.wave,${BOOT_CODE})
|
|||||||
disas: $(subst .txt,.disas,${BOOT_CODE})
|
disas: $(subst .txt,.disas,${BOOT_CODE})
|
||||||
|
|
||||||
# Assembling code
|
# Assembling code
|
||||||
%.txt:%.bin
|
%.stxt: %.bin
|
||||||
${Q}dd if=/dev/zero bs=1 count=65536 of="$(subst .bin,.stage,$<)" status=none
|
${Q}dd if=/dev/zero bs=1 count=2048 of="$(subst .bin,.stage,$<)" status=none
|
||||||
${Q}dd if="$<" of="$(subst .bin,.stage,$<)" conv=notrunc,nocreat 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}xxd -ps -c 2 "$(subst .bin,.stage,$<)" > "$@"
|
||||||
${Q}rm "$(subst .bin,.stage,$<)"
|
${Q}rm "$(subst .bin,.stage,$<)"
|
||||||
|
|
||||||
|
# Assembling code
|
||||||
|
%.txt:%.bin
|
||||||
|
${Q}dd if=/dev/zero bs=1 count=65536 of="$(subst .bin,.stage_short,$<)" status=none
|
||||||
|
${Q}dd if="$<" of="$(subst .bin,.stage_short,$<)" conv=notrunc,nocreat status=none
|
||||||
|
${Q}xxd -ps -c 2 "$(subst .bin,.stage_short,$<)" > "$@"
|
||||||
|
${Q}rm "$(subst .bin,.stage_short,$<)"
|
||||||
|
|
||||||
|
|
||||||
ifeq "${NO_ASM}" "0"
|
ifeq "${NO_ASM}" "0"
|
||||||
%.bin:%.asm
|
%.bin:%.asm
|
||||||
${QUIET_AS}
|
${QUIET_AS}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
,user,localhost,24.10.2023 00:59,file:///home/user/.config/libreoffice/4;
|
|
146
system/Makefile
146
system/Makefile
@ -1,6 +1,6 @@
|
|||||||
# This file is part of the 9086 project.
|
# 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
|
# 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
|
# 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
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
TOP_LEVEL_SOURCE=system.v
|
|
||||||
SOURCES=processor.v memory.v registers.v alu.v decoder.v general.v biu.v execute.v
|
SOURCES=processor.v memory.v registers.v alu.v decoder.v general.v biu.v execute.v
|
||||||
EVENT_SIM_TESTBENCH=testbench.v
|
|
||||||
VERILATOR_TESTBENCH=testbench.cpp
|
|
||||||
INCLUDES=exec_state_def.v alu_header.v config.v ucode_header.v error_header.v
|
INCLUDES=exec_state_def.v alu_header.v config.v ucode_header.v error_header.v
|
||||||
SYSTEM_VVP=system.vvp
|
|
||||||
VERILATOR_BIN=obj_dir/Vsystem
|
|
||||||
BOOT_CODE=boot_code.txt
|
|
||||||
GTKWSAVE=../gtkwave_savefile.gtkw
|
|
||||||
MICROCODE=ucode.txt
|
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
|
NO_ASM=0
|
||||||
include ../common.mk
|
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
|
#build options
|
||||||
VERILATOR_OPTS += --cc --exe
|
VERILATOR_OPTS += --cc --exe
|
||||||
|
|
||||||
@ -36,26 +64,114 @@ VERILATOR_OPTS += --cc --exe
|
|||||||
VERILATOR_OPTS += --trace-fst --threads 1 --autoflush
|
VERILATOR_OPTS += --trace-fst --threads 1 --autoflush
|
||||||
|
|
||||||
#linter options
|
#linter options
|
||||||
VERILATOR_OPTS += -Wall --Wno-DECLFILENAME -Wno-SYNCASYNCNET -Wno-MULTIDRIVEN
|
VERILATOR_OPTS += -Wall --Wno-DECLFILENAME
|
||||||
|
|
||||||
#optimisation options
|
#optimisation options
|
||||||
VERILATOR_OPTS += -x-assign fast --x-initial fast
|
VERILATOR_OPTS += -x-assign fast --x-initial fast
|
||||||
#For testing use:
|
#For testing use:
|
||||||
#VERILATOR_OPTS += -x-assign unique --x-initial unique
|
#VERILATOR_OPTS += -x-assign unique --x-initial unique
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#### SIMULATION RECIPES ####
|
||||||
|
################################################################################
|
||||||
|
|
||||||
# COMPILING
|
# COMPILING
|
||||||
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
|
${SYSTEM_VVP} : ${SIMULATED_SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||||
${QUIET_IVERILOG}
|
${QUIET_IVERILOG}
|
||||||
${Q}iverilog -g2012 -D CALCULATE_IPC -D OTUPUT_JSON_STATISTICS -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
|
${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}
|
${QUIET_VERILATOR}
|
||||||
${Q}verilator -DCALCULATE_IPC -DOTUPUT_JSON_STATISTICS ${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
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(call QUIET_CLEAN,system)
|
$(call QUIET_CLEAN,system)
|
||||||
${Q}rm -rf ${SYSTEM_VVP} *.fst boot_code.txt boot_code.bin *memdump *memdumptxt obj_dir *json
|
${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.
|
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
|
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
|
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_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: {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_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_AND: begin C_FLAG=0;OUT[7:0]=A[7:0]&B[7:0]; end
|
||||||
`ALU_OP_OR: begin C_FLAG=0;OUT=A|B; 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=A^B; 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=A<<B; end
|
`ALU_OP_SHIFT_LEFT: begin C_FLAG=(A&16'h80)==16'h80;OUT[7:0]=A[7:0]<<B; end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
245
system/biu.v
245
system/biu.v
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -45,39 +45,40 @@ module BIU (
|
|||||||
|
|
||||||
/**************** OUTSIDE WORLD ****************/
|
/**************** OUTSIDE WORLD ****************/
|
||||||
/* */ ,output wire [19:0] external_address_bus
|
/* */ ,output wire [19:0] external_address_bus
|
||||||
/* */ ,inout [15:0] external_data_bus,output reg read, output reg write,output reg BHE,output reg IOMEM
|
/* */ ,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 TO DE ****************/
|
||||||
/* */ ,output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION
|
/* */ ,output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION
|
||||||
/* */ ,output reg VALID_DATA, output reg DATA_DIR
|
/* */ ,output reg VALID_DATA
|
||||||
|
|
||||||
/**************** INPUT FROM DE ****************/
|
/**************** INPUT FROM DE ****************/
|
||||||
,input Wbit, input MEM_OR_IO, input valid_instruction_ack
|
,input Wbit, input MEM_OR_IO, input valid_instruction_ack
|
||||||
|
|
||||||
/**************** INPUT FROM EX ****************/
|
/**************** INPUT FROM EX ****************/
|
||||||
/* */ ,input jump_req, input write_request, input read_request
|
/* */ ,input jump_req, input write_request, input read_request
|
||||||
/* */ ,input[15:0] ADDRESS_INPUT
|
/* */ ,input[15:0] ADDRESS_INPUT, input [15:0] DATA_EX_WRITE
|
||||||
|
|
||||||
/************ BIDIRECTIONAL WITH EX ************/
|
/**************** OUTPUT TO EX *****************/
|
||||||
/* */ ,inout [15:0] DATA
|
/* */ ,output [15:0] DATA_EX_READ
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
/***************** STATISTICS *****************/
|
/***************** STATISTICS *****************/
|
||||||
/* */ ,output wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE_STAT, output wire VALID_INSTRUCTION_STAT
|
/* */ ,output wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE_STAT, output wire VALID_INSTRUCTION_STAT
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
assign FIFO_SIZE_STAT = FIFO_SIZE;
|
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);
|
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
|
`endif
|
||||||
|
|
||||||
reg [15:0] data_bus_output_register;
|
reg [15:0] data_bus_output_register;
|
||||||
assign external_data_bus=read?data_bus_output_register:16'hz;
|
assign external_data_bus_write=data_bus_output_register; //TODO: should we rename?
|
||||||
|
|
||||||
reg [15:0] DATA_OUT;
|
reg [15:0] DATA_OUT;
|
||||||
assign DATA=DATA_DIR ? 16'hz:DATA_OUT;
|
assign DATA_EX_READ=DATA_OUT; //TODO should we rename?
|
||||||
|
|
||||||
`define FIFO_SIZE_BYTES $rtoi($pow(2,`L1_CACHE_SIZE))
|
`define FIFO_SIZE_BYTES $rtoi($pow(2,`L1_CACHE_SIZE))
|
||||||
|
|
||||||
@ -89,21 +90,6 @@ wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE = FIFO_end-FIFO_start;
|
|||||||
reg [3:0] biu_state;
|
reg [3:0] biu_state;
|
||||||
reg sane;
|
reg sane;
|
||||||
|
|
||||||
always @(negedge reset) begin
|
|
||||||
biu_state <= `BIU_HALT;
|
|
||||||
write <= 1;
|
|
||||||
sane <= 0;
|
|
||||||
end
|
|
||||||
always @(posedge reset) begin
|
|
||||||
biu_state <= `BIU_RESET1;
|
|
||||||
/* verilator lint_off BLKSEQ */
|
|
||||||
FIFO_start = `L1_CACHE_SIZE'b0;
|
|
||||||
FIFO_end = `L1_CACHE_SIZE'b0;
|
|
||||||
/* verilator lint_on BLKSEQ */
|
|
||||||
end
|
|
||||||
|
|
||||||
reg jump_req_latch;
|
|
||||||
|
|
||||||
reg func;
|
reg func;
|
||||||
reg [19:0]INSTRUCTION_ADDRESS;
|
reg [19:0]INSTRUCTION_ADDRESS;
|
||||||
reg [19:0]DATA_ADDRESS;
|
reg [19:0]DATA_ADDRESS;
|
||||||
@ -111,13 +97,25 @@ reg [19:0]DATA_ADDRESS;
|
|||||||
assign external_address_bus= func ? INSTRUCTION_ADDRESS : DATA_ADDRESS ;
|
assign external_address_bus= func ? INSTRUCTION_ADDRESS : DATA_ADDRESS ;
|
||||||
|
|
||||||
always @(posedge clock) begin
|
always @(posedge clock) begin
|
||||||
if ( jump_req_latch ) begin
|
if ( reset == 0 ) begin
|
||||||
INSTRUCTION_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
|
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;
|
INSTRUCTION_LOCATION <= ADDRESS_INPUT;
|
||||||
func <= 1;
|
func <= 1;
|
||||||
jump_req_latch <= 0;
|
|
||||||
if (biu_state==`BIU_READ)
|
if (biu_state==`BIU_READ)
|
||||||
biu_state <= `BIU_NEXT_ACTION;
|
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
|
end else begin
|
||||||
case(biu_state)
|
case(biu_state)
|
||||||
`BIU_HALT: begin
|
`BIU_HALT: begin
|
||||||
@ -125,18 +123,14 @@ always @(posedge clock) begin
|
|||||||
`BIU_NEXT_ACTION: begin /* decide if we can read, if we are full or if we need to do something else */
|
`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
|
if (write_request) begin
|
||||||
func<=0;
|
func<=0;
|
||||||
DATA_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
|
DATA_ADDRESS <= { 4'hF , ADDRESS_INPUT };
|
||||||
DATA_DIR <= 1 ;
|
|
||||||
IOMEM <= MEM_OR_IO;
|
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) ;
|
biu_state <= (Wbit==0) ? `BIU_PUT_BYTE : (ADDRESS_INPUT[0:0]?`BIU_PUT_UNALIGNED_16BIT_DATA:`BIU_PUT_ALIGNED_16BIT_DATA) ;
|
||||||
INSTRUCTION_ADDRESS <= {4'b0,INSTRUCTION_LOCATION} ;
|
INSTRUCTION_ADDRESS <= {4'hF,INSTRUCTION_LOCATION} ;
|
||||||
/* verilator lint_off BLKSEQ */
|
FIFO_end<=FIFO_start;
|
||||||
FIFO_end=FIFO_start;
|
|
||||||
/* verilator lint_on BLKSEQ */
|
|
||||||
end else if ( read_request ) begin
|
end else if ( read_request ) begin
|
||||||
func<=0;
|
func<=0;
|
||||||
DATA_ADDRESS <= { 4'b0 , ADDRESS_INPUT };
|
DATA_ADDRESS <= { 4'hF , ADDRESS_INPUT };
|
||||||
DATA_DIR <= 0;
|
|
||||||
IOMEM <= MEM_OR_IO;
|
IOMEM <= MEM_OR_IO;
|
||||||
read <= 0;
|
read <= 0;
|
||||||
BHE <= 0;
|
BHE <= 0;
|
||||||
@ -161,23 +155,17 @@ always @(posedge clock) begin
|
|||||||
/*************** INSTRUCTION FIFO READ ***************/
|
/*************** INSTRUCTION FIFO READ ***************/
|
||||||
`BIU_READ: begin
|
`BIU_READ: begin
|
||||||
if(INSTRUCTION_ADDRESS[0:0]==0 && FIFO_SIZE<{{(`L1_CACHE_SIZE-1){1'b1}},1'b0})begin
|
if(INSTRUCTION_ADDRESS[0:0]==0 && FIFO_SIZE<{{(`L1_CACHE_SIZE-1){1'b1}},1'b0})begin
|
||||||
/* verilator lint_off BLKSEQ */
|
INPUT_FIFO[FIFO_end] <= external_data_bus_read[7:0];
|
||||||
INPUT_FIFO[FIFO_end] = external_data_bus[7:0];
|
INPUT_FIFO[FIFO_end+`L1_CACHE_SIZE'd1] <= external_data_bus_read[15:8];
|
||||||
INPUT_FIFO[FIFO_end+`L1_CACHE_SIZE'd1] = external_data_bus[15:8];
|
FIFO_end <= FIFO_end+`L1_CACHE_SIZE'd2;
|
||||||
FIFO_end = FIFO_end+`L1_CACHE_SIZE'd2;
|
|
||||||
/* verilator lint_on BLKSEQ */
|
|
||||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd2;
|
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd2;
|
||||||
end else if(INSTRUCTION_ADDRESS[0:0]==0)begin
|
end else if(INSTRUCTION_ADDRESS[0:0]==0)begin
|
||||||
/* verilator lint_off BLKSEQ */
|
INPUT_FIFO[FIFO_end] <= external_data_bus_read[7:0];
|
||||||
INPUT_FIFO[FIFO_end] = external_data_bus[7:0];
|
FIFO_end <= FIFO_end+`L1_CACHE_SIZE'd1;
|
||||||
FIFO_end = FIFO_end+`L1_CACHE_SIZE'd1;
|
|
||||||
/* verilator lint_on BLKSEQ */
|
|
||||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
||||||
end else begin
|
end else begin
|
||||||
/* verilator lint_off BLKSEQ */
|
INPUT_FIFO[FIFO_end] <= external_data_bus_read[15:8];
|
||||||
INPUT_FIFO[FIFO_end] = external_data_bus[15:8];
|
FIFO_end <= FIFO_end+`L1_CACHE_SIZE'd1;
|
||||||
FIFO_end = FIFO_end+`L1_CACHE_SIZE'd1;
|
|
||||||
/* verilator lint_on BLKSEQ */
|
|
||||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
||||||
end
|
end
|
||||||
biu_state <= `BIU_NEXT_ACTION;
|
biu_state <= `BIU_NEXT_ACTION;
|
||||||
@ -185,13 +173,12 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
/*************** DATA WRITE ***************/
|
/*************** DATA WRITE ***************/
|
||||||
//TODO TODO TODO flush fifo, self modifying code
|
|
||||||
`BIU_PUT_UNALIGNED_16BIT_DATA:begin
|
`BIU_PUT_UNALIGNED_16BIT_DATA:begin
|
||||||
`ifdef DEBUG_DATA_READ_WRITES
|
`ifdef DEBUG_DATA_READ_WRITES
|
||||||
$display("Writing 16bit %04x at %04x",DATA,DATA_ADDRESS);
|
$display("Writing 16bit %04x at %04x",DATA_EX_WRITE,DATA_ADDRESS);
|
||||||
`endif
|
`endif
|
||||||
BHE <= 0;
|
BHE <= 0;
|
||||||
data_bus_output_register <= {DATA[7:0],DATA[15:8]};
|
data_bus_output_register <= {DATA_EX_WRITE[7:0],DATA_EX_WRITE[15:8]};
|
||||||
write <= 0;
|
write <= 0;
|
||||||
biu_state <= `BIU_PUT_UNALIGNED_PREP_NEXT2;
|
biu_state <= `BIU_PUT_UNALIGNED_PREP_NEXT2;
|
||||||
end
|
end
|
||||||
@ -203,22 +190,22 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
`BIU_PUT_ALIGNED_16BIT_DATA:begin
|
`BIU_PUT_ALIGNED_16BIT_DATA:begin
|
||||||
`ifdef DEBUG_DATA_READ_WRITES
|
`ifdef DEBUG_DATA_READ_WRITES
|
||||||
$display("Writing 16bit %04x at %04x",DATA,DATA_ADDRESS);
|
$display("Writing 16bit %04x at %04x",DATA_EX_WRTIE,DATA_ADDRESS);
|
||||||
`endif
|
`endif
|
||||||
data_bus_output_register <= {DATA[15:8],DATA[7:0]};
|
data_bus_output_register <= {DATA_EX_WRITE[15:8],DATA_EX_WRITE[7:0]};
|
||||||
write <= 0;
|
write <= 0;
|
||||||
biu_state <= `BIU_WRITE_RELEASE;
|
biu_state <= `BIU_WRITE_RELEASE;
|
||||||
end
|
end
|
||||||
`BIU_PUT_BYTE:begin
|
`BIU_PUT_BYTE:begin
|
||||||
`ifdef DEBUG_DATA_READ_WRITES
|
`ifdef DEBUG_DATA_READ_WRITES
|
||||||
$display("Writing 8bit %02x at %04x",DATA[7:0],DATA_ADDRESS);
|
$display("Writing 8bit %02x at %04x",DATA_EX_WRITE[7:0],DATA_ADDRESS);
|
||||||
`endif
|
`endif
|
||||||
if(ADDRESS_INPUT[0:0]==0) begin
|
if(ADDRESS_INPUT[0:0]==0) begin
|
||||||
BHE <= 1;
|
BHE <= 1;
|
||||||
data_bus_output_register <= {8'b0,DATA[7:0]};
|
data_bus_output_register <= {8'b0,DATA_EX_WRITE[7:0]};
|
||||||
end else begin
|
end else begin
|
||||||
BHE <= 0;
|
BHE <= 0;
|
||||||
data_bus_output_register <= {DATA[7:0],8'b0};
|
data_bus_output_register <= {DATA_EX_WRITE[7:0],8'b0};
|
||||||
end
|
end
|
||||||
write <= 0;
|
write <= 0;
|
||||||
biu_state <= `BIU_WRITE_RELEASE;
|
biu_state <= `BIU_WRITE_RELEASE;
|
||||||
@ -235,7 +222,6 @@ always @(posedge clock) begin
|
|||||||
|
|
||||||
/*************** DATA READ ***************/
|
/*************** DATA READ ***************/
|
||||||
`define finished_read \
|
`define finished_read \
|
||||||
DATA_DIR <= 0; \
|
|
||||||
if ( read_request == 0 ) begin \
|
if ( read_request == 0 ) begin \
|
||||||
biu_state <= `BIU_NEXT_ACTION;\
|
biu_state <= `BIU_NEXT_ACTION;\
|
||||||
VALID_DATA <= 0;\
|
VALID_DATA <= 0;\
|
||||||
@ -244,20 +230,20 @@ always @(posedge clock) begin
|
|||||||
`BIU_GET_ALIGNED_DATA:begin
|
`BIU_GET_ALIGNED_DATA:begin
|
||||||
`ifdef DEBUG_DATA_READ_WRITES
|
`ifdef DEBUG_DATA_READ_WRITES
|
||||||
if(Wbit==1)
|
if(Wbit==1)
|
||||||
$display("Reading 16bit %04x from %04x",external_data_bus,DATA_ADDRESS);
|
$display("Reading 16bit %04x from %04x",external_data_bus_read,DATA_ADDRESS);
|
||||||
else
|
else
|
||||||
$display("Reading 8bit %02x from %04x",external_data_bus[7:0],DATA_ADDRESS);
|
$display("Reading 8bit %02x from %04x",external_data_bus_read[7:0],DATA_ADDRESS);
|
||||||
`endif
|
`endif
|
||||||
DATA_OUT <= (Wbit==1)? external_data_bus : {8'b0,external_data_bus[7:0]} ;
|
DATA_OUT <= (Wbit==1)? external_data_bus_read : {8'b0,external_data_bus_read[7:0]} ;
|
||||||
read <=1;
|
read <=1;
|
||||||
`finished_read
|
`finished_read
|
||||||
end
|
end
|
||||||
`BIU_GET_UNALIGNED_DATA:begin
|
`BIU_GET_UNALIGNED_DATA:begin
|
||||||
`ifdef DEBUG_DATA_READ_WRITES
|
`ifdef DEBUG_DATA_READ_WRITES
|
||||||
if(Wbit==0)
|
if(Wbit==0)
|
||||||
$display("Reading 8bit %02x from %04x",external_data_bus[15:8],DATA_ADDRESS);
|
$display("Reading 8bit %02x from %04x",external_data_bus_read[15:8],DATA_ADDRESS);
|
||||||
`endif
|
`endif
|
||||||
DATA_OUT[7:0] <= external_data_bus[15:8];
|
DATA_OUT[7:0] <= external_data_bus_read[15:8];
|
||||||
read <=1;
|
read <=1;
|
||||||
if(Wbit==1) begin
|
if(Wbit==1) begin
|
||||||
biu_state <= `BIU_GET_SECOND_BYTE;
|
biu_state <= `BIU_GET_SECOND_BYTE;
|
||||||
@ -272,9 +258,9 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
`BIU_GET_SECOND_BYTE1:begin
|
`BIU_GET_SECOND_BYTE1:begin
|
||||||
`ifdef DEBUG_DATA_READ_WRITES
|
`ifdef DEBUG_DATA_READ_WRITES
|
||||||
$display("Reading 16bit %02x from %04x",{external_data_bus[7:0],DATA_OUT[7:0]},DATA_ADDRESS-1);//read started a byte earlier
|
$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
|
`endif
|
||||||
DATA_OUT[15:8] <= external_data_bus[7:0];
|
DATA_OUT[15:8] <= external_data_bus_read[7:0];
|
||||||
`finished_read
|
`finished_read
|
||||||
read <=1;
|
read <=1;
|
||||||
end
|
end
|
||||||
@ -285,15 +271,12 @@ always @(posedge clock) begin
|
|||||||
VALID_DATA <= 0;
|
VALID_DATA <= 0;
|
||||||
end
|
end
|
||||||
`BIU_RESET2: begin
|
`BIU_RESET2: begin
|
||||||
/* verilator lint_off BLKSEQ */
|
FIFO_start <= `L1_CACHE_SIZE'b0;
|
||||||
FIFO_start = `L1_CACHE_SIZE'b0;
|
FIFO_end <= `L1_CACHE_SIZE'b0;
|
||||||
FIFO_end = `L1_CACHE_SIZE'b0;
|
|
||||||
/* verilator lint_on BLKSEQ */
|
|
||||||
biu_state <= `BIU_NEXT_ACTION;
|
biu_state <= `BIU_NEXT_ACTION;
|
||||||
INSTRUCTION_ADDRESS <= 20'h0FFF0;
|
INSTRUCTION_ADDRESS <= 20'hFFFF0;
|
||||||
INSTRUCTION_LOCATION <= 16'hFFF0;
|
INSTRUCTION_LOCATION <= 16'hFFF0;
|
||||||
VALID_DATA <= 0;
|
VALID_DATA <= 0;
|
||||||
DATA_DIR <= 0;
|
|
||||||
sane<=1;
|
sane<=1;
|
||||||
end
|
end
|
||||||
default: begin
|
default: begin
|
||||||
@ -303,60 +286,39 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
wire [2:0] Isize;
|
/* update VALID_INSTRUCTION and INSTRUCTION */
|
||||||
InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},Isize);
|
always @( posedge clock) begin
|
||||||
|
|
||||||
`ifdef INCLUDE_EARLY_CALC_CIRUIT
|
if(jump_req==1)begin
|
||||||
wire [2:0] fifoIsize;
|
VALID_INSTRUCTION <= 0;
|
||||||
wire Isit1;
|
end else if(sane==1) begin
|
||||||
InstrSize fifoInstrSize({INPUT_FIFO[FIFO_start][7:0],INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1][5:3]},fifoIsize);
|
//if(VALID_INSTRUCTION == 1 ) begin
|
||||||
Is1 Is1(INPUT_FIFO[FIFO_start][7:0],Isit1);
|
// `ifdef DOUBLE_INSTRUCTION_LOAD
|
||||||
`endif
|
// 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
|
||||||
`ifdef DOUBLE_INSTRUCTION_LOAD
|
// VALID_INSTRUCTION <= 1;
|
||||||
wire [2:0] fifoIsize2;
|
// INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||||
InstrSize fifoInstrSize2(
|
// INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||||
{ 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]}
|
// end else if((fifoIsize2==3) && (FIFO_SIZE > `L1_CACHE_SIZE'd2+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}))begin
|
||||||
,fifoIsize2
|
// VALID_INSTRUCTION <= 1;
|
||||||
);
|
// INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||||
`endif
|
// INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||||
|
// INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||||
always @( valid_instruction_ack ) begin
|
// end else if(FIFO_SIZE>`L1_CACHE_SIZE'd3+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize})begin
|
||||||
/* verilator lint_off BLKSEQ */
|
// VALID_INSTRUCTION <= 1;
|
||||||
FIFO_start = FIFO_start + {{`L1_CACHE_SIZE-3{1'b0}},Isize};
|
// INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
||||||
/* verilator lint_on BLKSEQ */
|
// INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||||
INSTRUCTION_LOCATION <= INSTRUCTION_LOCATION + {13'd0,Isize};
|
// INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||||
end
|
// INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
||||||
|
// end else
|
||||||
always @( FIFO_start or FIFO_end ) begin
|
// VALID_INSTRUCTION <= 0;
|
||||||
if(sane==1) begin
|
// end else begin
|
||||||
if(VALID_INSTRUCTION == 1 ) begin
|
// VALID_INSTRUCTION <= 0;
|
||||||
`ifdef DOUBLE_INSTRUCTION_LOAD
|
// end
|
||||||
if(FIFO_SIZE>`L1_CACHE_SIZE'd3+{{`L1_CACHE_SIZE-3{1'b0}},Isize})begin
|
// `else
|
||||||
if((fifoIsize2==2) && (FIFO_SIZE > `L1_CACHE_SIZE'd1+{{`L1_CACHE_SIZE-3{1'b0}},fifoIsize}))begin
|
// VALID_INSTRUCTION <= 0;
|
||||||
VALID_INSTRUCTION <= 1;
|
// `endif
|
||||||
INSTRUCTION[31:24] <= INPUT_FIFO[FIFO_start];
|
//end else begin
|
||||||
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]);
|
//$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
|
`ifdef EARLY_VALID_INSTRUCTION
|
||||||
if(FIFO_start==FIFO_end) begin
|
if(FIFO_start==FIFO_end) begin
|
||||||
@ -383,10 +345,11 @@ always @( FIFO_start or FIFO_end ) begin
|
|||||||
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||||
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||||
INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
||||||
end
|
end else
|
||||||
|
VALID_INSTRUCTION <= 0;
|
||||||
`else
|
`else
|
||||||
if(FIFO_start==FIFO_end) begin
|
if(FIFO_start==FIFO_end) begin
|
||||||
/*TODO: Same as on the first statment on the other side of the `ifdef */
|
/*TODO: Same as on the first statement on the other side of the `ifdef */
|
||||||
VALID_INSTRUCTION <= 0;
|
VALID_INSTRUCTION <= 0;
|
||||||
end else if(FIFO_SIZE>`L1_CACHE_SIZE'd3)begin
|
end else if(FIFO_SIZE>`L1_CACHE_SIZE'd3)begin
|
||||||
VALID_INSTRUCTION <= 1;
|
VALID_INSTRUCTION <= 1;
|
||||||
@ -394,19 +357,29 @@ always @( FIFO_start or FIFO_end ) begin
|
|||||||
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
INSTRUCTION[23:16] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1];
|
||||||
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
INSTRUCTION[15: 8] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd2];
|
||||||
INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
INSTRUCTION[ 7: 0] <= INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd3];
|
||||||
end
|
end else
|
||||||
|
VALID_INSTRUCTION <= 0;
|
||||||
`endif
|
`endif
|
||||||
end
|
//end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @( posedge jump_req ) begin
|
wire [2:0] Isize;
|
||||||
/* verilator lint_off BLKSEQ */
|
InstrSize InstrSize({INSTRUCTION[31:24],INSTRUCTION[21:19]},Isize);
|
||||||
FIFO_start = FIFO_end ;
|
|
||||||
/* verilator lint_on BLKSEQ */
|
`ifdef INCLUDE_EARLY_CALC_CIRCUIT
|
||||||
jump_req_latch <= 1;
|
wire [2:0] fifoIsize;
|
||||||
DATA_DIR <= 1;
|
wire Isit1;
|
||||||
VALID_INSTRUCTION <= 0;
|
InstrSize fifoInstrSize({INPUT_FIFO[FIFO_start][7:0],INPUT_FIFO[FIFO_start+`L1_CACHE_SIZE'd1][5:3]},fifoIsize);
|
||||||
end
|
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
|
endmodule
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
.ORG 0x84 ; INT 21
|
.ORG 0xFF00
|
||||||
DW 0xFFFF ; Code Segment
|
|
||||||
DW PRINT_INT_HANDLE ; Program Counter
|
|
||||||
|
|
||||||
.ORG 0x0100
|
|
||||||
start:
|
start:
|
||||||
MOV SP,#STACK
|
MOV SP,#STACK
|
||||||
MOV AX,#0x0000
|
MOV AX,#0x0000
|
||||||
@ -25,16 +21,15 @@ dec [si]
|
|||||||
dec cx
|
dec cx
|
||||||
cmp CX,#0x00
|
cmp CX,#0x00
|
||||||
MOV CH,#0x9A
|
MOV CH,#0x9A
|
||||||
TEST CH,#0x70
|
inw #0x20
|
||||||
|
CMP AX,#0xABCD
|
||||||
jz WAZZ
|
jz WAZZ
|
||||||
mov ah,#2
|
mov al,#'0
|
||||||
mov dl,#'1
|
out byte #0xA5
|
||||||
int #0x21
|
|
||||||
hlt
|
hlt
|
||||||
WAZZ:
|
WAZZ:
|
||||||
mov ah,#2
|
mov al,#'1
|
||||||
mov dl,#'0
|
out byte #0xA5
|
||||||
int #0x21
|
|
||||||
hlt
|
hlt
|
||||||
TEST_:
|
TEST_:
|
||||||
ADD AX,#0xDEAD
|
ADD AX,#0xDEAD
|
||||||
@ -52,5 +47,5 @@ iret
|
|||||||
STACK:
|
STACK:
|
||||||
|
|
||||||
.ORG 0xFFF0
|
.ORG 0xFFF0
|
||||||
MOV AX,#0x0100
|
MOV AX,#0xFF00
|
||||||
JMP AX
|
JMP AX
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -25,7 +25,7 @@
|
|||||||
/** OUTPUT **/
|
/** OUTPUT **/
|
||||||
/* These are usually set at build time*/
|
/* These are usually set at build time*/
|
||||||
//`define CALCULATE_IPC
|
//`define CALCULATE_IPC
|
||||||
//`define OTUPUT_JSON_STATISTICS
|
//`define OUTPUT_JSON_STATISTICS
|
||||||
|
|
||||||
/** Optimisations **/
|
/** Optimisations **/
|
||||||
|
|
||||||
@ -34,8 +34,10 @@
|
|||||||
* for the maximum instruction size worth of bytes */
|
* for the maximum instruction size worth of bytes */
|
||||||
`define EARLY_VALID_INSTRUCTION
|
`define EARLY_VALID_INSTRUCTION
|
||||||
|
|
||||||
|
/*********** CURRENTLY DOESN'T WORK *************/
|
||||||
/* Enables the ability in BIU to pre-decode two instructions, one after the other in memory*/
|
/* Enables the ability in BIU to pre-decode two instructions, one after the other in memory*/
|
||||||
`define DOUBLE_INSTRUCTION_LOAD
|
//`define DOUBLE_INSTRUCTION_LOAD
|
||||||
|
/************************************************/
|
||||||
|
|
||||||
/* Size is in powers of two with minimal 3.
|
/* Size is in powers of two with minimal 3.
|
||||||
* 3 : 8 Bytes
|
* 3 : 8 Bytes
|
||||||
@ -45,10 +47,21 @@
|
|||||||
`define L1_CACHE_SIZE 4
|
`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 **********/
|
/********** 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 OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
`define CALCULATE_IPC
|
`define CALCULATE_IPC
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
@ -58,12 +71,12 @@
|
|||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef EARLY_VALID_INSTRUCTION
|
`ifdef EARLY_VALID_INSTRUCTION
|
||||||
`define INCLUDE_EARLY_CALC_CIRUIT
|
`define INCLUDE_EARLY_CALC_CIRCUIT
|
||||||
`define EARLY_VALID_INSTRUCTION_ 1
|
`define EARLY_VALID_INSTRUCTION_ 1
|
||||||
`else
|
`else
|
||||||
`define EARLY_VALID_INSTRUCTION_ 0
|
`define EARLY_VALID_INSTRUCTION_ 0
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef CALCULATE_IPC
|
`ifdef CALCULATE_IPC
|
||||||
`define INCLUDE_EARLY_CALC_CIRUIT
|
`define INCLUDE_EARLY_CALC_CIRCUIT
|
||||||
`endif
|
`endif
|
||||||
|
495
system/decoder.v
495
system/decoder.v
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -62,7 +62,9 @@ module decoder(
|
|||||||
reg SIMPLE_MICRO; /* use simple decodings (=0) or microcode data (=1) */
|
reg SIMPLE_MICRO; /* use simple decodings (=0) or microcode data (=1) */
|
||||||
wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry;
|
wire [`UCODE_ADDR_BITS-1:0] ucode_seq_addr_entry;
|
||||||
reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr;
|
reg [`UCODE_ADDR_BITS-1:0] ucode_seq_addr;
|
||||||
|
/* verilator lint_off UNUSEDSIGNAL */
|
||||||
wire DEPENDS_ON_PREVIOUS;
|
wire DEPENDS_ON_PREVIOUS;
|
||||||
|
/* verilator lint_on UNUSEDSIGNAL */
|
||||||
wire set_params;
|
wire set_params;
|
||||||
|
|
||||||
wire MEM_OR_IO, HALT,Wbit,memio_address_select;
|
wire MEM_OR_IO, HALT,Wbit,memio_address_select;
|
||||||
@ -74,7 +76,7 @@ wire [`EXEC_STATE_BITS-1:0] next_state;
|
|||||||
wire [`ERROR_BITS-1:0] ERROR;
|
wire [`ERROR_BITS-1:0] ERROR;
|
||||||
|
|
||||||
instruction_decode instruction_decode(
|
instruction_decode instruction_decode(
|
||||||
/* INPUT */ IF2DE_INSTRUCTION,{8'h0,EX2DE_FLAGS}
|
/* INPUT */ IF2DE_INSTRUCTION,{8'h0,EX2DE_FLAGS}, clock
|
||||||
/* MICROCODE */ ,ucode_seq_addr_entry,SIMPLE_MICRO,ucode_seq_addr
|
/* MICROCODE */ ,ucode_seq_addr_entry,SIMPLE_MICRO,ucode_seq_addr
|
||||||
/* OUTPUT */ ,DEPENDS_ON_PREVIOUS, set_params, MEM_OR_IO,ERROR, HALT
|
/* OUTPUT */ ,DEPENDS_ON_PREVIOUS, set_params, MEM_OR_IO,ERROR, HALT
|
||||||
|
|
||||||
@ -89,129 +91,103 @@ instruction_decode instruction_decode(
|
|||||||
/* */ ,reg_write_addr, reg_read_port2_addr, reg_read_port1_addr
|
/* */ ,reg_write_addr, reg_read_port2_addr, reg_read_port1_addr
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [`DE_STATE_BITS-1:0] de_state;
|
|
||||||
|
|
||||||
|
|
||||||
always @(negedge reset) begin
|
|
||||||
de_state <= `DE_HALT; //TODO: race condition ??
|
|
||||||
`ifdef CALCULATE_IPC
|
|
||||||
new_instruction<=0;
|
|
||||||
`endif
|
|
||||||
valid_exec_data<=0;
|
|
||||||
instant_response <= 0;
|
|
||||||
stalled_response <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge reset) begin
|
|
||||||
de_state <= `DE_STATE_ENTRY;
|
|
||||||
/* need early init */
|
|
||||||
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
|
||||||
SIMPLE_MICRO <= 0;
|
|
||||||
owe_set_init <= 0;
|
|
||||||
set_initial_values<=0;
|
|
||||||
wait_exec<=0;
|
|
||||||
first_ucode <= 0;
|
|
||||||
HALT_LATCHED <= 0;
|
|
||||||
ERROR_LATCHED <= `ERROR_BITS'h0;
|
|
||||||
VALID_INSTRUCTION_ACK <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
wire [2:0] instr_end;
|
wire [2:0] instr_end;
|
||||||
InstrSize InstrSize({IF2DE_INSTRUCTION[31:24],IF2DE_INSTRUCTION[21:19]},instr_end);
|
InstrSize InstrSize({IF2DE_INSTRUCTION[31:24],IF2DE_INSTRUCTION[21:19]},instr_end);
|
||||||
|
|
||||||
reg owe_set_init;
|
reg owe_set_init;
|
||||||
|
|
||||||
//TODO: Why do we need to make a local copy on a register for the code inside the always @(next_state) to read it?
|
reg [1:0] wait_;
|
||||||
// For some reason the raw VALID_INSTRUCTION signal reads always 1 and it has something to do with the block
|
|
||||||
// being triggered by next_exec
|
|
||||||
reg VALID_INSTRUCTION_lc;
|
|
||||||
always @(VALID_INSTRUCTION)begin VALID_INSTRUCTION_lc<=VALID_INSTRUCTION; end
|
|
||||||
|
|
||||||
reg instant_response, stalled_response;
|
always @(posedge clock)begin
|
||||||
reg wait_exec;
|
if(reset==0)begin
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
always @(next_exec) begin
|
new_instruction<=0;
|
||||||
de_state<=`DE_STATE_ENTRY;
|
`endif
|
||||||
if ( VALID_INSTRUCTION_lc == 1 && DEPENDS_ON_PREVIOUS == 0 && ucode_seq_addr_entry==`UCODE_NO_INSTRUCTION) begin
|
valid_exec_data<=0;
|
||||||
instant_response <= !instant_response;
|
ucode_seq_addr <= `UCODE_NO_INSTRUCTION;
|
||||||
|
SIMPLE_MICRO <= 0;
|
||||||
|
owe_set_init <= 0;
|
||||||
|
set_initial_values<=0;
|
||||||
|
first_ucode <= 0;
|
||||||
|
HALT_LATCHED <= 0;
|
||||||
|
ERROR_LATCHED <= `ERROR_BITS'h0;
|
||||||
|
VALID_INSTRUCTION_ACK <= 0;
|
||||||
|
wait_<=0;
|
||||||
end else begin
|
end else begin
|
||||||
wait_exec<=0;
|
if(wait_==2) begin
|
||||||
|
//`define LATCH(VAR) VAR_LATCHED <= VAR; //TODO would this work?
|
||||||
|
IN_MOD_LATCHED <= IN_MOD;
|
||||||
|
OUT_MOD_LATCHED <= OUT_MOD;
|
||||||
|
RM_LATCHED <= RM;
|
||||||
|
MEM_OR_IO_LATCHED <= MEM_OR_IO;
|
||||||
|
PARAM1_LATCHED <= PARAM1;
|
||||||
|
PARAM2_LATCHED <= PARAM2;
|
||||||
|
ALU_OP_LATCHED <= ALU_OP;
|
||||||
|
in_alu_sel1_LATCHED <= in_alu_sel1;
|
||||||
|
in_alu_sel2_LATCHED <= in_alu_sel2;
|
||||||
|
reg_read_port1_addr_LATCHED <= reg_read_port1_addr;
|
||||||
|
reg_read_port2_addr_LATCHED <= reg_read_port2_addr;
|
||||||
|
reg_write_addr_LATCHED <= reg_write_addr;
|
||||||
|
Wbit_LATCHED <= Wbit;
|
||||||
|
ERROR_LATCHED <= ERROR;
|
||||||
|
HALT_LATCHED <= HALT;
|
||||||
|
next_state_LATCHED <= next_state;
|
||||||
|
memio_address_select_LATCHED <= memio_address_select;
|
||||||
|
|
||||||
|
if ( (ucode_seq_addr==`UCODE_NO_INSTRUCTION) && (ucode_seq_addr_entry!=`UCODE_NO_INSTRUCTION) )begin
|
||||||
|
/* switch to microcode decoding */
|
||||||
|
ucode_seq_addr <= ucode_seq_addr_entry;
|
||||||
|
SIMPLE_MICRO <= 1;
|
||||||
|
first_ucode <= 1;
|
||||||
|
set_initial_values <= 1;
|
||||||
|
valid_exec_data <= 0;
|
||||||
|
wait_<=1;
|
||||||
|
end else begin
|
||||||
|
if(SIMPLE_MICRO==0||first_ucode==1||owe_set_init==1)begin
|
||||||
|
first_ucode <= 0;
|
||||||
|
/* This runs at the start of the execution of an 8086 instruction */
|
||||||
|
`ifdef DEBUG_PC_ADDRESS
|
||||||
|
$display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,IF2DE_INSTRUCTION);
|
||||||
|
`endif
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
new_instruction <= !new_instruction;
|
||||||
|
`endif
|
||||||
|
owe_set_init<=0;
|
||||||
|
ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end};
|
||||||
|
VALID_INSTRUCTION_ACK <= 1;
|
||||||
|
end
|
||||||
|
if(set_params)begin
|
||||||
|
set_initial_values <= 1;
|
||||||
|
end
|
||||||
|
/* This runs at the start of each execution cycle, with microcode this is more than once per 8086 instruction */
|
||||||
|
valid_exec_data<=1;
|
||||||
|
wait_<=1;
|
||||||
|
if( SIMPLE_MICRO == 1 ) begin
|
||||||
|
ucode_seq_addr <= ucode_seq_addr_entry; /*Reused for next address*/
|
||||||
|
if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin
|
||||||
|
/*Finished microcode*/
|
||||||
|
SIMPLE_MICRO <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end else if(wait_!=0) begin
|
||||||
|
set_initial_values <= 0;
|
||||||
|
wait_<=0;
|
||||||
|
VALID_INSTRUCTION_ACK<=0;
|
||||||
|
end else if(next_exec==1'b1)begin
|
||||||
|
if ( ( VALID_INSTRUCTION == 1 || SIMPLE_MICRO == 1 ) /*&& DEPENDS_ON_PREVIOUS == 0 && ucode_seq_addr_entry==`UCODE_NO_INSTRUCTION*/) begin
|
||||||
|
wait_<=2;
|
||||||
|
end else
|
||||||
|
valid_exec_data<=0;
|
||||||
|
end else
|
||||||
|
valid_exec_data<=0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
reg first_ucode;
|
reg first_ucode;
|
||||||
|
|
||||||
always @(instant_response or stalled_response) begin
|
|
||||||
//`define LATCH(VAR) VAR_LATCHED <= VAR; //TODO would this work?
|
|
||||||
IN_MOD_LATCHED <= IN_MOD;
|
|
||||||
OUT_MOD_LATCHED <= OUT_MOD;
|
|
||||||
RM_LATCHED <= RM;
|
|
||||||
MEM_OR_IO_LATCHED <= MEM_OR_IO;
|
|
||||||
PARAM1_LATCHED <= PARAM1;
|
|
||||||
PARAM2_LATCHED <= PARAM2;
|
|
||||||
ALU_OP_LATCHED <= ALU_OP;
|
|
||||||
in_alu_sel1_LATCHED <= in_alu_sel1;
|
|
||||||
in_alu_sel2_LATCHED <= in_alu_sel2;
|
|
||||||
reg_read_port1_addr_LATCHED <= reg_read_port1_addr;
|
|
||||||
reg_read_port2_addr_LATCHED <= reg_read_port2_addr;
|
|
||||||
reg_write_addr_LATCHED <= reg_write_addr;
|
|
||||||
Wbit_LATCHED <= Wbit;
|
|
||||||
ERROR_LATCHED <= ERROR;
|
|
||||||
HALT_LATCHED <= HALT;
|
|
||||||
next_state_LATCHED <= next_state;
|
|
||||||
memio_address_select_LATCHED <= memio_address_select;
|
|
||||||
|
|
||||||
if ( (ucode_seq_addr==`UCODE_NO_INSTRUCTION) && (ucode_seq_addr_entry!=`UCODE_NO_INSTRUCTION) )begin
|
|
||||||
/* switch to microcode decoding */
|
|
||||||
ucode_seq_addr <= ucode_seq_addr_entry;
|
|
||||||
SIMPLE_MICRO <= 1;
|
|
||||||
first_ucode <= 1;
|
|
||||||
set_initial_values <= !set_initial_values;
|
|
||||||
/*keep de_state the same and rerun decode this time with all the data from the microcode rom*/
|
|
||||||
end else begin
|
|
||||||
if(SIMPLE_MICRO==0||first_ucode==1||owe_set_init==1)begin
|
|
||||||
first_ucode <= 0;
|
|
||||||
/* This runs at the start of the execution of an 8086 instruction */
|
|
||||||
`ifdef DEBUG_PC_ADDRESS
|
|
||||||
$display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,IF2DE_INSTRUCTION);
|
|
||||||
`endif
|
|
||||||
`ifdef CALCULATE_IPC
|
|
||||||
new_instruction <= !new_instruction;
|
|
||||||
`endif
|
|
||||||
owe_set_init<=0;
|
|
||||||
ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end};
|
|
||||||
VALID_INSTRUCTION_ACK <= !VALID_INSTRUCTION_ACK;
|
|
||||||
end
|
|
||||||
if(set_params)begin
|
|
||||||
set_initial_values <= !set_initial_values;
|
|
||||||
end
|
|
||||||
/* This runs at the start of each execution cycle, with microcode this is more than once per 8086 instruction */
|
|
||||||
valid_exec_data<=!valid_exec_data;
|
|
||||||
if( SIMPLE_MICRO == 1 ) begin
|
|
||||||
ucode_seq_addr <= ucode_seq_addr_entry; /*Reused for next address*/
|
|
||||||
if( ucode_seq_addr_entry == `UCODE_NO_INSTRUCTION )begin
|
|
||||||
/*Finished microcode*/
|
|
||||||
SIMPLE_MICRO <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
wait_exec<=1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clock) begin
|
|
||||||
case(de_state)
|
|
||||||
`DE_STATE_ENTRY:begin
|
|
||||||
if ( ( VALID_INSTRUCTION==1 || SIMPLE_MICRO == 1 ) && wait_exec==0) begin
|
|
||||||
stalled_response <= !stalled_response;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
`DE_HALT:begin
|
|
||||||
end
|
|
||||||
default:begin
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
@ -224,6 +200,7 @@ module microcode(
|
|||||||
);
|
);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
`ifndef YOSYS
|
||||||
string ucode_path;
|
string ucode_path;
|
||||||
if($value$plusargs("MICROCODE=%s",ucode_path))begin
|
if($value$plusargs("MICROCODE=%s",ucode_path))begin
|
||||||
$readmemb(ucode_path,ucode_rom,0,`UCODE_SIZE-1);
|
$readmemb(ucode_path,ucode_rom,0,`UCODE_SIZE-1);
|
||||||
@ -231,6 +208,10 @@ initial begin
|
|||||||
$display("Please supply microcode rom file as a runtime vvp argument +MICROCODE=<path>");
|
$display("Please supply microcode rom file as a runtime vvp argument +MICROCODE=<path>");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
`else
|
||||||
|
//TODO: don't have it hard coded
|
||||||
|
$readmemb("simplified_ucode.txt",ucode_rom,0,`UCODE_SIZE-1);
|
||||||
|
`endif
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [`UCODE_DATA_BITS-1:0] ucode_rom [ 0:`UCODE_SIZE-1 ];
|
reg [`UCODE_DATA_BITS-1:0] ucode_rom [ 0:`UCODE_SIZE-1 ];
|
||||||
@ -240,7 +221,9 @@ assign DATA=ucode_rom[ADDR];
|
|||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module instruction_decode(
|
module instruction_decode(
|
||||||
/* INPUTS */ input wire [31:0] INSTRUCTION,input wire [15:0] FLAGS
|
/* verilator lint_off UNUSEDSIGNAL */
|
||||||
|
/* INPUTS */ input wire [31:0] INSTRUCTION,input wire [15:0] FLAGS,input clock
|
||||||
|
/* verilator lint_on UNUSEDSIGNAL */
|
||||||
/* MICROCODE */ ,output reg [`UCODE_ADDR_BITS-1:0] seq_addr_entry, input wire SIMPLE_MICRO, input wire [`UCODE_ADDR_BITS-1:0] seq_addr_input
|
/* MICROCODE */ ,output reg [`UCODE_ADDR_BITS-1:0] seq_addr_entry, input wire SIMPLE_MICRO, input wire [`UCODE_ADDR_BITS-1:0] seq_addr_input
|
||||||
/* OUTPUT */ ,output reg DEPENDS_ON_PREVIOUS, output reg set_params,output reg MEM_OR_IO, output reg [`ERROR_BITS-1:0] ERROR, output reg HALT
|
/* OUTPUT */ ,output reg DEPENDS_ON_PREVIOUS, output reg set_params,output reg MEM_OR_IO, output reg [`ERROR_BITS-1:0] ERROR, output reg HALT
|
||||||
|
|
||||||
@ -265,16 +248,10 @@ wire [`UCODE_DATA_BITS-1:0] ucode_data;
|
|||||||
|
|
||||||
microcode ucode(seq_addr_input,ucode_data);
|
microcode ucode(seq_addr_input,ucode_data);
|
||||||
|
|
||||||
`define invalid_instruction next_state=`EXEC_WAIT;ERROR<=`ERR_UNIMPL_INSTRUCTION;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
`define invalid_instruction next_state=`EXEC_WAIT;ERROR<=`ERR_UNIMPL_INSTRUCTION;HALT<=0;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;opcode_size=0;DEPENDS_ON_PREVIOUS<=0;
|
||||||
`define unimpl_addressing_mode next_state=`EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
`define unimpl_addressing_mode next_state=`EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;HALT<=0;IN_MOD=3'b011;seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||||
|
`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO<=0;
|
||||||
|
`define normal_microcoded ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO<=0;
|
||||||
//TODO: A possible optimisation for instruction with 8bit parameter and
|
|
||||||
//opcode_size=0 would be to set PARAM1 here instead of sending execution over
|
|
||||||
//to EXEC_DE_LOAD_8_PARAM
|
|
||||||
|
|
||||||
`define normal_instruction seq_addr_entry<=`UCODE_NO_INSTRUCTION;ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO=0;
|
|
||||||
`define normal_microcoded ERROR<=`ERR_NO_ERROR;HALT<=0;MEM_OR_IO=0;
|
|
||||||
|
|
||||||
reg [1:0] PARAM_ACTION;
|
reg [1:0] PARAM_ACTION;
|
||||||
`define NO_LOAD 2'b00
|
`define NO_LOAD 2'b00
|
||||||
@ -287,7 +264,7 @@ reg Sbit,opcode_size;
|
|||||||
// then branching off of that instead of the raw bits. otherwise the code
|
// then branching off of that instead of the raw bits. otherwise the code
|
||||||
// would be identical
|
// would be identical
|
||||||
/* verilator lint_off BLKSEQ */
|
/* verilator lint_off BLKSEQ */
|
||||||
always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
always @( posedge clock ) begin
|
||||||
set_params = 1;
|
set_params = 1;
|
||||||
PARAM_ACTION = `NO_LOAD;
|
PARAM_ACTION = `NO_LOAD;
|
||||||
Sbit=0;//TODO: If no Sbit we assume it's 0,right?
|
Sbit=0;//TODO: If no Sbit we assume it's 0,right?
|
||||||
@ -298,21 +275,22 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
/* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/
|
/* 0 0 0 0 0 1 0 W | DATA | DATA if W |*/
|
||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=INSTRUCTION[24:24];
|
Wbit=INSTRUCTION[24:24];
|
||||||
|
Sbit=0;
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
reg_read_port2_addr={Wbit,3'b000};
|
reg_read_port2_addr<={Wbit,3'b000};
|
||||||
reg_write_addr={Wbit,3'b000};
|
reg_write_addr<={Wbit,3'b000};
|
||||||
ALU_OP=`ALU_OP_ADD;
|
ALU_OP<=`ALU_OP_ADD;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
if(Wbit)
|
if(Wbit)
|
||||||
PARAM_ACTION=`LOAD_16;
|
PARAM_ACTION=`LOAD_16;
|
||||||
else
|
else
|
||||||
PARAM_ACTION=`LOAD_8;
|
PARAM_ACTION=`LOAD_8;
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
11'b1000_00??_101, /* SUB */
|
11'b1000_00??_101, /* SUB */
|
||||||
11'b1000_00??_000 : /* ADD */ begin
|
11'b1000_00??_000 : /* ADD */ begin
|
||||||
@ -328,13 +306,13 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
if(IN_MOD==3'b011)begin
|
if(IN_MOD==3'b011)begin
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
reg_write_addr={Wbit,RM};
|
reg_write_addr<={Wbit,RM};
|
||||||
end else begin
|
end else begin
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
end
|
end
|
||||||
OUT_MOD=IN_MOD;
|
OUT_MOD=IN_MOD;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
case({Sbit,Wbit}) // TODO: Isn't this supposed to be just a LOAD_8?
|
case({Sbit,Wbit}) // TODO: Isn't this supposed to be just a LOAD_8?
|
||||||
2'b00,2'b11:begin
|
2'b00,2'b11:begin
|
||||||
@ -348,15 +326,15 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
case(INSTRUCTION[21:19])
|
case(INSTRUCTION[21:19])
|
||||||
3'b000: ALU_OP=`ALU_OP_ADD;
|
3'b000: ALU_OP<=`ALU_OP_ADD;
|
||||||
3'b101: ALU_OP=`ALU_OP_SUB_REVERSE;
|
3'b101: ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||||
default:begin
|
default:begin
|
||||||
/*Should be impossible*/
|
/*Should be impossible*/
|
||||||
`invalid_instruction
|
`invalid_instruction
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
11'b1000_00??_111 : begin
|
11'b1000_00??_111 : begin
|
||||||
/* CMP - compare Immediate with register / memory */
|
/* CMP - compare Immediate with register / memory */
|
||||||
@ -371,13 +349,13 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
OUT_MOD=3'b100;
|
OUT_MOD=3'b100;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
ALU_OP=`ALU_OP_SUB_REVERSE;
|
ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
if(IN_MOD==3'b011)begin
|
if(IN_MOD==3'b011)begin
|
||||||
/*compare register with param*/
|
/*compare register with param*/
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end else begin
|
end else begin
|
||||||
/*compare register indirect access
|
/*compare register indirect access
|
||||||
@ -391,7 +369,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
else
|
else
|
||||||
PARAM_ACTION=`LOAD_8;
|
PARAM_ACTION=`LOAD_8;
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
11'b1011_????_??? : begin
|
11'b1011_????_??? : begin
|
||||||
/* MOV - Move Immediate byte to register */
|
/* MOV - Move Immediate byte to register */
|
||||||
@ -402,16 +380,16 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
reg_write_addr={Wbit,INSTRUCTION[26:24]};
|
reg_write_addr<={Wbit,INSTRUCTION[26:24]};
|
||||||
if(Wbit)
|
if(Wbit)
|
||||||
PARAM_ACTION=`LOAD_16;
|
PARAM_ACTION=`LOAD_16;
|
||||||
else
|
else
|
||||||
PARAM_ACTION=`LOAD_8;
|
PARAM_ACTION=`LOAD_8;
|
||||||
PARAM2=0;
|
PARAM2=0;
|
||||||
ALU_OP=`ALU_OP_ADD;
|
ALU_OP<=`ALU_OP_ADD;
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -422,15 +400,15 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
RM=INSTRUCTION[18:16];
|
RM=INSTRUCTION[18:16];
|
||||||
Wbit=INSTRUCTION[24:24];
|
Wbit=INSTRUCTION[24:24];
|
||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
PARAM1=0;
|
PARAM1<=0;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
if(INSTRUCTION[25:25] == 1)begin
|
if(INSTRUCTION[25:25] == 1)begin
|
||||||
/* Mem/Reg to reg */
|
/* Mem/Reg to reg */
|
||||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||||
if(IN_MOD==3'b011)begin
|
if(IN_MOD==3'b011)begin
|
||||||
/*Reg to Reg*/
|
/*Reg to Reg*/
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end else begin
|
end else begin
|
||||||
/*Mem to Reg*/
|
/*Mem to Reg*/
|
||||||
@ -438,7 +416,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
next_state=`EXEC_MEMIO_READ;
|
next_state=`EXEC_MEMIO_READ;
|
||||||
end
|
end
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
reg_write_addr={Wbit,INSTRUCTION[21:19]};
|
reg_write_addr<={Wbit,INSTRUCTION[21:19]};
|
||||||
end else begin
|
end else begin
|
||||||
/* Reg to Mem/Reg */
|
/* Reg to Mem/Reg */
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
@ -446,18 +424,18 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
if(IN_MOD==3'b011)begin
|
if(IN_MOD==3'b011)begin
|
||||||
/*Reg to Reg*/
|
/*Reg to Reg*/
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_write_addr={Wbit,RM};
|
reg_write_addr<={Wbit,RM};
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end else begin
|
end else begin
|
||||||
/*Reg to Mem*/
|
/*Reg to Mem*/
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
next_state=`EXEC_DE_LOAD_REG_TO_PARAM;
|
next_state=`EXEC_DE_LOAD_REG_TO_PARAM;
|
||||||
end
|
end
|
||||||
reg_read_port2_addr={Wbit,INSTRUCTION[21:19]};
|
reg_read_port2_addr<={Wbit,INSTRUCTION[21:19]};
|
||||||
end
|
end
|
||||||
ALU_OP=`ALU_OP_ADD;
|
ALU_OP<=`ALU_OP_ADD;
|
||||||
|
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -471,17 +449,17 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu_sel1=2'b01;
|
in_alu_sel1=2'b01;
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
OUT_MOD=3'b011;
|
OUT_MOD=3'b011;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
PARAM2=1;
|
PARAM2=1;
|
||||||
reg_read_port1_addr={1'b1,INSTRUCTION[26:24]};
|
reg_read_port1_addr<={1'b1,INSTRUCTION[26:24]};
|
||||||
reg_write_addr={1'b1,INSTRUCTION[26:24]};
|
reg_write_addr<={1'b1,INSTRUCTION[26:24]};
|
||||||
if(INSTRUCTION[27:27]==0)
|
if(INSTRUCTION[27:27]==0)
|
||||||
ALU_OP=`ALU_OP_ADD;
|
ALU_OP<=`ALU_OP_ADD;
|
||||||
else
|
else
|
||||||
ALU_OP=`ALU_OP_SUB;
|
ALU_OP<=`ALU_OP_SUB;
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -496,33 +474,41 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
RM=INSTRUCTION[18:16];
|
RM=INSTRUCTION[18:16];
|
||||||
in_alu_sel2=(IN_MOD==3'b011)? 2'b01 : 2'b00;
|
in_alu_sel2=(IN_MOD==3'b011)? 2'b01 : 2'b00;
|
||||||
in_alu_sel1=2'b00;/* number 1 */
|
in_alu_sel1=2'b00;/* number 1 */
|
||||||
PARAM1=1;
|
PARAM1<=16'd1;
|
||||||
OUT_MOD=IN_MOD;
|
OUT_MOD=IN_MOD;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
|
|
||||||
/*in case IN_MOD=011 */
|
/*in case IN_MOD=011 */
|
||||||
reg_read_port2_addr={1'b0,RM};
|
reg_read_port2_addr<={1'b0,RM};
|
||||||
reg_write_addr={1'b0,RM};
|
reg_write_addr<={1'b0,RM};
|
||||||
|
|
||||||
ALU_OP=(INSTRUCTION[19:19]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
ALU_OP<=(INSTRUCTION[19:19]==1)?`ALU_OP_SUB_REVERSE:`ALU_OP_ADD;
|
||||||
if ( IN_MOD == 3'b011 )
|
if ( IN_MOD == 3'b011 )
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
else
|
else
|
||||||
next_state=`EXEC_MEMIO_READ;
|
next_state=`EXEC_MEMIO_READ;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
11'b1111_0100_??? : begin
|
11'b1111_0100_??? : begin
|
||||||
/* HLT - Halt */
|
/* HLT - Halt */
|
||||||
/* 1 1 1 1 0 1 0 0 | */
|
/* 1 1 1 1 0 1 0 0 | */
|
||||||
opcode_size=0;
|
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
HALT<=1;
|
HALT<=1;
|
||||||
ERROR<=`ERR_NO_ERROR;
|
ERROR<=`ERR_NO_ERROR;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||||
next_state=`EXEC_WAIT;
|
|
||||||
|
opcode_size=0;
|
||||||
|
Wbit=1;
|
||||||
|
in_alu_sel1=2'b10;
|
||||||
|
in_alu_sel2=2'b00;
|
||||||
|
PARAM2=16'hFFFF;
|
||||||
|
ALU_OP<=`ALU_OP_ADD_SIGNED_B;
|
||||||
|
OUT_MOD=3'b101;
|
||||||
|
MEM_OR_IO<=0;
|
||||||
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -537,18 +523,17 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,3'b000};
|
reg_read_port2_addr<={Wbit,3'b000};
|
||||||
OUT_MOD=3'b100;
|
OUT_MOD=3'b100;
|
||||||
ALU_OP=`ALU_OP_SUB_REVERSE;
|
ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
if(Wbit==1)
|
if(Wbit==1)
|
||||||
PARAM_ACTION=`LOAD_16;
|
PARAM_ACTION=`LOAD_16;
|
||||||
else begin
|
else begin
|
||||||
PARAM_ACTION=`LOAD_8;
|
PARAM_ACTION=`LOAD_8;
|
||||||
//PARAM1[7:0]=INSTRUCTION[7:0]; TODO:needed?
|
|
||||||
end
|
end
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -566,8 +551,8 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu_sel1=2'b10;
|
in_alu_sel1=2'b10;
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
||||||
ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
ALU_OP<=`ALU_OP_ADD_SIGNED_B;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
OUT_MOD=3'b101;
|
OUT_MOD=3'b101;
|
||||||
case(INSTRUCTION[27:25])
|
case(INSTRUCTION[27:25])
|
||||||
3'b000: begin
|
3'b000: begin
|
||||||
@ -577,7 +562,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
else begin
|
else begin
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end
|
end
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
3'b010: begin
|
3'b010: begin
|
||||||
/* Jump on (not) Zero */
|
/* Jump on (not) Zero */
|
||||||
@ -585,7 +570,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||||
else
|
else
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
3'b100: begin
|
3'b100: begin
|
||||||
/* Jump on (not) Sign */
|
/* Jump on (not) Sign */
|
||||||
@ -593,7 +578,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||||
else
|
else
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
3'b101: begin
|
3'b101: begin
|
||||||
/* Jump on (not) Parity */
|
/* Jump on (not) Parity */
|
||||||
@ -601,7 +586,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||||
else
|
else
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
3'b001: begin
|
3'b001: begin
|
||||||
/* Jump on (not) Carry */
|
/* Jump on (not) Carry */
|
||||||
@ -609,10 +594,10 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
next_state=`EXEC_NEXT_INSTRUCTION;
|
next_state=`EXEC_NEXT_INSTRUCTION;
|
||||||
else
|
else
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`invalid_instruction; /*We don't support that condition*/
|
`invalid_instruction /*We don't support that condition*/
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
DEPENDS_ON_PREVIOUS<=1;
|
DEPENDS_ON_PREVIOUS<=1;
|
||||||
@ -626,11 +611,11 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
in_alu_sel1=2'b10;
|
in_alu_sel1=2'b10;
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
PARAM2={{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
||||||
ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
ALU_OP<=`ALU_OP_ADD_SIGNED_B;
|
||||||
OUT_MOD=3'b101;
|
OUT_MOD=3'b101;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -656,7 +641,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM1=2;
|
PARAM1<=2;
|
||||||
seq_addr_entry<=`UCODE_RET_ENTRY;
|
seq_addr_entry<=`UCODE_RET_ENTRY;
|
||||||
`normal_microcoded
|
`normal_microcoded
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
@ -682,7 +667,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM2=2;
|
PARAM2=2;
|
||||||
reg_read_port2_addr={1'b1,INSTRUCTION[26:24]};
|
reg_read_port2_addr<={1'b1,INSTRUCTION[26:24]};
|
||||||
seq_addr_entry<=`UCODE_PUSH_ENTRY;
|
seq_addr_entry<=`UCODE_PUSH_ENTRY;
|
||||||
`normal_microcoded
|
`normal_microcoded
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
@ -695,18 +680,18 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Wbit=INSTRUCTION[24:24];
|
Wbit=INSTRUCTION[24:24];
|
||||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||||
RM={INSTRUCTION[18:16]};
|
RM={INSTRUCTION[18:16]};
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
if(Wbit==1)begin
|
if(Wbit==1)begin
|
||||||
PARAM_ACTION=`LOAD_16;
|
PARAM_ACTION=`LOAD_16;
|
||||||
end else begin
|
end else begin
|
||||||
PARAM_ACTION=`LOAD_8;
|
PARAM_ACTION=`LOAD_8;
|
||||||
end
|
end
|
||||||
in_alu_sel1=2'b00; /* PARAM1 */
|
in_alu_sel1=2'b00; /* PARAM1 */
|
||||||
ALU_OP=`ALU_OP_AND;
|
ALU_OP<=`ALU_OP_AND;
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b011:begin
|
3'b011:begin
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
@ -715,7 +700,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
OUT_MOD=3'b100;/*NULL*/
|
OUT_MOD=3'b100;/*NULL*/
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -726,7 +711,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Wbit=INSTRUCTION[24:24];
|
Wbit=INSTRUCTION[24:24];
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
RM=3'b000;
|
RM=3'b000;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
if(Wbit==1)begin
|
if(Wbit==1)begin
|
||||||
PARAM_ACTION=`LOAD_16;
|
PARAM_ACTION=`LOAD_16;
|
||||||
end else begin
|
end else begin
|
||||||
@ -734,11 +719,11 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
in_alu_sel1=2'b00; /* PARAM1 */
|
in_alu_sel1=2'b00; /* PARAM1 */
|
||||||
ALU_OP=`ALU_OP_AND;
|
ALU_OP<=`ALU_OP_AND;
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
OUT_MOD=3'b100;/*NULL*/
|
OUT_MOD=3'b100;/*NULL*/
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -748,8 +733,8 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM1=2;
|
PARAM1<=2;
|
||||||
reg_write_addr={1'b1,INSTRUCTION[26:24]};
|
reg_write_addr<={1'b1,INSTRUCTION[26:24]};
|
||||||
seq_addr_entry<=`UCODE_POP_ENTRY;
|
seq_addr_entry<=`UCODE_POP_ENTRY;
|
||||||
`normal_microcoded
|
`normal_microcoded
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
@ -762,19 +747,19 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Wbit=1;
|
Wbit=1;
|
||||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||||
RM=INSTRUCTION[18:16];
|
RM=INSTRUCTION[18:16];
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
in_alu_sel1=2'b11;
|
in_alu_sel1=2'b11;
|
||||||
if (IN_MOD==3'b011)begin
|
if (IN_MOD==3'b011)begin
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end else begin
|
end else begin
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
next_state=`EXEC_MEMIO_READ;
|
next_state=`EXEC_MEMIO_READ;
|
||||||
end
|
end
|
||||||
ALU_OP=`ALU_OP_ADD;
|
ALU_OP<=`ALU_OP_ADD;
|
||||||
OUT_MOD=3'b101;
|
OUT_MOD=3'b101;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
end
|
end
|
||||||
@ -785,7 +770,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
opcode_size=1;
|
opcode_size=1;
|
||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
in_alu_sel2=2'b11;
|
in_alu_sel2=2'b11;
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
if(Wbit==1)begin
|
if(Wbit==1)begin
|
||||||
PARAM_ACTION=`LOAD_16;
|
PARAM_ACTION=`LOAD_16;
|
||||||
end else begin
|
end else begin
|
||||||
@ -795,7 +780,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
OUT_MOD={1'b0,INSTRUCTION[23:22]};
|
OUT_MOD={1'b0,INSTRUCTION[23:22]};
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
RM=INSTRUCTION[18:16];
|
RM=INSTRUCTION[18:16];
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
@ -826,15 +811,17 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
in_alu_sel1=2'b00;
|
in_alu_sel1=2'b00;
|
||||||
in_alu_sel2=2'b11;
|
in_alu_sel2=2'b11;
|
||||||
reg_read_port1_addr={Wbit,3'b000};
|
reg_read_port1_addr<={Wbit,3'b000};
|
||||||
PARAM_ACTION=`LOAD_8;
|
PARAM_ACTION=`LOAD_8;
|
||||||
MEM_OR_IO=1;
|
|
||||||
HALT <= 0;
|
HALT <= 0;
|
||||||
PARAM1=0;
|
PARAM1<=0;
|
||||||
OUT_MOD={3'b000};
|
OUT_MOD={3'b000};
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
|
`normal_instruction
|
||||||
|
MEM_OR_IO<=1;
|
||||||
|
ALU_OP<=`ALU_OP_ADD;
|
||||||
end
|
end
|
||||||
11'b1100_1111_???:begin
|
11'b1100_1111_???:begin
|
||||||
/* IRET - Return from interrupt */
|
/* IRET - Return from interrupt */
|
||||||
@ -844,7 +831,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
opcode_size=0;
|
opcode_size=0;
|
||||||
Wbit=1;
|
Wbit=1;
|
||||||
Sbit=0;
|
Sbit=0;
|
||||||
PARAM1=2;
|
PARAM1<=2;
|
||||||
seq_addr_entry<=`UCODE_RET_ENTRY;
|
seq_addr_entry<=`UCODE_RET_ENTRY;
|
||||||
`normal_microcoded
|
`normal_microcoded
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
@ -859,7 +846,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
Wbit=INSTRUCTION[24:24];
|
Wbit=INSTRUCTION[24:24];
|
||||||
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
IN_MOD={1'b0,INSTRUCTION[23:22]};
|
||||||
RM={INSTRUCTION[18:16]};
|
RM={INSTRUCTION[18:16]};
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
if(Wbit==1)begin
|
if(Wbit==1)begin
|
||||||
PARAM_ACTION=`LOAD_16;
|
PARAM_ACTION=`LOAD_16;
|
||||||
end else begin
|
end else begin
|
||||||
@ -867,15 +854,15 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
end
|
end
|
||||||
in_alu_sel1=2'b00; /* PARAM1 */
|
in_alu_sel1=2'b00; /* PARAM1 */
|
||||||
case(INSTRUCTION[21:19])
|
case(INSTRUCTION[21:19])
|
||||||
3'b100: ALU_OP=`ALU_OP_AND;
|
3'b100: ALU_OP<=`ALU_OP_AND;
|
||||||
3'b001: ALU_OP=`ALU_OP_OR;
|
3'b001: ALU_OP<=`ALU_OP_OR;
|
||||||
default:begin end
|
default:begin end
|
||||||
endcase
|
endcase
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b011:begin
|
3'b011:begin
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
reg_write_addr={Wbit,RM};
|
reg_write_addr<={Wbit,RM};
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end
|
end
|
||||||
default:begin
|
default:begin
|
||||||
@ -886,7 +873,7 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
OUT_MOD=IN_MOD;
|
OUT_MOD=IN_MOD;
|
||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end
|
end
|
||||||
11'b0000_00??_???,11'b0010_10??_???,11'b0011_10??_???:begin
|
11'b0000_00??_???,11'b0010_10??_???,11'b0011_10??_???:begin
|
||||||
/* CMP - Compare Register/memory and register */
|
/* CMP - Compare Register/memory and register */
|
||||||
@ -901,11 +888,11 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
IN_MOD=3'b011;
|
IN_MOD=3'b011;
|
||||||
RM=INSTRUCTION[18:16];
|
RM=INSTRUCTION[18:16];
|
||||||
in_alu_sel1=2'b01;//constantly register
|
in_alu_sel1=2'b01;//constantly register
|
||||||
reg_read_port1_addr={Wbit,INSTRUCTION[21:19]};
|
reg_read_port1_addr<={Wbit,INSTRUCTION[21:19]};
|
||||||
if(IN_MOD==3'b011)begin
|
if(IN_MOD==3'b011)begin
|
||||||
in_alu_sel2=2'b01;
|
in_alu_sel2=2'b01;
|
||||||
reg_read_port2_addr={Wbit,RM};
|
reg_read_port2_addr<={Wbit,RM};
|
||||||
reg_write_addr={Wbit,RM};
|
reg_write_addr<={Wbit,RM};
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
end else begin
|
end else begin
|
||||||
in_alu_sel2=2'b00;
|
in_alu_sel2=2'b00;
|
||||||
@ -915,12 +902,12 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
PARAM_ACTION=`LOAD_8;
|
PARAM_ACTION=`LOAD_8;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
memio_address_select=0;
|
memio_address_select=0;
|
||||||
case (INSTRUCTION[29:26])
|
case (INSTRUCTION[29:26])
|
||||||
4'b0000: ALU_OP=`ALU_OP_ADD;
|
4'b0000: ALU_OP<=`ALU_OP_ADD;
|
||||||
4'b1010: ALU_OP=`ALU_OP_SUB;
|
4'b1010: ALU_OP<=`ALU_OP_SUB;
|
||||||
4'b1110: ALU_OP=`ALU_OP_SUB_REVERSE;
|
4'b1110: ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
case (INSTRUCTION[29:26])
|
case (INSTRUCTION[29:26])
|
||||||
@ -932,11 +919,33 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
DEPENDS_ON_PREVIOUS<=0;
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
next_state=`EXEC_WRITE_ENTRY;
|
next_state=`EXEC_WRITE_ENTRY;
|
||||||
if(INSTRUCTION[25:25]==1'b0) begin
|
if(INSTRUCTION[25:25]==1'b0) begin
|
||||||
`normal_instruction;
|
`normal_instruction
|
||||||
end else begin
|
end else begin
|
||||||
`unimpl_addressing_mode;
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
11'b1110_010?_???:begin
|
||||||
|
/* IN - Read from a defined port to AL or AX */
|
||||||
|
/* | 1 1 1 0 0 1 0 W | DATA 8 | */
|
||||||
|
memio_address_select=1;
|
||||||
|
OUT_MOD=3'b011;
|
||||||
|
Wbit=INSTRUCTION[24:24];
|
||||||
|
opcode_size=0;
|
||||||
|
in_alu_sel1=2'b00;
|
||||||
|
in_alu_sel2=2'b00;
|
||||||
|
PARAM2= {8'b0,INSTRUCTION[23:16]}; //TODO: this is a bit of a hack, i should've used PARAM_ACTION but it loads into PARAM1 and messes up my next_state
|
||||||
|
PARAM1<=0;
|
||||||
|
reg_write_addr<={Wbit,3'b000};
|
||||||
|
reg_read_port1_addr<={Wbit,3'b000};
|
||||||
|
DEPENDS_ON_PREVIOUS<=0;
|
||||||
|
IN_MOD=3'b110;
|
||||||
|
MEM_OR_IO<=1;
|
||||||
|
HALT<=0;
|
||||||
|
ERROR<=0;
|
||||||
|
ALU_OP<=`ALU_OP_ADD;
|
||||||
|
next_state=`EXEC_MEMIO_READ_SETADDR;
|
||||||
|
seq_addr_entry<=`UCODE_NO_INSTRUCTION;
|
||||||
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`invalid_instruction
|
`invalid_instruction
|
||||||
end
|
end
|
||||||
@ -955,51 +964,52 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
default: begin end /*impossible*/
|
default: begin end /*impossible*/
|
||||||
endcase
|
endcase
|
||||||
if(ucode_data[36:36]==0) /*Set reg write address*/
|
if(ucode_data[36:36]==0) /*Set reg write address*/
|
||||||
reg_write_addr = ucode_data[12:9 ];
|
reg_write_addr <= ucode_data[12:9 ];
|
||||||
in_alu_sel1 = ucode_data[14:13];
|
in_alu_sel1 = ucode_data[14:13];
|
||||||
in_alu_sel2 = ucode_data[16:15];
|
in_alu_sel2 = ucode_data[16:15];
|
||||||
OUT_MOD = ucode_data[19:17];
|
OUT_MOD = ucode_data[19:17];
|
||||||
/*1:1 map essentially but I want to keep the spec for these bits separate
|
/*1:1 map essentially but I want to keep the spec for these bits separate
|
||||||
* from the alu op select bits*/
|
* from the alu op select bits*/
|
||||||
case(ucode_data[22:20])
|
case(ucode_data[22:20])
|
||||||
3'b000: ALU_OP=`ALU_OP_ADD;
|
3'b000: ALU_OP<=`ALU_OP_ADD;
|
||||||
3'b001: ALU_OP=`ALU_OP_SUB;
|
3'b001: ALU_OP<=`ALU_OP_SUB;
|
||||||
3'b010: ALU_OP=`ALU_OP_AND;
|
3'b010: ALU_OP<=`ALU_OP_AND;
|
||||||
3'b011: ALU_OP=`ALU_OP_OR;
|
3'b011: ALU_OP<=`ALU_OP_OR;
|
||||||
3'b100: ALU_OP=`ALU_OP_XOR;
|
3'b100: ALU_OP<=`ALU_OP_XOR;
|
||||||
3'b101: ALU_OP=`ALU_OP_ADD_SIGNED_B;
|
3'b101: ALU_OP<=`ALU_OP_ADD_SIGNED_B;
|
||||||
3'b110: ALU_OP=`ALU_OP_SUB_REVERSE;
|
3'b110: ALU_OP<=`ALU_OP_SUB_REVERSE;
|
||||||
3'b111: ALU_OP=`ALU_OP_SHIFT_LEFT;
|
3'b111: ALU_OP<=`ALU_OP_SHIFT_LEFT;
|
||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
if(ucode_data[34:34]==0) /* Set reg read port 1 address */
|
if(ucode_data[34:34]==0) /* Set reg read port 1 address */
|
||||||
reg_read_port1_addr=ucode_data[26:23];
|
reg_read_port1_addr<=ucode_data[26:23];
|
||||||
IN_MOD=ucode_data[29:27];
|
IN_MOD=ucode_data[29:27];
|
||||||
if(ucode_data[35:35]==0) /* Set reg read port 1 address */
|
if(ucode_data[35:35]==0) /* Set reg read port 1 address */
|
||||||
reg_read_port2_addr=ucode_data[33:30];
|
reg_read_port2_addr<=ucode_data[33:30];
|
||||||
if(ucode_data[37:37]==1) /* Overwrite Wbit */
|
if(ucode_data[37:37]==1) /* Overwrite Wbit */
|
||||||
Wbit=ucode_data[38:38];
|
Wbit=ucode_data[38:38];
|
||||||
memio_address_select=ucode_data[39:39];
|
memio_address_select=ucode_data[39:39];
|
||||||
MEM_OR_IO=0;
|
MEM_OR_IO<=0;
|
||||||
HALT <= 0;
|
HALT <= 0;
|
||||||
|
ERROR <= 0; //TODO probably, right?
|
||||||
end
|
end
|
||||||
|
|
||||||
if(PARAM_ACTION==`LOAD_8)begin
|
if(PARAM_ACTION==`LOAD_8)begin
|
||||||
if(opcode_size==0)begin
|
if(opcode_size==0)begin
|
||||||
if({Sbit,Wbit}==2'b11)begin
|
if({Sbit,Wbit}==2'b11)begin
|
||||||
/*signed "16bit" read*/
|
/*signed "16bit" read*/
|
||||||
PARAM1 = {{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
PARAM1 <= {{8{INSTRUCTION[23:23]}},INSTRUCTION[23:16]};
|
||||||
end else begin
|
end else begin
|
||||||
//PARAM1[7:0] = INSTRUCTION[23:16];
|
//PARAM1[7:0] = INSTRUCTION[23:16];
|
||||||
PARAM1 = {8'b0,INSTRUCTION[23:16]};
|
PARAM1 <= {8'b0,INSTRUCTION[23:16]};
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if({Sbit,Wbit}==2'b11)begin
|
if({Sbit,Wbit}==2'b11)begin
|
||||||
/*signed "16bit" read*/
|
/*signed "16bit" read*/
|
||||||
PARAM1 = {{8{INSTRUCTION[15:15]}},INSTRUCTION[15:8]};
|
PARAM1 <= {{8{INSTRUCTION[15:15]}},INSTRUCTION[15:8]};
|
||||||
end else begin
|
end else begin
|
||||||
//PARAM1[7:0] = INSTRUCTION[15:8];
|
//PARAM1[7:0] = INSTRUCTION[15:8];
|
||||||
PARAM1 = {8'b0,INSTRUCTION[15:8]};
|
PARAM1 <= {8'b0,INSTRUCTION[15:8]};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
@ -1008,11 +1018,11 @@ always @( FLAGS or INSTRUCTION or SIMPLE_MICRO or seq_addr_input ) begin
|
|||||||
endcase
|
endcase
|
||||||
end else if (PARAM_ACTION == `LOAD_16) begin
|
end else if (PARAM_ACTION == `LOAD_16) begin
|
||||||
if(opcode_size==0)begin
|
if(opcode_size==0)begin
|
||||||
PARAM1[7:0] = INSTRUCTION[23:16];
|
PARAM1[7:0] <= INSTRUCTION[23:16];
|
||||||
PARAM1[15:8] = INSTRUCTION[15:8];
|
PARAM1[15:8] <= INSTRUCTION[15:8];
|
||||||
end else begin
|
end else begin
|
||||||
PARAM1[15:8] = INSTRUCTION[7:0];
|
PARAM1[15:8] <= INSTRUCTION[7:0];
|
||||||
PARAM1[7:0] = INSTRUCTION[15:8];
|
PARAM1[7:0] <= INSTRUCTION[15:8];
|
||||||
end
|
end
|
||||||
case(IN_MOD)
|
case(IN_MOD)
|
||||||
3'b000,3'b001,3'b010: next_state = `EXEC_MEMIO_READ;
|
3'b000,3'b001,3'b010: next_state = `EXEC_MEMIO_READ;
|
||||||
@ -1029,7 +1039,7 @@ endmodule
|
|||||||
/* IN: {INSTRUCTION[31:24],INSTRUCTION[21:19]} */
|
/* IN: {INSTRUCTION[31:24],INSTRUCTION[21:19]} */
|
||||||
/* OUT: number in bytes */
|
/* OUT: number in bytes */
|
||||||
module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT );
|
module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT );
|
||||||
always @( IN ) begin
|
always @* begin
|
||||||
casez(IN)
|
casez(IN)
|
||||||
11'b0000_010?_??? : VERDICT = 3'd2+{2'b0,IN[3:3]}; /* ADD - Add Immediate word/byte to accumulator */
|
11'b0000_010?_??? : VERDICT = 3'd2+{2'b0,IN[3:3]}; /* ADD - Add Immediate word/byte to accumulator */
|
||||||
11'b1000_00??_101 : VERDICT = 3'd3+{2'b0,(IN[4:3]==2'b01)}; /* SUB - Subtract immediate word/byte from register/memory */
|
11'b1000_00??_101 : VERDICT = 3'd3+{2'b0,(IN[4:3]==2'b01)}; /* SUB - Subtract immediate word/byte from register/memory */
|
||||||
@ -1059,15 +1069,16 @@ module InstrSize ( input [10:0] IN, output reg [2:0] VERDICT );
|
|||||||
11'b1010_100?_??? : VERDICT = 3'd2+{2'b0,IN[3:3]}; /* TEST - Bitwise AND affecting only flags */
|
11'b1010_100?_??? : VERDICT = 3'd2+{2'b0,IN[3:3]}; /* TEST - Bitwise AND affecting only flags */
|
||||||
11'b0000_00??_??? : VERDICT = 3'd2; /* ADD - Reg/memory with register to either */
|
11'b0000_00??_??? : VERDICT = 3'd2; /* ADD - Reg/memory with register to either */
|
||||||
11'b0010_10??_??? : VERDICT = 3'd2; /* SUB - Reg/memory with register to either */
|
11'b0010_10??_??? : VERDICT = 3'd2; /* SUB - Reg/memory with register to either */
|
||||||
11'b0011_10??_??? : VERDICT = 3'd2; /* CMP - Compare Register/memory and register */
|
11'b0011_10??_??? : VERDICT = 3'd2; /* CMP - Compare Register/memory and register */
|
||||||
|
11'b1110_010?_??? : VERDICT = 3'd2; /* IN - Read from a defined port to AL or AX */
|
||||||
default: VERDICT = 3'd7;
|
default: VERDICT = 3'd7;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
`ifdef INCLUDE_EARLY_CALC_CIRUIT
|
`ifdef INCLUDE_EARLY_CALC_CIRCUIT
|
||||||
module Is1 ( input [7:0] IN, output reg VERDICT );
|
module Is1 ( input [7:0] IN, output reg VERDICT );
|
||||||
always @( IN ) begin
|
always @* begin
|
||||||
casez(IN)
|
casez(IN)
|
||||||
8'b0100_???? : VERDICT = 1; /* DEC - Decrement Register | INC - Increment Register */
|
8'b0100_???? : VERDICT = 1; /* DEC - Decrement Register | INC - Increment Register */
|
||||||
8'b1111_0100 : VERDICT = 1; /* HLT - Halt */
|
8'b1111_0100 : VERDICT = 1; /* HLT - Halt */
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -21,6 +21,7 @@
|
|||||||
`define EXEC_STATE_BITS 4
|
`define EXEC_STATE_BITS 4
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: Please clean this up
|
||||||
`define EXEC_WAIT 4'b1100
|
`define EXEC_WAIT 4'b1100
|
||||||
|
|
||||||
/*DECODE SATE*/
|
/*DECODE SATE*/
|
||||||
|
416
system/execute.v
416
system/execute.v
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -42,10 +42,10 @@ module execute_unit (
|
|||||||
/* */ ,output reg biu_read_request, output reg biu_jump_req,output reg biu_write_request
|
/* */ ,output reg biu_read_request, output reg biu_jump_req,output reg biu_write_request
|
||||||
|
|
||||||
/*************** INPUT FROM BIU ****************/
|
/*************** INPUT FROM BIU ****************/
|
||||||
/* */ ,input BIU_VALID_DATA, input biu_data_direction
|
/* */ ,input BIU_VALID_DATA,input [15:0] BIU_EX_DATA_READ
|
||||||
|
|
||||||
/************ BIDIRECTIONAL WITH BIU ***********/
|
/**************** OUTPUT TO BIU ****************/
|
||||||
/* */ ,inout [15:0] BIU_DATA
|
/* */ ,output [15:0] BIU_EX_DATA_WRITE
|
||||||
|
|
||||||
/***************** REGISTERS *****************/
|
/***************** REGISTERS *****************/
|
||||||
/* */ ,input [15:0] reg_read_port1_data ,input [15:0] reg_read_port2_data, output reg [3:0] reg_read_port1_addr
|
/* */ ,input [15:0] reg_read_port1_data ,input [15:0] reg_read_port2_data, output reg [3:0] reg_read_port1_addr
|
||||||
@ -57,7 +57,7 @@ assign _ALU_O_ = ALU_O;
|
|||||||
reg [`EXEC_STATE_BITS-1:0] exec_state;
|
reg [`EXEC_STATE_BITS-1:0] exec_state;
|
||||||
reg [15:0] PARAM1,PARAM2;
|
reg [15:0] PARAM1,PARAM2;
|
||||||
|
|
||||||
assign BIU_DATA = biu_data_direction ? (memio_address_select ? reg_read_port1_data : ALU_O): 16'hz;
|
assign BIU_EX_DATA_WRITE = memio_address_select ? reg_read_port1_data : ALU_O;
|
||||||
|
|
||||||
/*############ ALU / Execution units ################################################## */
|
/*############ ALU / Execution units ################################################## */
|
||||||
|
|
||||||
@ -93,233 +93,231 @@ ALU ALU1(
|
|||||||
|
|
||||||
/*############ Execute logic ########################################################## */
|
/*############ Execute logic ########################################################## */
|
||||||
|
|
||||||
always @(valid_input) begin
|
|
||||||
exec_state <= init_state;
|
|
||||||
reg_write_we <= 1;
|
|
||||||
biu_jump_req <= 0;
|
|
||||||
use_exec_reg_addr <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @( set_initial_values) begin
|
|
||||||
PARAM1 <= PARAM1_INIT;
|
|
||||||
PARAM2 <= PARAM2_INIT;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(negedge reset) begin
|
|
||||||
exec_state <= `EXEC_WAIT;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge reset) begin
|
|
||||||
exec_state <= `EXEC_RESET;
|
|
||||||
next_exec <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
`define unimpl_addressing_mode exec_state <= `EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;
|
`define unimpl_addressing_mode exec_state <= `EXEC_WAIT;ERROR <= `ERR_UNIMPL_ADDRESSING_MODE;
|
||||||
|
|
||||||
`define finished_instruction next_exec<=!next_exec; exec_state <= `EXEC_WAIT;
|
`define finished_instruction exec_state <= `EXEC_WAIT;next_exec<=1;
|
||||||
|
|
||||||
always @(posedge clock) begin
|
always @(posedge clock) begin
|
||||||
case (exec_state)
|
if ( !reset ) begin
|
||||||
`EXEC_RESET: begin
|
exec_state <= `EXEC_RESET;
|
||||||
biu_write_request <= 0;
|
end else begin
|
||||||
biu_read_request <= 0;
|
if ( set_initial_values )begin
|
||||||
biu_jump_req <= 0;
|
PARAM1 <= PARAM1_INIT;
|
||||||
reg_write_we <= 1;
|
PARAM2 <= PARAM2_INIT;
|
||||||
exec_state <= `EXEC_WAIT;
|
|
||||||
next_exec <= 0;
|
|
||||||
ERROR <= `ERR_NO_ERROR;
|
|
||||||
end
|
end
|
||||||
`EXEC_WAIT:begin
|
begin
|
||||||
reg_write_we <= 1;
|
case (exec_state)
|
||||||
use_exec_reg_addr <= 0;
|
`EXEC_RESET: begin
|
||||||
ERROR<=`ERR_NO_ERROR;
|
biu_write_request <= 0;
|
||||||
end
|
biu_read_request <= 0;
|
||||||
`EXEC_DE_LOAD_REG_TO_PARAM:begin
|
biu_jump_req <= 0;
|
||||||
PARAM2<=reg_read_port2_data;
|
reg_write_we <= 1;
|
||||||
case(IN_MOD)
|
exec_state <= `EXEC_WAIT;
|
||||||
3'b000,3'b001,3'b010: exec_state <= `EXEC_MEMIO_READ;
|
ERROR <= `ERR_NO_ERROR;
|
||||||
default: exec_state <= `EXEC_WRITE_ENTRY;
|
end
|
||||||
endcase
|
`EXEC_WAIT:begin
|
||||||
end
|
if(valid_input)begin
|
||||||
`EXEC_MEMIO_READ:begin
|
exec_state <= init_state;
|
||||||
/*Decode MOD R/M, read the data and place it to PARAM1*/
|
next_exec<=0;
|
||||||
case (IN_MOD)
|
end else begin
|
||||||
3'b000,
|
next_exec<=1;
|
||||||
3'b001,
|
end
|
||||||
3'b010:begin
|
biu_jump_req <= 0;
|
||||||
case (RM)
|
reg_write_we <= 1;
|
||||||
3'b000:begin
|
use_exec_reg_addr <= 0;
|
||||||
/*[BX]+[SI]*/
|
ERROR<=`ERR_NO_ERROR;
|
||||||
`unimpl_addressing_mode
|
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
|
end
|
||||||
3'b001:begin
|
3'b110:begin /* SP Indirect read*/
|
||||||
/*[BX]+[SI]*/
|
reg_read_port1_addr <= 4'b1100;
|
||||||
`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;
|
use_exec_reg_addr <= 1;
|
||||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
||||||
end
|
end
|
||||||
3'b101:begin
|
default: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
|
`unimpl_addressing_mode
|
||||||
end
|
end
|
||||||
3'b111:begin
|
|
||||||
/*[BX]*/
|
|
||||||
reg_read_port1_addr <= 4'b1011;
|
|
||||||
use_exec_reg_addr <= 1;
|
|
||||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
|
||||||
end
|
|
||||||
endcase
|
endcase
|
||||||
if(IN_MOD!=3'b000)begin
|
end
|
||||||
/*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/
|
`EXEC_MEMIO_READ_SETADDR:begin
|
||||||
`unimpl_addressing_mode;
|
/* 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
|
||||||
end
|
end
|
||||||
3'b110:begin /* SP Indirect read*/
|
`EXEC_NEXT_INSTRUCTION:begin
|
||||||
reg_read_port1_addr <= 4'b1100;
|
`finished_instruction
|
||||||
use_exec_reg_addr <= 1;
|
/*necessary for biu to see we went on another state from decode to give us a new instruction*/
|
||||||
exec_state <= `EXEC_MEMIO_READ_SETADDR;
|
|
||||||
end
|
end
|
||||||
default:begin
|
`EXEC_WRITE_ENTRY:begin
|
||||||
`unimpl_addressing_mode
|
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
|
end
|
||||||
endcase
|
`EXEC_JUMP_RELEASE:begin
|
||||||
end
|
biu_jump_req <= 0;
|
||||||
`EXEC_MEMIO_READ_SETADDR:begin
|
`finished_instruction
|
||||||
if(memio_address_select==0)
|
end
|
||||||
BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
|
`EXEC_MEMIO_WRITE:begin
|
||||||
else
|
/* if memio_address_select == 0 ADDRESS: reg_read_port1_data DATA:ALU1_O */
|
||||||
BIU_ADDRESS_INPUT <= ALU_O;
|
/* if memio_address_select == 1 ADDRESS: ALU1_O DATA: reg_read_port1_data */
|
||||||
|
|
||||||
if ( BIU_VALID_DATA == 1 ) begin
|
biu_write_request <= 1;
|
||||||
exec_state <= `EXEC_WRITE_ENTRY;
|
|
||||||
PARAM2 <= BIU_DATA;
|
if(memio_address_select==0)
|
||||||
biu_read_request <= 0;
|
BIU_ADDRESS_INPUT <= reg_read_port1_data[15: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
|
else
|
||||||
case (RM) /* Duplicate code with write... */
|
BIU_ADDRESS_INPUT <= ALU_O;
|
||||||
3'b000:begin
|
|
||||||
/*[BX]+[SI]*/
|
if (write == 0) begin //TODO: don't do it that way or better yet don't do it at all somehow
|
||||||
`unimpl_addressing_mode
|
biu_write_request <= 0;
|
||||||
end
|
`finished_instruction
|
||||||
3'b001:begin
|
end
|
||||||
/*[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
|
end
|
||||||
default:begin
|
default:begin
|
||||||
`unimpl_addressing_mode
|
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`EXEC_JUMP_RELEASE:begin
|
end
|
||||||
biu_jump_req <= 0;
|
|
||||||
`finished_instruction
|
|
||||||
end
|
|
||||||
`EXEC_MEMIO_WRITE:begin
|
|
||||||
/* if memio_address_select == 0 ADDRESS: reg_read_port1_data DATA:ALU1_O */
|
|
||||||
/* if memio_address_select == 1 ADDRESS: ALU1_O DATA: reg_read_port1_data */
|
|
||||||
|
|
||||||
biu_write_request <= 1;
|
|
||||||
|
|
||||||
if(memio_address_select==0)
|
|
||||||
BIU_ADDRESS_INPUT <= reg_read_port1_data[15:0];
|
|
||||||
else
|
|
||||||
BIU_ADDRESS_INPUT <= ALU_O;
|
|
||||||
|
|
||||||
if (write == 0) begin //TODO: don't do it that was or better yet don't do it at all somehow
|
|
||||||
biu_write_request <= 0;
|
|
||||||
`finished_instruction
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
default:begin
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
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.
|
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
|
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
|
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.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -19,30 +19,55 @@
|
|||||||
|
|
||||||
/* This warning is because we don't use the full address bus. */
|
/* This warning is because we don't use the full address bus. */
|
||||||
/* verilator lint_off UNUSEDSIGNAL */
|
/* 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 */
|
/* verilator lint_on UNUSEDSIGNAL */
|
||||||
|
|
||||||
reg [15:0] memory [0:32768];
|
reg [15:0] memory [0:(RAM_SIZE_IN_BYTES/2)-1];
|
||||||
|
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
`ifndef YOSYS
|
||||||
string boot_code;
|
string boot_code;
|
||||||
if(!$value$plusargs("BOOT_CODE=%s",boot_code))begin
|
if(!$value$plusargs("BOOT_CODE=%s",boot_code))begin
|
||||||
$display("No boot code specified. Please add +BOOT_CODE=<path> to your vvp args");
|
$display("No boot code specified. Please add +BOOT_CODE=<path> to your vvp args");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
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
|
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
|
|
||||||
if( cs == 0 ) begin
|
always @(posedge clock) begin
|
||||||
|
if( cs == 0 && wr == 0) begin
|
||||||
if(BHE==0)
|
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)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -20,6 +20,7 @@
|
|||||||
`include "exec_state_def.v"
|
`include "exec_state_def.v"
|
||||||
`include "alu_header.v"
|
`include "alu_header.v"
|
||||||
`include "config.v"
|
`include "config.v"
|
||||||
|
`include "error_header.v"
|
||||||
|
|
||||||
//HALT: active high
|
//HALT: active high
|
||||||
//IOMEM: 1=IO 0=MEM
|
//IOMEM: 1=IO 0=MEM
|
||||||
@ -31,19 +32,19 @@
|
|||||||
module processor (
|
module processor (
|
||||||
|
|
||||||
/* MISC */ input clock, input reset, output wire HALT,output [`ERROR_BITS-1:0] ERROR
|
/* MISC */ input clock, input reset, output wire HALT,output [`ERROR_BITS-1:0] ERROR
|
||||||
/* MEMORY / IO */ ,output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM
|
/* MEMORY / IO */ ,output [19:0] external_address_bus, input [15:0] external_data_bus_read, output [15:0] external_data_bus_write, input wait_state, output read, output write,output BHE,output IOMEM
|
||||||
|
|
||||||
`ifdef CALCULATE_IPC
|
`ifdef CALCULATE_IPC
|
||||||
/* STATISTICS */ ,output wire new_instruction
|
/* STATISTICS */ ,output wire new_instruction
|
||||||
`endif
|
`endif
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
/* */ ,output wire [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT, output wire VALID_INSTRUCTION_STAT, output wire jump_req_debug
|
/* */ ,output wire [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT, output wire VALID_INSTRUCTION_STAT, output wire jump_req_debug
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
assign jump_req_debug=biu_jump_req;
|
assign jump_req_debug=biu_jump_req;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
@ -84,10 +85,10 @@ execute_unit execute_unit (
|
|||||||
/* */ ,biu_read_request, biu_jump_req, biu_write_request
|
/* */ ,biu_read_request, biu_jump_req, biu_write_request
|
||||||
|
|
||||||
/*************** INPUT FROM BIU ****************/
|
/*************** INPUT FROM BIU ****************/
|
||||||
/* */ ,BIU_VALID_DATA, BIU_DATA_DIR
|
/* */ ,BIU_VALID_DATA,BIU_EX_DATA_READ
|
||||||
|
|
||||||
/************ BIDIRECTIONAL WITH BIU ***********/
|
/**************** OUTPUT TO BIU ****************/
|
||||||
/* */ ,BIU_DATA
|
/* */ ,BIU_EX_DATA_WRITE
|
||||||
|
|
||||||
/***************** REGISTERS *****************/
|
/***************** REGISTERS *****************/
|
||||||
/* */ ,reg_read_port1_data, reg_read_port2_data, EXEC_reg_read_port1_addr
|
/* */ ,reg_read_port1_data, reg_read_port2_data, EXEC_reg_read_port1_addr
|
||||||
@ -98,11 +99,10 @@ execute_unit execute_unit (
|
|||||||
/*############ Bus Interface Unit ############################################### */
|
/*############ Bus Interface Unit ############################################### */
|
||||||
|
|
||||||
wire [15:0] INSTRUCTION_LOCATION;
|
wire [15:0] INSTRUCTION_LOCATION;
|
||||||
wire [15:0] BIU_DATA;
|
wire [15:0] BIU_EX_DATA_READ,BIU_EX_DATA_WRITE;
|
||||||
wire [31:0] IF2DE_INSTRUCTION;
|
wire [31:0] IF2DE_INSTRUCTION;
|
||||||
wire BIU_VALID_DATA;
|
wire BIU_VALID_DATA;
|
||||||
wire VALID_INSTRUCTION;
|
wire VALID_INSTRUCTION;
|
||||||
wire BIU_DATA_DIR;
|
|
||||||
|
|
||||||
BIU BIU(
|
BIU BIU(
|
||||||
/***************** GENERAL *****************/
|
/***************** GENERAL *****************/
|
||||||
@ -110,23 +110,24 @@ BIU BIU(
|
|||||||
|
|
||||||
/**************** OUTSIDE WORLD ****************/
|
/**************** OUTSIDE WORLD ****************/
|
||||||
/* */ ,external_address_bus
|
/* */ ,external_address_bus
|
||||||
/* */ ,external_data_bus,read,write,BHE,IOMEM
|
/* */ ,external_data_bus_read,external_data_bus_write,read,write,BHE,IOMEM
|
||||||
|
/* */ ,wait_state
|
||||||
|
|
||||||
/**************** OUTPUT TO DE ****************/
|
/**************** OUTPUT TO DE ****************/
|
||||||
/* */ ,IF2DE_INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION
|
/* */ ,IF2DE_INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION
|
||||||
/* */ ,BIU_VALID_DATA,BIU_DATA_DIR
|
/* */ ,BIU_VALID_DATA
|
||||||
|
|
||||||
/**************** INPUT FROM DE ****************/
|
/**************** INPUT FROM DE ****************/
|
||||||
,Wbit,MEM_OR_IO,VALID_INSTRUCTION_ACK
|
,Wbit,MEM_OR_IO,VALID_INSTRUCTION_ACK
|
||||||
|
|
||||||
/**************** INPUT FROM EX ****************/
|
/**************** INPUT FROM EX ****************/
|
||||||
/* */ ,biu_jump_req,biu_write_request,biu_read_request
|
/* */ ,biu_jump_req,biu_write_request,biu_read_request
|
||||||
/* */ ,BIU_ADDRESS_INPUT
|
/* */ ,BIU_ADDRESS_INPUT,BIU_EX_DATA_WRITE
|
||||||
|
|
||||||
/************ BIDIRECTIONAL WITH EX ************/
|
/***************** OUTPUT TO EX ****************/
|
||||||
/* */ ,BIU_DATA
|
/* */ ,BIU_EX_DATA_READ
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
/***************** STATISTICS *****************/
|
/***************** STATISTICS *****************/
|
||||||
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT
|
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT
|
||||||
`endif
|
`endif
|
||||||
@ -188,13 +189,14 @@ assign reg_read_port1_addr = use_exec_reg_addr ? EXEC_reg_read_port1_addr : DE_r
|
|||||||
wire [15:0] reg_read_port1_data, reg_read_port2_data;
|
wire [15:0] reg_read_port1_data, reg_read_port2_data;
|
||||||
|
|
||||||
register_file register_file(
|
register_file register_file(
|
||||||
/* WRITE */ .write_port1_addr(reg_write_addr),
|
/* WRITE */ .write_port1_addr(reg_write_addr), //TODO: should this come from exec instead?
|
||||||
/* */ .write_port1_data(ALU_O),
|
/* */ .write_port1_data(ALU_O),
|
||||||
/* */ .write_port1_we(reg_write_we),
|
/* */ .write_port1_we(reg_write_we),
|
||||||
/* READ 1 */ .read_port1_addr(reg_read_port1_addr),
|
/* READ 1 */ .read_port1_addr(reg_read_port1_addr),
|
||||||
/* */ .read_port1_data(reg_read_port1_data),
|
/* */ .read_port1_data(reg_read_port1_data),
|
||||||
/* READ 2 */ .read_port2_addr(DE_reg_read_port2_addr),
|
/* READ 2 */ .read_port2_addr(DE_reg_read_port2_addr),
|
||||||
/* */ .read_port2_data(reg_read_port2_data)
|
/* */ .read_port2_data(reg_read_port2_data),
|
||||||
|
/* GENERAL */ .clock(clock)
|
||||||
);
|
);
|
||||||
|
|
||||||
/*############################################################################### */
|
/*############################################################################### */
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
/* Register address format:
|
/* Register address format:
|
||||||
* [W-bit] [ 3-bit address] */
|
* [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] write_port1_addr;
|
||||||
input [3:0] read_port1_addr;
|
input [3:0] read_port1_addr;
|
||||||
input [3:0] read_port2_addr;
|
input [3:0] read_port2_addr;
|
||||||
@ -32,11 +33,11 @@ input write_port1_we;
|
|||||||
|
|
||||||
reg [15:0] registers [7:0];
|
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] :
|
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] ) );
|
( 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] :
|
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] ) );
|
( 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] ) );
|
||||||
|
|
||||||
@ -48,47 +49,48 @@ assign read_port2_data[7:0] = ( read_port2_addr[3:3] ? registers[read_port2_addr
|
|||||||
wire write_Wbit;
|
wire write_Wbit;
|
||||||
assign write_Wbit=write_port1_addr[3:3];
|
assign write_Wbit=write_port1_addr[3:3];
|
||||||
|
|
||||||
always @(negedge write_port1_we) begin
|
always @(posedge clock) begin
|
||||||
if(write_Wbit==1)begin
|
if(write_port1_we==0)begin
|
||||||
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
|
if(write_Wbit==1)begin
|
||||||
registers[write_port1_addr[2:0]] <= write_port1_data;
|
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
|
||||||
end else begin
|
registers[write_port1_addr[2:0]] <= write_port1_data;
|
||||||
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
|
|
||||||
if(write_port1_addr[2:2]==1)begin
|
|
||||||
/* Byte */
|
|
||||||
registers[ {1'b0,write_port1_addr[1:0]} ][15:8] <= write_port1_data[7:0];
|
|
||||||
end else begin
|
end else begin
|
||||||
/* Byte */
|
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
|
||||||
registers[ {1'b0,write_port1_addr[1:0]} ][7:0] <= write_port1_data[7:0];
|
if(write_port1_addr[2:2]==1)begin
|
||||||
|
/* Byte */
|
||||||
|
registers[ {1'b0,write_port1_addr[1:0]} ][15:8] <= write_port1_data[7:0];
|
||||||
|
end else begin
|
||||||
|
/* Byte */
|
||||||
|
registers[ {1'b0,write_port1_addr[1:0]} ][7:0] <= write_port1_data[7:0];
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
`ifdef DEBUG_REG_WRITES
|
||||||
|
// Icarus Verilog really doesn't like non-blocking assignments
|
||||||
|
// here
|
||||||
|
/* verilator lint_off BLKSEQ */
|
||||||
|
if(write_port1_addr[3:2]==2'b11)begin
|
||||||
|
case(write_port1_addr[1:0])
|
||||||
|
2'b00: debug_name="sp";
|
||||||
|
2'b01: debug_name="bp";
|
||||||
|
2'b10: debug_name="si";
|
||||||
|
2'b11: debug_name="di";
|
||||||
|
endcase
|
||||||
|
end else begin
|
||||||
|
case(write_port1_addr[1:0])
|
||||||
|
2'b00: debug_name="ax";
|
||||||
|
2'b01: debug_name="cx";
|
||||||
|
2'b10: debug_name="dx";
|
||||||
|
2'b11: debug_name="bx";
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
/* verilator lint_on BLKSEQ */
|
||||||
|
if (write_Wbit)
|
||||||
|
debug_address<=write_port1_addr[2:0];
|
||||||
|
else
|
||||||
|
debug_address<={1'b0,write_port1_addr[1:0]};
|
||||||
|
|
||||||
|
`endif
|
||||||
end
|
end
|
||||||
`ifdef DEBUG_REG_WRITES
|
|
||||||
// Icarus Verilog really doesn't like non-blocking assignments
|
|
||||||
// here
|
|
||||||
/* verilator lint_off BLKSEQ */
|
|
||||||
if(write_port1_addr[3:2]==2'b11)begin
|
|
||||||
case(write_port1_addr[1:0])
|
|
||||||
2'b00: debug_name="sp";
|
|
||||||
2'b01: debug_name="bp";
|
|
||||||
2'b10: debug_name="si";
|
|
||||||
2'b11: debug_name="di";
|
|
||||||
endcase
|
|
||||||
end else begin
|
|
||||||
case(write_port1_addr[1:0])
|
|
||||||
2'b00: debug_name="ax";
|
|
||||||
2'b01: debug_name="cx";
|
|
||||||
2'b10: debug_name="dx";
|
|
||||||
2'b11: debug_name="bx";
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
/* verilator lint_on BLKSEQ */
|
|
||||||
if (write_Wbit)
|
|
||||||
debug_address<=write_port1_addr[2:0];
|
|
||||||
else
|
|
||||||
debug_address<={1'b0,write_port1_addr[1:0]};
|
|
||||||
|
|
||||||
`endif
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifdef DEBUG_REG_WRITES
|
`ifdef DEBUG_REG_WRITES
|
||||||
|
231
system/system.v
231
system/system.v
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -22,52 +22,66 @@
|
|||||||
`include "config.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_BITS-1:0] 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
|
`ifdef CALCULATE_IPC
|
||||||
wire new_instruction;
|
wire new_instruction;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
wire unsigned [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT;
|
wire unsigned [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT;
|
||||||
wire VALID_INSTRUCTION_STAT,jump_req;
|
wire VALID_INSTRUCTION_STAT,jump_req;
|
||||||
`endif
|
`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(
|
processor p(
|
||||||
/* MISC */ clock,reset,HALT,ERROR
|
/* 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
|
`ifdef CALCULATE_IPC
|
||||||
/* STATISTICS */ ,new_instruction
|
/* STATISTICS */ ,new_instruction
|
||||||
`endif
|
`endif
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT, jump_req
|
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT, jump_req
|
||||||
`endif
|
`endif
|
||||||
);
|
);
|
||||||
|
|
||||||
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
wire [15:0] data_bus_read_RAM;
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
doublemem #(.RAM_SIZE_IN_BYTES(65536)) sysmem(address_bus[15:0],data_bus_read_RAM,data_bus_write_CPU,rd,wr,BHE,IOMEM,clock);
|
||||||
|
|
||||||
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
string stats_name,version,commit;
|
string stats_name,version,commit;
|
||||||
integer json_file_descriptor;
|
integer json_file_descriptor;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
`ifndef YOSYS
|
||||||
string waveform_name;
|
string waveform_name;
|
||||||
|
`endif
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
`ifndef SYNTHESIS
|
||||||
$dumpfile(waveform_name);
|
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
||||||
$dumpvars(0,p,cycles);
|
$dumpfile(waveform_name);
|
||||||
end
|
$dumpvars(0,p,cycles);
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
end
|
||||||
if(!$value$plusargs("VERSION=%s",version)) version="unkown";
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
if(!$value$plusargs("COMMIT=%s",commit)) commit="unkown";
|
if(!$value$plusargs("VERSION=%s",version)) version="unkown";
|
||||||
if($value$plusargs("STATS=%s",stats_name))begin
|
if(!$value$plusargs("COMMIT=%s",commit)) commit="unkown";
|
||||||
json_file_descriptor=$fopen(stats_name,"w");
|
if($value$plusargs("STATS=%s",stats_name))begin
|
||||||
$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);
|
json_file_descriptor=$fopen(stats_name,"w");
|
||||||
first_json_cycle = 1;
|
$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);
|
||||||
end else
|
first_json_cycle = 1;
|
||||||
json_file_descriptor=0;
|
end else
|
||||||
|
json_file_descriptor=0;
|
||||||
|
`endif
|
||||||
|
sane=0;
|
||||||
|
finish=0;
|
||||||
`endif
|
`endif
|
||||||
sane=0;
|
|
||||||
finish=0;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
//integer killswitch=0;
|
//integer killswitch=0;
|
||||||
@ -81,7 +95,7 @@ end
|
|||||||
// end
|
// end
|
||||||
//end
|
//end
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
reg first_json_cycle;
|
reg first_json_cycle;
|
||||||
always @(negedge clock)begin
|
always @(negedge clock)begin
|
||||||
if(finish < 2 && json_file_descriptor!=0 && sane)begin
|
if(finish < 2 && json_file_descriptor!=0 && sane)begin
|
||||||
@ -91,96 +105,127 @@ always @(negedge clock)begin
|
|||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
reg [15:0]data_bus_IO;
|
||||||
|
|
||||||
|
`ifndef SYNTHESIS
|
||||||
always @(negedge wr) begin
|
always @(negedge wr) begin
|
||||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
|
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )begin
|
||||||
$write("%s" ,data_bus[15:8]);
|
$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
|
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
|
`ifdef CALCULATE_IPC
|
||||||
|
/* verilator lint_off MULTIDRIVEN */
|
||||||
reg [128:0] instruction_count;
|
reg [128:0] instruction_count;
|
||||||
|
/* verilator lint_on MULTIDRIVEN */
|
||||||
always @(new_instruction) begin
|
always @(new_instruction) begin
|
||||||
instruction_count<=instruction_count+1;
|
instruction_count<=instruction_count+1;
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
reg [1:0] finish;
|
|
||||||
string memdump_name;
|
|
||||||
always @(posedge HALT) begin
|
|
||||||
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
|
||||||
$writememh(memdump_name, sysmem.memory,0,32767);
|
|
||||||
end
|
|
||||||
finish<=2'd1;
|
|
||||||
end
|
|
||||||
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
`ifndef SYNTHESIS
|
||||||
reg [128:0] instruction_count_temp;
|
|
||||||
`endif
|
|
||||||
always @(posedge clock) begin
|
|
||||||
/* Allow some clock cycles for the waveform*/
|
|
||||||
case(finish)
|
|
||||||
2'd0: begin end
|
|
||||||
2'd1: begin
|
|
||||||
finish <= 2;
|
|
||||||
/* instruction_count gets updated at the sme time as HALT is pulled so wait a clock cycle to get an accurate reading*/
|
|
||||||
$display("\x1b[7mProcessor halted.\nCycles run for : %0d\x1b[m",cycles);
|
|
||||||
`ifdef CALCULATE_IPC
|
|
||||||
/* verilator lint_off REALCVT */
|
|
||||||
$display("\x1b[7mInstr. per cycle : %f\x1b[m", $itor(instruction_count) / $itor(cycles) );
|
|
||||||
/* verilator lint_on REALCVT */
|
|
||||||
`endif
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
|
||||||
instruction_count_temp <= instruction_count;
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
2'd2: begin
|
|
||||||
finish <= 3;
|
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
|
||||||
if(json_file_descriptor!=0)
|
|
||||||
$fdisplay(json_file_descriptor,"],\n\"Total Cycles\":%0d,\n\"Instructions run\":%0d\n}",cycles-1,instruction_count_temp);
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
2'd3: $finish;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge reset)begin
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
sane<=1;
|
reg [128:0] instruction_count_temp;
|
||||||
end
|
`endif
|
||||||
reg sane;
|
|
||||||
always @( ERROR ) begin
|
string memdump_name;
|
||||||
if ( ERROR != `ERR_NO_ERROR && sane == 1 ) begin
|
|
||||||
$display("PROCESSOR RUN INTO AN ERROR.");
|
always @(posedge HALT) begin
|
||||||
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
|
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||||
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
$writememh(memdump_name, sysmem.memory,0,32767);
|
||||||
end
|
end
|
||||||
finish<=2'd1;
|
finish<=2'd1;
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
reg [128:0] cycles;
|
/* verilator lint_off MULTIDRIVEN */
|
||||||
|
reg [1:0] finish;
|
||||||
|
/* verilator lint_on MULTIDRIVEN */
|
||||||
|
|
||||||
always @(negedge clock)begin
|
reg sane;
|
||||||
if(reset==1)
|
reg [128:0] cycles;
|
||||||
cycles<=cycles+1;
|
|
||||||
else begin
|
always @(posedge reset)begin
|
||||||
cycles<=0;
|
sane<=1;
|
||||||
`ifdef OTUPUT_JSON_STATISTICS
|
|
||||||
instruction_count <= 0;
|
|
||||||
`endif
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
always @(posedge clock) begin
|
||||||
|
/* Allow some clock cycles for the waveform*/
|
||||||
|
case(finish)
|
||||||
|
2'd0: begin end
|
||||||
|
2'd1: begin
|
||||||
|
finish <= 2;
|
||||||
|
/* instruction_count gets updated at the sme time as HALT is pulled so wait a clock cycle to get an accurate reading*/
|
||||||
|
$display("\x1b[7mProcessor halted.\nCycles run for : %0d\x1b[m",cycles);
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
$display("\x1b[7mInstr. per cycle : %f\x1b[m", $itor(instruction_count) / $itor(cycles) );
|
||||||
|
`endif
|
||||||
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
|
instruction_count_temp <= instruction_count;
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
2'd2: begin
|
||||||
|
finish <= 3;
|
||||||
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
|
if(json_file_descriptor!=0)
|
||||||
|
$fdisplay(json_file_descriptor,"],\n\"Total Cycles\":%0d,\n\"Instructions run\":%0d\n}",cycles-1,instruction_count_temp);
|
||||||
|
`endif
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
2'd3: begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always @( ERROR ) begin
|
||||||
|
if ( ERROR != `ERR_NO_ERROR && sane == 1 ) begin
|
||||||
|
$display("PROCESSOR RUN INTO AN ERROR.");
|
||||||
|
case (ERROR)
|
||||||
|
default:begin
|
||||||
|
end
|
||||||
|
`ERR_UNIMPL_INSTRUCTION:begin
|
||||||
|
$display("Unimplemented instruction");
|
||||||
|
end
|
||||||
|
`ERR_UNIMPL_ADDRESSING_MODE: begin
|
||||||
|
$display("Unimplemented addressing mode");
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
$display("Cycles run for: %0d",cycles-1);
|
||||||
|
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||||
|
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
||||||
|
end
|
||||||
|
finish<=2'd1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(negedge clock)begin
|
||||||
|
if(reset==1)
|
||||||
|
cycles<=cycles+1;
|
||||||
|
else begin
|
||||||
|
cycles<=0;
|
||||||
|
`ifdef OUTPUT_JSON_STATISTICS
|
||||||
|
instruction_count <= 0;
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -36,6 +36,7 @@ int main(int argc, char** argv) {
|
|||||||
tick();
|
tick();
|
||||||
system_state->reset=0;
|
system_state->reset=0;
|
||||||
tick();
|
tick();
|
||||||
|
tick();
|
||||||
system_state->reset=1;
|
system_state->reset=1;
|
||||||
|
|
||||||
// Simulate until $finish
|
// Simulate until $finish
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -25,7 +25,7 @@ wire clock;
|
|||||||
reg reset;
|
reg reset;
|
||||||
reg clk_enable;
|
reg clk_enable;
|
||||||
wire [19:0]address_bus;
|
wire [19:0]address_bus;
|
||||||
wire [15:0]data_bus;
|
wire [15:0]data_bus_write;
|
||||||
wire rd,wr,HALT;
|
wire rd,wr,HALT;
|
||||||
wire [2:0] ERROR;
|
wire [2:0] ERROR;
|
||||||
wire IOMEM;
|
wire IOMEM;
|
||||||
@ -33,7 +33,7 @@ wire IOMEM;
|
|||||||
system system( .clock(clock),
|
system system( .clock(clock),
|
||||||
.reset(reset),
|
.reset(reset),
|
||||||
.address_bus(address_bus),
|
.address_bus(address_bus),
|
||||||
.data_bus(data_bus),
|
.data_bus_write(data_bus_write),
|
||||||
.rd(rd),
|
.rd(rd),
|
||||||
.wr(wr),
|
.wr(wr),
|
||||||
.HALT(HALT),
|
.HALT(HALT),
|
||||||
@ -49,22 +49,26 @@ initial begin
|
|||||||
do_reset = 0;
|
do_reset = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [1:0]do_reset;
|
reg [2:0]do_reset;
|
||||||
|
|
||||||
always @(posedge clock) begin
|
always @(posedge clock) begin
|
||||||
case(do_reset)
|
case(do_reset)
|
||||||
2'd0:begin
|
3'd0:begin
|
||||||
do_reset<=1;
|
do_reset<=1;
|
||||||
end
|
end
|
||||||
2'd1:begin
|
3'd1:begin
|
||||||
do_reset<=2;
|
do_reset<=2;
|
||||||
reset <= 0;
|
reset <= 0;
|
||||||
end
|
end
|
||||||
2'd2:begin
|
3'd2:begin
|
||||||
do_reset<=3;
|
do_reset<=3;
|
||||||
|
reset <= 0;
|
||||||
|
end
|
||||||
|
3'd3:begin
|
||||||
|
do_reset<=4;
|
||||||
reset <= 1;
|
reset <= 1;
|
||||||
end
|
end
|
||||||
2'd3:begin
|
3'd4:begin
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This file is part of the 9086 project.
|
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
|
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
|
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.
|
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
|
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
|
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
|
@ -1,11 +1,29 @@
|
|||||||
#!/bin/sh
|
#!/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
|
set -euf
|
||||||
|
|
||||||
print_help(){
|
print_help(){
|
||||||
echo "$0 <json data file> <function> <output filename>"
|
echo "$0 <json data file> <function> <output filename>"
|
||||||
echo " Possible functions:"
|
echo " Possible functions:"
|
||||||
echo " cache_time : graph of cache utilisation in bytes over time in clock cycles"
|
echo " cache_time : graph of cache utilisation in bytes over time in clock cycles"
|
||||||
echo " cache_util_freq : graph of the likelyhood of the cache for each utilisation"
|
echo " cache_util_freq : graph of the likelihood of the cache for each utilisation"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$#" != 3 ] || ! [ -e "$1" ]
|
if [ "$#" != 3 ] || ! [ -e "$1" ]
|
||||||
|
Loading…
Reference in New Issue
Block a user