diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..453baae --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,118 @@ +# This file is a template, and might need editing before it works on your project. +# This is a sample GitLab CI/CD configuration file that should run without any modifications. +# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts, +# it uses echo commands to simulate the pipeline execution. +# +# A pipeline is composed of independent jobs that run scripts, grouped into stages. +# Stages run in sequential order, but jobs within stages run in parallel. +# +# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages +# +# You can copy and paste this template into a new `.gitlab-ci.yml` file. +# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword. +# +# To contribute improvements to CI/CD templates, please follow the Development guide at: +# https://docs.gitlab.com/ee/development/cicd/templates.html +# This specific template is located at: +# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml + +variables: + GIT_SUBMODULE_STRATEGY: recursive + +stages: # List of stages for jobs, and their order of execution + - toolchain + - build + - simulate + +build toolchain: + tags: + - linux + stage: toolchain + script: + - source init_env.sh + - cd sw/cc65 + - make -j + artifacts: + paths: + - sw/cc65/bin + - sw/cc65/lib + +build fpga: # This job runs in the build stage, which runs first. + tags: + - efinity + - linux + stage: build + script: + - source init_env.sh + - cd hw/efinix_fpga + - make + +build sim: + tags: + - iverilog + - linux + stage: build + artifacts: + paths: + - hw/efinix_fpga/simulation/sim_top + - hw/efinix_fpga/simulation/init_hex.mem + script: + - source init_env.sh + - cd hw/efinix_fpga/simulation + - make sim_top + dependencies: + - build toolchain + +build bios: + tags: + - linux + stage: build + script: + - source init_env.sh + - cd sw/ + - make bios + dependencies: + - build toolchain + +build kernel: + tags: + - linux + stage: build + script: + - source init_env.sh + - cd sw/ + - make kernel + dependencies: + - build toolchain + +run sim: + tags: + - linux + - iverilog + stage: simulate + artifacts: + paths: + - hw/efinix_fpga/simulation/sim_top.vcd + script: + - source init_env.sh + - cd hw/efinix_fpga/simulation + - make sim + dependencies: + - build sim + +full sim: + tags: + - linux + - iverilog + stage: simulate + artifacts: + paths: + - hw/efinix_fpga/simulation/sim_top.vcd + script: + - source init_env.sh + - cd hw/efinix_fpga/simulation + - make clean + - TEST_PROGRAM=$REPO_TOP/sw/bios/bios.hex TEST_FOLDER=$REPO_TOP/sw/bios make full_sim + dependencies: + - build toolchain + diff --git a/.gitmodules b/.gitmodules index 21b2181..da7e628 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "sw/cc65"] path = sw/cc65 url = https://git.byronlathi.com/bslathi19/cc65 +[submodule "hw/efinix_fpga/simulation/src/verilog-6502"] + path = hw/efinix_fpga/simulation/src/verilog-6502 + url = https://git.byronlathi.com/bslathi19/verilog-6502 +[submodule "hw/efinix_fpga/simulation/src/verilog-sd-emulator"] + path = hw/efinix_fpga/simulation/src/verilog-sd-emulator + url = https://git.byronlathi.com/bslathi19/verilog-sd-emulator diff --git a/hw/efinix_fpga/init_hex.mem b/hw/efinix_fpga/init_hex.mem index 8d41c16..65dd39a 100644 --- a/hw/efinix_fpga/init_hex.mem +++ b/hw/efinix_fpga/init_hex.mem @@ -1,9 +1,9 @@ @00000000 00 80 4C 00 00 8D 13 92 8E 14 92 8D 1A 92 8E 1B 92 88 B9 FF FF 8D 24 92 88 B9 FF FF 8D 23 92 8C -26 92 20 FF FF A0 FF D0 E8 60 00 00 CC FD 00 00 -00 00 A2 FF 9A D8 A9 00 85 04 A9 DF 85 05 20 44 -FE 20 B9 FA 20 52 F0 58 20 69 F2 6C FC FF 20 AD +26 92 20 FF FF A0 FF D0 E8 60 00 00 4B FD 00 00 +00 00 A2 FF 9A D8 A9 00 85 04 A9 DF 85 05 20 C3 +FD 20 38 FA 20 52 F0 58 20 69 F2 6C FC FF 20 2C FA 00 A0 00 F0 07 A9 52 A2 F0 4C 05 92 60 AD FF EF A2 00 60 8D FF EF 60 20 4F F2 C9 0A D0 05 A9 0D 20 4F F2 60 DA 5A A8 B2 04 AA A9 1B 20 4F F2 @@ -13,19 +13,19 @@ A9 63 20 4F F2 68 60 40 DA BA 48 E8 E8 BD 00 01 29 10 D0 06 68 FA 20 68 F2 40 68 FA 7C BF F0 C5 F0 C9 F0 CA F0 20 9A F0 40 40 20 68 F0 40 48 A0 04 B1 04 09 40 20 3F F2 88 B1 04 20 3F F2 88 10 -F8 68 09 01 20 3F F2 20 A9 FB 60 A2 08 A9 FF 20 +F8 68 09 01 20 3F F2 20 28 FB 60 A2 08 A9 FF 20 3F F2 C9 FF D0 03 CA D0 F4 60 85 0C 86 0D 20 EB -F0 92 0C A9 FF 20 3F F2 A0 01 91 0C 20 96 FB 60 -AA 20 20 FD A9 FF 20 3F F2 92 0C E6 0C D0 02 E6 +F0 92 0C A9 FF 20 3F F2 A0 01 91 0C 20 15 FB 60 +AA 20 9F FC A9 FF 20 3F F2 92 0C E6 0C D0 02 E6 0D CA D0 F0 60 85 0C 86 0D 20 EB F0 C9 02 B0 12 -E6 0C D0 02 E6 0C A5 0C A6 0D 20 4D FD A9 04 20 +E6 0C D0 02 E6 0C A5 0C A6 0D 20 CC FC A9 04 20 10 F1 60 48 A9 FF 20 3F F2 A9 00 20 33 F2 A9 FF 20 3F F2 68 20 CE F0 20 EB F0 A8 A9 FF 20 3F F2 A9 00 20 39 F2 A9 FF 20 3F F2 98 A2 00 60 A9 00 20 39 F2 20 8B F1 A9 FF 20 3F F2 A9 00 20 39 F2 A2 50 A9 FF 20 3F F2 CA D0 F8 60 A2 01 A9 C8 3A -D0 FD CA D0 F8 60 85 0E 86 0F A9 FF 92 0E 20 20 -FD A5 04 85 10 A5 05 85 11 20 51 FB A0 00 B1 10 +D0 FD CA D0 F8 60 85 0E 86 0F A9 FF 92 0E 20 9F +FC A5 04 85 10 A5 05 85 11 20 D0 FA A0 00 B1 10 91 04 C8 B1 10 91 04 C8 B1 10 91 04 C8 B1 10 91 04 A9 FF 20 3F F2 A9 00 20 33 F2 A9 FF 20 3F F2 A9 11 A0 04 91 04 A9 00 20 CE F0 20 EB F0 C9 FF @@ -37,211 +37,211 @@ EB A9 FF 20 3F F2 A9 FF 20 3F F2 A5 15 92 0E A5 F2 68 60 A9 01 8D DB EF 60 9C DB EF 60 A9 00 8D DA EF AD DB EF 30 FB AD D9 EF 60 8D E6 EF 60 48 8D E6 EF AD E7 EF 89 02 D0 F9 68 60 AD E6 EF A2 -00 60 AD E7 EF A2 00 60 60 20 74 FB A2 00 86 06 -86 07 A9 00 20 0B FC 20 5A FB A9 89 A2 FE 20 1A -FB 20 3A F3 C9 00 20 B8 FC D0 03 4C 98 F2 A9 81 -A2 FE 20 1A FB 4C 2E F3 A9 77 A2 FE 20 1A FB A0 -05 20 C7 FB 20 0B FC AD 00 92 AE 01 92 20 4D FD -A9 0C 20 D8 FB 20 96 F1 A0 07 91 04 A0 07 A2 00 -B1 04 C9 00 20 BE FC D0 03 4C DC F2 A0 06 A2 00 -B1 04 C9 FE 20 BE FC F0 03 4C E5 F2 A2 00 A9 00 +00 60 AD E7 EF A2 00 60 60 20 F3 FA A2 00 86 06 +86 07 A9 00 20 8A FB 20 D9 FA A9 05 A2 FE 20 99 +FA 20 3A F3 C9 00 20 37 FC D0 03 4C 98 F2 A9 FE +A2 FD 20 99 FA 4C 2E F3 A9 F5 A2 FD 20 99 FA A0 +05 20 46 FB 20 8A FB AD 00 92 AE 01 92 20 CC FC +A9 0C 20 57 FB 20 96 F1 A0 07 91 04 A0 07 A2 00 +B1 04 C9 00 20 3D FC D0 03 4C DC F2 A0 06 A2 00 +B1 04 C9 FE 20 3D FC F0 03 4C E5 F2 A2 00 A9 00 D0 03 4C E9 F2 A2 00 A9 01 D0 03 4C FA F2 AD 00 -92 AE 01 92 20 3C F6 4C 2B F3 A0 06 A2 00 B1 04 -A2 00 29 F0 20 9F FA D0 03 4C 16 F3 A9 81 A2 FE -20 1A FB 4C 2B F3 A9 67 A2 FE 20 4D FD A0 08 A2 -00 B1 04 20 4D FD A0 04 20 E6 FA 6C 00 92 4C 31 -F3 4C 31 F3 A0 0C 20 85 FA 60 20 81 FB A9 00 20 -37 FD 20 6E F1 4C 71 F3 A0 00 A2 00 18 A9 01 71 -04 91 04 A0 00 A2 00 B1 04 C9 FF 20 BE FC D0 03 -4C 71 F3 A9 AB A2 FE 20 1A FB A2 00 A9 01 4C A8 -F4 20 AC F4 A0 01 91 04 C9 01 20 B8 FC D0 C9 A2 -00 A9 00 A0 06 20 65 FD A0 07 20 BE FB E0 03 D0 -02 C9 E8 20 D7 FC F0 03 4C 9E F3 4C AA F3 A0 06 -A2 00 A9 01 20 75 FA 4C 88 F3 A9 01 20 D8 FB 20 -C9 F4 A0 01 A2 00 B1 04 C9 01 20 B8 FC D0 03 4C -D0 F3 A9 A1 A2 FE 20 1A FB A2 00 A9 01 4C A8 F4 -A0 05 A2 00 B1 04 C9 AA 20 B8 FC D0 03 4C E7 F3 -A2 00 A9 01 4C A8 F4 A2 00 A9 00 A0 00 91 04 A0 -00 A2 00 B1 04 C9 FF 20 BE FC D0 03 4C 0D F4 A9 -91 A2 FE 20 1A FB A2 00 A9 01 4C A8 F4 20 EB F5 -A0 01 91 04 A0 01 A2 00 B1 04 C9 02 20 D7 FC D0 -03 4C 2B F4 20 08 F6 A0 01 91 04 A2 00 A9 00 A0 -06 20 65 FD A0 07 20 BE FB E0 03 D0 02 C9 E8 20 -D7 FC F0 03 4C 4A F4 4C 56 F4 A0 06 A2 00 A9 01 -20 75 FA 4C 34 F4 A0 00 A2 00 18 A9 01 71 04 91 -04 A0 01 A2 00 B1 04 C9 00 20 B8 FC D0 81 A2 00 -A9 00 A0 06 20 65 FD A0 07 20 BE FB E0 03 D0 02 -C9 E8 20 D7 FC F0 03 4C 8D F4 4C 99 F4 A0 06 A2 -00 A9 01 20 75 FA 4C 77 F4 A9 01 20 D8 FB 20 71 -F5 A2 00 A9 00 4C A8 F4 20 AE FB 60 A2 00 A9 00 -20 37 FD A2 00 86 06 86 07 A9 00 20 0B FC A2 00 -A9 94 20 43 F1 4C C8 F4 60 20 4D FD A2 00 A9 FF -20 3F F2 A2 00 A9 00 20 33 F2 A2 00 A9 FF 20 3F -F2 A2 00 A9 08 20 37 FD A2 01 A9 00 85 06 A9 00 -85 07 A9 AA 20 0B FC A2 00 A9 86 20 CE F0 A0 01 -20 BE FB 20 25 F1 A2 00 A9 FF 20 3F F2 A2 00 A9 -00 20 39 F2 A2 00 A9 FF 20 3F F2 20 96 FB 60 20 -4D FD A2 00 A9 FF 20 3F F2 A2 00 A9 00 20 33 F2 -A2 00 A9 FF 20 3F F2 A2 00 A9 0D 20 37 FD A2 00 -86 06 86 07 A9 00 20 0B FC A2 00 A9 00 20 CE F0 -A0 01 20 BE FB 20 FA F0 A2 00 A9 FF 20 3F F2 A2 -00 A9 00 20 39 F2 A2 00 A9 FF 20 3F F2 20 96 FB -60 20 4D FD 20 51 FB A2 00 A9 FF 20 3F F2 A2 00 -A9 00 20 33 F2 A2 00 A9 FF 20 3F F2 A0 00 91 04 -A0 00 A2 00 B1 04 C9 FF 20 B8 FC D0 03 4C B1 F5 -4C A3 F5 A2 00 A9 FF 20 3F F2 C9 FF 20 B8 FC D0 -F2 A2 00 A9 3A 20 37 FD A2 00 86 06 86 07 A9 00 -20 0B FC A2 00 A9 00 20 CE F0 A0 02 20 BE FB 20 -25 F1 A2 00 A9 FF 20 3F F2 A2 00 A9 00 20 39 F2 -A2 00 A9 FF 20 3F F2 20 A4 FB 60 A2 00 A9 37 20 -37 FD A2 00 86 06 86 07 A9 00 20 0B FC A2 00 A9 -00 20 43 F1 4C 07 F6 60 A2 00 A9 29 20 37 FD A2 -00 86 06 A9 40 85 07 A9 00 20 0B FC A2 00 A9 00 -20 43 F1 4C 26 F6 60 20 4D FD 20 74 FB A0 03 A2 -00 B1 04 4C 36 F6 A0 0E 20 85 FA 60 20 4D FD A9 -00 20 37 FD 20 5A FB A2 00 A9 00 A0 00 20 65 FD -A0 01 20 BE FB E0 02 20 D7 FC F0 03 4C 62 F6 4C -C4 F6 A9 B5 A2 FE 20 4D FD A0 06 20 BE FB A0 00 -20 B3 FB 20 4D FD A0 07 A2 00 A9 01 20 75 FA A0 -04 20 E6 FA A0 02 A2 00 B1 04 C9 1F 20 BE FC D0 -03 4C A6 F6 A9 B9 A2 FE 20 1A FB A2 00 A9 00 A0 -02 91 04 4C B8 F6 A2 00 A9 20 20 68 F0 A0 02 A2 -00 18 A9 01 71 04 91 04 A0 00 A2 00 A9 01 20 75 -FA 4C 50 F6 A9 B9 A2 FE 20 1A FB 20 A9 FB 60 A0 -00 B1 1A E6 1A D0 02 E6 1B 60 AD 4A 92 8D 45 92 -20 7B F7 A9 45 A2 92 20 4D FD 20 2E FD 4C 02 92 -A5 18 38 E9 02 85 18 B0 02 C6 19 60 AD 4F 92 D0 -11 20 19 F7 4C 98 FA AD 4F 92 D0 06 20 19 F7 4C -92 FA 20 19 F7 85 06 86 07 20 F0 F6 A0 01 B1 18 -AA 88 B1 18 60 A0 00 84 0C 84 0D B1 1A 38 E9 30 -90 2C C9 0A B0 28 20 D3 F6 48 A5 0C A6 0D 06 0C -26 0D 06 0C 26 0D 65 0C 85 0C 8A 65 0D 85 0D 06 -0C 26 0D 68 65 0C 85 0C 90 D1 E6 0D B0 CD A5 0C -A6 0D 60 AC 51 92 EE 51 92 99 52 92 60 A9 52 A2 -92 18 6D 51 92 90 01 E8 4C 4D FD A5 1C A6 1D 4C -4D FD 20 DA F6 EE 4B 92 D0 F8 EE 4C 92 D0 F3 60 -20 7B F7 AD 66 92 AE 67 92 20 4D FD AD 68 92 AE -69 92 20 4D FD 4C 02 92 84 0C 20 0B FC 20 6D F7 -A5 0C 4C 3B FC 84 0C 20 0B FC 20 6D F7 A5 0C 4C -7C FC 48 A0 05 B9 18 00 99 3F 92 88 10 F7 68 85 -18 86 19 20 8E FB 85 1A 86 1B 20 8E FB 85 1C 86 -1D A9 00 A8 91 1C C8 91 1C C8 B1 1C 8D 03 92 C8 -B1 1C 8D 04 92 A5 1A 85 0C A5 1B 85 0D A0 00 B1 -1A F0 0B C9 25 F0 07 C8 D0 F5 E6 1B D0 F1 98 18 -65 1A 85 1A 90 02 E6 1B 38 E5 0C 85 0E A5 1B E5 -0D 85 0F 05 0E F0 25 20 74 FB A0 05 A5 1D 91 04 -88 A5 1C 91 04 88 A5 0D 91 04 88 A5 0C 91 04 88 -A5 0F 91 04 88 A5 0E 91 04 20 02 92 20 CF F6 AA -D0 0B A2 05 BD 3F 92 95 18 CA 10 F8 60 C9 25 D0 -09 B1 1A C9 25 D0 09 20 D3 F6 20 DD F6 4C F5 F7 -A9 00 A2 0B 9D 46 92 CA 10 FA B1 1A C9 2D D0 05 -8E 46 92 F0 19 C9 2B D0 05 8E 47 92 F0 10 C9 20 -D0 05 8E 48 92 F0 07 C9 23 D0 09 8E 49 92 20 D3 -F6 4C 7A F8 A2 20 C9 30 D0 06 AA 20 D3 F6 B1 1A -8E 4A 92 C9 2A D0 09 20 D3 F6 20 19 F7 4C C3 F8 -20 25 F7 8D 4B 92 8E 4C 92 8C 4D 92 8C 4E 92 B1 -1A C9 2E D0 1B 20 D3 F6 B1 1A C9 2A D0 09 20 D3 -F6 20 19 F7 4C EA F8 20 25 F7 8D 4D 92 8E 4E 92 -B1 1A C9 7A F0 19 C9 68 F0 15 C9 74 F0 11 C9 6A -F0 08 C9 4C F0 04 C9 6C D0 0B A9 FF 8D 4F 92 20 -D3 F6 4C F0 F8 8C 51 92 A2 52 8E 66 92 A2 92 8E -67 92 20 D3 F6 C9 63 D0 0D 20 19 F7 8D 52 92 A2 -00 A9 01 4C 1C FA C9 64 F0 04 C9 69 D0 2D A2 00 -AD 48 92 F0 02 A2 20 AD 47 92 F0 02 A2 2B 8E 50 -92 20 07 F7 A4 07 30 0B AC 50 92 F0 06 8C 52 92 -EE 51 92 A0 0A 20 A8 F7 4C 13 FA C9 6E D0 15 20 -19 F7 85 0C 86 0D A0 00 B1 1C 91 0C C8 B1 1C 91 -0C 4C F5 F7 C9 6F D0 27 20 07 F7 AC 49 92 F0 17 -48 86 14 05 14 05 06 05 07 0D 4D 92 0D 4E 92 F0 -06 A9 30 20 63 F7 68 A0 08 20 A8 F7 4C 13 FA C9 -70 D0 0D A2 00 8E 4F 92 E8 8E 49 92 A9 78 D0 27 -C9 73 D0 0C 20 19 F7 8D 66 92 8E 67 92 4C 13 FA -C9 75 D0 0B 20 FC F6 A0 0A 20 B5 F7 4C 13 FA C9 -78 F0 04 C9 58 D0 29 48 AD 49 92 F0 0A A9 30 20 -63 F7 A9 58 20 63 F7 20 FC F6 A0 10 20 B5 F7 68 -C9 78 D0 09 AD 66 92 AE 67 92 20 A5 FD 4C 13 FA -4C F5 F7 AD 66 92 AE 67 92 20 8F FD 8D 68 92 8E -69 92 AD 4D 92 0D 4E 92 F0 15 AE 4D 92 EC 68 92 -AD 4E 92 A8 ED 69 92 B0 06 8E 68 92 8C 69 92 38 -AD 4B 92 ED 68 92 AA AD 4C 92 ED 69 92 B0 03 A9 -00 AA 49 FF 8D 4C 92 8A 49 FF 8D 4B 92 AD 46 92 -D0 03 20 85 F7 20 90 F7 AD 46 92 F0 03 20 85 F7 -4C F5 F7 A0 00 18 71 04 91 04 48 C8 8A 71 04 91 -04 AA 68 60 C8 48 18 98 65 04 85 04 90 02 E6 05 -68 60 A0 FF E0 80 B0 02 A0 00 84 06 84 07 60 E0 -00 D0 06 AA D0 03 A9 01 60 A2 00 8A 60 A0 00 F0 -07 A9 52 A2 F0 4C 05 92 60 A9 00 85 0C A9 F0 85 -0D A9 00 85 0E A9 92 85 0F A2 CD A9 FF 85 14 A0 -00 E8 F0 0D B1 0C 91 0E C8 D0 F6 E6 0D E6 0F D0 -F0 E6 14 D0 EF 60 8C 6A 92 88 88 98 18 65 04 85 -0C A6 05 90 01 E8 86 0D A0 01 B1 0C AA 88 B1 0C -20 4D FD A5 0C A6 0D 20 14 FE AC 6A 92 4C 85 FA -85 0C 86 0D 20 75 F0 4C 1E FB 85 0C 86 0D A0 00 -B1 0C F0 0E C8 84 14 20 68 F0 A4 14 D0 F2 E6 0D -D0 EE 60 E0 00 D0 15 4A AA BD E3 FE 90 05 4A 4A -4A 4A 18 29 0F AA BD D8 FE A2 00 60 38 A9 00 AA -60 A4 04 D0 02 C6 05 C6 04 60 A5 04 38 E9 02 85 -04 90 01 60 C6 05 60 A5 04 38 E9 04 85 04 90 01 -60 C6 05 60 A5 04 38 E9 06 85 04 90 01 60 C6 05 -60 A5 04 38 E9 07 85 04 90 01 60 C6 05 60 A0 01 -B1 04 AA 88 B1 04 E6 04 F0 05 E6 04 F0 03 60 E6 -04 E6 05 60 A0 03 4C 85 FA A0 05 4C 85 FA A0 08 -4C 85 FA 85 0C 86 0D A2 00 B1 0C 60 A0 01 B1 04 -AA 88 B1 04 60 A0 03 B1 04 85 07 88 B1 04 85 06 -88 B1 04 AA 88 B1 04 60 A2 00 18 65 04 48 8A 65 -05 AA 68 60 18 49 FF 69 01 48 8A 49 FF 69 00 AA -A5 06 49 FF 69 00 85 06 A5 07 49 FF 69 00 85 07 -68 60 A9 00 AA A0 00 84 06 84 07 48 20 67 FB A0 -03 A5 07 91 04 88 A5 06 91 04 88 8A 91 04 68 88 -91 04 60 85 14 20 8E FB 85 0E 86 0F 85 10 86 11 -20 20 FD 20 8E FB 85 06 86 07 60 20 23 FC A6 07 -A4 14 C0 0A D0 39 A5 06 05 0D 05 0C D0 11 E0 80 -D0 0D A0 0B B9 CC FE 91 0E 88 10 F8 4C B3 FC 8A -10 1D A9 2D A0 00 91 0E E6 0E D0 02 E6 0F A5 0C -A6 0D 20 E4 FB 85 0C 86 0D 4C 7F FC 20 23 FC A9 -00 48 A0 20 A9 00 06 0C 26 0D 26 06 26 07 2A C5 -14 90 04 E5 14 E6 0C 88 D0 EC A8 B9 BC FE 48 A5 -0C 05 0D 05 06 05 07 D0 D9 A0 00 68 91 0E F0 03 -C8 D0 F8 A5 10 A6 11 60 D0 06 A2 00 8A 60 D0 FA -A2 00 A9 01 60 F0 F9 30 F7 A2 00 8A 60 F0 02 10 -EF A2 00 8A 60 F0 E9 90 E7 A2 00 8A 60 F0 DB A2 -00 8A 2A 60 20 0D FD A6 11 F0 13 B1 0C 91 0E C8 -B1 0C 91 0E C8 D0 F4 E6 0D E6 0F CA D0 ED A6 10 -F0 08 B1 0C 91 0E C8 CA D0 F8 4C 8E FB 85 10 86 -11 20 20 FD C8 B1 04 AA 86 0F 88 B1 04 85 0E 60 -A0 01 B1 04 85 0D 88 B1 04 85 0C 4C 96 FB A9 01 -4C 4B FD A0 00 B1 04 A4 04 F0 07 C6 04 A0 00 91 -04 60 C6 05 C6 04 91 04 60 A9 00 A2 00 48 A5 04 -38 E9 02 85 04 B0 02 C6 05 A0 01 8A 91 04 68 88 -91 04 60 A0 00 91 04 C8 48 8A 91 04 68 60 85 0E -86 0F 20 20 FD B1 0C D1 0E D0 0C AA F0 10 C8 D0 -F4 E6 0D E6 0F D0 EE B0 03 A2 FF 60 A2 01 60 85 -0E 86 0F A2 00 A0 00 B1 0E F0 08 C8 D0 F9 E6 0F -E8 D0 F4 98 60 85 0C 86 0D 85 0E 86 0F A0 00 B1 -0C F0 14 20 37 FB 29 02 F0 06 B1 0C 69 20 91 0C -C8 D0 EC E6 0D D0 E8 A5 0E A6 0F 60 20 8E FB 85 -0E 86 0F E8 8E 31 92 AA E8 8E 30 92 20 20 FD 20 -8E FB 85 10 86 11 A0 00 84 14 B1 10 18 65 0E 91 -10 C8 B1 10 65 0F 91 10 CE 30 92 F0 11 A4 14 B1 -0C C8 D0 02 E6 0D 84 14 20 68 F0 4C F8 FD CE 31 -92 D0 EA 60 85 0C 86 0D A9 00 8D 2A 92 8D 2B 92 -A0 01 B1 04 AA 88 B1 04 20 4D FD A0 02 A9 2A 91 -04 C8 A9 92 91 04 A5 0C A6 0D 20 C2 F7 AD 2A 92 -AE 2B 92 60 A9 32 85 0C A9 92 85 0D A9 00 A8 A2 -00 F0 0A 91 0C C8 D0 FB E6 0D CA D0 F6 C0 39 F0 -05 91 0C C8 D0 F7 60 62 61 64 20 74 6F 6B 65 6E -3A 20 25 78 0D 0A 00 53 75 63 63 65 73 73 0D 0A -00 45 72 72 6F 72 0D 0A 00 53 74 61 72 74 0D 0A -00 6F 70 5F 63 6F 6E 64 20 65 72 72 6F 72 0D 0A -00 49 46 20 43 6F 6E 64 0D 0A 00 47 6F 20 49 44 -4C 45 0D 0A 00 25 32 78 00 0D 0A 00 30 31 32 33 -34 35 36 37 38 39 41 42 43 44 45 46 2D 32 31 34 -37 34 38 33 36 34 38 00 00 01 02 0C 09 0A 10 40 -50 A0 D0 66 66 66 66 A6 88 88 66 66 66 66 66 66 -66 66 66 09 00 00 00 00 00 00 00 33 33 33 33 33 -00 00 00 50 55 55 25 22 22 22 22 22 22 22 22 22 -02 00 00 40 44 44 14 11 11 11 11 11 11 11 11 11 -01 00 70 00 00 00 00 00 00 00 00 00 00 00 00 00 +92 AE 01 92 20 BB F5 4C 2B F3 A0 06 A2 00 B1 04 +A2 00 29 F0 20 1E FA D0 03 4C 16 F3 A9 FE A2 FD +20 99 FA 4C 2B F3 A9 E6 A2 FD 20 CC FC A0 08 A2 +00 B1 04 20 CC FC A0 04 20 65 FA 6C 00 92 4C 31 +F3 4C 31 F3 A0 0C 20 04 FA 60 20 00 FB A9 00 20 +B6 FC 20 6E F1 4C 71 F3 A0 00 A2 00 18 A9 01 71 +04 91 04 A0 00 A2 00 B1 04 C9 FF 20 3D FC D0 03 +4C 71 F3 A9 24 A2 FE 20 99 FA A2 00 A9 01 4C 27 +F4 20 2B F4 A0 01 91 04 C9 01 20 37 FC D0 C9 A9 +01 20 57 FB 20 48 F4 A0 01 A2 00 B1 04 C9 01 20 +37 FC D0 03 4C A5 F3 A9 1B A2 FE 20 99 FA A2 00 +A9 01 4C 27 F4 A0 05 A2 00 B1 04 C9 AA 20 37 FC +D0 03 4C BC F3 A2 00 A9 01 4C 27 F4 A2 00 A9 00 +A0 00 91 04 A0 00 A2 00 B1 04 C9 FF 20 3D FC D0 +03 4C E2 F3 A9 0C A2 FE 20 99 FA A2 00 A9 01 4C +27 F4 20 6A F5 A0 01 91 04 A0 01 A2 00 B1 04 C9 +02 20 56 FC D0 03 4C 00 F4 20 87 F5 A0 01 91 04 +A0 00 A2 00 18 A9 01 71 04 91 04 A0 01 A2 00 B1 +04 C9 00 20 37 FC D0 AC A9 01 20 57 FB 20 F0 F4 +A2 00 A9 00 4C 27 F4 20 2D FB 60 A2 00 A9 00 20 +B6 FC A2 00 86 06 86 07 A9 00 20 8A FB A2 00 A9 +94 20 43 F1 4C 47 F4 60 20 CC FC A2 00 A9 FF 20 +3F F2 A2 00 A9 00 20 33 F2 A2 00 A9 FF 20 3F F2 +A2 00 A9 08 20 B6 FC A2 01 A9 00 85 06 A9 00 85 +07 A9 AA 20 8A FB A2 00 A9 86 20 CE F0 A0 01 20 +3D FB 20 25 F1 A2 00 A9 FF 20 3F F2 A2 00 A9 00 +20 39 F2 A2 00 A9 FF 20 3F F2 20 15 FB 60 20 CC +FC A2 00 A9 FF 20 3F F2 A2 00 A9 00 20 33 F2 A2 +00 A9 FF 20 3F F2 A2 00 A9 0D 20 B6 FC A2 00 86 +06 86 07 A9 00 20 8A FB A2 00 A9 00 20 CE F0 A0 +01 20 3D FB 20 FA F0 A2 00 A9 FF 20 3F F2 A2 00 +A9 00 20 39 F2 A2 00 A9 FF 20 3F F2 20 15 FB 60 +20 CC FC 20 D0 FA A2 00 A9 FF 20 3F F2 A2 00 A9 +00 20 33 F2 A2 00 A9 FF 20 3F F2 A0 00 91 04 A0 +00 A2 00 B1 04 C9 FF 20 37 FC D0 03 4C 30 F5 4C +22 F5 A2 00 A9 FF 20 3F F2 C9 FF 20 37 FC D0 F2 +A2 00 A9 3A 20 B6 FC A2 00 86 06 86 07 A9 00 20 +8A FB A2 00 A9 00 20 CE F0 A0 02 20 3D FB 20 25 +F1 A2 00 A9 FF 20 3F F2 A2 00 A9 00 20 39 F2 A2 +00 A9 FF 20 3F F2 20 23 FB 60 A2 00 A9 37 20 B6 +FC A2 00 86 06 86 07 A9 00 20 8A FB A2 00 A9 00 +20 43 F1 4C 86 F5 60 A2 00 A9 29 20 B6 FC A2 00 +86 06 A9 40 85 07 A9 00 20 8A FB A2 00 A9 00 20 +43 F1 4C A5 F5 60 20 CC FC 20 F3 FA A0 03 A2 00 +B1 04 4C B5 F5 A0 0E 20 04 FA 60 20 CC FC A9 00 +20 B6 FC 20 D9 FA A2 00 A9 00 A0 00 20 E4 FC A0 +01 20 3D FB E0 02 20 56 FC F0 03 4C E1 F5 4C 43 +F6 A9 2D A2 FE 20 CC FC A0 06 20 3D FB A0 00 20 +32 FB 20 CC FC A0 07 A2 00 A9 01 20 F4 F9 A0 04 +20 65 FA A0 02 A2 00 B1 04 C9 1F 20 3D FC D0 03 +4C 25 F6 A9 31 A2 FE 20 99 FA A2 00 A9 00 A0 02 +91 04 4C 37 F6 A2 00 A9 20 20 68 F0 A0 02 A2 00 +18 A9 01 71 04 91 04 A0 00 A2 00 A9 01 20 F4 F9 +4C CF F5 A9 31 A2 FE 20 99 FA 20 28 FB 60 A0 00 +B1 1A E6 1A D0 02 E6 1B 60 AD 4A 92 8D 45 92 20 +FA F6 A9 45 A2 92 20 CC FC 20 AD FC 4C 02 92 A5 +18 38 E9 02 85 18 B0 02 C6 19 60 AD 4F 92 D0 11 +20 98 F6 4C 17 FA AD 4F 92 D0 06 20 98 F6 4C 11 +FA 20 98 F6 85 06 86 07 20 6F F6 A0 01 B1 18 AA +88 B1 18 60 A0 00 84 0C 84 0D B1 1A 38 E9 30 90 +2C C9 0A B0 28 20 52 F6 48 A5 0C A6 0D 06 0C 26 +0D 06 0C 26 0D 65 0C 85 0C 8A 65 0D 85 0D 06 0C +26 0D 68 65 0C 85 0C 90 D1 E6 0D B0 CD A5 0C A6 +0D 60 AC 51 92 EE 51 92 99 52 92 60 A9 52 A2 92 +18 6D 51 92 90 01 E8 4C CC FC A5 1C A6 1D 4C CC +FC 20 59 F6 EE 4B 92 D0 F8 EE 4C 92 D0 F3 60 20 +FA F6 AD 66 92 AE 67 92 20 CC FC AD 68 92 AE 69 +92 20 CC FC 4C 02 92 84 0C 20 8A FB 20 EC F6 A5 +0C 4C BA FB 84 0C 20 8A FB 20 EC F6 A5 0C 4C FB +FB 48 A0 05 B9 18 00 99 3F 92 88 10 F7 68 85 18 +86 19 20 0D FB 85 1A 86 1B 20 0D FB 85 1C 86 1D +A9 00 A8 91 1C C8 91 1C C8 B1 1C 8D 03 92 C8 B1 +1C 8D 04 92 A5 1A 85 0C A5 1B 85 0D A0 00 B1 1A +F0 0B C9 25 F0 07 C8 D0 F5 E6 1B D0 F1 98 18 65 +1A 85 1A 90 02 E6 1B 38 E5 0C 85 0E A5 1B E5 0D +85 0F 05 0E F0 25 20 F3 FA A0 05 A5 1D 91 04 88 +A5 1C 91 04 88 A5 0D 91 04 88 A5 0C 91 04 88 A5 +0F 91 04 88 A5 0E 91 04 20 02 92 20 4E F6 AA D0 +0B A2 05 BD 3F 92 95 18 CA 10 F8 60 C9 25 D0 09 +B1 1A C9 25 D0 09 20 52 F6 20 5C F6 4C 74 F7 A9 +00 A2 0B 9D 46 92 CA 10 FA B1 1A C9 2D D0 05 8E +46 92 F0 19 C9 2B D0 05 8E 47 92 F0 10 C9 20 D0 +05 8E 48 92 F0 07 C9 23 D0 09 8E 49 92 20 52 F6 +4C F9 F7 A2 20 C9 30 D0 06 AA 20 52 F6 B1 1A 8E +4A 92 C9 2A D0 09 20 52 F6 20 98 F6 4C 42 F8 20 +A4 F6 8D 4B 92 8E 4C 92 8C 4D 92 8C 4E 92 B1 1A +C9 2E D0 1B 20 52 F6 B1 1A C9 2A D0 09 20 52 F6 +20 98 F6 4C 69 F8 20 A4 F6 8D 4D 92 8E 4E 92 B1 +1A C9 7A F0 19 C9 68 F0 15 C9 74 F0 11 C9 6A F0 +08 C9 4C F0 04 C9 6C D0 0B A9 FF 8D 4F 92 20 52 +F6 4C 6F F8 8C 51 92 A2 52 8E 66 92 A2 92 8E 67 +92 20 52 F6 C9 63 D0 0D 20 98 F6 8D 52 92 A2 00 +A9 01 4C 9B F9 C9 64 F0 04 C9 69 D0 2D A2 00 AD +48 92 F0 02 A2 20 AD 47 92 F0 02 A2 2B 8E 50 92 +20 86 F6 A4 07 30 0B AC 50 92 F0 06 8C 52 92 EE +51 92 A0 0A 20 27 F7 4C 92 F9 C9 6E D0 15 20 98 +F6 85 0C 86 0D A0 00 B1 1C 91 0C C8 B1 1C 91 0C +4C 74 F7 C9 6F D0 27 20 86 F6 AC 49 92 F0 17 48 +86 14 05 14 05 06 05 07 0D 4D 92 0D 4E 92 F0 06 +A9 30 20 E2 F6 68 A0 08 20 27 F7 4C 92 F9 C9 70 +D0 0D A2 00 8E 4F 92 E8 8E 49 92 A9 78 D0 27 C9 +73 D0 0C 20 98 F6 8D 66 92 8E 67 92 4C 92 F9 C9 +75 D0 0B 20 7B F6 A0 0A 20 34 F7 4C 92 F9 C9 78 +F0 04 C9 58 D0 29 48 AD 49 92 F0 0A A9 30 20 E2 +F6 A9 58 20 E2 F6 20 7B F6 A0 10 20 34 F7 68 C9 +78 D0 09 AD 66 92 AE 67 92 20 24 FD 4C 92 F9 4C +74 F7 AD 66 92 AE 67 92 20 0E FD 8D 68 92 8E 69 +92 AD 4D 92 0D 4E 92 F0 15 AE 4D 92 EC 68 92 AD +4E 92 A8 ED 69 92 B0 06 8E 68 92 8C 69 92 38 AD +4B 92 ED 68 92 AA AD 4C 92 ED 69 92 B0 03 A9 00 +AA 49 FF 8D 4C 92 8A 49 FF 8D 4B 92 AD 46 92 D0 +03 20 04 F7 20 0F F7 AD 46 92 F0 03 20 04 F7 4C +74 F7 A0 00 18 71 04 91 04 48 C8 8A 71 04 91 04 +AA 68 60 C8 48 18 98 65 04 85 04 90 02 E6 05 68 +60 A0 FF E0 80 B0 02 A0 00 84 06 84 07 60 E0 00 +D0 06 AA D0 03 A9 01 60 A2 00 8A 60 A0 00 F0 07 +A9 52 A2 F0 4C 05 92 60 A9 00 85 0C A9 F0 85 0D +A9 00 85 0E A9 92 85 0F A2 CD A9 FF 85 14 A0 00 +E8 F0 0D B1 0C 91 0E C8 D0 F6 E6 0D E6 0F D0 F0 +E6 14 D0 EF 60 8C 6A 92 88 88 98 18 65 04 85 0C +A6 05 90 01 E8 86 0D A0 01 B1 0C AA 88 B1 0C 20 +CC FC A5 0C A6 0D 20 93 FD AC 6A 92 4C 04 FA 85 +0C 86 0D 20 75 F0 4C 9D FA 85 0C 86 0D A0 00 B1 +0C F0 0E C8 84 14 20 68 F0 A4 14 D0 F2 E6 0D D0 +EE 60 E0 00 D0 15 4A AA BD 5A FE 90 05 4A 4A 4A +4A 18 29 0F AA BD 4F FE A2 00 60 38 A9 00 AA 60 +A4 04 D0 02 C6 05 C6 04 60 A5 04 38 E9 02 85 04 +90 01 60 C6 05 60 A5 04 38 E9 04 85 04 90 01 60 +C6 05 60 A5 04 38 E9 06 85 04 90 01 60 C6 05 60 +A5 04 38 E9 07 85 04 90 01 60 C6 05 60 A0 01 B1 +04 AA 88 B1 04 E6 04 F0 05 E6 04 F0 03 60 E6 04 +E6 05 60 A0 03 4C 04 FA A0 05 4C 04 FA A0 08 4C +04 FA 85 0C 86 0D A2 00 B1 0C 60 A0 01 B1 04 AA +88 B1 04 60 A0 03 B1 04 85 07 88 B1 04 85 06 88 +B1 04 AA 88 B1 04 60 A2 00 18 65 04 48 8A 65 05 +AA 68 60 18 49 FF 69 01 48 8A 49 FF 69 00 AA A5 +06 49 FF 69 00 85 06 A5 07 49 FF 69 00 85 07 68 +60 A9 00 AA A0 00 84 06 84 07 48 20 E6 FA A0 03 +A5 07 91 04 88 A5 06 91 04 88 8A 91 04 68 88 91 +04 60 85 14 20 0D FB 85 0E 86 0F 85 10 86 11 20 +9F FC 20 0D FB 85 06 86 07 60 20 A2 FB A6 07 A4 +14 C0 0A D0 39 A5 06 05 0D 05 0C D0 11 E0 80 D0 +0D A0 0B B9 43 FE 91 0E 88 10 F8 4C 32 FC 8A 10 +1D A9 2D A0 00 91 0E E6 0E D0 02 E6 0F A5 0C A6 +0D 20 63 FB 85 0C 86 0D 4C FE FB 20 A2 FB A9 00 +48 A0 20 A9 00 06 0C 26 0D 26 06 26 07 2A C5 14 +90 04 E5 14 E6 0C 88 D0 EC A8 B9 33 FE 48 A5 0C +05 0D 05 06 05 07 D0 D9 A0 00 68 91 0E F0 03 C8 +D0 F8 A5 10 A6 11 60 D0 06 A2 00 8A 60 D0 FA A2 +00 A9 01 60 F0 F9 30 F7 A2 00 8A 60 F0 02 10 EF +A2 00 8A 60 F0 E9 90 E7 A2 00 8A 60 F0 DB A2 00 +8A 2A 60 20 8C FC A6 11 F0 13 B1 0C 91 0E C8 B1 +0C 91 0E C8 D0 F4 E6 0D E6 0F CA D0 ED A6 10 F0 +08 B1 0C 91 0E C8 CA D0 F8 4C 0D FB 85 10 86 11 +20 9F FC C8 B1 04 AA 86 0F 88 B1 04 85 0E 60 A0 +01 B1 04 85 0D 88 B1 04 85 0C 4C 15 FB A9 01 4C +CA FC A0 00 B1 04 A4 04 F0 07 C6 04 A0 00 91 04 +60 C6 05 C6 04 91 04 60 A9 00 A2 00 48 A5 04 38 +E9 02 85 04 B0 02 C6 05 A0 01 8A 91 04 68 88 91 +04 60 A0 00 91 04 C8 48 8A 91 04 68 60 85 0E 86 +0F 20 9F FC B1 0C D1 0E D0 0C AA F0 10 C8 D0 F4 +E6 0D E6 0F D0 EE B0 03 A2 FF 60 A2 01 60 85 0E +86 0F A2 00 A0 00 B1 0E F0 08 C8 D0 F9 E6 0F E8 +D0 F4 98 60 85 0C 86 0D 85 0E 86 0F A0 00 B1 0C +F0 14 20 B6 FA 29 02 F0 06 B1 0C 69 20 91 0C C8 +D0 EC E6 0D D0 E8 A5 0E A6 0F 60 20 0D FB 85 0E +86 0F E8 8E 31 92 AA E8 8E 30 92 20 9F FC 20 0D +FB 85 10 86 11 A0 00 84 14 B1 10 18 65 0E 91 10 +C8 B1 10 65 0F 91 10 CE 30 92 F0 11 A4 14 B1 0C +C8 D0 02 E6 0D 84 14 20 68 F0 4C 77 FD CE 31 92 +D0 EA 60 85 0C 86 0D A9 00 8D 2A 92 8D 2B 92 A0 +01 B1 04 AA 88 B1 04 20 CC FC A0 02 A9 2A 91 04 +C8 A9 92 91 04 A5 0C A6 0D 20 41 F7 AD 2A 92 AE +2B 92 60 A9 32 85 0C A9 92 85 0D A9 00 A8 A2 00 +F0 0A 91 0C C8 D0 FB E6 0D CA D0 F6 C0 39 F0 05 +91 0C C8 D0 F7 60 62 61 64 20 74 6F 6B 65 6E 3A +20 25 78 0A 00 53 75 63 63 65 73 73 0A 00 45 72 +72 6F 72 0A 00 53 74 61 72 74 0A 00 6F 70 5F 63 +6F 6E 64 20 65 72 72 6F 72 0A 00 49 46 20 43 6F +6E 64 0A 00 47 6F 20 49 44 4C 45 0A 00 25 32 78 +00 0A 00 30 31 32 33 34 35 36 37 38 39 41 42 43 +44 45 46 2D 32 31 34 37 34 38 33 36 34 38 00 00 +01 02 0C 09 0A 10 40 50 A0 D0 66 66 66 66 A6 88 +88 66 66 66 66 66 66 66 66 66 09 00 00 00 00 00 +00 00 33 33 33 33 33 00 00 00 50 55 55 25 22 22 +22 22 22 22 22 22 22 02 00 00 40 44 44 14 11 11 +11 11 11 11 11 11 11 01 00 70 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/hw/efinix_fpga/simulation/Makefile b/hw/efinix_fpga/simulation/Makefile index c3b0f2e..e59b38c 100644 --- a/hw/efinix_fpga/simulation/Makefile +++ b/hw/efinix_fpga/simulation/Makefile @@ -1,20 +1,48 @@ -TARGETS= timer interrupt_controller spi_controller -TB=$(patsubst %, %_tb.sv, $(TARGETS)) +SRCS=$(shell find src/ -type f -name "*.*v") +SRCS+=$(shell find ../ip/ -type f -name "*.*v" -not \( -name "*tmpl*" \)) +SRCS+=$(shell find ../src/ -type f -name "*.*v") -all: $(TARGETS) +INC=$(shell find include/ -type f) -timer: timer_tb.sv - iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv +TEST_PROGRAM_NAME?=loop_test +TEST_FOLDER?=$(REPO_TOP)/sw/test_code/$(TEST_PROGRAM_NAME) +TEST_PROGRAM?=$(REPO_TOP)/sw/test_code/$(TEST_PROGRAM_NAME)/$(TEST_PROGRAM_NAME).hex -spi_controller: spi_controller_tb.sv ../spi_controller.sv - iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv +SD_IMAGE_PATH?=$(REPO_TOP)/sw/script/fs.fat.hex -interrupt_controller: interrupt_controller_tb.sv - iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv +#TODO implement something like sources.list + +TOP_MODULE=sim_top +TARGET=sim_top +INIT_MEM=init_hex.mem +SD_IMAGE=sd_image.mem +FLAGS=-DSIM -DRTL_SIM + +all: sim + +.PHONY: sim +sim: $(TARGET) + vvp $(TARGET) -fst + +.PHONY: full_sim +full_sim: $(TARGET) $(SD_IMAGE) + vvp $(TARGET) -fst + + +$(TARGET): $(INIT_MEM) $(SRCS) + iverilog -g2005-sv $(FLAGS) -s $(TOP_MODULE) -o $(TARGET) $(INC) $(SRCS) + +$(INIT_MEM): + $(MAKE) -C $(TEST_FOLDER) + cp $(TEST_PROGRAM) ./init_hex.mem + +# The script that makes this file uses relative paths +$(SD_IMAGE): + sh $(REPO_TOP)/sw/script/create_verilog_image.sh + cp $(SD_IMAGE_PATH) $(SD_IMAGE) .PHONY: clean - clean: - rm -f $(TARGETS) - rm -f *.vcd - rm -f *.vvp \ No newline at end of file + rm -rf $(TARGET) + rm -rf $(INIT_MEM) + rm -rf $(SD_IMAGE) diff --git a/hw/efinix_fpga/simulation/include/super6502_sdram_controller_define.vh b/hw/efinix_fpga/simulation/include/super6502_sdram_controller_define.vh new file mode 100644 index 0000000..3bbfa9a --- /dev/null +++ b/hw/efinix_fpga/simulation/include/super6502_sdram_controller_define.vh @@ -0,0 +1,80 @@ +// ============================================================================= +// Generated by efx_ipmgr +// Version: 2023.1.150 +// IP Version: 5.0 +// ============================================================================= + +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2023 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +//////////////////////////////////////////////////////////////////////////////// + +localparam fSYS_MHz = 100; +localparam fCK_MHz = 200; +localparam tIORT_u = 2; +localparam CL = 3; +localparam BL = 1; +localparam DDIO_TYPE = "SOFT"; +localparam DQ_WIDTH = 8; +localparam DQ_GROUP = 2; +localparam BA_WIDTH = 2; +localparam ROW_WIDTH = 13; +localparam COL_WIDTH = 9; +localparam tPWRUP = 200000; +localparam tRAS = 44; +localparam tRAS_MAX = 120000; +localparam tRC = 66; +localparam tRCD = 20; +localparam tREF = 64000000; +localparam tRFC = 66; +localparam tRP = 20; +localparam tWR = 2; +localparam tMRD = 2; +localparam SDRAM_MODE = "Native"; +localparam DATA_RATE = 2; +localparam AXI_AWADDR_WIDTH = 24; +localparam AXI_WDATA_WIDTH = 32; +localparam AXI_ARADDR_WIDTH = 24; +localparam AXI_RDATA_WIDTH = 32; +localparam AXI_AWID_WIDTH = 4; +localparam AXI_AWUSER_WIDTH = 2; +localparam AXI_WUSER_WIDTH = 2; +localparam AXI_BID_WIDTH = 4; +localparam AXI_BUSER_WIDTH = 2; +localparam AXI_ARID_WIDTH = 4; +localparam AXI_ARUSER_WIDTH = 3; +localparam AXI_RUSER_WIDTH = 3; diff --git a/hw/efinix_fpga/simulation/interrupt_controller_tb.sv b/hw/efinix_fpga/simulation/interrupt_controller_tb.sv deleted file mode 100644 index 7cd41e8..0000000 --- a/hw/efinix_fpga/simulation/interrupt_controller_tb.sv +++ /dev/null @@ -1,76 +0,0 @@ -module sim(); - -timeunit 10ns; -timeprecision 1ns; - -logic clk; -logic reset; -logic [2:0] addr; -logic [7:0] i_data; -logic [7:0] o_data; -logic cs; -logic rwb; - -logic irqb_master; -logic irqb0, irqb1, irqb2, irqb3, irqb4, irqb5, irqb6, irqb7; - -interrupt_controller dut( - .*); - -always #100 clk = clk === 1'b0; - -task write_reg(input logic [2:0] _addr, input logic [7:0] _data); - @(negedge clk); - cs <= '1; - addr <= _addr; - rwb <= '0; - i_data <= '1; - @(posedge clk); - i_data <= _data; - @(negedge clk); - cs <= '0; - rwb <= '1; -endtask - -task read_reg(input logic [2:0] _addr, output logic [7:0] _data); - @(negedge clk); - cs <= '1; - addr <= _addr; - rwb <= '1; - i_data <= '1; - @(posedge clk); - _data <= o_data; - @(negedge clk); - cs <= '0; - rwb <= '1; -endtask - -initial -begin - $dumpfile("interrupt_controller.vcd"); - $dumpvars(0,sim); -end - -initial begin - reset <= '1; - irqb0 <= '1; - irqb1 <= '1; - irqb2 <= '1; - irqb3 <= '1; - irqb4 <= '1; - irqb5 <= '1; - irqb6 <= '1; - irqb7 <= '1; - repeat(5) @(posedge clk); - reset <= '0; - - repeat(5) @(posedge clk); - - irqb0 <= '0; - - repeat(5) @(posedge clk); - - $finish(); -end - -endmodule diff --git a/hw/efinix_fpga/simulation/spi_controller_tb.sv b/hw/efinix_fpga/simulation/spi_controller_tb.sv deleted file mode 100644 index ad20da4..0000000 --- a/hw/efinix_fpga/simulation/spi_controller_tb.sv +++ /dev/null @@ -1,102 +0,0 @@ -module sim(); - -timeunit 10ns; -timeprecision 1ns; - -logic clk_50; - -logic i_clk; -logic i_rst; - -logic i_cs; -logic i_rwb; -logic [1:0] i_addr; -logic [7:0] i_data; -logic [7:0] o_data; - -logic o_spi_cs; -logic o_spi_clk; -logic o_spi_mosi; -logic i_spi_miso; - -spi_controller dut(.*); - -always #1 clk_50 = clk_50 === 1'b0; -always #100 i_clk = i_clk === 1'b0; - -task write_reg(input logic [2:0] _addr, input logic [7:0] _data); - @(negedge i_clk); - i_cs <= '1; - i_addr <= _addr; - i_rwb <= '0; - i_data <= '1; - @(posedge i_clk); - i_data <= _data; - @(negedge i_clk); - i_cs <= '0; - i_rwb <= '1; -endtask - -task read_reg(input logic [2:0] _addr, output logic [7:0] _data); - @(negedge i_clk); - i_cs <= '1; - i_addr <= _addr; - i_rwb <= '1; - i_data <= '1; - @(posedge i_clk); - _data <= o_data; - @(negedge i_clk); - i_cs <= '0; - i_rwb <= '1; -endtask - -initial -begin - $dumpfile("spi_controller.vcd"); - $dumpvars(0,sim); -end - -logic [7:0] data; - -initial begin - i_rst <= '1; - repeat(5) @(posedge i_clk); - i_cs <= '0; - i_rwb <= '1; - i_addr <= '0; - i_rst <= '0; - - repeat(5) @(posedge i_clk); - - write_reg(3, 1); - write_reg(2, 8'hFF); - data = (1 << 7); - while(data & (1 << 7)) begin - read_reg(3, data); - end - write_reg(3, 0); - read_reg(1, data); - assert(data == 8'h55); - - repeat(50) @(posedge i_clk); - - $finish(); -end - - -logic [7:0] _spi_device_data; - -initial begin - _spi_device_data <= 8'h55; -end - -always @(edge o_spi_clk) begin - if (o_spi_cs == '0) begin - if (o_spi_clk == '1) - i_spi_miso <= _spi_device_data[7]; - if (o_spi_clk == '0) - _spi_device_data <= _spi_device_data << 1; - end -end - -endmodule diff --git a/hw/efinix_fpga/simulation/src/generic_sdr.v b/hw/efinix_fpga/simulation/src/generic_sdr.v new file mode 100644 index 0000000..8cbcfcb --- /dev/null +++ b/hw/efinix_fpga/simulation/src/generic_sdr.v @@ -0,0 +1,1145 @@ +/************************************************************************** +* +* File Name: sdr.v +* Version: 2.2 +* Date: October 12th, 2010 +* Model: BUS Functional +* Simulator: Model Technology +* +* Dependencies: None +* +* Email: modelsupport@micron.com +* Company: Micron Technology, Inc. +* +* Description: Micron SDRAM Verilog model +* +* Limitation: - Doesn't check for refresh timing +* +* Note: - Set simulator resolution to "ps" accuracy +* - Set Debug = 0 to disable $display messages +* +* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +* +* Copyright � 2001 Micron Semiconductor Products, Inc. +* All rights researved +* +* Rev Author Date Changes +* --- -------------------------- --------------------------------------- +* 2.3 SH 05/12/2016 - Update tAC, tHZ timing +* Micron Technology Inc. +* +* 2.2 SH 10/12/2010 - Combine all parts into sdr_parameters.vh +* Micron Technology Inc. +* +* 2.1 SH 06/06/2002 - Typo in bank multiplex +* Micron Technology Inc. +* +* 2.0 SH 04/30/2002 - Second release +* Micron Technology Inc. +* +**************************************************************************/ + +`timescale 1ns / 1ps +`define x8 +`define CLK_200 +`define SYS_CLK_100 + +module generic_sdr (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm); + +`include "include/super6502_sdram_controller_define.vh" + +parameter tCK = 1000/fCK_MHz; // tCK ns Nominal Clock Cycle Time +`ifdef CLK_200 + parameter real tAC3 = 4.5; // tAC3 ns Access time from CLK (pos edge) CL = 3 + parameter real tAC2 = 4.5; // tAC2 ns Access time from CLK (pos edge) CL = 2 + parameter real tAC1 = 4.5; // tAC1 ns Parameter definition for compilation - CL = 1 illegal for sg75 +`elsif CLK_166 + parameter real tAC3 = 5.4; // tAC3 ns Access time from CLK (pos edge) CL = 3 + parameter real tAC2 = 5.4; // tAC2 ns Access time from CLK (pos edge) CL = 2 + parameter real tAC1 = 5.4; // tAC1 ns Parameter definition for compilation - CL = 1 illegal for sg75 +`elsif CLK_133 + parameter real tAC3 = 6.0; // tAC3 ns Access time from CLK (pos edge) CL = 3 + parameter real tAC2 = 6.0; // tAC2 ns Access time from CLK (pos edge) CL = 2 + parameter real tAC1 = 6.0; // tAC1 ns Parameter definition for compilation - CL = 1 illegal for sg75 +`endif + +`ifdef CLK_200 + parameter real tHZ3 = 4.5; // tHZ3 ns Data Out High Z time - CL = 3 + parameter real tHZ2 = 4.5; // tHZ2 ns Data Out High Z time - CL = 2 + parameter real tHZ1 = 4.5; // tHZ1 ns Parameter definition for compilation - CL = 1 illegal for sg75 +`elsif CLK_166 + parameter real tHZ3 = 5.4; // tHZ3 ns Data Out High Z time - CL = 3 + parameter real tHZ2 = 5.4; // tHZ2 ns Data Out High Z time - CL = 2 + parameter real tHZ1 = 5.4; // tHZ1 ns Parameter definition for compilation - CL = 1 illegal for sg75 +`elsif CLK_133 + parameter real tHZ3 = 6.0; // tHZ3 ns Data Out High Z time - CL = 3 + parameter real tHZ2 = 6.0; // tHZ2 ns Data Out High Z time - CL = 2 + parameter real tHZ1 = 6.0; // tHZ1 ns Parameter definition for compilation - CL = 1 illegal for sg75 +`endif + +parameter tOH = 2.7; // tOH ns Data Out Hold time +parameter tRRD = 2.0; // tRRD tCK Active bank a to Active bank b command time (2 * tCK) +parameter tWRa = tCK; // tWR ns Write recovery time (auto-precharge mode - must add 1 CLK) +parameter tWRm = 2*tCK; // tWR ns Write recovery time +parameter ADDR_BITS = ROW_WIDTH; // Set this parameter to control how many Address bits are used +parameter ROW_BITS = ROW_WIDTH; // Set this parameter to control how many Row bits are used +parameter COL_BITS = COL_WIDTH; // Set this parameter to control how many Column bits are used +parameter DQ_BITS = DQ_WIDTH; // Set this parameter to control how many Data bits are used +parameter DM_BITS = 1; // Set this parameter to control how many DM bits are used +parameter BA_BITS = BA_WIDTH; // Bank bits +parameter mem_sizes = 2**(ROW_BITS+COL_BITS) - 1; + + input Clk; + input Cke; + input Cs_n; + input Ras_n; + input Cas_n; + input We_n; + input [ADDR_BITS - 1 : 0] Addr; + input [BA_BITS - 1 : 0] Ba; + inout [DQ_BITS - 1 : 0] Dq; + input [DM_BITS - 1 : 0] Dqm; + + reg [DQ_BITS - 1 : 0] Bank0 [0 : mem_sizes]; + reg [DQ_BITS - 1 : 0] Bank1 [0 : mem_sizes]; + reg [DQ_BITS - 1 : 0] Bank2 [0 : mem_sizes]; + reg [DQ_BITS - 1 : 0] Bank3 [0 : mem_sizes]; + + reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline + reg [COL_BITS - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline + reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline + reg [1 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline + reg [ADDR_BITS - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr; + + reg [ADDR_BITS - 1 : 0] Mode_reg; + reg [DQ_BITS - 1 : 0] Dq_reg, Dq_dqm; + reg [COL_BITS - 1 : 0] Col_temp, Burst_counter; + + reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate + reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge + + reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command + reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks) + reg Auto_precharge [0 : 3]; // RW Auto Precharge (Bank) + reg Read_precharge [0 : 3]; // R Auto Precharge + reg Write_precharge [0 : 3]; // W Auto Precharge + reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge + reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge + reg [1 : 0] RW_interrupt_bank; // RW Interrupt Bank + integer RW_interrupt_counter [0 : 3]; // RW Interrupt Counter + integer Count_precharge [0 : 3]; // RW Auto Precharge Counter + + reg Data_in_enable; + reg Data_out_enable; + + reg [1 : 0] Bank, Prev_bank; + reg [ADDR_BITS - 1 : 0] Row; + reg [COL_BITS - 1 : 0] Col, Col_brst; + + // Internal system clock + reg CkeZ, Sys_clk; + + // Commands Decode + wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n; + wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n; + wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n; + wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n; + wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n; + wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n; + wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n; + + // Burst Length Decode + wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0]; + wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0]; + wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0]; + wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0]; + wire Burst_length_f = Mode_reg[2] & Mode_reg[1] & Mode_reg[0]; + + // CAS Latency Decode + wire [2 : 0] Cas_latency = {Mode_reg[6], Mode_reg[5], Mode_reg[4]}; + + // Write Burst Mode + wire Write_burst_mode = Mode_reg[9]; + + wire Debug = 1'b0; // Debug messages : 1 = On + wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ + + assign Dq = Dq_reg; // DQ buffer + + // Commands Operation + `define ACT 0 + `define NOP 1 + `define READ 2 + `define WRITE 3 + `define PRECH 4 + `define A_REF 5 + `define BST 6 + `define LMR 7 + + // These timing dynamically adjust based on CAS Latency + time tAC, tHZ; + + // Timing Check variable + time MRD_chk; + time WR_chkm [0 : 3]; + time RFC_chk, RRD_chk; + time RC_chk0, RC_chk1, RC_chk2, RC_chk3; + time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; + time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; + time RP_chk0, RP_chk1, RP_chk2, RP_chk3; + + initial begin + Dq_reg = {DQ_BITS{1'bz}}; + Data_in_enable = 0; Data_out_enable = 0; + Act_b0 = 1; Act_b1 = 1; Act_b2 = 1; Act_b3 = 1; + Pc_b0 = 0; Pc_b1 = 0; Pc_b2 = 0; Pc_b3 = 0; + WR_chkm[0] = 0; WR_chkm[1] = 0; WR_chkm[2] = 0; WR_chkm[3] = 0; + RW_interrupt_read[0] = 0; RW_interrupt_read[1] = 0; RW_interrupt_read[2] = 0; RW_interrupt_read[3] = 0; + RW_interrupt_write[0] = 0; RW_interrupt_write[1] = 0; RW_interrupt_write[2] = 0; RW_interrupt_write[3] = 0; + MRD_chk = 0; RFC_chk = 0; RRD_chk = 0; + RAS_chk0 = 0; RAS_chk1 = 0; RAS_chk2 = 0; RAS_chk3 = 0; + RCD_chk0 = 0; RCD_chk1 = 0; RCD_chk2 = 0; RCD_chk3 = 0; + RC_chk0 = 0; RC_chk1 = 0; RC_chk2 = 0; RC_chk3 = 0; + RP_chk0 = 0; RP_chk1 = 0; RP_chk2 = 0; RP_chk3 = 0; + $timeformat (-9, 1, " ns", 12); + end + + // System clock generator + always begin + @ (posedge Clk) begin + Sys_clk = CkeZ; + CkeZ = Cke; + end + @ (negedge Clk) begin + Sys_clk = 1'b0; + end + end + + // Adjust tAC, tHZ based on CAS Latency + always @ (Cas_latency) begin + case (Cas_latency) + 1 : begin tAC = tAC1; tHZ = tHZ1; end + 2 : begin tAC = tAC2; tHZ = tHZ2; end + 3 : begin tAC = tAC3; tHZ = tHZ3; end + endcase + end + + always @ (posedge Sys_clk) begin + // Internal Commamd Pipelined + Command[0] = Command[1]; + Command[1] = Command[2]; + Command[2] = Command[3]; + Command[3] = `NOP; + + Col_addr[0] = Col_addr[1]; + Col_addr[1] = Col_addr[2]; + Col_addr[2] = Col_addr[3]; + Col_addr[3] = {COL_BITS{1'b0}}; + + Bank_addr[0] = Bank_addr[1]; + Bank_addr[1] = Bank_addr[2]; + Bank_addr[2] = Bank_addr[3]; + Bank_addr[3] = 2'b0; + + Bank_precharge[0] = Bank_precharge[1]; + Bank_precharge[1] = Bank_precharge[2]; + Bank_precharge[2] = Bank_precharge[3]; + Bank_precharge[3] = 2'b0; + + A10_precharge[0] = A10_precharge[1]; + A10_precharge[1] = A10_precharge[2]; + A10_precharge[2] = A10_precharge[3]; + A10_precharge[3] = 1'b0; + + // Dqm pipeline for Read + Dqm_reg0 = Dqm_reg1; + Dqm_reg1 = Dqm; + + // Read or Write with Auto Precharge Counter + if (Auto_precharge[0] === 1'b1) begin + Count_precharge[0] = Count_precharge[0] + 1; + end + if (Auto_precharge[1] === 1'b1) begin + Count_precharge[1] = Count_precharge[1] + 1; + end + if (Auto_precharge[2] === 1'b1) begin + Count_precharge[2] = Count_precharge[2] + 1; + end + if (Auto_precharge[3] === 1'b1) begin + Count_precharge[3] = Count_precharge[3] + 1; + end + + // Read or Write Interrupt Counter + if (RW_interrupt_write[0] === 1'b1) begin + RW_interrupt_counter[0] = RW_interrupt_counter[0] + 1; + end + if (RW_interrupt_write[1] === 1'b1) begin + RW_interrupt_counter[1] = RW_interrupt_counter[1] + 1; + end + if (RW_interrupt_write[2] === 1'b1) begin + RW_interrupt_counter[2] = RW_interrupt_counter[2] + 1; + end + if (RW_interrupt_write[3] === 1'b1) begin + RW_interrupt_counter[3] = RW_interrupt_counter[3] + 1; + end + + // tMRD Counter + MRD_chk = MRD_chk + 1; + + // Auto Refresh + if (Aref_enable === 1'b1) begin + if (Debug) begin + $display ("%m : at time %t AREF : Auto Refresh", $time); + end + + // Auto Refresh to Auto Refresh + if ($time - RFC_chk < tRFC) begin + $display ("%m : at time %t ERROR: tRFC violation during Auto Refresh", $time); + end + + // Precharge to Auto Refresh + if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) || + ($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin + $display ("%m : at time %t ERROR: tRP violation during Auto Refresh", $time); + end + + // Precharge to Refresh + if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin + $display ("%m : at time %t ERROR: All banks must be Precharge before Auto Refresh", $time); + end + + // Load Mode Register to Auto Refresh + if (MRD_chk < tMRD) begin + $display ("%m : at time %t ERROR: tMRD violation during Auto Refresh", $time); + end + + // Record Current tRFC time + RFC_chk = $time; + end + + // Load Mode Register + if (Mode_reg_enable === 1'b1) begin + // Register Mode + Mode_reg = Addr; + + // Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode + if (Debug) begin + $display ("%m : at time %t LMR : Load Mode Register", $time); + // CAS Latency + case (Addr[6 : 4]) + 3'b010 : $display ("%m : CAS Latency = 2"); + 3'b011 : $display ("%m : CAS Latency = 3"); + default : $display ("%m : CAS Latency = Reserved"); + endcase + + // Burst Length + case (Addr[2 : 0]) + 3'b000 : $display ("%m : Burst Length = 1"); + 3'b001 : $display ("%m : Burst Length = 2"); + 3'b010 : $display ("%m : Burst Length = 4"); + 3'b011 : $display ("%m : Burst Length = 8"); + 3'b111 : $display ("%m : Burst Length = Full"); + default : $display ("%m : Burst Length = Reserved"); + endcase + + // Burst Type + if (Addr[3] === 1'b0) begin + $display ("%m : Burst Type = Sequential"); + end else if (Addr[3] === 1'b1) begin + $display ("%m : Burst Type = Interleaved"); + end else begin + $display ("%m : Burst Type = Reserved"); + end + + // Write Burst Mode + if (Addr[9] === 1'b0) begin + $display ("%m : Write Burst Mode = Programmed Burst Length"); + end else if (Addr[9] === 1'b1) begin + $display ("%m : Write Burst Mode = Single Location Access"); + end else begin + $display ("%m : Write Burst Mode = Reserved"); + end + end + + // Precharge to Load Mode Register + if (Pc_b0 === 1'b0 && Pc_b1 === 1'b0 && Pc_b2 === 1'b0 && Pc_b3 === 1'b0) begin + $display ("%m : at time %t ERROR: all banks must be Precharge before Load Mode Register", $time); + end + + // Precharge to Load Mode Register + if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) || + ($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin + $display ("%m : at time %t ERROR: tRP violation during Load Mode Register", $time); + end + + // Auto Refresh to Load Mode Register + if ($time - RFC_chk < tRFC) begin + $display ("%m : at time %t ERROR: tRFC violation during Load Mode Register", $time); + end + + // Load Mode Register to Load Mode Register + if (MRD_chk < tMRD) begin + $display ("%m : at time %t ERROR: tMRD violation during Load Mode Register", $time); + end + + // Reset MRD Counter + MRD_chk = 0; + end + + // Active Block (Latch Bank Address and Row Address) + if (Active_enable === 1'b1) begin + // Activate an open bank can corrupt data + if ((Ba === 2'b00 && Act_b0 === 1'b1) || (Ba === 2'b01 && Act_b1 === 1'b1) || + (Ba === 2'b10 && Act_b2 === 1'b1) || (Ba === 2'b11 && Act_b3 === 1'b1)) begin + $display ("%m : at time %t ERROR: Bank already activated -- data can be corrupted", $time); + end + + // Activate Bank 0 + if (Ba === 2'b00 && Pc_b0 === 1'b1) begin + // Debug Message + if (Debug) begin + $display ("%m : at time %t ACT : Bank = 0 Row = %d", $time, Addr); + end + + // ACTIVE to ACTIVE command period + if ($time - RC_chk0 < tRC) begin + $display ("%m : at time %t ERROR: tRC violation during Activate bank 0", $time); + end + + // Precharge to Activate Bank 0 + if ($time - RP_chk0 < tRP) begin + $display ("%m : at time %t ERROR: tRP violation during Activate bank 0", $time); + end + + // Record variables + Act_b0 = 1'b1; + Pc_b0 = 1'b0; + B0_row_addr = Addr [ADDR_BITS - 1 : 0]; + RAS_chk0 = $time; + RC_chk0 = $time; + RCD_chk0 = $time; + end + + if (Ba == 2'b01 && Pc_b1 == 1'b1) begin + // Debug Message + if (Debug) begin + $display ("%m : at time %t ACT : Bank = 1 Row = %d", $time, Addr); + end + + // ACTIVE to ACTIVE command period + if ($time - RC_chk1 < tRC) begin + $display ("%m : at time %t ERROR: tRC violation during Activate bank 1", $time); + end + + // Precharge to Activate Bank 1 + if ($time - RP_chk1 < tRP) begin + $display ("%m : at time %t ERROR: tRP violation during Activate bank 1", $time); + end + + // Record variables + Act_b1 = 1'b1; + Pc_b1 = 1'b0; + B1_row_addr = Addr [ADDR_BITS - 1 : 0]; + RAS_chk1 = $time; + RC_chk1 = $time; + RCD_chk1 = $time; + end + + if (Ba == 2'b10 && Pc_b2 == 1'b1) begin + // Debug Message + if (Debug) begin + $display ("%m : at time %t ACT : Bank = 2 Row = %d", $time, Addr); + end + + // ACTIVE to ACTIVE command period + if ($time - RC_chk2 < tRC) begin + $display ("%m : at time %t ERROR: tRC violation during Activate bank 2", $time); + end + + // Precharge to Activate Bank 2 + if ($time - RP_chk2 < tRP) begin + $display ("%m : at time %t ERROR: tRP violation during Activate bank 2", $time); + end + + // Record variables + Act_b2 = 1'b1; + Pc_b2 = 1'b0; + B2_row_addr = Addr [ADDR_BITS - 1 : 0]; + RAS_chk2 = $time; + RC_chk2 = $time; + RCD_chk2 = $time; + end + + if (Ba == 2'b11 && Pc_b3 == 1'b1) begin + // Debug Message + if (Debug) begin + $display ("%m : at time %t ACT : Bank = 3 Row = %d", $time, Addr); + end + + // ACTIVE to ACTIVE command period + if ($time - RC_chk3 < tRC) begin + $display ("%m : at time %t ERROR: tRC violation during Activate bank 3", $time); + end + + // Precharge to Activate Bank 3 + if ($time - RP_chk3 < tRP) begin + $display ("%m : at time %t ERROR: tRP violation during Activate bank 3", $time); + end + + // Record variables + Act_b3 = 1'b1; + Pc_b3 = 1'b0; + B3_row_addr = Addr [ADDR_BITS - 1 : 0]; + RAS_chk3 = $time; + RC_chk3 = $time; + RCD_chk3 = $time; + end + + // Active Bank A to Active Bank B + if ((Prev_bank != Ba) && ($time - RRD_chk < tRRD)) begin + $display ("%m : at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba); + end + + // Auto Refresh to Activate + if ($time - RFC_chk < tRFC) begin + $display ("%m : at time %t ERROR: tRFC violation during Activate bank = %d", $time, Ba); + end + + // Load Mode Register to Active + if (MRD_chk < tMRD ) begin + $display ("%m : at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba); + end + + // Record variables for checking violation + RRD_chk = $time; + Prev_bank = Ba; + end + + // Precharge Block + if (Prech_enable == 1'b1) begin + // Load Mode Register to Precharge + if ($time - MRD_chk < tMRD) begin + $display ("%m : at time %t ERROR: tMRD violaiton during Precharge", $time); + end + + // Precharge Bank 0 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b00)) && Act_b0 === 1'b1) begin + Act_b0 = 1'b0; + Pc_b0 = 1'b1; + RP_chk0 = $time; + + // Debug Message + if (Debug) begin + $display ("%m : at time %t PRECHARGE : Bank = 0", $time); + end + + // Activate to Precharge + if ($time - RAS_chk0 < tRAS) begin + $display ("%m : at time %t ERROR: tRAS violation during Precharge", $time); + end + + // tWR violation check for write + if ($time - WR_chkm[0] < tWRm) begin + $display ("%m : at time %t ERROR: tWR violation during Precharge", $time); + end + end + + // Precharge Bank 1 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b01)) && Act_b1 === 1'b1) begin + Act_b1 = 1'b0; + Pc_b1 = 1'b1; + RP_chk1 = $time; + + // Debug Message + if (Debug) begin + $display ("%m : at time %t PRECHARGE : Bank = 1", $time); + end + + // Activate to Precharge + if ($time - RAS_chk1 < tRAS) begin + $display ("%m : at time %t ERROR: tRAS violation during Precharge", $time); + end + + // tWR violation check for write + if ($time - WR_chkm[1] < tWRm) begin + $display ("%m : at time %t ERROR: tWR violation during Precharge", $time); + end + end + + // Precharge Bank 2 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b10)) && Act_b2 === 1'b1) begin + Act_b2 = 1'b0; + Pc_b2 = 1'b1; + RP_chk2 = $time; + + // Debug Message + if (Debug) begin + $display ("%m : at time %t PRECHARGE : Bank = 2", $time); + end + + // Activate to Precharge + if ($time - RAS_chk2 < tRAS) begin + $display ("%m : at time %t ERROR: tRAS violation during Precharge", $time); + end + + // tWR violation check for write + if ($time - WR_chkm[2] < tWRm) begin + $display ("%m : at time %t ERROR: tWR violation during Precharge", $time); + end + end + + // Precharge Bank 3 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b11)) && Act_b3 === 1'b1) begin + Act_b3 = 1'b0; + Pc_b3 = 1'b1; + RP_chk3 = $time; + + // Debug Message + if (Debug) begin + $display ("%m : at time %t PRECHARGE : Bank = 3", $time); + end + + // Activate to Precharge + if ($time - RAS_chk3 < tRAS) begin + $display ("%m : at time %t ERROR: tRAS violation during Precharge", $time); + end + + // tWR violation check for write + if ($time - WR_chkm[3] < tWRm) begin + $display ("%m : at time %t ERROR: tWR violation during Precharge", $time); + end + end + + // Precharge truncation with DQM set + if ((Data_in_enable == 1'b1) && ~(&Dqm)) begin + $display ("%m : at time %t ERROR: DQM not asserted during Precharge truncation", $time); + end + + // Terminate a Write Immediately (if same bank or all banks) + if (Data_in_enable === 1'b1 && (Bank === Ba || Addr[10] === 1'b1)) begin + Data_in_enable = 1'b0; + end + + // Precharge Command Pipeline for Read + Command[Cas_latency - 1] = `PRECH; + Bank_precharge[Cas_latency - 1] = Ba; + A10_precharge[Cas_latency - 1] = Addr[10]; + end + + // Burst terminate + if (Burst_term === 1'b1) begin + // Terminate a Write Immediately + if (Data_in_enable == 1'b1) begin + Data_in_enable = 1'b0; + end + + // Terminate a Read Depend on CAS Latency + Command[Cas_latency - 1] = `BST; + + // Display debug message + if (Debug) begin + $display ("%m : at time %t BST : Burst Terminate",$time); + end + end + + // Read, Write, Column Latch + if (Read_enable === 1'b1) begin + // Check to see if bank is open (ACT) + if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) || + (Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin + $display("%m : at time %t ERROR: Bank is not Activated for Read", $time); + end + + // Activate to Read or Write + if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD) || + (Ba == 2'b01) && ($time - RCD_chk1 < tRCD) || + (Ba == 2'b10) && ($time - RCD_chk2 < tRCD) || + (Ba == 2'b11) && ($time - RCD_chk3 < tRCD)) begin + $display("%m : at time %t ERROR: tRCD violation during Read", $time); + end + + // CAS Latency pipeline + Command[Cas_latency - 1] = `READ; + Col_addr[Cas_latency - 1] = Addr; + Bank_addr[Cas_latency - 1] = Ba; + + // Read interrupt Write (terminate Write immediately) + if (Data_in_enable == 1'b1) begin + Data_in_enable = 1'b0; + + // Interrupting a Write with Autoprecharge + if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin + RW_interrupt_write[RW_interrupt_bank] = 1'b1; + RW_interrupt_counter[RW_interrupt_bank] = 0; + + // Display debug message + if (Debug) begin + $display ("%m : at time %t NOTE : Read interrupt Write with Autoprecharge", $time); + end + end + end + + // Read with Auto Precharge + if (Addr[10] == 1'b1) begin + Auto_precharge[Ba] = 1'b1; + Count_precharge[Ba] = 0; + RW_interrupt_bank = Ba; + Read_precharge[Ba] = 1'b1; + end + end + + // Write Command + if (Write_enable == 1'b1) begin + // Activate to Write + if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) || + (Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin + $display("%m : at time %t ERROR: Bank is not Activated for Write", $time); + end + + // Activate to Read or Write + if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD) || + (Ba == 2'b01) && ($time - RCD_chk1 < tRCD) || + (Ba == 2'b10) && ($time - RCD_chk2 < tRCD) || + (Ba == 2'b11) && ($time - RCD_chk3 < tRCD)) begin + $display("%m : at time %t ERROR: tRCD violation during Read", $time); + end + + // Latch Write command, Bank, and Column + Command[0] = `WRITE; + Col_addr[0] = Addr; + Bank_addr[0] = Ba; + + // Write interrupt Write (terminate Write immediately) + if (Data_in_enable == 1'b1) begin + Data_in_enable = 1'b0; + + // Interrupting a Write with Autoprecharge + if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin + RW_interrupt_write[RW_interrupt_bank] = 1'b1; + + // Display debug message + if (Debug) begin + $display ("%m : at time %t NOTE : Read Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank); + end + end + end + + // Write interrupt Read (terminate Read immediately) + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + + // Interrupting a Read with Autoprecharge + if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin + RW_interrupt_read[RW_interrupt_bank] = 1'b1; + + // Display debug message + if (Debug) begin + $display ("%m : at time %t NOTE : Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank); + end + end + end + + // Write with Auto Precharge + if (Addr[10] == 1'b1) begin + Auto_precharge[Ba] = 1'b1; + Count_precharge[Ba] = 0; + RW_interrupt_bank = Ba; + Write_precharge[Ba] = 1'b1; + end + end + + /* + Write with Auto Precharge Calculation + The device start internal precharge when: + 1. Meet minimum tRAS requirement + and 2. tWR cycle(s) after last valid data + or 3. Interrupt by a Read or Write (with or without Auto Precharge) + + Note: Model is starting the internal precharge 1 cycle after they meet all the + requirement but tRP will be compensate for the time after the 1 cycle. + */ + if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin + if ((($time - RAS_chk0 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) || + (RW_interrupt_write[0] == 1'b1 && RW_interrupt_counter[0] >= 1)) begin // Case 3 + Auto_precharge[0] = 1'b0; + Write_precharge[0] = 1'b0; + RW_interrupt_write[0] = 1'b0; + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); + end + end + end + if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin + if ((($time - RAS_chk1 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) || + (RW_interrupt_write[1] == 1'b1 && RW_interrupt_counter[1] >= 1)) begin // Case 3 + Auto_precharge[1] = 1'b0; + Write_precharge[1] = 1'b0; + RW_interrupt_write[1] = 1'b0; + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); + end + end + end + if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin + if ((($time - RAS_chk2 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) || + (RW_interrupt_write[2] == 1'b1 && RW_interrupt_counter[2] >= 1)) begin // Case 3 + Auto_precharge[2] = 1'b0; + Write_precharge[2] = 1'b0; + RW_interrupt_write[2] = 1'b0; + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); + end + end + end + if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin + if ((($time - RAS_chk3 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) || + (RW_interrupt_write[3] == 1'b1 && RW_interrupt_counter[3] >= 1)) begin // Case 3 + Auto_precharge[3] = 1'b0; + Write_precharge[3] = 1'b0; + RW_interrupt_write[3] = 1'b0; + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); + end + end + end + + // Read with Auto Precharge Calculation + // The device start internal precharge: + // 1. Meet minimum tRAS requirement + // and 2. CAS Latency - 1 cycles before last burst + // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) + if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin + if ((($time - RAS_chk0 >= tRAS) && // Case 1 + ((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) || + (RW_interrupt_read[0] == 1'b1)) begin // Case 3 + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $time; + Auto_precharge[0] = 1'b0; + Read_precharge[0] = 1'b0; + RW_interrupt_read[0] = 1'b0; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); + end + end + end + if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin + if ((($time - RAS_chk1 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) || + (RW_interrupt_read[1] == 1'b1)) begin + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $time; + Auto_precharge[1] = 1'b0; + Read_precharge[1] = 1'b0; + RW_interrupt_read[1] = 1'b0; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); + end + end + end + if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin + if ((($time - RAS_chk2 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) || + (RW_interrupt_read[2] == 1'b1)) begin + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $time; + Auto_precharge[2] = 1'b0; + Read_precharge[2] = 1'b0; + RW_interrupt_read[2] = 1'b0; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); + end + end + end + if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin + if ((($time - RAS_chk3 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) || + (RW_interrupt_read[3] == 1'b1)) begin + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $time; + Auto_precharge[3] = 1'b0; + Read_precharge[3] = 1'b0; + RW_interrupt_read[3] = 1'b0; + if (Debug) begin + $display("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); + end + end + end + + // Internal Precharge or Bst + if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks + if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + end + end + end else if (Command[0] == `BST) begin // BST terminate a read to current bank + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + end + end + + if (Data_out_enable == 1'b0) begin + Dq_reg <= #tOH {DQ_BITS{1'bz}}; + end + + // Detect Read or Write command + if (Command[0] == `READ) begin + Bank = Bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + case (Bank_addr[0]) + 2'b00 : Row = B0_row_addr; + 2'b01 : Row = B1_row_addr; + 2'b10 : Row = B2_row_addr; + 2'b11 : Row = B3_row_addr; + endcase + Burst_counter = 0; + Data_in_enable = 1'b0; + Data_out_enable = 1'b1; + end else if (Command[0] == `WRITE) begin + Bank = Bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + case (Bank_addr[0]) + 2'b00 : Row = B0_row_addr; + 2'b01 : Row = B1_row_addr; + 2'b10 : Row = B2_row_addr; + 2'b11 : Row = B3_row_addr; + endcase + Burst_counter = 0; + Data_in_enable = 1'b1; + Data_out_enable = 1'b0; + end + + // DQ buffer (Driver/Receiver) + if (Data_in_enable == 1'b1) begin // Writing Data to Memory + // Array buffer + case (Bank) + 2'b00 : Dq_dqm = Bank0 [{Row, Col}]; + 2'b01 : Dq_dqm = Bank1 [{Row, Col}]; + 2'b10 : Dq_dqm = Bank2 [{Row, Col}]; + 2'b11 : Dq_dqm = Bank3 [{Row, Col}]; + endcase + + // Dqm operation +`ifdef x4 + if (Dqm[0] == 1'b0) begin + Dq_dqm [ 3 : 0] = Dq [ 3 : 0]; + end +`elsif x8 + if (Dqm[0] == 1'b0) begin + Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; + end +`elsif x16 + if (Dqm[0] == 1'b0) begin + Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; + end + if (Dqm[1] == 1'b0) begin + Dq_dqm [15 : 8] = Dq [15 : 8]; + end +`endif + + // Write to memory + case (Bank) + 2'b00 : Bank0 [{Row, Col}] = Dq_dqm; + 2'b01 : Bank1 [{Row, Col}] = Dq_dqm; + 2'b10 : Bank2 [{Row, Col}] = Dq_dqm; + 2'b11 : Bank3 [{Row, Col}] = Dq_dqm; + endcase + + // Display debug message + if (Dqm !== 2'b11) begin + // Record tWR for manual precharge + WR_chkm [Bank] = $time; + + if (Debug) begin + $display("%m : at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %h", $time, Bank, Row, Col, Dq_dqm); + end + end else begin + if (Debug) begin + $display("%m : at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); + end + end + + // Advance burst counter subroutine + #tHZ Burst_decode; + + end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory + // Array buffer + case (Bank) + 2'b00 : Dq_dqm = Bank0[{Row, Col}]; + 2'b01 : Dq_dqm = Bank1[{Row, Col}]; + 2'b10 : Dq_dqm = Bank2[{Row, Col}]; + 2'b11 : Dq_dqm = Bank3[{Row, Col}]; + endcase + + // Dqm operation +`ifdef x4 + if (Dqm_reg0 [0] == 1'b1) begin + Dq_dqm [ 3 : 0] = 4'bz; + end +`elsif x8 + if (Dqm_reg0 [0] == 1'b1) begin + Dq_dqm [ 7 : 0] = 8'bz; + end +`elsif x16 + if (Dqm_reg0 [0] == 1'b1) begin + Dq_dqm [ 7 : 0] = 8'bz; + end + if (Dqm_reg0 [1] == 1'b1) begin + Dq_dqm [15 : 8] = 8'bz; + end +`endif + + // Display debug message + Dq_reg = #tAC Dq_dqm; + if (Debug) begin + $display("%m : at time %t READ : Bank = %d Row = %d, Col = %d, Dqm = %b, Data = %h", $time, Bank, Row, Col, Dqm_reg0, Dq_reg); + end + + // Advance burst counter subroutine + Burst_decode; + end + end + + // Burst counter decode + task Burst_decode; + begin + // Advance Burst Counter + Burst_counter = Burst_counter + 1; + + // Burst Type + if (Mode_reg[3] == 1'b0) begin // Sequential Burst + Col_temp = Col + 1; + end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst + Col_temp[2] = Burst_counter[2] ^ Col_brst[2]; + Col_temp[1] = Burst_counter[1] ^ Col_brst[1]; + Col_temp[0] = Burst_counter[0] ^ Col_brst[0]; + end + + // Burst Length + if (Burst_length_2) begin // Burst Length = 2 + Col [0] = Col_temp [0]; + end else if (Burst_length_4) begin // Burst Length = 4 + Col [1 : 0] = Col_temp [1 : 0]; + end else if (Burst_length_8) begin // Burst Length = 8 + Col [2 : 0] = Col_temp [2 : 0]; + end else begin // Burst Length = FULL + Col = Col_temp; + end + + // Burst Read Single Write + if (Write_burst_mode == 1'b1) begin + Data_in_enable = 1'b0; + end + + // Data Counter + if (Burst_length_1 == 1'b1) begin + if (Burst_counter >= 1) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_2 == 1'b1) begin + if (Burst_counter >= 2) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_4 == 1'b1) begin + if (Burst_counter >= 4) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_8 == 1'b1) begin + if (Burst_counter >= 8) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end + end + endtask + + // Timing Parameters for -75 (133 MHz @ CL3) + specify + specparam + tAH = 0.8, // Addr, Ba Hold Time + tAS = 1.5, // Addr, Ba Setup Time + `ifdef CLK_166 + tCK3 = 6, + `elsif CLK_133 + tCK3 = 7.5, + `elsif CLK_100 + tCK3 = 10, + `elsif CLK_200 + tCK3 = 5, + `endif + tCH = 2.5, // Clock High-Level Width + tCL = 2.5, // Clock Low-Level Width + tCKH = 0.8, // CKE Hold Time + tCKS = 1.5, // CKE Setup Time + tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time + tCMS = 1.5, // CS#, RAS#, CAS#, WE#, DQM# Setup Time + tDH = 0.8, // Data-in Hold Time + tDS = 1.5; // Data-in Setup Time + $width (posedge Clk, tCH); + $width (negedge Clk, tCL); + $period (negedge Clk, tCK3); + $period (posedge Clk, tCK3); + $setuphold(posedge Clk, Cke, tCKS, tCKH); + $setuphold(posedge Clk, Cs_n, tCMS, tCMH); + $setuphold(posedge Clk, Cas_n, tCMS, tCMH); + $setuphold(posedge Clk, Ras_n, tCMS, tCMH); + $setuphold(posedge Clk, We_n, tCMS, tCMH); + $setuphold(posedge Clk, Addr, tAS, tAH); + $setuphold(posedge Clk, Ba, tAS, tAH); + $setuphold(posedge Clk, Dqm, tCMS, tCMH); + $setuphold(posedge Dq_chk, Dq, tDS, tDH); + endspecify + +endmodule diff --git a/hw/efinix_fpga/simulation/src/sim_top.sv b/hw/efinix_fpga/simulation/src/sim_top.sv new file mode 100644 index 0000000..a01f70c --- /dev/null +++ b/hw/efinix_fpga/simulation/src/sim_top.sv @@ -0,0 +1,177 @@ +`timescale 1ns/1ps + +module sim_top(); + +`include "include/super6502_sdram_controller_define.vh" + +logic r_sysclk, r_sdrclk, r_clk_50, r_clk_cpu; + +// clk_100 +initial begin + r_sysclk <= '1; + forever begin + #5 r_sysclk <= ~r_sysclk; + end +end + +// clk_200 +initial begin + r_sdrclk <= '1; + forever begin + #2.5 r_sdrclk <= ~r_sdrclk; + end +end + +// clk_50 +initial begin + r_clk_50 <= '1; + forever begin + #10 r_clk_50 <= ~r_clk_50; + end +end + +// clk_cpu +initial begin + r_clk_cpu <= '1; + forever begin + #125 r_clk_cpu <= ~r_clk_cpu; + end +end + +// initial begin +// #275000 $finish(); +// end + +initial begin + $dumpfile("sim_top.vcd"); + $dumpvars(0,sim_top); +end + +logic button_reset; + +initial begin + button_reset <= '0; + repeat(10) @(r_clk_cpu); + button_reset <= '1; + repeat(1000000) @(r_clk_cpu); + $finish(); +end + +logic w_cpu_reset; +logic [15:0] w_cpu_addr; +logic [7:0] w_cpu_data_from_cpu, w_cpu_data_from_dut; +logic w_cpu_rdy; +logic w_cpu_we; +logic w_cpu_phi2; + +//TODO: this +cpu_65c02 u_cpu( + .phi2(w_cpu_phi2), + .reset(~w_cpu_reset), + .AB(w_cpu_addr), + .RDY(w_cpu_rdy), + .IRQ('0), + .NMI('0), + .DI_s1(w_cpu_data_from_dut), + .DO(w_cpu_data_from_cpu), + .WE(w_cpu_we) +); + +logic w_dut_uart_rx, w_dut_uart_tx; + +sim_uart u_sim_uart( + .clk_50(r_clk_50), + .reset(~w_cpu_reset), + .rx_i(w_dut_uart_tx), + .tx_o(w_dut_uart_rx) +); + +logic w_sd_cs; +logic w_spi_clk; +logic w_spi_mosi; +logic w_spi_miso; + +sd_card_emu u_sd_card_emu( + .rst(~w_cpu_reset), + .clk(w_spi_clk), + .cs(w_sd_cs), + .mosi(w_spi_mosi), + .miso(w_spi_miso) +); + + +super6502 u_dut( + .i_sysclk(r_sysclk), + .i_sdrclk(r_sdrclk), + .i_tACclk(~r_sdrclk), + .clk_50(r_clk_50), + .clk_cpu(r_clk_cpu), + .button_reset(button_reset), + .cpu_resb(w_cpu_reset), + .cpu_addr(w_cpu_addr), + .cpu_data_out(w_cpu_data_from_dut), + .cpu_data_in(w_cpu_data_from_cpu), + .cpu_rwb(~w_cpu_we), + .cpu_rdy(w_cpu_rdy), + .cpu_phi2(w_cpu_phi2), + + .uart_rx(w_dut_uart_rx), + .uart_tx(w_dut_uart_tx), + + .sd_cs(w_sd_cs), + .spi_clk(w_spi_clk), + .spi_mosi(w_spi_mosi), + .spi_miso(w_spi_miso), + + .o_sdr_CKE(w_sdr_CKE), + .o_sdr_n_CS(w_sdr_n_CS), + .o_sdr_n_WE(w_sdr_n_WE), + .o_sdr_n_RAS(w_sdr_n_RAS), + .o_sdr_n_CAS(w_sdr_n_CAS), + .o_sdr_BA(w_sdr_BA), + .o_sdr_ADDR(w_sdr_ADDR), + .i_sdr_DATA(w_sdr_DQ), + .o_sdr_DATA(w_sdr_DATA), + .o_sdr_DATA_oe(w_sdr_DATA_oe), + .o_sdr_DQM(w_sdr_DQM) +); + +wire w_sdr_CKE; +wire w_sdr_n_CS; +wire w_sdr_n_WE; +wire w_sdr_n_RAS; +wire w_sdr_n_CAS; +wire [BA_WIDTH -1:0]w_sdr_BA; +wire [ROW_WIDTH -1:0]w_sdr_ADDR; +wire [DQ_GROUP *DQ_WIDTH -1:0]w_sdr_DATA; +wire [DQ_GROUP *DQ_WIDTH -1:0]w_sdr_DATA_oe; +wire [DQ_GROUP -1:0]w_sdr_DQM; +wire [DQ_GROUP *DQ_WIDTH -1:0]w_sdr_DQ; + +genvar i, j; +generate + for (i=0; i= 25'hf000 && i_addr <= 25'hffff) && ~config_reg_sel; -assign o_timer_cs = (i_addr >= 25'heff8 && i_addr <= 25'heffb) && ~config_reg_sel; -assign o_multiplier_cs = (i_addr >= 25'heff0 && i_addr <= 25'heff7) && ~config_reg_sel; -assign o_divider_cs = (i_addr >= 25'hefe8 && i_addr <= 25'hefef) && ~config_reg_sel; -assign o_uart_cs = (i_addr >= 25'hefe6 && i_addr <= 25'hefe7) && ~config_reg_sel; -assign o_spi_cs = (i_addr >= 25'hefd8 && i_addr <= 25'hefdb) && ~config_reg_sel; -assign o_leds_cs = (i_addr == 25'hefff) && ~config_reg_sel; -assign o_sdram_cs = (i_addr < 25'he000 || i_addr >= 25'h10000) && ~config_reg_sel; - -endmodule \ No newline at end of file diff --git a/hw/efinix_fpga/src/sdram_adapter.sv b/hw/efinix_fpga/src/sdram_adapter.sv index c9c1603..be3c816 100644 --- a/hw/efinix_fpga/src/sdram_adapter.sv +++ b/hw/efinix_fpga/src/sdram_adapter.sv @@ -70,10 +70,11 @@ assign o_sdr_DQM = w_sdr_DQM[0+:2]; // But basically if we are in access, and cpuclk goes low, go back to wait. // If something actually happened, we would be in one of the read/write states. -enum bit [1:0] {ACCESS, READ_WAIT, WRITE_WAIT, WAIT} state, next_state; +enum bit [2:0] {ACCESS, PRE_READ, READ_WAIT, PRE_WRITE, WRITE_WAIT, WAIT} state, next_state; logic w_read, w_write, w_last; -logic [23:0] w_addr, r_addr; +logic [23:0] w_read_addr, w_write_addr; +logic [23:0] r_read_addr, r_write_addr; logic [31:0] w_data_i, w_data_o; logic [3:0] w_dm, r_dm; @@ -86,25 +87,15 @@ logic [31:0] r_write_data; logic [1:0] counter, next_counter; -always @(posedge i_sysclk) begin - if (i_arst) begin - state <= WAIT; - counter <= '0; - end else begin - state <= next_state; - counter <= next_counter; - r_write_data <= w_data_i; - r_addr <= w_addr; - r_dm <= w_dm; - end - - if (w_data_valid) - o_data <= _data; -end +logic [7:0] o_data_next; + +logic [23:0] addr_mux_out; + +logic slow_mem; logic r_wait; logic _r_wait; -assign o_wait = r_wait; +assign o_wait = (r_wait | slow_mem) & i_cs; // we need to assert rdy low until a falling edge if a reset happens @@ -126,6 +117,20 @@ always @(posedge i_sysclk or posedge i_arst) begin end end end + + if (i_arst) begin + state <= WAIT; + counter <= '0; + end else begin + state <= next_state; + counter <= next_counter; + r_write_data <= w_data_i; + r_read_addr <= w_read_addr; + r_write_addr <= w_write_addr; + r_dm <= w_dm; + end + + o_data <= o_data_next; end //because of timing issues, We really need to trigger @@ -157,10 +162,12 @@ end always_comb begin + slow_mem = '0; next_state = state; next_counter = counter; - w_addr = '0; + w_read_addr = '0; + w_write_addr = '0; w_dm = '0; w_read = '0; w_write = '0; @@ -171,65 +178,81 @@ always_comb begin unique case (state) WAIT: begin - if (i_cs & i_cpuclk) + if (i_cs & ~i_cpuclk) next_state = ACCESS; end ACCESS: begin // only do something if selected if (i_cs) begin - w_addr = {{i_addr[24:2]}, {1'b0}};; // divide by 2, set last bit to 0 - + w_read_addr = {{i_addr[24:2]}, {1'b0}}; // divide by 2, set last bit to 0 + w_write_addr = {{i_addr[24:2]}, {1'b0}}; // divide by 2, set last bit to 0 + addr_mux_out = w_read_addr; if (i_rwb) begin //read - w_read = '1; - w_last = '1; - // dm is not needed for reads? - if (w_rd_ack) next_state = READ_WAIT; + next_state = PRE_READ; end else begin //write w_data_i = i_data << (8*i_addr[1:0]); - //w_data_i = {4{i_data}}; //does anything get through? w_dm = ~(4'b1 << i_addr[1:0]); - if (~i_cpuclk) begin - w_write = '1; - w_last = '1; - next_state = WRITE_WAIT; - end + next_state = PRE_WRITE; end end end + PRE_WRITE: begin + w_data_i = r_write_data; + w_write_addr = r_write_addr; + addr_mux_out = w_write_addr; + w_dm = r_dm; + //w_data_i = {4{i_data}}; //does anything get through? + if (~i_cpuclk) begin + w_write = '1; + w_last = '1; + next_state = WRITE_WAIT; + end + end + WRITE_WAIT: begin // stay in this state until write is acknowledged. + w_write_addr = r_write_addr; + addr_mux_out = w_write_addr; w_write = '1; w_last = '1; w_data_i = r_write_data; w_dm = r_dm; - w_addr = r_addr; if (w_wr_ack) next_state = WAIT; end + + PRE_READ: begin + w_read_addr = r_read_addr; + addr_mux_out = w_read_addr; + w_read = '1; + w_last = '1; + slow_mem = '1; + // dm is not needed for reads? + if (w_rd_ack) next_state = READ_WAIT; + end READ_WAIT: begin + w_read_addr = r_read_addr; + addr_mux_out = w_read_addr; + slow_mem = '1; if (w_rd_valid) begin w_data_valid = '1; _data = w_data_o[8*i_addr[1:0]+:8]; end // you must wait until the next cycle! - if (~i_cpuclk) begin + if (w_data_valid) begin next_state = WAIT; end end endcase -end -//this seems scuffed -logic [23:0] addr_mux_out; -always_comb begin - if (state == ACCESS) begin - addr_mux_out = w_addr; + if (w_data_valid) begin + o_data_next = _data; end else begin - addr_mux_out = r_addr; + o_data_next = o_data; end end @@ -245,10 +268,11 @@ logic [3:0] o_dbg_BA; logic [25:0] o_dbg_ADDR; logic [31:0] o_dbg_DATA_out; logic [31:0] o_dbg_DATA_in; -logic o_sdr_init_done; +logic sdr_init_done; logic [3:0] o_sdr_state; assign o_ref_req = o_dbg_ref_req; +assign o_sdr_init_done = sdr_init_done; sdram_controller u_sdram_controller( @@ -265,7 +289,7 @@ sdram_controller u_sdram_controller( .i_din(r_write_data), //Data to write to SDRAM. Twice normal width when running at half speed (hence the even addresses) .i_dm(r_dm), //dm (r_dm) .o_dout(w_data_o), //Data read from SDRAM, doubled as above. - .o_sdr_init_done(o_sdr_init_done), //Indicates that the SDRAM initialization is done. + .o_sdr_init_done(sdr_init_done), //Indicates that the SDRAM initialization is done. .o_wr_ack(w_wr_ack), //Write acknowledge, handshake with we .o_rd_ack(w_rd_ack), //Read acknowledge, handshake with re .o_rd_valid(w_rd_valid),//Read valid. The data on o_dout is valid diff --git a/hw/efinix_fpga/src/spi_controller.sv b/hw/efinix_fpga/src/spi_controller.sv index 2d085e4..9f5c09d 100644 --- a/hw/efinix_fpga/src/spi_controller.sv +++ b/hw/efinix_fpga/src/spi_controller.sv @@ -90,6 +90,7 @@ always_comb begin 1: o_data = r_input_data; 2:; 3: o_data = {active, r_control[6:0]}; + default: o_data = 'x; endcase end diff --git a/hw/efinix_fpga/src/super6502.sv b/hw/efinix_fpga/src/super6502.sv index 6fa9b79..bd76451 100644 --- a/hw/efinix_fpga/src/super6502.sv +++ b/hw/efinix_fpga/src/super6502.sv @@ -15,7 +15,7 @@ module super6502 input button_reset, input pll_cpu_locked, input clk_50, - input clk_2, + input clk_cpu, input logic [15:0] cpu_addr, output logic [7:0] cpu_data_out, output logic [7:0] cpu_data_oe, @@ -60,11 +60,11 @@ assign cpu_nmib = '1; logic w_wait; assign cpu_rdy = ~w_wait; -assign cpu_phi2 = clk_2; +assign cpu_phi2 = clk_cpu; logic w_sdr_init_done; -always @(posedge clk_2) begin +always @(posedge clk_cpu) begin if (button_reset == '0) begin cpu_resb <= '0; end @@ -94,18 +94,6 @@ logic w_uart_cs; logic w_mapper_cs; logic w_spi_cs; -addr_decode u_addr_decode( - .i_addr(w_sdram_addr), - .config_reg_sel(w_control_reg_cs), - .o_rom_cs(w_rom_cs), - .o_leds_cs(w_leds_cs), - .o_timer_cs(w_timer_cs), - .o_multiplier_cs(w_multiplier_cs), - .o_divider_cs(w_divider_cs), - .o_uart_cs(w_uart_cs), - .o_spi_cs(w_spi_cs), - .o_sdram_cs(w_sdram_cs) -); logic [7:0] w_rom_data_out; logic [7:0] w_leds_data_out; @@ -118,6 +106,16 @@ logic [7:0] w_mapper_data_out; logic [7:0] w_sdram_data_out; always_comb begin + w_rom_cs = cpu_addr >= 16'hf000 && cpu_addr <= 16'hffff; + w_timer_cs = cpu_addr >= 16'heff8 && cpu_addr <= 16'heffb; + w_multiplier_cs = cpu_addr >= 16'heff0 && cpu_addr <= 16'heff7; + w_divider_cs = cpu_addr >= 16'hefe8 && cpu_addr <= 16'hefef; + w_uart_cs = cpu_addr >= 16'hefe6 && cpu_addr <= 16'hefe7; + w_spi_cs = cpu_addr >= 16'hefd8 && cpu_addr <= 16'hefdb; + w_leds_cs = cpu_addr == 16'hefff; + w_sdram_cs = cpu_addr < 16'he000; + + if (w_rom_cs) cpu_data_out = w_rom_data_out; else if (w_leds_cs) @@ -154,13 +152,13 @@ mapper u_mapper( ); rom #(.DATA_WIDTH(8), .ADDR_WIDTH(12)) u_rom( - .addr(w_sdram_addr[11:0]), - .clk(clk_2), + .addr(cpu_addr[11:0]), + .clk(clk_cpu), .data(w_rom_data_out) ); leds u_leds( - .clk(clk_2), + .clk(clk_cpu), .i_data(cpu_data_in), .o_data(w_leds_data_out), .cs(w_leds_cs), @@ -171,7 +169,7 @@ leds u_leds( logic w_timer_irqb; timer u_timer( - .clk(clk_2), + .clk(clk_cpu), .reset(~cpu_resb), .i_data(cpu_data_in), .o_data(w_timer_data_out), @@ -182,7 +180,7 @@ timer u_timer( ); multiplier u_multiplier( - .clk(clk_2), + .clk(clk_cpu), .reset(~cpu_resb), .i_data(cpu_data_in), .o_data(w_multiplier_data_out), @@ -192,7 +190,7 @@ multiplier u_multiplier( ); divider_wrapper u_divider( - .clk(clk_2), + .clk(clk_cpu), .divclk(clk_50), .reset(~cpu_resb), .i_data(cpu_data_in), @@ -205,7 +203,7 @@ divider_wrapper u_divider( logic w_uart_irqb; uart_wrapper u_uart( - .clk(clk_2), + .clk(clk_cpu), .clk_50(clk_50), .reset(~cpu_resb), .i_data(cpu_data_in), @@ -219,7 +217,7 @@ uart_wrapper u_uart( ); spi_controller spi_controller( - .i_clk(clk_2), + .i_clk(clk_cpu), .i_rst(~cpu_resb), .i_cs(w_spi_cs), .i_rwb(cpu_rwb), @@ -235,7 +233,7 @@ spi_controller spi_controller( sdram_adapter u_sdram_adapter( - .i_cpuclk(clk_2), + .i_cpuclk(clk_cpu), .i_arst(~button_reset), .i_sysclk(i_sysclk), .i_sdrclk(i_sdrclk), @@ -265,7 +263,7 @@ sdram_adapter u_sdram_adapter( ); interrupt_controller u_interrupt_controller( - .clk(clk_2), + .clk(clk_cpu), .reset(~cpu_resb), .i_data(cpu_data_in), .o_data(w_irq_data_out), diff --git a/hw/efinix_fpga/src/timer.sv b/hw/efinix_fpga/src/timer.sv index fa7f743..abebef9 100644 --- a/hw/efinix_fpga/src/timer.sv +++ b/hw/efinix_fpga/src/timer.sv @@ -123,6 +123,8 @@ always_comb begin o_data = status; end + default: o_data = 'x; + endcase end diff --git a/hw/efinix_fpga/src/uart_wrapper.sv b/hw/efinix_fpga/src/uart_wrapper.sv index 04d35e3..3262233 100644 --- a/hw/efinix_fpga/src/uart_wrapper.sv +++ b/hw/efinix_fpga/src/uart_wrapper.sv @@ -46,7 +46,7 @@ enum bit [1:0] {READY, WAIT, TRANSMIT} state, next_state; always_ff @(posedge clk_50) begin if (reset) begin - state = READY; + state <= READY; irqb <= '1; end else begin state <= next_state; @@ -54,23 +54,27 @@ always_ff @(posedge clk_50) begin end always_ff @(negedge clk) begin - status[1] <= tx_busy | tx_en; + if (reset) begin + status <= '0; + end else begin + status[1] <= tx_busy | tx_en; - status[0] <= status[0] | rx_data_valid; - if (cs & ~addr & rwb) begin - status[0] <= 0; - end + status[0] <= status[0] | rx_data_valid; + if (cs & ~addr & rwb) begin + status[0] <= 0; + end - if (cs & ~rwb) begin - case (addr) - 1'b0: begin - tx_data <= i_data; - end + if (cs & ~rwb) begin + case (addr) + 1'b0: begin + tx_data <= i_data; + end - 1'b1: begin - control <= i_data; - end - endcase + 1'b1: begin + control <= i_data; + end + endcase + end end end @@ -79,7 +83,7 @@ always_comb begin case (addr) 1'b0: begin o_data = rx_data; - end + end 1'b1: begin o_data = status; diff --git a/hw/efinix_fpga/super6502.xml b/hw/efinix_fpga/super6502.xml index d2ecbe3..55c88b1 100644 --- a/hw/efinix_fpga/super6502.xml +++ b/hw/efinix_fpga/super6502.xml @@ -1,106 +1,106 @@ - + + - - - + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - + + + - \ No newline at end of file + diff --git a/hw/efinix_fpga/init_env.sh b/init_env.sh similarity index 83% rename from hw/efinix_fpga/init_env.sh rename to init_env.sh index 22ec0d4..443f828 100644 --- a/hw/efinix_fpga/init_env.sh +++ b/init_env.sh @@ -3,6 +3,8 @@ # ENV=".env/$HOSTNAME" +export REPO_TOP=$(git rev-parse --show-toplevel) + # if [ ! -d "$ENV" ]; then # mkdir -p "$ENV" # fi @@ -19,7 +21,12 @@ # source "$ENV/efinity/2023.1/bin/setup.sh" # export PATH=$PATH:"$EFXPT_HOME/bin" -source $EFX_SETUP +if [ -n "$EFX_SETUP" ]; then + source $EFX_SETUP +else + echo "EFX_SETUP not defined!" +fi + # python -m venv .user_venv --system-site-packages # . .user_venv/bin/activate diff --git a/sw/.gitignore b/sw/.gitignore index ec73f2b..5e3b75b 100644 --- a/sw/.gitignore +++ b/sw/.gitignore @@ -53,3 +53,6 @@ modules.order Module.symvers Mkfile.old dkms.conf + +# Filesystem Images +*.fat diff --git a/sw/Makefile b/sw/Makefile index c379713..ad99e40 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -1,6 +1,6 @@ -.PHONY: all install bootloader kernel clean +.PHONY: all install bios kernel clean -all: toolchain bootloader kernel +all: toolchain bios kernel install: all sh script/format_disk.sh @@ -9,14 +9,14 @@ install: all toolchain: @$(MAKE) -j4 -C cc65 -bootloader: - @$(MAKE) -C bootloader +bios: + @$(MAKE) -C bios kernel: @$(MAKE) -C kernel clean: - @$(MAKE) -C bootloader --no-print-directory $@ + @$(MAKE) -C bios --no-print-directory $@ @$(MAKE) -C kernel --no-print-directory $@ - @$(MAKE) -C cc65 --no-print-directory $@ \ No newline at end of file + @$(MAKE) -C cc65 --no-print-directory $@ diff --git a/sw/bios/Makefile b/sw/bios/Makefile index 3a9399a..f35b1a5 100644 --- a/sw/bios/Makefile +++ b/sw/bios/Makefile @@ -1,5 +1,5 @@ CC=../cc65/bin/cl65 -CFLAGS=-T -t none -I. --cpu "65C02" +CFLAGS=-T -t none -I. --cpu "65C02" -DRTL_SIM LDFLAGS=-C link.ld -m $(NAME).map NAME=bios @@ -7,7 +7,7 @@ NAME=bios BIN=$(NAME).bin HEX=$(NAME).hex -FPGA_IMG=../../hw/efinix_fpga/init_hex.mem +FPGA_IMG=$(REPO_TOP)/hw/efinix_fpga/init_hex.mem EFX_RUN=/home/byron/Software/efinity/2023.1/scripts/efx_run.py EFX_PRJ=/home/byron/Projects/super6502/hw/efinix_fpga/super6502.xml diff --git a/sw/bios/boot2.s b/sw/bios/boot2.s index 920303f..01c14ff 100644 --- a/sw/bios/boot2.s +++ b/sw/bios/boot2.s @@ -335,10 +335,10 @@ _start: @end: bra @end -str: .asciiz "boot2\r\n" +str: .asciiz "boot2\n" kernel_str: .asciiz "KERNEL O65" -_good: .asciiz "Found KERNEL\r\n" -word_str: .asciiz "Word Value: %x\r\n" +_good: .asciiz "Found KERNEL\n" +word_str: .asciiz "Word Value: %x\n" -opt_str: .asciiz "Opt Len: %x, Opt Type: %x\r\n" -opt_done: .asciiz "Options done. total option length: %x\r\n" \ No newline at end of file +opt_str: .asciiz "Opt Len: %x, Opt Type: %x\n" +opt_done: .asciiz "Options done. total option length: %x\n" \ No newline at end of file diff --git a/sw/bios/bootloader.s b/sw/bios/bootloader.s index d928332..da6a20f 100644 --- a/sw/bios/bootloader.s +++ b/sw/bios/bootloader.s @@ -173,12 +173,12 @@ _main: @end: bra @end -str: .asciiz "boot\r\n" +str: .asciiz "boot\n" _boot2_str: .asciiz "BOOT2 BIN" -_fail: .asciiz "not bootloader\r\n" -_good: .asciiz "found bootloader!\r\n" -_cluster: .asciiz "cluster: %lx\r\n" -_addr: .asciiz "addr: %x\r\n" +_fail: .asciiz "not bootloader\n" +_good: .asciiz "found bootloader!\n" +_cluster: .asciiz "cluster: %lx\n" +_addr: .asciiz "addr: %x\n" _end: .res (440+_start-_end) diff --git a/sw/bios/devices/sd_card.c b/sw/bios/devices/sd_card.c index 8eaf708..6be2cc3 100644 --- a/sw/bios/devices/sd_card.c +++ b/sw/bios/devices/sd_card.c @@ -20,17 +20,19 @@ uint8_t SD_init() cmdAttempts++; if(cmdAttempts == CMD0_MAX_ATTEMPTS) { - cputs("Go IDLE\r\n"); + cputs("Go IDLE\n"); return SD_ERROR; } } +#ifndef RTL_SIM for (i = 0; i < 1000; i++); +#endif SD_sendIfCond(res); if(res[0] != SD_IN_IDLE_STATE) { - cputs("IF Cond\r\n"); + cputs("IF Cond\n"); return SD_ERROR; } @@ -44,7 +46,7 @@ uint8_t SD_init() { if(cmdAttempts == CMD55_MAX_ATTEMPTS) { - cputs("op_cond error\r\n"); + cputs("op_cond error\n"); return SD_ERROR; } @@ -54,13 +56,17 @@ uint8_t SD_init() res[0] = SD_sendOpCond(); } +#ifndef RTL_SIM for (i = 0; i < 1000; i++); +#endif cmdAttempts++; } while(res[0] != SD_READY); +#ifndef RTL_SIM for (i = 0; i < 1000; i++); +#endif SD_readOCR(res); @@ -304,7 +310,7 @@ void SD_sendStatus(uint8_t *res) // while(++readAttempts != SD_MAX_READ_ATTEMPTS) // if((read = spi_exchange(0xFF)) != 0xFF) break; -// cprintf("read attempts: %d\r\n", readAttempts); +// cprintf("read attempts: %d\n", readAttempts); // // if response token is 0xFE // if(read == SD_START_TOKEN) diff --git a/sw/bios/devices/sd_print.c b/sw/bios/devices/sd_print.c index 7e3d305..73f39aa 100644 --- a/sw/bios/devices/sd_print.c +++ b/sw/bios/devices/sd_print.c @@ -13,7 +13,7 @@ void SD_printBuf(uint8_t *buf) cprintf("%2x", *buf++); if(colCount == 31) { - cputs("\r\n"); + cputs("\n"); colCount = 0; } else @@ -22,5 +22,5 @@ void SD_printBuf(uint8_t *buf) colCount++; } } - cputs("\r\n"); + cputs("\n"); } diff --git a/sw/bios/main.c b/sw/bios/main.c index 27a701d..0f7d779 100644 --- a/sw/bios/main.c +++ b/sw/bios/main.c @@ -19,16 +19,16 @@ int main() { uint32_t addr = 0x00000000; uint16_t i; - cputs("Start\r\n"); + cputs("Start\n"); // initialize sd card if(SD_init() != SD_SUCCESS) { - cputs("Error\r\n"); + cputs("Error\n"); } else { - cputs("Success\r\n"); + cputs("Success\n"); res[0] = SD_readSingleBlock(addr, buf, &token); @@ -38,9 +38,9 @@ int main() { //else if error token received, print else if(!(token & 0xF0)) { - cputs("Error\r\n"); + cputs("Error\n"); } else { - cprintf("bad token: %x\r\n", token); + cprintf("bad token: %x\n", token); } __asm__ ("jmp (%v)", buf); diff --git a/sw/kernel/kernel.c b/sw/kernel/kernel.c index 246ce06..2a111a8 100644 --- a/sw/kernel/kernel.c +++ b/sw/kernel/kernel.c @@ -16,7 +16,7 @@ int main() { cprintf("%s", string); - cprintf("Here is a long string: %s\r\n", longstring); + cprintf("Here is a long string: %s\n", longstring); while(1); diff --git a/sw/script/create_verilog_image.sh b/sw/script/create_verilog_image.sh new file mode 100644 index 0000000..51249fd --- /dev/null +++ b/sw/script/create_verilog_image.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +BOOTLOADER=$REPO_TOP/sw/bios/bootloader.bin +FILE=$REPO_TOP/sw/script/fs.fat + +TMPMOUNT=/tmp/lo +FSDIR=$REPO_TOP/sw/fsdir + +MNT=/run/media/$USER/SUPER6502 + +V=-v + +# Smallest number of blocks where mkfs doesn't complain +BLOCKS=33296 + +rm $FILE + +echo "$(tput bold setaf 11)Creating Filesystem$(tput sgr 0)" +mkfs.vfat $V -I -F32 -C $FILE -n SUPER6502 $BLOCKS +echo + +echo "$(tput bold setaf 11)Modifying Boot Sector$(tput sgr 0)" +dd if=$BOOTLOADER of=$FILE bs=1 conv=notrunc count=11 $STATUS +dd if=$BOOTLOADER of=$FILE bs=1 conv=notrunc count=380 seek=71 skip=71 $STATUS + + +LOOP=$(udisksctl loop-setup -f $FILE | grep -o "/dev/loop\([0-9]\)\+") +MNT=$(udisksctl mount -b $LOOP $TMPMOUNT | grep -o "\([A-Za-z/-]*/\)SUPER6502") + +echo "$(tput bold setaf 11)Copying Files$(tput sgr 0)" +cp $V -r $FSDIR/* $MNT +echo + +udisksctl unmount -b $LOOP + +udisksctl loop-delete -b $LOOP + +echo "$(tput bold setaf 11)Converting Image to Verilog$(tput sgr 0)" +objcopy --input-target=binary --output-target=verilog --verilog-data-width=1 $FILE $FILE.hex +echo "$(tput bold setaf 10)Done!$(tput sgr 0)" diff --git a/sw/script/format_disk.sh b/sw/script/format_disk.sh index af66e59..8c77237 100644 --- a/sw/script/format_disk.sh +++ b/sw/script/format_disk.sh @@ -1,6 +1,6 @@ #!/bin/bash -BOOTLOADER=../bios/bootloader.bin +BOOTLOADER=$REPO_TOP/sw/bios/bootloader.bin DEVICE=/dev/mmcblk0 TMPBOOTSECT=/tmp/bootsect TMPMOUNT=/tmp/sd diff --git a/sw/test_code/indirect_test/Makefile b/sw/test_code/indirect_test/Makefile new file mode 100644 index 0000000..5fbaadc --- /dev/null +++ b/sw/test_code/indirect_test/Makefile @@ -0,0 +1,39 @@ +CC=../../cc65/bin/cl65 +LD=../../cc65/bin/cl65 +CFLAGS=-T -t none -I. --cpu "65C02" +LDFLAGS=-C link.ld -m $(NAME).map + +NAME=indirect_test + +BIN=$(NAME).bin +HEX=$(NAME).hex + +LISTS=lists + +SRCS=$(wildcard *.s) $(wildcard *.c) +SRCS+=$(wildcard **/*.s) $(wildcard **/*.c) +OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) +OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) + +# Make sure the kernel linked to correct address, no relocation! +all: $(HEX) + +$(HEX): $(BIN) + objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX) + +$(BIN): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +%.o: %.c $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +%.o: %.s $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +$(LISTS): + mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + +.PHONY: clean +clean: + rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + diff --git a/sw/test_code/indirect_test/link.ld b/sw/test_code/indirect_test/link.ld new file mode 100644 index 0000000..66a42fe --- /dev/null +++ b/sw/test_code/indirect_test/link.ld @@ -0,0 +1,35 @@ +MEMORY +{ + ZP: start = $0, size = $100, type = rw, define = yes; + SDRAM: start = $9200, size = $4d00, type = rw, define = yes; + ROM: start = $F000, size = $1000, file = %O; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + DATA: load = ROM, type = rw, define = yes, run = SDRAM; + BSS: load = SDRAM, type = bss, define = yes; + HEAP: load = SDRAM, type = bss, optional = yes; + STARTUP: load = ROM, type = ro; + ONCE: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro; + RODATA: load = ROM, type = ro; + VECTORS: load = ROM, type = ro, start = $FFFA; +} + +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, type = weak; + __STACKSTART__: type = weak, value = $0800; # 2k stack +} diff --git a/sw/test_code/indirect_test/main.s b/sw/test_code/indirect_test/main.s new file mode 100644 index 0000000..65cf841 --- /dev/null +++ b/sw/test_code/indirect_test/main.s @@ -0,0 +1,20 @@ +.export _init, _nmi_int, _irq_int + +.code + +_nmi_int: +_irq_int: + +_init: + ldx #$ff + txs + + lda #$aa + sta $01 + lda #$bb + sta $00 + ldy #$1 + lda #$cc + sta ($00),y + +@end: bra @end \ No newline at end of file diff --git a/sw/test_code/indirect_test/vectors.s b/sw/test_code/indirect_test/vectors.s new file mode 100644 index 0000000..81ae6e0 --- /dev/null +++ b/sw/test_code/indirect_test/vectors.s @@ -0,0 +1,14 @@ +; --------------------------------------------------------------------------- +; vectors.s +; --------------------------------------------------------------------------- +; +; Defines the interrupt vector table. + +.import _init +.import _nmi_int, _irq_int + +.segment "VECTORS" + +.addr _nmi_int ; NMI vector +.addr _init ; Reset vector +.addr _irq_int ; IRQ/BRK vector \ No newline at end of file diff --git a/sw/test_code/jsr_test/Makefile b/sw/test_code/jsr_test/Makefile new file mode 100644 index 0000000..262a351 --- /dev/null +++ b/sw/test_code/jsr_test/Makefile @@ -0,0 +1,39 @@ +CC=../../cc65/bin/cl65 +LD=../../cc65/bin/cl65 +CFLAGS=-T -t none -I. --cpu "65C02" +LDFLAGS=-C link.ld -m $(NAME).map + +NAME=jsr_test + +BIN=$(NAME).bin +HEX=$(NAME).hex + +LISTS=lists + +SRCS=$(wildcard *.s) $(wildcard *.c) +SRCS+=$(wildcard **/*.s) $(wildcard **/*.c) +OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) +OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) + +# Make sure the kernel linked to correct address, no relocation! +all: $(HEX) + +$(HEX): $(BIN) + objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX) + +$(BIN): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +%.o: %.c $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +%.o: %.s $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +$(LISTS): + mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + +.PHONY: clean +clean: + rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + diff --git a/sw/test_code/jsr_test/link.ld b/sw/test_code/jsr_test/link.ld new file mode 100644 index 0000000..66a42fe --- /dev/null +++ b/sw/test_code/jsr_test/link.ld @@ -0,0 +1,35 @@ +MEMORY +{ + ZP: start = $0, size = $100, type = rw, define = yes; + SDRAM: start = $9200, size = $4d00, type = rw, define = yes; + ROM: start = $F000, size = $1000, file = %O; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + DATA: load = ROM, type = rw, define = yes, run = SDRAM; + BSS: load = SDRAM, type = bss, define = yes; + HEAP: load = SDRAM, type = bss, optional = yes; + STARTUP: load = ROM, type = ro; + ONCE: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro; + RODATA: load = ROM, type = ro; + VECTORS: load = ROM, type = ro, start = $FFFA; +} + +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, type = weak; + __STACKSTART__: type = weak, value = $0800; # 2k stack +} diff --git a/sw/test_code/jsr_test/main.s b/sw/test_code/jsr_test/main.s new file mode 100644 index 0000000..4c74c59 --- /dev/null +++ b/sw/test_code/jsr_test/main.s @@ -0,0 +1,23 @@ +.export _init, _nmi_int, _irq_int + +.code + +_nmi_int: +_irq_int: + +_init: + ldx #$ff + txs + lda #$00 + jsr subroutine + sta $00 +@1: bra @1 + +subroutine: + inc + jsr suborutine2 + rts + +suborutine2: + inc + rts \ No newline at end of file diff --git a/sw/test_code/jsr_test/vectors.s b/sw/test_code/jsr_test/vectors.s new file mode 100644 index 0000000..81ae6e0 --- /dev/null +++ b/sw/test_code/jsr_test/vectors.s @@ -0,0 +1,14 @@ +; --------------------------------------------------------------------------- +; vectors.s +; --------------------------------------------------------------------------- +; +; Defines the interrupt vector table. + +.import _init +.import _nmi_int, _irq_int + +.segment "VECTORS" + +.addr _nmi_int ; NMI vector +.addr _init ; Reset vector +.addr _irq_int ; IRQ/BRK vector \ No newline at end of file diff --git a/sw/test_code/loop_test/Makefile b/sw/test_code/loop_test/Makefile new file mode 100644 index 0000000..d854069 --- /dev/null +++ b/sw/test_code/loop_test/Makefile @@ -0,0 +1,39 @@ +CC=../../cc65/bin/cl65 +LD=../../cc65/bin/cl65 +CFLAGS=-T -t none -I. --cpu "65C02" +LDFLAGS=-C link.ld -m $(NAME).map + +NAME=loop_test + +BIN=$(NAME).bin +HEX=$(NAME).hex + +LISTS=lists + +SRCS=$(wildcard *.s) $(wildcard *.c) +SRCS+=$(wildcard **/*.s) $(wildcard **/*.c) +OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) +OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) + +# Make sure the kernel linked to correct address, no relocation! +all: $(HEX) + +$(HEX): $(BIN) + objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX) + +$(BIN): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +%.o: %.c $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +%.o: %.s $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +$(LISTS): + mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + +.PHONY: clean +clean: + rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + diff --git a/sw/test_code/loop_test/link.ld b/sw/test_code/loop_test/link.ld new file mode 100644 index 0000000..66a42fe --- /dev/null +++ b/sw/test_code/loop_test/link.ld @@ -0,0 +1,35 @@ +MEMORY +{ + ZP: start = $0, size = $100, type = rw, define = yes; + SDRAM: start = $9200, size = $4d00, type = rw, define = yes; + ROM: start = $F000, size = $1000, file = %O; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + DATA: load = ROM, type = rw, define = yes, run = SDRAM; + BSS: load = SDRAM, type = bss, define = yes; + HEAP: load = SDRAM, type = bss, optional = yes; + STARTUP: load = ROM, type = ro; + ONCE: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro; + RODATA: load = ROM, type = ro; + VECTORS: load = ROM, type = ro, start = $FFFA; +} + +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, type = weak; + __STACKSTART__: type = weak, value = $0800; # 2k stack +} diff --git a/sw/test_code/loop_test/main.s b/sw/test_code/loop_test/main.s new file mode 100644 index 0000000..4cd88ca --- /dev/null +++ b/sw/test_code/loop_test/main.s @@ -0,0 +1,16 @@ +.export _init, _nmi_int, _irq_int + +.code + +_nmi_int: +_irq_int: + +_init: + lda #$00 +@1: inc + sta $01 + lda $01 + cmp $01 + beq @1 + +@end: bra @end \ No newline at end of file diff --git a/sw/test_code/loop_test/vectors.s b/sw/test_code/loop_test/vectors.s new file mode 100644 index 0000000..81ae6e0 --- /dev/null +++ b/sw/test_code/loop_test/vectors.s @@ -0,0 +1,14 @@ +; --------------------------------------------------------------------------- +; vectors.s +; --------------------------------------------------------------------------- +; +; Defines the interrupt vector table. + +.import _init +.import _nmi_int, _irq_int + +.segment "VECTORS" + +.addr _nmi_int ; NMI vector +.addr _init ; Reset vector +.addr _irq_int ; IRQ/BRK vector \ No newline at end of file diff --git a/sw/test_code/simple_mem_test/Makefile b/sw/test_code/simple_mem_test/Makefile new file mode 100644 index 0000000..34a0ce9 --- /dev/null +++ b/sw/test_code/simple_mem_test/Makefile @@ -0,0 +1,39 @@ +CC=../../cc65/bin/cl65 +LD=../../cc65/bin/cl65 +CFLAGS=-T -t none -I. --cpu "65C02" +LDFLAGS=-C link.ld -m $(NAME).map + +NAME=simple_mem_test + +BIN=$(NAME).bin +HEX=$(NAME).hex + +LISTS=lists + +SRCS=$(wildcard *.s) $(wildcard *.c) +SRCS+=$(wildcard **/*.s) $(wildcard **/*.c) +OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) +OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) + +# Make sure the kernel linked to correct address, no relocation! +all: $(HEX) + +$(HEX): $(BIN) + objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX) + +$(BIN): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +%.o: %.c $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +%.o: %.s $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +$(LISTS): + mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + +.PHONY: clean +clean: + rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + diff --git a/sw/test_code/simple_mem_test/link.ld b/sw/test_code/simple_mem_test/link.ld new file mode 100644 index 0000000..66a42fe --- /dev/null +++ b/sw/test_code/simple_mem_test/link.ld @@ -0,0 +1,35 @@ +MEMORY +{ + ZP: start = $0, size = $100, type = rw, define = yes; + SDRAM: start = $9200, size = $4d00, type = rw, define = yes; + ROM: start = $F000, size = $1000, file = %O; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + DATA: load = ROM, type = rw, define = yes, run = SDRAM; + BSS: load = SDRAM, type = bss, define = yes; + HEAP: load = SDRAM, type = bss, optional = yes; + STARTUP: load = ROM, type = ro; + ONCE: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro; + RODATA: load = ROM, type = ro; + VECTORS: load = ROM, type = ro, start = $FFFA; +} + +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, type = weak; + __STACKSTART__: type = weak, value = $0800; # 2k stack +} diff --git a/sw/test_code/simple_mem_test/main.s b/sw/test_code/simple_mem_test/main.s new file mode 100644 index 0000000..d7ce83d --- /dev/null +++ b/sw/test_code/simple_mem_test/main.s @@ -0,0 +1,24 @@ +.export _init, _nmi_int, _irq_int + +.code + +_nmi_int: +_irq_int: + +_init: + lda #$aa + sta $10 + lda #$55 + sta $11 + + lda #$ff + sta $12 + lda #$00 + sta $13 + + lda $10 + lda $11 + lda $12 + lda $13 + +@1: bra @1 \ No newline at end of file diff --git a/sw/test_code/simple_mem_test/vectors.s b/sw/test_code/simple_mem_test/vectors.s new file mode 100644 index 0000000..81ae6e0 --- /dev/null +++ b/sw/test_code/simple_mem_test/vectors.s @@ -0,0 +1,14 @@ +; --------------------------------------------------------------------------- +; vectors.s +; --------------------------------------------------------------------------- +; +; Defines the interrupt vector table. + +.import _init +.import _nmi_int, _irq_int + +.segment "VECTORS" + +.addr _nmi_int ; NMI vector +.addr _init ; Reset vector +.addr _irq_int ; IRQ/BRK vector \ No newline at end of file