diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b7dc184e..78a78be1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -61,6 +61,26 @@ tiny-dma-run: job: prepare-non-free strategy: depend +lite-backend-run: + stage: iDMA + needs: + - prepare-non-free + trigger: + include: + - artifact: idma-non-free/ci/gitlab-lite-backend-ci.yml + job: prepare-non-free + strategy: depend + +obi-backend-run: + stage: iDMA + needs: + - prepare-non-free + trigger: + include: + - artifact: idma-non-free/ci/gitlab-obi-backend-ci.yml + job: prepare-non-free + strategy: depend + 4d-ext-run: stage: iDMA needs: diff --git a/Bender.lock b/Bender.lock index c9a15d8b..7f1edb38 100644 --- a/Bender.lock +++ b/Bender.lock @@ -1,7 +1,7 @@ packages: axi: - revision: 9a53b3c66d32725e5c5656b02e1caf07c5f79a97 - version: 0.37.0 + revision: 2f395b176bee1c769c80f060a4345fda965bb04b + version: 0.38.0 source: Git: https://github.com/pulp-platform/axi.git dependencies: @@ -17,14 +17,14 @@ packages: - common_verification - tech_cells_generic common_verification: - revision: 5def6fee3f010b603357d7b941661892aeafcc5d - version: 0.2.2 + revision: 9c07fa860593b2caabd9b5681740c25fac04b878 + version: 0.2.3 source: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] register_interface: - revision: 1e23b79db80cb89b4d27fdbd10776df33d6a2ff4 - version: 0.3.3 + revision: d59b4f1c77469dcb23f370f32769af309c4add6a + version: 0.3.4 source: Git: https://github.com/pulp-platform/register_interface.git dependencies: diff --git a/Bender.yml b/Bender.yml index 610786d6..c9587c09 100644 --- a/Bender.yml +++ b/Bender.yml @@ -11,7 +11,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.26.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.2 } - axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.37.0 } + axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.38.0 } register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.3.1 } export_include_dirs: @@ -31,6 +31,8 @@ sources: - src/idma_channel_coupler.sv # Level 2 - src/idma_axi_transport_layer.sv + - src/idma_axi_lite_transport_layer.sv + - src/idma_obi_transport_layer.sv - src/idma_legalizer.sv # Level 3 - src/idma_backend.sv @@ -81,18 +83,27 @@ sources: - target: synthesis files: - src/synth_wrapper/idma_backend_synth.sv + - src/synth_wrapper/idma_lite_backend_synth.sv + - src/synth_wrapper/idma_obi_backend_synth.sv - src/synth_wrapper/idma_nd_backend_synth.sv - target: test + defines: + TARGET_SIMULATION: ~ include_dirs: - test files: # Level 0: - test/idma_intf.sv + - test/idma_tb_per2axi.sv + - test/idma_obi_asserter.sv # Level 1: - test/idma_test.sv + - test/idma_obi2axi_bridge.sv # Level 2: - test/tb_idma_backend.sv + - test/tb_idma_lite_backend.sv + - test/tb_idma_obi_backend.sv - test/tb_idma_nd_backend.sv - target: test # 64bit descriptor frontend diff --git a/README.md b/README.md index 923ae239..6e9a0761 100644 --- a/README.md +++ b/README.md @@ -56,14 +56,24 @@ a simulation can be launched using: ```bash make prepare_sim -vsim -c -do "source scripts/compile_vsim.tcl; quit" -vsim -c -t 1ps -voptargs=+acc \ - +job_file=jobs/backend/man_simple.txt \ +export VSIM="questa-2022.3 vsim" +$VSIM -c -do "source scripts/compile_vsim.tcl; quit" +$VSIM -c -t 1ps -voptargs=+acc \ + +job_file=jobs/backend/man_same_dst_simple.txt \ -logfile logs/backend.simple.vsim.log \ -wlf logs/backend.simple.wlf \ - tb_idma_backend \ + tb_idma_obi_backend \ -do "source scripts/start_vsim.tcl; run -all" ``` +with gui: +``` +$VSIM -t 1ps -voptargs=+acc \ + +job_file=jobs/backend/man_same_dst_simple.txt \ + -logfile logs/backend.simple.vsim.log \ + -wlf logs/backend.simple.wlf \ + tb_idma_obi_backend \ + -do "source scripts/start_vsim.tcl; source scripts/waves/vsim_obi_backend.do; run -all" +``` Where: - `+job_file=jobs/backend/man_simple.txt` can point to any valid [job file](jobs/README.md) diff --git a/jobs.json b/jobs.json index cba7f4b6..a7b57d09 100644 --- a/jobs.json +++ b/jobs.json @@ -2,16 +2,17 @@ "backend" : { "seed" : 1336, "man_jobs" : { - "simple" : "backend/man_simple.txt", - "huge" : "backend/man_huge.txt", - "large" : "backend/man_large.txt", - "medium" : "backend/man_medium.txt", - "mixed" : "backend/man_mixed.txt", - "small" : "backend/man_small.txt", - "tiny" : "backend/man_tiny.txt", - "error_simple" : "backend/man_error_simple.txt", - "error_mixed" : "backend/man_error_mixed.txt", - "zero_transfer" : "backend/man_zero_transfer.txt" + "simple" : "backend/man_simple.txt", + "same_dst_simple" : "backend/man_same_dst_simple.txt", + "huge" : "backend/man_huge.txt", + "large" : "backend/man_large.txt", + "medium" : "backend/man_medium.txt", + "mixed" : "backend/man_mixed.txt", + "small" : "backend/man_small.txt", + "tiny" : "backend/man_tiny.txt", + "error_simple" : "backend/man_error_simple.txt", + "error_mixed" : "backend/man_error_mixed.txt", + "zero_transfer" : "backend/man_zero_transfer.txt" }, "gen_jobs" : { }, @@ -68,6 +69,48 @@ "ErrorHandling" : 0 } }, + "lite-backend" : { + "seed" : 1336, + "man_jobs" : { + "simple" : "backend/man_simple.txt", + "same_dst_simple" : "backend/man_same_dst_simple.txt", + "huge" : "backend/man_huge.txt", + "large" : "backend/man_large.txt", + "medium" : "backend/man_medium.txt", + "mixed" : "backend/man_mixed.txt", + "small" : "backend/man_small.txt", + "tiny" : "backend/man_tiny.txt", + "error_simple" : "backend/man_error_simple.txt", + "error_mixed" : "backend/man_error_mixed.txt", + "zero_transfer" : "backend/man_zero_transfer.txt" + }, + "gen_jobs" : { + }, + "testbench" : "tb_idma_lite_backend", + "synth_top" : "idma_lite_backend_synth", + "overrides" : { + } + }, + "obi-backend" : { + "seed" : 1336, + "man_jobs" : { + "simple" : "backend/man_simple.txt", + "same_dst_simple" : "backend/man_same_dst_simple.txt", + "huge" : "backend/man_huge.txt", + "large" : "backend/man_large.txt", + "medium" : "backend/man_medium.txt", + "mixed" : "backend/man_mixed.txt", + "small" : "backend/man_small.txt", + "tiny" : "backend/man_tiny.txt", + "zero_transfer" : "backend/man_zero_transfer.txt" + }, + "gen_jobs" : { + }, + "testbench" : "tb_idma_obi_backend", + "synth_top" : "idma_obi_backend_synth", + "overrides" : { + } + }, "4d-ext" : { "seed" : 1336, "man_jobs" : { diff --git a/jobs/backend/man_same_dst_simple.txt b/jobs/backend/man_same_dst_simple.txt new file mode 100644 index 00000000..2cda889f --- /dev/null +++ b/jobs/backend/man_same_dst_simple.txt @@ -0,0 +1,1024 @@ +20 +0xab627764 +0xd6e77ce5 +4 +1 +0 +0 +0 +310 +0x52a6ef2c +0xd6e77d19 +1 +1 +1 +0 +0 +594 +0xc1714202 +0xd6e77dce +1 +16 +1 +0 +0 +220 +0x712046f0 +0xd6e77dc1 +8 +4 +1 +1 +0 +25 +0x4c7e826c +0xd6e77e2f +2 +8 +1 +1 +0 +1012 +0x3658e84 +0xd6e77c56 +128 +64 +0 +0 +0 +925 +0x7a2748f5 +0xd6e780b4 +64 +8 +1 +1 +0 +512 +0x52f4bf8b +0xd6e78623 +8 +1 +1 +1 +0 +75 +0xac6ac8f5 +0xd6e7867f +8 +2 +0 +0 +0 +243 +0xa370c383 +0xd6e7863d +4 +64 +1 +1 +0 +515 +0x9b9189f1 +0xd6e7881a +128 +64 +0 +0 +0 +237 +0xa8aab7f7 +0xd6e78950 +32 +1 +0 +0 +0 +968 +0xf8171827 +0xd6e78800 +64 +2 +0 +0 +0 +4 +0x7e1f386d +0xd6e78ba9 +32 +16 +0 +0 +0 +494 +0x5f398235 +0xd6e78c61 +8 +128 +0 +0 +0 +902 +0xc2bdf5b1 +0xd6e790d7 +8 +1 +0 +0 +0 +534 +0x3cff5a28 +0xd6e78ec4 +1 +128 +1 +1 +0 +203 +0x2f53dffd +0xd6e78f2f +4 +16 +1 +1 +0 +930 +0x4e2d8ad1 +0xd6e78d62 +64 +8 +0 +0 +0 +324 +0x33dde290 +0xd6e78cdd +128 +2 +0 +0 +0 +756 +0x454c74ca +0xd6e78a8a +2 +1 +1 +1 +0 +306 +0x2534fd0c +0xd6e78c91 +64 +2 +0 +0 +0 +662 +0x4a456932 +0xd6e79016 +8 +8 +0 +0 +0 +884 +0xdfff2bc3 +0xd6e79488 +128 +128 +1 +0 +0 +184 +0x6a941413 +0xd6e79622 +32 +64 +1 +0 +0 +486 +0x2f078106 +0xd6e7948d +128 +32 +0 +0 +0 +814 +0xf74f53d3 +0xd6e79541 +2 +1 +1 +0 +0 +669 +0x50774103 +0xd6e79743 +32 +64 +0 +0 +0 +902 +0x95fba959 +0xd6e794ab +4 +32 +1 +1 +0 +743 +0x90694767 +0xd6e795b6 +16 +128 +1 +0 +0 +488 +0x74e13c18 +0xd6e798a8 +64 +8 +1 +0 +0 +929 +0x5231fbbe +0xd6e79b6e +16 +128 +0 +0 +0 +520 +0xab0e7e96 +0xd6e79a1e +4 +64 +1 +0 +0 +270 +0x72462b77 +0xd6e79b1a +4 +4 +0 +0 +0 +478 +0x9579ebb6 +0xd6e79ad7 +16 +8 +0 +0 +0 +649 +0x994d13 +0xd6e79c0e +4 +8 +0 +0 +0 +482 +0xf0257c3 +0xd6e79b44 +8 +16 +1 +1 +0 +178 +0x7aa43bd +0xd6e79c91 +16 +1 +0 +0 +0 +205 +0xb0f62cc9 +0xd6e79d66 +64 +32 +0 +0 +0 +82 +0x935f34b4 +0xd6e79e2e +16 +32 +1 +1 +0 +262 +0x60ee88f4 +0xd6e79f62 +128 +128 +0 +0 +0 +490 +0x2f0965e +0xd6e7a0c5 +2 +8 +0 +0 +0 +93 +0xc0590ab1 +0xd6e7a2c4 +1 +32 +1 +1 +0 +241 +0x6f1a022f +0xd6e7a2fc +8 +64 +1 +1 +0 +537 +0x517e425a +0xd6e7a371 +32 +128 +0 +0 +0 +769 +0xfceaf94a +0xd6e7a3f0 +128 +32 +0 +0 +0 +182 +0x935b08f1 +0xd6e7a78e +32 +32 +1 +1 +0 +892 +0xa15916f7 +0xd6e7a788 +2 +1 +0 +0 +0 +1014 +0xda0cc69c +0xd6e7a470 +64 +2 +0 +0 +0 +105 +0x1d25c7a4 +0xd6e7a426 +64 +128 +1 +0 +0 +108 +0x60251471 +0xd6e7a3e8 +16 +128 +0 +0 +0 +638 +0x4c276034 +0xd6e7a3ad +16 +64 +1 +1 +0 +522 +0xf7107954 +0xd6e7a54e +4 +32 +1 +1 +0 +218 +0xbc3b5d59 +0xd6e7a76d +64 +1 +0 +0 +0 +208 +0x682ec1d9 +0xd6e7a7a3 +128 +1 +0 +0 +0 +563 +0xa7121d53 +0xd6e7a70e +128 +8 +1 +1 +0 +61 +0xfb6dd258 +0xd6e7a8d8 +128 +4 +0 +0 +0 +387 +0x2d36f5de +0xd6e7a96d +16 +32 +1 +1 +0 +927 +0x8389563c +0xd6e7ac1f +16 +32 +1 +0 +0 +594 +0x4a781f33 +0xd6e7ac9d +2 +4 +0 +0 +0 +29 +0x1536cb24 +0xd6e7ae98 +2 +4 +0 +0 +0 +502 +0x283d23bc +0xd6e7ae32 +4 +32 +0 +0 +0 +1013 +0xb65f105b +0xd6e7b37e +16 +4 +0 +0 +0 +454 +0x2ad833aa +0xd6e7b453 +128 +128 +1 +1 +0 +428 +0xe89e1092 +0xd6e7b61e +16 +4 +0 +0 +0 +980 +0x139f7ff2 +0xd6e7b6a1 +32 +4 +0 +0 +0 +709 +0x95013a2c +0xd6e7b408 +1 +128 +1 +1 +0 +504 +0xadc2ecb7 +0xd6e7b700 +64 +128 +1 +0 +0 +983 +0x1f6209ed +0xd6e7b8b2 +16 +2 +1 +0 +0 +167 +0xee273541 +0xd6e7bbec +128 +128 +0 +0 +0 +42 +0x7775e17b +0xd6e7bc15 +16 +16 +1 +0 +0 +772 +0xdc53323 +0xd6e7b938 +128 +1 +0 +0 +0 +233 +0x8577e228 +0xd6e7b94a +8 +64 +1 +1 +0 +762 +0xbc866c5b +0xd6e7b720 +16 +32 +0 +0 +0 +556 +0xad8a6447 +0xd6e7b8ed +8 +8 +1 +0 +0 +705 +0x4ed1d0d4 +0xd6e7bb62 +8 +8 +0 +0 +0 +611 +0x29ed524b +0xd6e7bd25 +4 +1 +1 +0 +0 +446 +0xbbbd8a10 +0xd6e7c131 +8 +64 +1 +1 +0 +261 +0xba58b983 +0xd6e7c3a9 +64 +1 +1 +0 +0 +220 +0xe630564d +0xd6e7c4a4 +1 +16 +1 +0 +0 +507 +0x253141dd +0xd6e7c3c4 +128 +8 +1 +0 +0 +583 +0x4627f662 +0xd6e7c676 +32 +32 +0 +0 +0 +1004 +0x9826c2a9 +0xd6e7c8ba +2 +16 +1 +1 +0 +284 +0x22fa3d00 +0xd6e7cc4a +4 +32 +1 +0 +0 +133 +0x334e53c8 +0xd6e7cc88 +16 +4 +1 +1 +0 +719 +0x4556387a +0xd6e7cc87 +64 +1 +1 +0 +0 +211 +0xdbe7c8fa +0xd6e7cc40 +8 +8 +0 +0 +0 +179 +0xdf534d08 +0xd6e7ccdc +8 +8 +0 +0 +0 +163 +0xf939fca6 +0xd6e7cc53 +1 +16 +0 +0 +0 +678 +0xc190a258 +0xd6e7ca2d +1 +8 +1 +0 +0 +189 +0xdee0489e +0xd6e7cc57 +64 +4 +0 +0 +0 +358 +0x82ea8ae9 +0xd6e7cbd3 +16 +1 +1 +0 +0 +412 +0xcd80ec58 +0xd6e7cc07 +1 +4 +1 +1 +0 +839 +0xfd6c3082 +0xd6e7d065 +2 +4 +0 +0 +0 +117 +0x11f02d0 +0xd6e7d2a6 +128 +1 +0 +0 +0 +41 +0xe5434e60 +0xd6e7d32e +4 +1 +1 +0 +0 +954 +0x54880a11 +0xd6e7d13e +4 +1 +1 +1 +0 +780 +0x52440847 +0xd6e7d4b6 +16 +1 +1 +0 +0 +372 +0xf1adf83e +0xd6e7d5f2 +8 +16 +0 +0 +0 +505 +0x2a706331 +0xd6e7d8ee +64 +64 +1 +1 +0 +761 +0x95604d48 +0xd6e7d8f4 +128 +8 +1 +1 +0 +688 +0xb7749118 +0xd6e7d7f9 +32 +32 +1 +1 +0 +522 +0x3b4a94c5 +0xd6e7da92 +64 +16 +1 +1 +0 +577 +0x16b03077 +0xd6e7da79 +64 +64 +0 +0 +0 +469 +0xad83edd7 +0xd6e7dbfa +8 +8 +1 +1 +0 +827 +0xaad9df5d +0xd6e7dfaf +8 +32 +0 +0 +0 +613 +0xf08dbe0 +0xd6e7e4c1 +64 +4 +1 +1 +0 +631 +0x7f47b73b +0xd6e7e778 +128 +8 +0 +0 +0 +192 +0xa48be595 +0xd6e7e811 +1 +128 +0 +0 +0 +589 +0xe5937caa +0xd6e7e869 +4 +128 +1 +1 +0 +333 +0xfce0c503 +0xd6e7e7d6 +4 +4 +0 +0 +0 +899 +0x94789006 +0xd6e7e979 +4 +16 +1 +0 +0 +23 +0x2b1d8757 +0xd6e7eaee +1 +2 +0 +0 +0 +777 +0x81c3f782 +0xd6e7eb0b +4 +8 +1 +0 +0 +152 +0xc84976f8 +0xd6e7ebe4 +4 +8 +0 +0 +0 +465 +0x8664eb6d +0xd6e7ecc1 +8 +1 +1 +0 +0 +243 +0x4bd65c03 +0xd6e7ed48 +8 +4 +0 +0 +0 +675 +0x13f62abb +0xd6e7eec0 +16 +8 +1 +0 +0 +561 +0x803cd90f +0xd6e7eceb +64 +4 +1 +1 +0 +904 +0x992a1d6d +0xd6e7ee78 +128 +16 +0 +0 +0 +474 +0x16595fcd +0xd6e7ede8 +4 +16 +1 +1 +0 +620 +0xe5d60d1e +0xd6e7ed8a +1 +128 +0 +0 +0 +975 +0x15b549d5 +0xd6e7f34b +1 +1 +1 +0 +0 +1003 +0x9a08d3c8 +0xd6e7f74d +4 +16 +1 +1 +0 +102 +0x58924777 +0xd6e7f9c0 +1 +2 +1 +0 +0 +392 +0xd92842db +0xd6e7fb0d +1 +128 +0 +0 +0 +836 +0x179d7efb +0xd6e7fb44 +64 +32 +0 +0 +0 +385 +0x612746ad +0xd6e7f9e6 +2 +1 +1 +1 +0 \ No newline at end of file diff --git a/scripts/waves/vsim_lite_backend.do b/scripts/waves/vsim_lite_backend.do new file mode 100644 index 00000000..228c31be --- /dev/null +++ b/scripts/waves/vsim_lite_backend.do @@ -0,0 +1,211 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/clk_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/rst_ni +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/testmode_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/idma_req_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/req_valid_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/req_ready_o +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/idma_rsp_o +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/rsp_valid_o +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/rsp_ready_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/idma_eh_req_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/eh_req_valid_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/eh_req_ready_o +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/protocol_req_o +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/protocol_rsp_i +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/busy_o +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/dp_busy +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/dp_poison +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_req +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_req +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_last_burst +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_last_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_super_last +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_dp_req_in_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_dp_req_in_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_dp_req_out_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_dp_req_out_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_dp_req_out_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_dp_req_out_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_dp_req_out +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_dp_req_out +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_dp_rsp +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_dp_rsp +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_dp_rsp_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_dp_rsp_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/r_dp_rsp_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/w_dp_rsp_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/ar_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/aw_ready +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/aw_ready_dp +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/aw_valid_dp +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/aw_req_dp +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/legalizer_flush +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/legalizer_kill +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/is_length_zero +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/req_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/idma_rsp +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/rsp_valid +add wave -noupdate -expand -group Backend /tb_idma_lite_backend/i_idma_backend/rsp_ready +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/clk_i +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/rst_ni +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/req_i +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/valid_i +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/ready_o +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_req_o +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_valid_o +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_ready_i +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_req_o +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_valid_o +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_ready_i +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/flush_i +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/kill_i +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_busy_o +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_busy_o +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_tf_q +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_tf_q +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/opt_tf_q +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_tf_ena +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_tf_ena +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_page_offset +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_num_bytes_to_pb +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_page_offset +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_num_bytes_to_pb +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/c_num_bytes_to_pb +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_page_addr_width +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_page_addr_width +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_page_size +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_page_size +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_num_bytes_possible +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_num_bytes +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_addr_offset +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_done +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_num_bytes_possible +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_num_bytes +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_addr_offset +add wave -noupdate -group Legalizer /tb_idma_lite_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_done +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/clk_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/rst_ni +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/testmode_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/axi_lite_req_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/axi_lite_rsp_i +add wave -noupdate -group {Transport Layer} -expand /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/r_dp_req_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/r_dp_valid_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/r_dp_ready_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/r_dp_rsp_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/r_dp_valid_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/r_dp_ready_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/w_dp_req_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/w_dp_valid_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/w_dp_ready_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/w_dp_rsp_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/w_dp_valid_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/w_dp_ready_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/ar_req_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/ar_valid_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/ar_ready_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/aw_req_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/aw_valid_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/aw_ready_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/dp_poison_i +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/r_dp_busy_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/w_dp_busy_o +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_busy_o +add wave -noupdate -group {Transport Layer} -expand /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_in +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/read_aligned_in_mask +add wave -noupdate -group {Transport Layer} -expand /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/mask_in +add wave -noupdate -group {Transport Layer} -expand /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_in_valid +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_in_ready +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/in_valid +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/in_ready +add wave -noupdate -group {Transport Layer} -expand /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/mask_out +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_out +add wave -noupdate -group {Transport Layer} -expand /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_out_valid +add wave -noupdate -group {Transport Layer} -expand /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_out_ready +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/write_happening +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/ready_to_write +add wave -noupdate -group {Transport Layer} /tb_idma_lite_backend/i_idma_backend/gen_axi_lite_transport_layer/i_idma_axi_lite_transport_layer/buffer_clean +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/clk_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/rst_ni +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/testmode_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/rsp_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/rsp_valid_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/rsp_ready_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/eh_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/eh_valid_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/eh_ready_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/r_addr_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/r_consume_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_addr_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_consume_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/legalizer_flush_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/legalizer_kill_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/dp_busy_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/dp_poison_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/r_dp_rsp_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/r_dp_valid_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/r_dp_ready_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_dp_rsp_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_dp_valid_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_dp_ready_o +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_last_burst_i +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/state_q +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/r_addr_head +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_addr_head +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/r_store_pop +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/w_store_pop +add wave -noupdate -group {Error Handler} /tb_idma_lite_backend/i_idma_backend/gen_error_handler/i_idma_error_handler/num_outst_q +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/clk_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/rst_ni +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/testmode_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/r_rsp_valid_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/r_rsp_ready_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/r_rsp_first_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/r_decouple_aw_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_decouple_aw_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_req_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_valid_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_ready_o +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_req_o +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_valid_o +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_ready_i +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_req_in +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_req_out +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_ready +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_valid +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/first +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_sent +add wave -noupdate -group R-AW-Coupler /tb_idma_lite_backend/i_idma_backend/gen_r_aw_coupler/i_idma_channel_coupler/aw_to_send_q +add wave -noupdate -divider BUS +add wave -noupdate -group {AXI IF} -label AW /tb_idma_lite_backend/i_aw_hl/in_wave +add wave -noupdate -group {AXI IF} -label AR /tb_idma_lite_backend/i_ar_hl/in_wave +add wave -noupdate -group {AXI IF} -label W /tb_idma_lite_backend/i_w_hl/in_wave +add wave -noupdate -group {AXI IF} -label R /tb_idma_lite_backend/i_r_hl/in_wave +add wave -noupdate -group {AXI IF} -label B /tb_idma_lite_backend/i_b_hl/in_wave +add wave -noupdate -group {iDMA IF} -label {iDMA REQ} /tb_idma_lite_backend/i_req_hl/in_wave +add wave -noupdate -group {iDMA IF} -label {iDMA RSP} -expand -subitemconfig {/tb_idma_lite_backend/i_rsp_hl/in_wave.pld -expand} /tb_idma_lite_backend/i_rsp_hl/in_wave +add wave -noupdate -group {iDMA IF} -label {iDMA EH} /tb_idma_lite_backend/i_eh_hl/in_wave +add wave -noupdate -group Busy -expand /tb_idma_lite_backend/i_idma_backend/busy_o +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {210998 ps} 0} +quietly wave cursor active 1 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 427 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {1121282 ps} {1235722 ps} diff --git a/scripts/waves/vsim_obi_backend.do b/scripts/waves/vsim_obi_backend.do new file mode 100644 index 00000000..01218ed2 --- /dev/null +++ b/scripts/waves/vsim_obi_backend.do @@ -0,0 +1,165 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/clk_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/rst_ni +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/testmode_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/idma_req_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/req_valid_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/req_ready_o +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/idma_rsp_o +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/rsp_valid_o +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/rsp_ready_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/idma_eh_req_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/eh_req_valid_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/eh_req_ready_o +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/protocol_req_o +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/protocol_rsp_i +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/busy_o +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/dp_busy +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/dp_poison +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_req +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_req +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_last_burst +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_last_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_super_last +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_dp_req_in_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_dp_req_in_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_dp_req_out_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_dp_req_out_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_dp_req_out_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_dp_req_out_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_dp_req_out +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_dp_req_out +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_dp_rsp +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_dp_rsp +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_dp_rsp_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_dp_rsp_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/r_dp_rsp_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/w_dp_rsp_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/ar_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/aw_ready +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/aw_ready_dp +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/aw_valid_dp +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/aw_req_dp +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/legalizer_flush +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/legalizer_kill +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/is_length_zero +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/req_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/idma_rsp +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/rsp_valid +add wave -noupdate -expand -group Backend /tb_idma_obi_backend/i_idma_backend/rsp_ready +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/clk_i +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/rst_ni +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/req_i +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/valid_i +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/ready_o +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_req_o +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_valid_o +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_ready_i +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_req_o +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_valid_o +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_ready_i +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/flush_i +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/kill_i +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_busy_o +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_busy_o +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_tf_q +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_tf_q +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/opt_tf_q +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_tf_ena +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_tf_ena +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_page_offset +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_num_bytes_to_pb +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_page_offset +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_num_bytes_to_pb +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/c_num_bytes_to_pb +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_page_addr_width +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_page_addr_width +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_page_size +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_page_size +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_num_bytes_possible +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_num_bytes +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_addr_offset +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/r_done +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_num_bytes_possible +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_num_bytes +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_addr_offset +add wave -noupdate -group Legalizer /tb_idma_obi_backend/i_idma_backend/gen_hw_legalizer/i_idma_legalizer/w_done +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/clk_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/rst_ni +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/testmode_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/obi_req_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/obi_rsp_i +add wave -noupdate -group {Transport Layer} -expand /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/r_dp_req_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/r_dp_valid_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/r_dp_ready_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/r_dp_rsp_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/r_dp_valid_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/r_dp_ready_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/w_aw_dp_req_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/w_dp_valid_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/w_dp_ready_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/w_dp_rsp_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/w_dp_valid_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/w_dp_ready_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/ar_req_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/ar_valid_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/ar_ready_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/dp_poison_i +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/r_dp_busy_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/w_dp_busy_o +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_busy_o +add wave -noupdate -group {Transport Layer} -expand /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_in +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/read_aligned_in_mask +add wave -noupdate -group {Transport Layer} -expand /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/mask_in +add wave -noupdate -group {Transport Layer} -expand /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_in_valid +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_in_ready +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/in_valid +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/in_ready +add wave -noupdate -group {Transport Layer} -expand /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/mask_out +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_out +add wave -noupdate -group {Transport Layer} -expand /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_out_valid +add wave -noupdate -group {Transport Layer} -expand /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_out_ready +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/write_happening +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/ready_to_write +add wave -noupdate -group {Transport Layer} /tb_idma_obi_backend/i_idma_backend/gen_obi_transport_layer/i_idma_obi_transport_layer/buffer_clean +add wave -noupdate -divider BUS +add wave -noupdate -group {OBI Read IF} -label {OBI A} /tb_idma_obi_backend/i_obi_read_a_hl/in_wave +add wave -noupdate -group {OBI Read IF} -label {OBI R} /tb_idma_obi_backend/i_obi_read_r_hl/in_wave +add wave -noupdate -group {AXI Read IF} -label {AXI REQ} /tb_idma_obi_backend/axi_read_req +add wave -noupdate -group {AXI Read IF} -label {AXI RSP} /tb_idma_obi_backend/axi_read_rsp +add wave -noupdate -group {OBI Write IF} -label {OBI A} /tb_idma_obi_backend/i_obi_write_a_hl/in_wave +add wave -noupdate -group {OBI Write IF} -label {OBI R} /tb_idma_obi_backend/i_obi_write_r_hl/in_wave +add wave -noupdate -group {AXI Write IF} -label {AXI REQ} /tb_idma_obi_backend/axi_write_req +add wave -noupdate -group {AXI Write IF} -label {AXI RSP} /tb_idma_obi_backend/axi_write_rsp +add wave -noupdate -group {AXI IF} -label AW /tb_idma_obi_backend/i_aw_hl/in_wave +add wave -noupdate -group {AXI IF} -label AR /tb_idma_obi_backend/i_ar_hl/in_wave +add wave -noupdate -group {AXI IF} -label W /tb_idma_obi_backend/i_w_hl/in_wave +add wave -noupdate -group {AXI IF} -label R /tb_idma_obi_backend/i_r_hl/in_wave +add wave -noupdate -group {AXI IF} -label B /tb_idma_obi_backend/i_b_hl/in_wave +add wave -noupdate -group {iDMA IF} -label {iDMA REQ} /tb_idma_obi_backend/i_req_hl/in_wave +add wave -noupdate -group {iDMA IF} -label {iDMA RSP} -expand -subitemconfig {/tb_idma_obi_backend/i_rsp_hl/in_wave.pld -expand} /tb_idma_obi_backend/i_rsp_hl/in_wave +add wave -noupdate -group {iDMA IF} -label {iDMA EH} /tb_idma_obi_backend/i_eh_hl/in_wave +add wave -noupdate -group Busy -expand /tb_idma_obi_backend/i_idma_backend/busy_o +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {210998 ps} 0} +quietly wave cursor active 1 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 427 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {1121282 ps} {1235722 ps} diff --git a/src/idma_axi_lite_transport_layer.sv b/src/idma_axi_lite_transport_layer.sv new file mode 100644 index 00000000..1951ceb5 --- /dev/null +++ b/src/idma_axi_lite_transport_layer.sv @@ -0,0 +1,332 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Thomas Benz +// Tobias Senti + +`include "common_cells/registers.svh" + +/// Implementing the AXI4 transport layer in the iDMA backend. +module idma_axi_lite_transport_layer #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `r_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_req_t` type: + parameter type r_dp_rsp_t = logic, + /// `r_dp_req_t` type: + parameter type w_dp_rsp_t = logic, + /// AXI-Lite `AW` channel type + parameter type axi_lite_aw_chan_t = logic, + /// AXI-Lite `AR` channel type + parameter type axi_lite_ar_chan_t = logic, + /// AXI-Lite Request channel type + parameter type axi_lite_req_t = logic, + /// AXI-Lite Response channel type + parameter type axi_lite_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// AXI-Lite manager port request + output axi_lite_req_t axi_lite_req_o, + /// AXI-Lite manager port response + input axi_lite_rsp_t axi_lite_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input axi_lite_ar_chan_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input axi_lite_aw_chan_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] buffer_in; + + // read aligned in mask. needs to be shifted together with the data before + // it can be used to mask valid data flowing into the buffer + strb_t read_aligned_in_mask; + + // in mask is write aligned: it is the result of the read aligned in mask + // that is shifted together with the data in the barrel shifter + strb_t mask_in; + + // inbound control signals to the read buffer: controlled by the read process + strb_t buffer_in_valid; + strb_t buffer_in_ready; + logic in_valid; + logic in_ready; + + // corresponds to the strobe: the write aligned data that is currently valid in the buffer + strb_t mask_out; + + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out; + + // A temporary signal required to write the output of the buffer to before assigning it to + // the AXI bus. This is required to be compatible with some of the Questasim Versions and some + // of the parametrizations (e.g. DataWidth = 16) + data_t buffer_data_masked; + + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid; + strb_t buffer_out_ready; + + // write happens + logic write_happening; + // buffer is ready to write the requested data + logic ready_to_write; + // buffer is completely empty + logic buffer_clean; + + //-------------------------------------- + // Read meta channel + //-------------------------------------- + // connect the ar requests to the AXI bus + assign axi_lite_req_o.ar = ar_req_i; + assign axi_lite_req_o.ar_valid = ar_valid_i; + assign ar_ready_o = axi_lite_rsp_i.ar_ready; + + + //-------------------------------------- + // In mask generation + //-------------------------------------- + // in contiguous transfers that are unaligned, there will be some + // invalid bytes at the beginning and the end of the stream + // example: 25B in 64 bit system + // iiiivvvv|vvvvvvvv|vvvvvvvv|vvvvviii + // first msk|----full mask----|last msk + + assign read_aligned_in_mask = ('1 << r_dp_req_i.offset) & + ((r_dp_req_i.tailer != '0) ? ('1 >> (StrbWidth - r_dp_req_i.tailer)) : '1); + + //-------------------------------------- + // Barrel shifter + //-------------------------------------- + // data arrives in chunks of length DATA_WDITH, the buffer will be filled with + // the realigned data. StrbWidth bytes will be inserted starting from the + // provided address, overflows will naturally wrap + + // a barrel shifter is a concatenation of the same array with twice and a normal + // shift. Optimized for Synopsys DesignWare. + assign buffer_in = {axi_lite_rsp_i.r.data, axi_lite_rsp_i.r.data} >> (r_dp_req_i.shift * 8); + assign mask_in = {read_aligned_in_mask, read_aligned_in_mask} >> r_dp_req_i.shift; + + + //-------------------------------------- + // Read control + //-------------------------------------- + // the buffer can be pushed to if all the masked FIFO buffers (mask_in) are ready. + assign in_ready = &(buffer_in_ready | ~mask_in); + // the read can accept data if the buffer is ready and the response channel is ready + assign axi_lite_req_o.r_ready = in_ready & r_dp_ready_i; + + // once valid data is applied, it can be pushed in all the selected (mask_in) buffers + // be sure the response channel is ready + assign in_valid = axi_lite_rsp_i.r_valid & in_ready & r_dp_ready_i; + assign buffer_in_valid = in_valid ? mask_in : '0; + + // r_dp_ready_o is triggered by the element arriving from the read + assign r_dp_ready_o = r_dp_valid_i & r_dp_ready_i & axi_lite_rsp_i.r_valid & in_ready; + + // connect r_dp response payload + assign r_dp_rsp_o.resp = axi_lite_rsp_i.r.resp; + assign r_dp_rsp_o.last = 1'b1; + assign r_dp_rsp_o.first = 1'b1; + + // r_dp_valid_o is triggered once the element is here + assign r_dp_valid_o = axi_lite_rsp_i.r_valid & in_ready; + + + //-------------------------------------- + // Write meta channel + //-------------------------------------- + // connect the aw requests to the AXI bus + assign axi_lite_req_o.aw = aw_req_i; + assign axi_lite_req_o.aw_valid = aw_valid_i; + assign aw_ready_o = axi_lite_rsp_i.aw_ready; + + + //-------------------------------------- + // Out mask generation -> (wstrb mask) + //-------------------------------------- + // only pop the data actually needed for write from the buffer, + // determine valid data to pop by calculation the wstrb + + assign mask_out = ('1 << w_dp_req_i.offset) & + ((w_dp_req_i.tailer != '0) ? ('1 >> (StrbWidth - w_dp_req_i.tailer)) : '1); + + + //-------------------------------------- + // Write control + //-------------------------------------- + // write is decoupled from read, due to misalignment in the read/write + // addresses, page crossing can be encountered at any time. + // To handle this efficiently, a 2-to-1 or 1-to-2 mapping of r/w beats + // is required. The write unit needs to keep track of progress through + // a counter and cannot use `r last` for that. + + // Once buffer contains a full line -> all FIFOs are non-empty push it out. + + // all elements needed (defined by the mask) are in the buffer and the buffer is non-empty + assign ready_to_write = ((buffer_out_valid & mask_out) == mask_out) & (buffer_out_valid != '0); + + // the buffer is completely empty and idle + assign buffer_clean = &(~buffer_out_valid); + + // write happening: both the bus (w_ready) and the buffer (ready_to_write) is high + assign write_happening = ready_to_write & axi_lite_rsp_i.w_ready; + + // the main buffer is conditionally to the write mask popped + assign buffer_out_ready = write_happening ? mask_out : '0; + + // signal the bus that we are ready + assign axi_lite_req_o.w_valid = ready_to_write; + + // connect data and strobe either directly or mask invalid data + if (MaskInvalidData) begin : gen_mask_invalid_data + + // always_comb process implements masking of invalid data + always_comb begin : proc_mask + // defaults + axi_lite_req_o.w.data = '0; + axi_lite_req_o.w.strb = '0; + buffer_data_masked = '0; + // control the write to the bus apply data to the bus only if data should be written + if (ready_to_write == 1'b1 & !dp_poison_i) begin + // assign data from buffers, mask non valid entries + for (int i = 0; i < StrbWidth; i++) begin + buffer_data_masked[i*8 +: 8] = mask_out[i] ? buffer_out[i] : 8'b0; + end + // assign the output + axi_lite_req_o.w.data = buffer_data_masked; + // assign the out mask to the strobe + axi_lite_req_o.w.strb = mask_out; + end + end + + end else begin : gen_direct_connect + // not used signal + assign buffer_data_masked = '0; + // simpler: direct connection + assign axi_lite_req_o.w.data = buffer_out; + assign axi_lite_req_o.w.strb = dp_poison_i ? '0 : mask_out; + end + + // we are ready for the next transfer internally, once the w last signal is applied + assign w_dp_ready_o = write_happening; + + //-------------------------------------- + // Write response + //-------------------------------------- + // connect w_dp response payload + assign w_dp_rsp_o.resp = axi_lite_rsp_i.b.resp; + + // w_dp_valid_o is triggered once the write answer is here + assign w_dp_valid_o = axi_lite_rsp_i.b_valid; + + // create back pressure on the b channel if the higher parts of the DMA cannot accept more + // write responses + assign axi_lite_req_o.b_ready = w_dp_ready_i; + + //-------------------------------------- + // Buffer + //-------------------------------------- + idma_buffer #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_idma_buffer ( + .clk_i, + .rst_ni, + .testmode_i, + .data_i ( buffer_in ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready ) + ); + + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i | r_dp_ready_o; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = !buffer_clean; + +endmodule : idma_axi_lite_transport_layer diff --git a/src/idma_backend.sv b/src/idma_backend.sv index 82d3b461..2962e340 100644 --- a/src/idma_backend.sv +++ b/src/idma_backend.sv @@ -2,13 +2,16 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // -// Thomas Benz +// Thomas Benz +// Tobias Senti `include "axi/typedef.svh" `include "idma/guard.svh" -/// The iDMA backend implements an arbitrary 1D copy engine using the AXI4 protocol. +/// The iDMA backend implements an arbitrary 1D copy engine module idma_backend #( + /// Protocol used + parameter idma_pkg::protocol_e Protocol = idma_pkg::AXI, /// Data width parameter int unsigned DataWidth = 32'd16, /// Address width @@ -49,10 +52,14 @@ module idma_backend #( parameter type idma_eh_req_t = logic, /// iDMA busy signal parameter type idma_busy_t = logic, - /// AXI4+ATOP request type - parameter type axi_req_t = logic, - /// AXI4+ATOP response type - parameter type axi_rsp_t = logic, + /// Protocol request type + parameter type protocol_req_t = logic, + /// Protocol response type + parameter type protocol_rsp_t = logic, + /// Address Write Channel type + parameter type aw_chan_t = logic, + /// Address Read Channel type + parameter type ar_chan_t = logic, /// Strobe Width (do not override!) parameter int unsigned StrbWidth = DataWidth / 8, /// Offset Width (do not override!) @@ -86,10 +93,10 @@ module idma_backend #( /// Error handler request ready output logic eh_req_ready_o, - /// AXI4+ATOP manager port request - output axi_req_t axi_req_o, - /// AXI4+ATOP manager port response - input axi_rsp_t axi_rsp_i, + /// Manager port request + output protocol_req_t protocol_req_o, + /// Manager port response + input protocol_rsp_t protocol_rsp_i, /// iDMA busy flags output idma_busy_t busy_o @@ -114,10 +121,6 @@ module idma_backend #( /// Transfer length type typedef logic [TFLenWidth-1:0] tf_len_t; - // AXI4+ATOP define macros for the AX channels - `AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) - `AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) - /// The datapath read request type holds all the information required to configure the read /// part of the datapath. The type consists of: /// - `offset`: The bus offset of the read @@ -167,7 +170,7 @@ module idma_backend #( /// The iDMA read request bundles an `AR` type and a datapath read response type together. typedef struct packed { r_dp_req_t r_dp_req; - axi_ar_chan_t ar_req; + ar_chan_t ar_req; } idma_r_req_t; /// The iDMA write request bundles an `AW` type and a datapath write response type together. It @@ -178,12 +181,17 @@ module idma_backend #( /// - `decouple_aw`: indicates this is an R-AW decoupled transfer typedef struct packed { w_dp_req_t w_dp_req; - axi_aw_chan_t aw_req; + aw_chan_t aw_req; logic last; logic super_last; logic decouple_aw; } idma_w_req_t; + typedef struct packed { + w_dp_req_t w_dp_req; + aw_chan_t aw_req; + } w_aw_dp_req_t; + /// The mutable transfer options type holds important information that is mutated by the /// `legalizer` block. typedef struct packed { @@ -235,6 +243,7 @@ module idma_backend #( logic r_dp_req_out_ready, w_dp_req_out_ready; r_dp_req_t r_dp_req_out; w_dp_req_t w_dp_req_out; + w_aw_dp_req_t w_aw_dp_req_out; // datapah responses r_dp_rsp_t r_dp_rsp; @@ -248,10 +257,10 @@ module idma_backend #( logic aw_valid_dp, ar_valid_dp; // Ax request from R-AW coupler to datapath - axi_aw_chan_t aw_req_dp; + aw_chan_t aw_req_dp; // Ax request from the decoupling stage to the datapath - axi_ar_chan_t ar_req_dp; + ar_chan_t ar_req_dp; // flush and preemptively empty the legalizer logic legalizer_flush, legalizer_kill; @@ -309,6 +318,7 @@ module idma_backend #( if (HardwareLegalizer) begin : gen_hw_legalizer // hardware legalizer is present idma_legalizer #( + .Protocol ( Protocol ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), .idma_req_t ( idma_req_t ), @@ -353,36 +363,56 @@ module idma_backend #( assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - 'd1) >> OffsetWidth); - // assemble AR request - assign r_req.ar_req = '{ - id: idma_req_i.opt.axi_id, - addr: { idma_req_i.src_addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: len, - size: axi_pkg::size_t'(OffsetWidth), - burst: idma_req_i.opt.src.burst, - lock: idma_req_i.opt.src.lock, - cache: idma_req_i.opt.src.cache, - prot: idma_req_i.opt.src.prot, - qos: idma_req_i.opt.src.qos, - region: idma_req_i.opt.src.region, - user: '0 - }; - // assemble AW request - assign w_req.aw_req = '{ - id: idma_req_i.opt.axi_id, - addr: { idma_req_i.dst_addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: len, - size: axi_pkg::size_t'(OffsetWidth), - burst: idma_req_i.opt.dst.burst, - lock: idma_req_i.opt.dst.lock, - cache: idma_req_i.opt.dst.cache, - prot: idma_req_i.opt.dst.prot, - qos: idma_req_i.opt.dst.qos, - region: idma_req_i.opt.dst.region, - user: '0, - atop: '0 - }; + if (Protocol == idma_pkg::AXI) begin : gen_axi_ar_aw_req + // assemble AR request + assign r_req.ar_req = '{ + id: idma_req_i.opt.axi_id, + addr: { idma_req_i.src_addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: len, + size: axi_pkg::size_t'(OffsetWidth), + burst: idma_req_i.opt.src.burst, + lock: idma_req_i.opt.src.lock, + cache: idma_req_i.opt.src.cache, + prot: idma_req_i.opt.src.prot, + qos: idma_req_i.opt.src.qos, + region: idma_req_i.opt.src.region, + user: '0 + }; + + // assemble AW request + assign w_req.aw_req = '{ + id: idma_req_i.opt.axi_id, + addr: { idma_req_i.dst_addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: len, + size: axi_pkg::size_t'(OffsetWidth), + burst: idma_req_i.opt.dst.burst, + lock: idma_req_i.opt.dst.lock, + cache: idma_req_i.opt.dst.cache, + prot: idma_req_i.opt.dst.prot, + qos: idma_req_i.opt.dst.qos, + region: idma_req_i.opt.dst.region, + user: '0, + atop: '0 + }; + end else if (Protocol == idma_pkg::AXI_LITE) begin : gen_axi_lite_ar_aw_req + // assemble AR request + assign r_req.ar_req = '{ + addr: { idma_req_i.src_addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + prot: idma_req_i.opt.src.prot + }; + + // assemble AW request + assign w_req.aw_req = '{ + addr: { idma_req_i.dst_addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + prot: idma_req_i.opt.dst.prot + }; + end else begin : gen_ar_aw_req_error + `IDMA_NONSYNTH_BLOCK( + $fatal(1, "Backend: legalizer bypass ar aw req not implemented for requested ", + "protocol!"); + ) + end // assemble read datapath request assign r_req.r_dp_req = '{ @@ -514,28 +544,48 @@ module idma_backend #( .ready_i ( r_dp_req_out_ready ) ); - idma_stream_fifo #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); + if(Protocol == idma_pkg::OBI) begin : gen_obi_w_aw_dp_req_fifo + idma_stream_fifo #( + .Depth ( NumAxInFlight ), + .type_t ( w_aw_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( { w_req.w_dp_req, w_req.aw_req } ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_aw_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + end else begin : gen_w_dp_fifo + idma_stream_fifo #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + end // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay fall_through_register #( - .T ( axi_ar_chan_t ) + .T ( ar_chan_t ) ) i_ar_fall_through_register ( .clk_i, .rst_ni, @@ -553,76 +603,182 @@ module idma_backend #( //-------------------------------------- // Last flag store //-------------------------------------- - idma_stream_fifo #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - + //if (Protocol == idma_pkg::AXI) begin : gen_last_flag_fifo + if (1'b1) begin : gen_last_flag_fifo + idma_stream_fifo #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + end else if (Protocol == idma_pkg::AXI_LITE) begin : gen_last_flag_bypass + //For AXI-Lite every transfer is last + assign w_super_last = 1'b1; + assign w_last_burst = 1'b1; + assign w_last_ready = 1'b1; + end else begin : gen_last_flag_error + `IDMA_NONSYNTH_BLOCK( + $fatal(1, "Backend: last flag bypass not implemented for requested protocol!"); + ) + end //-------------------------------------- // Transport Layer / Datapath //-------------------------------------- - idma_axi_transport_layer #( - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .axi_aw_chan_t ( axi_aw_chan_t ), - .axi_ar_chan_t ( axi_ar_chan_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ) - ) i_idma_axi_transport_layer ( - .clk_i, - .rst_ni, - .testmode_i, - .axi_req_o, - .axi_rsp_i, - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ) - ); - + if (Protocol == idma_pkg::AXI) begin : gen_axi_transport_layer + idma_axi_transport_layer #( + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .axi_aw_chan_t ( aw_chan_t ), + .axi_ar_chan_t ( ar_chan_t ), + .axi_req_t ( protocol_req_t ), + .axi_rsp_t ( protocol_rsp_t ) + ) i_idma_axi_transport_layer ( + .clk_i, + .rst_ni, + .testmode_i, + .axi_req_o ( protocol_req_o ), + .axi_rsp_i ( protocol_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ) + ); + end else if (Protocol == idma_pkg::AXI_LITE) begin : gen_axi_lite_transport_layer + idma_axi_lite_transport_layer #( + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .axi_lite_aw_chan_t ( aw_chan_t ), + .axi_lite_ar_chan_t ( ar_chan_t ), + .axi_lite_req_t ( protocol_req_t ), + .axi_lite_rsp_t ( protocol_rsp_t ) + ) i_idma_axi_lite_transport_layer ( + .clk_i, + .rst_ni, + .testmode_i, + .axi_lite_req_o ( protocol_req_o ), + .axi_lite_rsp_i ( protocol_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ) + ); + end else if (Protocol == idma_pkg::OBI) begin : gen_obi_transport_layer + idma_obi_transport_layer #( + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_aw_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .obi_a_chan_t ( ar_chan_t ), + .obi_req_t ( protocol_req_t ), + .obi_rsp_t ( protocol_rsp_t ) + ) i_idma_obi_transport_layer ( + .clk_i, + .rst_ni, + .testmode_i, + .obi_req_o ( protocol_req_o ), + .obi_rsp_i ( protocol_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_aw_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .read_meta_req_i ( ar_req_dp ), + .read_meta_valid_i ( ar_valid_dp ), + .read_meta_ready_o ( ar_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ) + ); + end else begin : gen_transport_layer_error + `IDMA_NONSYNTH_BLOCK( + $fatal(1, "Backend: transport layer not implemented for requested protocol!"); + ) + end //-------------------------------------- // R-AW channel coupler //-------------------------------------- - if (RAWCouplingAvail) begin : gen_r_aw_coupler + if(Protocol == idma_pkg::OBI) begin : gen_obi_coupler + //AW Meta Channel not needed + assign aw_ready = 1'b1; + assign aw_valid_dp = 1'b0; + assign aw_req_dp = '0; + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end else if (RAWCouplingAvail) begin : gen_r_aw_coupler // instantiate the channel coupler idma_channel_coupler #( .NumAxInFlight ( NumAxInFlight ), @@ -630,13 +786,13 @@ module idma_backend #( .UserWidth ( UserWidth ), .AxiIdWidth ( AxiIdWidth ), .PrintFifoInfo ( PrintFifoInfo ), - .axi_aw_chan_t ( axi_aw_chan_t ) + .axi_aw_chan_t ( aw_chan_t ) ) i_idma_channel_coupler ( .clk_i, .rst_ni, .testmode_i, - .r_rsp_valid_i ( axi_rsp_i.r_valid ), - .r_rsp_ready_i ( axi_req_o.r_ready ), + .r_rsp_valid_i ( protocol_rsp_i.r_valid ), + .r_rsp_ready_i ( protocol_req_o.r_ready ), .r_rsp_first_i ( r_dp_rsp.first ), .r_decouple_aw_i ( r_dp_req_out.decouple_aw ), .aw_decouple_aw_i ( w_req.decouple_aw ), @@ -653,7 +809,7 @@ module idma_backend #( // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay fall_through_register #( - .T ( axi_aw_chan_t ) + .T ( aw_chan_t ) ) i_aw_fall_through_register ( .clk_i, .rst_ni, diff --git a/src/idma_legalizer.sv b/src/idma_legalizer.sv index 0eb853e8..d7359310 100644 --- a/src/idma_legalizer.sv +++ b/src/idma_legalizer.sv @@ -2,15 +2,19 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // -// Thomas Benz +// Thomas Benz +// Tobias Senti `include "common_cells/registers.svh" `include "common_cells/assertions.svh" +`include "idma/guard.svh" /// Legalizes a generic 1D transfer according to the rules given by the /// AXI4 protocol. Bursts are cut at 4kiB boundaries and are a maximum of /// 256 beats long. module idma_legalizer #( + /// Protocol used + parameter idma_pkg::protocol_e Protocol = idma_pkg::AXI, /// Data width parameter int unsigned DataWidth = 32'd16, /// Address width @@ -65,13 +69,16 @@ module idma_legalizer #( /// Write machine of the legalizer is busy output logic w_busy_o ); + /// Maximum number of beats within a burst + localparam int unsigned MaxBeatsPerBurst = idma_pkg::determineMaxBeatsPerBurst(Protocol); /// Stobe width localparam int unsigned StrbWidth = DataWidth / 8; /// Offset width localparam int unsigned OffsetWidth = $clog2(StrbWidth); /// The size of a page in byte - localparam int unsigned PageSize = (256 * StrbWidth > 4096) ? 4096 : 256 * StrbWidth; + localparam int unsigned PageSize = (MaxBeatsPerBurst * StrbWidth > 4096) ? + 4096 : MaxBeatsPerBurst * StrbWidth; /// The width of page offset byte addresses localparam int unsigned PageAddrWidth = $clog2(PageSize); @@ -128,7 +135,7 @@ module idma_legalizer #( // smaller chunks than the AXI page size? r_page_addr_width = OffsetWidth + (opt_tf_q.src_reduce_len ? opt_tf_q.src_max_llen : 'd8); // a page can be a maximum of 4kB (12 bit) - r_page_addr_width = r_page_addr_width > 'd12 ? 'd12 : r_page_addr_width; + r_page_addr_width = r_page_addr_width > PageAddrWidth ? PageAddrWidth : r_page_addr_width; end // calculate the page size in byte assign r_page_size = (1 << r_page_addr_width); @@ -158,7 +165,7 @@ module idma_legalizer #( // smaller chunks than the AXI page size? w_page_addr_width = OffsetWidth + (opt_tf_q.dst_reduce_len ? opt_tf_q.dst_max_llen : 'd8); // a page can be a maximum of 4kB (12 bit) - w_page_addr_width = w_page_addr_width > 'd12 ? 'd12 : w_page_addr_width; + w_page_addr_width = w_page_addr_width > PageAddrWidth ? PageAddrWidth : w_page_addr_width; end // calculate the page size in byte assign w_page_size = (1 << w_page_addr_width); @@ -304,36 +311,69 @@ module idma_legalizer #( //-------------------------------------- // Connect outputs //-------------------------------------- - // assign the signals for the read meta channel - assign r_req_o.ar_req = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 - }; + if (Protocol == idma_pkg::AXI) begin : gen_axi_ar_aw_req + // assign the signals for the read meta channel + assign r_req_o.ar_req = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + // assign the signals for the write meta channel + assign w_req_o.aw_req = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + end else if (Protocol == idma_pkg::AXI_LITE) begin : gen_axi_lite_ar_aw_req + // assign the signals for the read meta channel + assign r_req_o.ar_req = '{ + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + prot: opt_tf_q.src_axi_opt.prot + }; + + // assign the signals for the write meta channel + assign w_req_o.aw_req = '{ + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + prot: opt_tf_q.dst_axi_opt.prot + }; + end else if (Protocol == idma_pkg::OBI) begin : gen_obi_ar_aw_req + assign r_req_o.ar_req = '{ + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '1, //TODO: Placeholder, read everything + we: 1'b0, + wdata: '0 + }; - // assign the signals for the write meta channel - assign w_req_o.aw_req = '{ - id: opt_tf_q.axi_id, - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 - }; + // assign the signals for the write meta channel + assign w_req_o.aw_req = '{ + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '0, + we: 1, + wdata: '0 + }; + end else begin : gen_ar_aw_req_error + `IDMA_NONSYNTH_BLOCK( + $fatal(1, "Legalizer: ar ar req not implemented for requested protocol!"); + ) + end // assign the signals needed to set-up the read data path assign r_req_o.r_dp_req = '{ @@ -344,12 +384,26 @@ module idma_legalizer #( }; // assign the signals needed to set-up the write data path - assign w_req_o.w_dp_req = '{ - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - num_beats: w_req_o.aw_req.len, - is_single: w_req_o.aw_req.len == '0 - }; + if (Protocol == idma_pkg::AXI) begin : gen_axi_w_dp_req + assign w_req_o.w_dp_req = '{ + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + num_beats: w_req_o.aw_req.len, + is_single: w_req_o.aw_req.len == '0 + }; + end else if (Protocol inside { idma_pkg::AXI_LITE, idma_pkg::OBI} ) begin + : gen_axi_lite_obi_w_dp_req + assign w_req_o.w_dp_req = '{ + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + num_beats: 'd0, + is_single: 1'b1 + }; + end else begin : gen_w_dp_req_error + `IDMA_NONSYNTH_BLOCK( + $fatal(1, "Legalizer: w dp req not implemented for requested protocol!"); + ) + end // last burst in generic 1D transfer? assign w_req_o.last = w_done; diff --git a/src/idma_obi_transport_layer.sv b/src/idma_obi_transport_layer.sv new file mode 100644 index 00000000..8c54a421 --- /dev/null +++ b/src/idma_obi_transport_layer.sv @@ -0,0 +1,307 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Thomas Benz +// Tobias Senti + +`include "common_cells/registers.svh" + +/// Implementing the OBI transport layer in the iDMA backend. +module idma_obi_transport_layer #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// OBI `A` channel type + parameter type obi_a_chan_t = logic, + /// OBI Request channel type + parameter type obi_req_t = logic, + /// OBI Response channel type + parameter type obi_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input obi_a_chan_t read_meta_req_i, + /// Read meta request valid + input logic read_meta_valid_i, + /// Read meta request ready + output logic read_meta_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o, + + /// OBI manager port request + output obi_req_t obi_req_o, + /// OBI manager port response + input obi_rsp_t obi_rsp_i +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] buffer_in; + + // read aligned in mask. needs to be shifted together with the data before + // it can be used to mask valid data flowing into the buffer + strb_t read_aligned_in_mask; + + // in mask is write aligned: it is the result of the read aligned in mask + // that is shifted together with the data in the barrel shifter + strb_t mask_in; + + // inbound control signals to the read buffer: controlled by the read process + strb_t buffer_in_valid; + strb_t buffer_in_ready; + logic in_valid; + logic in_ready; + + // corresponds to the strobe: the write aligned data that is currently valid in the buffer + strb_t mask_out; + + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out; + + // A temporary signal required to write the output of the buffer to before assigning it to + // the OBI bus. This is required to be compatible with some of the Questasim Versions and some + // of the parametrizations (e.g. DataWidth = 16) + data_t buffer_data_masked; + + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid; + strb_t buffer_out_ready; + + // write happens + logic write_happening; + // buffer is ready to write the requested data + logic ready_to_write; + // buffer is completely empty + logic buffer_clean; + + //-------------------------------------- + // Read meta channel + //-------------------------------------- + // connect the read requests to the OBI bus + assign obi_req_o.read.a = read_meta_req_i; + assign obi_req_o.read.a_req = read_meta_valid_i; + assign read_meta_ready_o = obi_rsp_i.read.a_gnt; + + //-------------------------------------- + // In mask generation + //-------------------------------------- + // in contiguous transfers that are unaligned, there will be some + // invalid bytes at the beginning and the end of the stream + // example: 25B in 64 bit system + // iiiivvvv|vvvvvvvv|vvvvvvvv|vvvvviii + // first msk|----full mask----|last msk + + assign read_aligned_in_mask = ('1 << r_dp_req_i.offset) & + ((r_dp_req_i.tailer != '0) ? ('1 >> (StrbWidth - r_dp_req_i.tailer)) : '1); + + //-------------------------------------- + // Barrel shifter + //-------------------------------------- + // data arrives in chunks of length DATA_WDITH, the buffer will be filled with + // the realigned data. StrbWidth bytes will be inserted starting from the + // provided address, overflows will naturally wrap + + // a barrel shifter is a concatenation of the same array with twice and a normal + // shift. Optimized for Synopsys DesignWare. + assign buffer_in = {obi_rsp_i.read.r.rdata, obi_rsp_i.read.r.rdata} >> (r_dp_req_i.shift * 8); + assign mask_in = {read_aligned_in_mask, read_aligned_in_mask} >> r_dp_req_i.shift; + + + //-------------------------------------- + // Read control + //-------------------------------------- + // the buffer can be pushed to if all the masked FIFO buffers (mask_in) are ready. + assign in_ready = &(buffer_in_ready | ~mask_in); + // the read can accept data if the buffer is ready and the response channel is ready + assign obi_req_o.read.r_ready = in_ready & r_dp_ready_i; + + // once valid data is applied, it can be pushed in all the selected (mask_in) buffers + // be sure the response channel is ready + assign in_valid = obi_rsp_i.read.r_valid & r_dp_ready_i; + assign buffer_in_valid = in_valid ? mask_in : '0; + + // r_dp_ready_o is triggered by the element arriving from the read + assign r_dp_ready_o = r_dp_valid_i & r_dp_ready_i & obi_rsp_i.read.r_valid & in_ready; + + // connect r_dp response payload + assign r_dp_rsp_o.resp = '0; + assign r_dp_rsp_o.last = 1'b1; + assign r_dp_rsp_o.first = 1'b1; + + // r_dp_valid_o is triggered once the element is here + assign r_dp_valid_o = obi_rsp_i.read.r_valid & in_ready; + + //-------------------------------------- + // Out mask generation -> (be mask) + //-------------------------------------- + // only pop the data actually needed for write from the buffer, + // determine valid data to pop by calculation the be + + assign mask_out = ('1 << w_dp_req_i.w_dp_req.offset) & + ((w_dp_req_i.w_dp_req.tailer != '0) ? ('1 >> (StrbWidth - w_dp_req_i.w_dp_req.tailer)) + : '1); + + //-------------------------------------- + // Write control + //-------------------------------------- + + // all elements needed (defined by the mask) are in the buffer and the buffer is non-empty + assign ready_to_write = ((buffer_out_valid & mask_out) == mask_out) & (buffer_out_valid != '0); + + // the buffer is completely empty and idle + assign buffer_clean = &(~buffer_out_valid); + + // write happening: both the bus (a_gnt) and the buffer (ready_to_write) is high + assign write_happening = ready_to_write & obi_rsp_i.write.a_gnt; + + // the main buffer is conditionally to the write mask popped + assign buffer_out_ready = write_happening ? mask_out : '0; + + // signal the bus that we are ready + assign obi_req_o.write.a_req = ready_to_write; + + // connect data and strobe either directly or mask invalid data + if (MaskInvalidData) begin : gen_mask_invalid_data + + // always_comb process implements masking of invalid data + always_comb begin : proc_mask + // defaults + obi_req_o.write.a.addr = w_dp_req_i.aw_req.addr; + obi_req_o.write.a.we = 1'b1; + obi_req_o.write.a.wdata = '0; + obi_req_o.write.a.be = '0; + buffer_data_masked = '0; + // control the write to the bus apply data to the bus only if data should be written + if (ready_to_write == 1'b1 & !dp_poison_i) begin + // assign data from buffers, mask non valid entries + for (int i = 0; i < StrbWidth; i++) begin + buffer_data_masked[i*8 +: 8] = mask_out[i] ? buffer_out[i] : 8'b0; + end + // assign the output + obi_req_o.write.a.wdata = buffer_data_masked; + // assign the out mask to the strobe + obi_req_o.write.a.be = mask_out; + end + end + + end else begin : gen_direct_connect + // not used signal + assign buffer_data_masked = '0; + // simpler: direct connection + assign obi_req_o.write.a.wdata = buffer_out; + assign obi_req_o.write.a.be = dp_poison_i ? '0 : mask_out; + end + + // we are ready for the next transfer internally, once a write is happening + assign w_dp_ready_o = write_happening; + + //-------------------------------------- + // Write response + //-------------------------------------- + // connect w_dp response payload + assign w_dp_rsp_o.resp = '0; + + // w_dp_valid_o is triggered once the write answer is here + assign w_dp_valid_o = obi_rsp_i.write.r_valid; + + // create back pressure on the r channel if the higher parts of the DMA cannot accept more + // write responses + assign obi_req_o.write.r_ready = w_dp_ready_i; + + //-------------------------------------- + // Buffer + //-------------------------------------- + idma_buffer #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_idma_buffer ( + .clk_i, + .rst_ni, + .testmode_i, + .data_i ( buffer_in ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready ) + ); + + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i | r_dp_ready_o; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = !buffer_clean; + +endmodule : idma_obi_transport_layer diff --git a/src/idma_pkg.sv b/src/idma_pkg.sv index bbd87bb0..e283f0db 100644 --- a/src/idma_pkg.sv +++ b/src/idma_pkg.sv @@ -2,7 +2,8 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // -// Thomas Benz +// Thomas Benz +// Tobias Senti /// iDMA Package /// Contains all static type definitions @@ -79,4 +80,24 @@ package idma_pkg; logic dst_reduce_len; } backend_options_t; + /// Supported Protocols + /// - `AXI`: Full AXI + /// - `AXI_LITE`: AXI Lite + /// - `OBI`: OBI + typedef enum logic[1:0] { + AXI, + AXI_LITE, + OBI + } protocol_e; + + /// Determines the maximum number of beats allowed within a burst depending on the protocol + /// - `protocol`: The protocol that is used + function automatic int unsigned determineMaxBeatsPerBurst(protocol_e protocol); + case (protocol) + AXI: return 256; + // AXI-Lite and OBI do not have bursts + default: return 1; + endcase + endfunction + endpackage : idma_pkg diff --git a/src/include/idma/typedef.svh b/src/include/idma/typedef.svh index 936421e0..51bb8906 100644 --- a/src/include/idma/typedef.svh +++ b/src/include/idma/typedef.svh @@ -92,4 +92,43 @@ `IDMA_TYPEDEF_ND_REQ_T(idma_nd_req_t, idma_req_t, idma_d_req_t) //////////////////////////////////////////////////////////////////////////////////////////////////// +`define IDMA_OBI_TYPEDEF_A_CHAN_T(a_chan_t, addr_t, data_t, strb_t) \ + typedef struct packed { \ + addr_t addr; \ + logic we; \ + strb_t be; \ + data_t wdata; \ + } a_chan_t; + +`define IDMA_OBI_TYPEDEF_R_CHAN_T(r_chan_t, data_t) \ + typedef struct packed { \ + data_t rdata; \ + } r_chan_t; + +`define IDMA_OBI_TYPEDEF_REQ_T(req_t, a_chan_t) \ + typedef struct packed { \ + a_chan_t a; \ + logic a_req; \ + logic r_ready; \ + } req_t; + +`define IDMA_OBI_TYPEDEF_RESP_T(resp_t, r_chan_t) \ + typedef struct packed { \ + logic a_gnt; \ + r_chan_t r; \ + logic r_valid; \ + } resp_t; + +`define IDMA_OBI_TYPEDEF_BIDIRECT_REQ_T(bidirect_req_t, req_t) \ + typedef struct packed { \ + req_t write; \ + req_t read; \ + } bidirect_req_t; + +`define IDMA_OBI_TYPEDEF_BIDIRECT_RESP_T(bidirect_resp_t, resp_t) \ + typedef struct packed { \ + resp_t write; \ + resp_t read; \ + } bidirect_resp_t; + `endif diff --git a/src/synth_wrapper/idma_backend_synth.sv b/src/synth_wrapper/idma_backend_synth.sv index 4bd98384..cccc51cf 100644 --- a/src/synth_wrapper/idma_backend_synth.sv +++ b/src/synth_wrapper/idma_backend_synth.sv @@ -2,7 +2,8 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // -// Thomas Benz +// Thomas Benz +// Tobias Senti `include "axi/typedef.svh" `include "idma/typedef.svh" @@ -214,8 +215,10 @@ module idma_backend_synth #( .idma_rsp_t ( idma_rsp_t ), .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ) + .protocol_req_t ( axi_req_t ), + .protocol_rsp_t ( axi_rsp_t ), + .aw_chan_t ( axi_aw_chan_t ), + .ar_chan_t ( axi_ar_chan_t ) ) i_idma_backend ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -229,8 +232,8 @@ module idma_backend_synth #( .idma_eh_req_i ( eh_req_i ), .eh_req_valid_i ( eh_req_valid_i ), .eh_req_ready_o ( eh_req_ready_o ), - .axi_req_o ( axi_req_o ), - .axi_rsp_i ( axi_rsp_i ), + .protocol_req_o ( axi_req_o ), + .protocol_rsp_i ( axi_rsp_i ), .busy_o ( idma_busy_o ) ); diff --git a/src/synth_wrapper/idma_lite_backend_synth.sv b/src/synth_wrapper/idma_lite_backend_synth.sv new file mode 100644 index 00000000..dfd91a28 --- /dev/null +++ b/src/synth_wrapper/idma_lite_backend_synth.sv @@ -0,0 +1,268 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Thomas Benz +// Tobias Senti + +`include "axi/typedef.svh" +`include "idma/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_lite_backend_synth #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b1, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output idma_pkg::idma_busy_t idma_busy_o, + + output addr_t axi_lite_aw_addr_o, + output axi_pkg::prot_t axi_lite_aw_prot_o, + output logic axi_lite_aw_valid_o, + input logic axi_lite_aw_ready_i, + output data_t axi_lite_w_data_o, + output strb_t axi_lite_w_strb_o, + output logic axi_lite_w_valid_o, + input logic axi_lite_w_ready_i, + input axi_pkg::resp_t axi_lite_b_resp_i, + input logic axi_lite_b_valid_i, + output logic axi_lite_b_ready_o, + output addr_t axi_lite_ar_addr_o, + output axi_pkg::prot_t axi_lite_ar_prot_o, + output logic axi_lite_ar_valid_o, + input logic axi_lite_ar_ready_i, + input data_t axi_lite_r_data_i, + input axi_pkg::resp_t axi_lite_r_resp_i, + input logic axi_lite_r_valid_i, + output logic axi_lite_r_ready_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI-Lite types + `AXI_LITE_TYPEDEF_AW_CHAN_T(axi_lite_aw_chan_t, addr_t) + `AXI_LITE_TYPEDEF_W_CHAN_T(axi_lite_w_chan_t, data_t, strb_t) + `AXI_LITE_TYPEDEF_B_CHAN_T(axi_lite_b_chan_t) + + `AXI_LITE_TYPEDEF_AR_CHAN_T(axi_lite_ar_chan_t, addr_t) + `AXI_LITE_TYPEDEF_R_CHAN_T(axi_lite_r_chan_t, data_t) + + `AXI_LITE_TYPEDEF_REQ_T(axi_lite_req_t, axi_lite_aw_chan_t, axi_lite_w_chan_t, + axi_lite_ar_chan_t) + `AXI_LITE_TYPEDEF_RESP_T(axi_lite_rsp_t, axi_lite_b_chan_t, axi_lite_r_chan_t) + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + // local types + axi_lite_req_t axi_lite_req_o; + axi_lite_rsp_t axi_lite_rsp_i; + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + // DUT instantiation + idma_backend #( + .Protocol ( idma_pkg::AXI_LITE ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .protocol_req_t ( axi_lite_req_t ), + .protocol_rsp_t ( axi_lite_rsp_t ), + .aw_chan_t ( axi_lite_aw_chan_t ), + .ar_chan_t ( axi_lite_ar_chan_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .protocol_req_o ( axi_lite_req_o ), + .protocol_rsp_i ( axi_lite_rsp_i ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + assign axi_lite_aw_addr_o = axi_lite_req_o.aw.addr; + assign axi_lite_aw_prot_o = axi_lite_req_o.aw.prot; + assign axi_lite_aw_valid_o = axi_lite_req_o.aw_valid; + assign axi_lite_w_data_o = axi_lite_req_o.w.data; + assign axi_lite_w_strb_o = axi_lite_req_o.w.strb; + assign axi_lite_w_valid_o = axi_lite_req_o.w_valid; + assign axi_lite_b_ready_o = axi_lite_req_o.b_ready; + assign axi_lite_ar_addr_o = axi_lite_req_o.ar.addr; + assign axi_lite_ar_prot_o = axi_lite_req_o.ar.prot; + assign axi_lite_ar_valid_o = axi_lite_req_o.ar_valid; + assign axi_lite_r_ready_o = axi_lite_req_o.r_ready; + + assign axi_lite_rsp_i.aw_ready = axi_lite_aw_ready_i; + assign axi_lite_rsp_i.w_ready = axi_lite_w_ready_i; + assign axi_lite_rsp_i.b.resp = axi_lite_b_resp_i; + assign axi_lite_rsp_i.b_valid = axi_lite_b_valid_i; + assign axi_lite_rsp_i.ar_ready = axi_lite_ar_ready_i; + assign axi_lite_rsp_i.r.data = axi_lite_r_data_i; + assign axi_lite_rsp_i.r.resp = axi_lite_r_resp_i; + assign axi_lite_rsp_i.r_valid = axi_lite_r_valid_i; + +endmodule : idma_lite_backend_synth diff --git a/src/synth_wrapper/idma_nd_backend_synth.sv b/src/synth_wrapper/idma_nd_backend_synth.sv index 0d4f4a88..4fdc40b4 100644 --- a/src/synth_wrapper/idma_nd_backend_synth.sv +++ b/src/synth_wrapper/idma_nd_backend_synth.sv @@ -2,7 +2,8 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // -// Thomas Benz +// Thomas Benz +// Tobias Senti `include "axi/typedef.svh" `include "idma/typedef.svh" @@ -249,8 +250,10 @@ module idma_nd_backend_synth #( .idma_rsp_t ( idma_rsp_t ), .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ) + .protocol_req_t ( axi_req_t ), + .protocol_rsp_t ( axi_rsp_t ), + .aw_chan_t ( axi_aw_chan_t ), + .ar_chan_t ( axi_ar_chan_t ) ) i_idma_backend ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -264,8 +267,8 @@ module idma_nd_backend_synth #( .idma_eh_req_i ( eh_req_i ), .eh_req_valid_i ( eh_req_valid_i ), .eh_req_ready_o ( eh_req_ready_o ), - .axi_req_o ( axi_req_o ), - .axi_rsp_i ( axi_rsp_i ), + .protocol_req_o ( axi_req_o ), + .protocol_rsp_i ( axi_rsp_i ), .busy_o ( idma_busy_o ) ); diff --git a/src/synth_wrapper/idma_obi_backend_synth.sv b/src/synth_wrapper/idma_obi_backend_synth.sv new file mode 100644 index 00000000..618e3908 --- /dev/null +++ b/src/synth_wrapper/idma_obi_backend_synth.sv @@ -0,0 +1,263 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Thomas Benz +// Tobias Senti + +`include "axi/typedef.svh" +`include "idma/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_obi_backend_synth #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b0, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output idma_pkg::idma_busy_t idma_busy_o, + + output logic obi_write_req_a_req_o, + output addr_t obi_write_req_a_addr_o, + output logic obi_write_req_a_we_o, + output strb_t obi_write_req_a_be_o, + output data_t obi_write_req_a_wdata_o, + output logic obi_write_req_r_ready_o, + + output logic obi_read_req_a_req_o, + output addr_t obi_read_req_a_addr_o, + output logic obi_read_req_a_we_o, + output strb_t obi_read_req_a_be_o, + output data_t obi_read_req_a_wdata_o, + output logic obi_read_req_r_ready_o, + + input logic obi_write_rsp_a_gnt_i, + input logic obi_write_rsp_r_valid_i, + input data_t obi_write_rsp_r_rdata_i, + + input logic obi_read_rsp_a_gnt_i, + input logic obi_read_rsp_r_valid_i, + input data_t obi_read_rsp_r_rdata_i +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // OBI types + `IDMA_OBI_TYPEDEF_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t) + `IDMA_OBI_TYPEDEF_R_CHAN_T(obi_r_chan_t, data_t) + + `IDMA_OBI_TYPEDEF_REQ_T(obi_master_req_t, obi_a_chan_t) + `IDMA_OBI_TYPEDEF_RESP_T(obi_master_rsp_t, obi_r_chan_t) + + `IDMA_OBI_TYPEDEF_BIDIRECT_REQ_T(obi_req_t, obi_master_req_t) + `IDMA_OBI_TYPEDEF_BIDIRECT_RESP_T(obi_rsp_t, obi_master_rsp_t) + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + // local types + obi_req_t obi_req_o; + obi_rsp_t obi_rsp_i; + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + // DUT instantiation + idma_backend #( + .Protocol ( idma_pkg::OBI ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .protocol_req_t ( obi_req_t ), + .protocol_rsp_t ( obi_rsp_t ), + .aw_chan_t ( obi_a_chan_t ), + .ar_chan_t ( obi_a_chan_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .protocol_req_o ( obi_req_o ), + .protocol_rsp_i ( obi_rsp_i ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + assign obi_read_req_a_req_o = obi_req_o.read.a_req; + assign obi_read_req_a_addr_o = obi_req_o.read.a.addr; + assign obi_read_req_a_we_o = obi_req_o.read.a.we; + assign obi_read_req_a_be_o = obi_req_o.read.a.be; + assign obi_read_req_a_wdata_o = obi_req_o.read.a.wdata; + assign obi_read_req_r_ready_o = obi_req_o.read.r_ready; + + assign obi_write_req_a_req_o = obi_req_o.write.a_req; + assign obi_write_req_a_addr_o = obi_req_o.write.a.addr; + assign obi_write_req_a_we_o = obi_req_o.write.a.we; + assign obi_write_req_a_be_o = obi_req_o.write.a.be; + assign obi_write_req_a_wdata_o = obi_req_o.write.a.wdata; + assign obi_write_req_r_ready_o = obi_req_o.write.r_ready; + + assign obi_rsp_i.read.a_gnt = obi_read_rsp_a_gnt_i; + assign obi_rsp_i.read.r_valid = obi_read_rsp_r_valid_i; + assign obi_rsp_i.read.r.rdata = obi_read_rsp_r_rdata_i; + + assign obi_rsp_i.write.a_gnt = obi_write_rsp_a_gnt_i; + assign obi_rsp_i.write.r_valid = obi_write_rsp_r_valid_i; + assign obi_rsp_i.write.r.rdata = obi_write_rsp_r_rdata_i; + +endmodule : idma_obi_backend_synth diff --git a/test/idma_obi2axi_bridge.sv b/test/idma_obi2axi_bridge.sv new file mode 100644 index 00000000..9968424b --- /dev/null +++ b/test/idma_obi2axi_bridge.sv @@ -0,0 +1,107 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Tobias Senti + +module idma_obi2axi_bridge #( + parameter int unsigned DataWidth = 32, + parameter int unsigned AddrWidth = 32, + parameter int unsigned UserWidth = 1, + parameter int unsigned IdWidth = 1, + parameter type obi_master_req_t = logic, + parameter type obi_master_rsp_t = logic, + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic +)( + input logic clk_i, + input logic rst_ni, + + input obi_master_req_t obi_master_req_i, + output obi_master_rsp_t obi_master_rsp_o, + + output axi_req_t axi_req_o, + input axi_rsp_t axi_rsp_i +); + + assign axi_req_o.aw.atop = '0; + + idma_tb_per2axi #( + .NB_CORES ( 4 ), + .PER_ADDR_WIDTH ( AddrWidth ), + .PER_ID_WIDTH ( IdWidth ), + .AXI_ADDR_WIDTH ( AddrWidth ), + .AXI_DATA_WIDTH ( DataWidth ), + .AXI_USER_WIDTH ( UserWidth ), + .AXI_ID_WIDTH ( IdWidth ), + .AXI_STRB_WIDTH ( DataWidth / 8 ) + ) i_per2axi ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( 1'b0 ), + + .per_slave_req_i ( obi_master_req_i.a_req ), + .per_slave_add_i ( obi_master_req_i.a.addr ), + .per_slave_we_i ( !obi_master_req_i.a.we ), + .per_slave_wdata_i ( obi_master_req_i.a.wdata ), + .per_slave_be_i ( obi_master_req_i.a.be ), + .per_slave_id_i ( '0), + .per_slave_gnt_o ( obi_master_rsp_o.a_gnt ), + + .per_slave_r_valid_o ( obi_master_rsp_o.r_valid ), + .per_slave_r_opc_o ( ), + .per_slave_r_id_o ( ), + .per_slave_r_rdata_o ( obi_master_rsp_o.r.rdata ), + .per_slave_r_ready_i ( obi_master_req_i.r_ready ), + + .axi_master_aw_valid_o ( axi_req_o.aw_valid ), + .axi_master_aw_addr_o ( axi_req_o.aw.addr ), + .axi_master_aw_prot_o ( axi_req_o.aw.prot ), + .axi_master_aw_region_o ( axi_req_o.aw.region ), + .axi_master_aw_len_o ( axi_req_o.aw.len ), + .axi_master_aw_size_o ( axi_req_o.aw.size ), + .axi_master_aw_burst_o ( axi_req_o.aw.burst ), + .axi_master_aw_lock_o ( axi_req_o.aw.lock ), + .axi_master_aw_cache_o ( axi_req_o.aw.cache ), + .axi_master_aw_qos_o ( axi_req_o.aw.qos ), + .axi_master_aw_id_o ( axi_req_o.aw.id ), + .axi_master_aw_user_o ( axi_req_o.aw.user ), + .axi_master_aw_ready_i ( axi_rsp_i.aw_ready ), + + .axi_master_ar_valid_o ( axi_req_o.ar_valid ), + .axi_master_ar_addr_o ( axi_req_o.ar.addr ), + .axi_master_ar_prot_o ( axi_req_o.ar.prot ), + .axi_master_ar_region_o ( axi_req_o.ar.region ), + .axi_master_ar_len_o ( axi_req_o.ar.len ), + .axi_master_ar_size_o ( axi_req_o.ar.size ), + .axi_master_ar_burst_o ( axi_req_o.ar.burst ), + .axi_master_ar_lock_o ( axi_req_o.ar.lock ), + .axi_master_ar_cache_o ( axi_req_o.ar.cache ), + .axi_master_ar_qos_o ( axi_req_o.ar.qos ), + .axi_master_ar_id_o ( axi_req_o.ar.id ), + .axi_master_ar_user_o ( axi_req_o.ar.user ), + .axi_master_ar_ready_i ( axi_rsp_i.ar_ready ), + + .axi_master_w_valid_o ( axi_req_o.w_valid ), + .axi_master_w_data_o ( axi_req_o.w.data ), + .axi_master_w_strb_o ( axi_req_o.w.strb ), + .axi_master_w_user_o ( axi_req_o.w.user ), + .axi_master_w_last_o ( axi_req_o.w.last ), + .axi_master_w_ready_i ( axi_rsp_i.w_ready ), + + .axi_master_r_valid_i ( axi_rsp_i.r_valid ), + .axi_master_r_data_i ( axi_rsp_i.r.data ), + .axi_master_r_resp_i ( axi_rsp_i.r.resp ), + .axi_master_r_last_i ( axi_rsp_i.r.last ), + .axi_master_r_id_i ( axi_rsp_i.r.id ), + .axi_master_r_user_i ( axi_rsp_i.r.user ), + .axi_master_r_ready_o ( axi_req_o.r_ready ), + + .axi_master_b_valid_i ( axi_rsp_i.b_valid ), + .axi_master_b_resp_i ( axi_rsp_i.b.resp ), + .axi_master_b_id_i ( axi_rsp_i.b.id ), + .axi_master_b_user_i ( axi_rsp_i.b.user ), + .axi_master_b_ready_o ( axi_req_o.b_ready ) + ); + +endmodule : idma_obi2axi_bridge diff --git a/test/idma_obi_asserter.sv b/test/idma_obi_asserter.sv new file mode 100644 index 00000000..95f69c8c --- /dev/null +++ b/test/idma_obi_asserter.sv @@ -0,0 +1,38 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Tobias Senti + +`include "common_cells/assertions.svh" + +/// Checks for compliance with the OBI spec !!!Not complete!!! +module idma_obi_asserter #( + parameter type obi_master_req_t = logic, + parameter type obi_master_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + input obi_master_req_t obi_master_req_i, + input obi_master_rsp_t obi_master_rsp_i +); + //R-2.1 + `ASSERT(OBIAReqLowDuringReset, !rst_ni |-> !obi_master_req_i.a_req, clk_i, 1'b0) + //R-2.2 + `ASSERT(OBIRValidLowDuringReset, !rst_ni |-> !obi_master_rsp_i.r_valid, clk_i, 1'b0) + + //R-3.1 - Stable during address phase + `ASSERT(OBIReadStableDuringAddressPhase, ((obi_master_req_i.a_req && !obi_master_req_i.a.we && !obi_master_rsp_i.a_gnt) |=> + $stable({obi_master_req_i.a_req, obi_master_req_i.a.we, obi_master_req_i.a.addr, obi_master_req_i.a.be})), clk_i, !rst_ni) + + `ASSERT(OBIWriteStableDuringAddressPhase, ((obi_master_req_i.a_req && obi_master_req_i.a.we && !obi_master_rsp_i.a_gnt) |=> + $stable({obi_master_req_i.a_req, obi_master_req_i.a})), clk_i, !rst_ni) + + //R-4.1 - Stable during response phase + `ASSERT(OBIStableDuringResponsePhase, ((obi_master_rsp_i.r_valid && !obi_master_req_i.r_ready) |=> + $stable({obi_master_rsp_i.r_valid, obi_master_rsp_i.r})), clk_i, !rst_ni) + + //R-5 - Response phase should only be sent after the corresponding address phase has ended + +endmodule : idma_obi_asserter diff --git a/test/idma_tb_per2axi.sv b/test/idma_tb_per2axi.sv new file mode 100644 index 00000000..98a0133e --- /dev/null +++ b/test/idma_tb_per2axi.sv @@ -0,0 +1,1028 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Commit: 892fcad60b6374fe558cbde76f4a529d473ba5ca +// Compiled by morty-0.8.0 / 2022-10-25 10:05:33.986890469 +02:00 +module idma_tb_fifo_v3 #( + parameter bit FALL_THROUGH = 1'b0, + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned DEPTH = 8, + parameter type dtype = logic [DATA_WIDTH-1:0], + parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1 +) ( + input logic clk_i, + input logic rst_ni, + input logic flush_i, + input logic testmode_i, + output logic full_o, + output logic empty_o, + output logic [ADDR_DEPTH-1:0] usage_o, + input dtype data_i, + input logic push_i, + output dtype data_o, + input logic pop_i +); + localparam int unsigned FifoDepth = (DEPTH > 0) ? DEPTH : 1; + logic gate_clock; + logic [ADDR_DEPTH - 1:0] read_pointer_n, read_pointer_q, write_pointer_n, write_pointer_q; + logic [ADDR_DEPTH:0] status_cnt_n, status_cnt_q; + dtype [FifoDepth - 1:0] mem_n, mem_q; + assign usage_o = status_cnt_q[ADDR_DEPTH-1:0]; + if (DEPTH == 0) begin : gen_pass_through + assign empty_o = ~push_i; + assign full_o = ~pop_i; + end else begin : gen_fifo + assign full_o = (status_cnt_q == FifoDepth[ADDR_DEPTH:0]); + assign empty_o = (status_cnt_q == 0) & ~(FALL_THROUGH & push_i); + end + always_comb begin : read_write_comb + read_pointer_n = read_pointer_q; + write_pointer_n = write_pointer_q; + status_cnt_n = status_cnt_q; + data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q]; + mem_n = mem_q; + gate_clock = 1'b1; + if (push_i && ~full_o) begin + mem_n[write_pointer_q] = data_i; + gate_clock = 1'b0; + if (write_pointer_q == FifoDepth[ADDR_DEPTH-1:0] - 1) write_pointer_n = '0; + else write_pointer_n = write_pointer_q + 1; + status_cnt_n = status_cnt_q + 1; + end + if (pop_i && ~empty_o) begin + if (read_pointer_n == FifoDepth[ADDR_DEPTH-1:0] - 1) read_pointer_n = '0; + else read_pointer_n = read_pointer_q + 1; + status_cnt_n = status_cnt_q - 1; + end + if (push_i && pop_i && ~full_o && ~empty_o) status_cnt_n = status_cnt_q; + if (FALL_THROUGH && (status_cnt_q == 0) && push_i) begin + data_o = data_i; + if (pop_i) begin + status_cnt_n = status_cnt_q; + read_pointer_n = read_pointer_q; + write_pointer_n = write_pointer_q; + end + end + end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + read_pointer_q <= '0; + write_pointer_q <= '0; + status_cnt_q <= '0; + end else begin + if (flush_i) begin + read_pointer_q <= '0; + write_pointer_q <= '0; + status_cnt_q <= '0; + end else begin + read_pointer_q <= read_pointer_n; + write_pointer_q <= write_pointer_n; + status_cnt_q <= status_cnt_n; + end + end + end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + mem_q <= '0; + end else if (!gate_clock) begin + mem_q <= mem_n; + end + end + initial begin + assert (DEPTH > 0) + else $error("DEPTH must be greater than 0."); + end + full_write : + assert property (@(posedge clk_i) disable iff (~rst_ni) (full_o |-> ~push_i)) + else $fatal(1, "Trying to push new data although the FIFO is full."); + empty_read : + assert property (@(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i)) + else $fatal(1, "Trying to pop data although the FIFO is empty."); +endmodule +module idma_tb_fifo_v2 #( + parameter bit FALL_THROUGH = 1'b0, + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned DEPTH = 8, + parameter int unsigned ALM_EMPTY_TH = 1, + parameter int unsigned ALM_FULL_TH = 1, + parameter type dtype = logic [DATA_WIDTH-1:0], + parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1 +) ( + input logic clk_i, + input logic rst_ni, + input logic flush_i, + input logic testmode_i, + output logic full_o, + output logic empty_o, + output logic alm_full_o, + output logic alm_empty_o, + input dtype data_i, + input logic push_i, + output dtype data_o, + input logic pop_i +); + logic [ADDR_DEPTH-1:0] usage; + if (DEPTH == 0) begin + assign alm_full_o = 1'b0; + assign alm_empty_o = 1'b0; + end else begin + assign alm_full_o = (usage >= ALM_FULL_TH[ADDR_DEPTH-1:0]); + assign alm_empty_o = (usage <= ALM_EMPTY_TH[ADDR_DEPTH-1:0]); + end + idma_tb_fifo_v3 #( + .FALL_THROUGH(FALL_THROUGH), + .DATA_WIDTH (DATA_WIDTH), + .DEPTH (DEPTH), + .dtype (dtype) + ) i_fifo_v3 ( + .clk_i, + .rst_ni, + .flush_i, + .testmode_i, + .full_o, + .empty_o, + .usage_o(usage), + .data_i, + .push_i, + .data_o, + .pop_i + ); + initial begin + assert (ALM_FULL_TH <= DEPTH) + else $error("ALM_FULL_TH can't be larger than the DEPTH."); + assert (ALM_EMPTY_TH <= DEPTH) + else $error("ALM_EMPTY_TH can't be larger than the DEPTH."); + end +endmodule +module idma_tb_fifo #( + parameter bit FALL_THROUGH = 1'b0, + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned DEPTH = 8, + parameter int unsigned THRESHOLD = 1, + parameter type dtype = logic [DATA_WIDTH-1:0] +) ( + input logic clk_i, + input logic rst_ni, + input logic flush_i, + input logic testmode_i, + output logic full_o, + output logic empty_o, + output logic threshold_o, + input dtype data_i, + input logic push_i, + output dtype data_o, + input logic pop_i +); + idma_tb_fifo_v2 #( + .FALL_THROUGH(FALL_THROUGH), + .DATA_WIDTH (DATA_WIDTH), + .DEPTH (DEPTH), + .ALM_FULL_TH (THRESHOLD), + .dtype (dtype) + ) impl ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (flush_i), + .testmode_i (testmode_i), + .full_o (full_o), + .empty_o (empty_o), + .alm_full_o (threshold_o), + .alm_empty_o(), + .data_i (data_i), + .push_i (push_i), + .data_o (data_o), + .pop_i (pop_i) + ); +endmodule +module idma_tb_axi_single_slice #( + parameter int BUFFER_DEPTH = -1, + parameter int DATA_WIDTH = -1 +) ( + input logic clk_i, + input logic rst_ni, + input logic testmode_i, + input logic valid_i, + output logic ready_o, + input logic [DATA_WIDTH-1:0] data_i, + input logic ready_i, + output logic valid_o, + output logic [DATA_WIDTH-1:0] data_o +); + logic full, empty; + assign ready_o = ~full; + assign valid_o = ~empty; + idma_tb_fifo #( + .FALL_THROUGH(1'b1), + .DATA_WIDTH (DATA_WIDTH), + .DEPTH (BUFFER_DEPTH) + ) i_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .threshold_o(), + .testmode_i (testmode_i), + .full_o (full), + .empty_o (empty), + .data_i (data_i), + .push_i (valid_i & ready_o), + .data_o (data_o), + .pop_i (ready_i & valid_o) + ); +endmodule +module idma_tb_axi_ar_buffer #( + parameter int ID_WIDTH = -1, + parameter int ADDR_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1 +) ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic slave_valid_i, + input logic [ADDR_WIDTH-1:0] slave_addr_i, + input logic [ 2:0] slave_prot_i, + input logic [ 3:0] slave_region_i, + input logic [ 7:0] slave_len_i, + input logic [ 2:0] slave_size_i, + input logic [ 1:0] slave_burst_i, + input logic slave_lock_i, + input logic [ 3:0] slave_cache_i, + input logic [ 3:0] slave_qos_i, + input logic [ ID_WIDTH-1:0] slave_id_i, + input logic [USER_WIDTH-1:0] slave_user_i, + output logic slave_ready_o, + output logic master_valid_o, + output logic [ADDR_WIDTH-1:0] master_addr_o, + output logic [ 2:0] master_prot_o, + output logic [ 3:0] master_region_o, + output logic [ 7:0] master_len_o, + output logic [ 2:0] master_size_o, + output logic [ 1:0] master_burst_o, + output logic master_lock_o, + output logic [ 3:0] master_cache_o, + output logic [ 3:0] master_qos_o, + output logic [ ID_WIDTH-1:0] master_id_o, + output logic [USER_WIDTH-1:0] master_user_o, + input logic master_ready_i +); + logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_in; + logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_out; + assign s_data_in = { + slave_cache_i, + slave_prot_i, + slave_lock_i, + slave_burst_i, + slave_size_i, + slave_len_i, + slave_qos_i, + slave_region_i, + slave_addr_i, + slave_user_i, + slave_id_i + }; + assign {master_cache_o, master_prot_o, master_lock_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out; + idma_tb_axi_single_slice #( + .BUFFER_DEPTH(BUFFER_DEPTH), + .DATA_WIDTH (29 + ADDR_WIDTH + USER_WIDTH + ID_WIDTH) + ) i_axi_single_slice ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .testmode_i(test_en_i), + .valid_i (slave_valid_i), + .ready_o (slave_ready_o), + .data_i (s_data_in), + .ready_i (master_ready_i), + .valid_o (master_valid_o), + .data_o (s_data_out) + ); +endmodule +module idma_tb_axi_aw_buffer #( + parameter int ID_WIDTH = -1, + parameter int ADDR_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1 +) ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic slave_valid_i, + input logic [ADDR_WIDTH-1:0] slave_addr_i, + input logic [ 2:0] slave_prot_i, + input logic [ 3:0] slave_region_i, + input logic [ 7:0] slave_len_i, + input logic [ 2:0] slave_size_i, + input logic [ 1:0] slave_burst_i, + input logic slave_lock_i, + input logic [ 3:0] slave_cache_i, + input logic [ 3:0] slave_qos_i, + input logic [ ID_WIDTH-1:0] slave_id_i, + input logic [USER_WIDTH-1:0] slave_user_i, + output logic slave_ready_o, + output logic master_valid_o, + output logic [ADDR_WIDTH-1:0] master_addr_o, + output logic [ 2:0] master_prot_o, + output logic [ 3:0] master_region_o, + output logic [ 7:0] master_len_o, + output logic [ 2:0] master_size_o, + output logic [ 1:0] master_burst_o, + output logic master_lock_o, + output logic [ 3:0] master_cache_o, + output logic [ 3:0] master_qos_o, + output logic [ ID_WIDTH-1:0] master_id_o, + output logic [USER_WIDTH-1:0] master_user_o, + input logic master_ready_i +); + logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_in; + logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_out; + assign s_data_in = { + slave_cache_i, + slave_prot_i, + slave_lock_i, + slave_burst_i, + slave_size_i, + slave_len_i, + slave_qos_i, + slave_region_i, + slave_addr_i, + slave_user_i, + slave_id_i + }; + assign {master_cache_o, master_prot_o, master_lock_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out; + idma_tb_axi_single_slice #( + .BUFFER_DEPTH(BUFFER_DEPTH), + .DATA_WIDTH (29 + ADDR_WIDTH + USER_WIDTH + ID_WIDTH) + ) i_axi_single_slice ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .testmode_i(test_en_i), + .valid_i (slave_valid_i), + .ready_o (slave_ready_o), + .data_i (s_data_in), + .ready_i (master_ready_i), + .valid_o (master_valid_o), + .data_o (s_data_out) + ); +endmodule +module idma_tb_axi_b_buffer #( + parameter int ID_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1 +) ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic slave_valid_i, + input logic [ 1:0] slave_resp_i, + input logic [ ID_WIDTH-1:0] slave_id_i, + input logic [USER_WIDTH-1:0] slave_user_i, + output logic slave_ready_o, + output logic master_valid_o, + output logic [ 1:0] master_resp_o, + output logic [ ID_WIDTH-1:0] master_id_o, + output logic [USER_WIDTH-1:0] master_user_o, + input logic master_ready_i +); + logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_in; + logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_out; + assign s_data_in = {slave_id_i, slave_user_i, slave_resp_i}; + assign {master_id_o, master_user_o, master_resp_o} = s_data_out; + idma_tb_axi_single_slice #( + .BUFFER_DEPTH(BUFFER_DEPTH), + .DATA_WIDTH (2 + USER_WIDTH + ID_WIDTH) + ) i_axi_single_slice ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .testmode_i(test_en_i), + .valid_i (slave_valid_i), + .ready_o (slave_ready_o), + .data_i (s_data_in), + .ready_i (master_ready_i), + .valid_o (master_valid_o), + .data_o (s_data_out) + ); +endmodule +module idma_tb_axi_r_buffer #( + parameter ID_WIDTH = 4, + parameter DATA_WIDTH = 64, + parameter USER_WIDTH = 6, + parameter BUFFER_DEPTH = 8, + parameter STRB_WIDTH = DATA_WIDTH / 8 +) ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic slave_valid_i, + input logic [DATA_WIDTH-1:0] slave_data_i, + input logic [ 1:0] slave_resp_i, + input logic [USER_WIDTH-1:0] slave_user_i, + input logic [ ID_WIDTH-1:0] slave_id_i, + input logic slave_last_i, + output logic slave_ready_o, + output logic master_valid_o, + output logic [DATA_WIDTH-1:0] master_data_o, + output logic [ 1:0] master_resp_o, + output logic [USER_WIDTH-1:0] master_user_o, + output logic [ ID_WIDTH-1:0] master_id_o, + output logic master_last_o, + input logic master_ready_i +); + logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_in; + logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_out; + assign s_data_in = {slave_id_i, slave_user_i, slave_data_i, slave_resp_i, slave_last_i}; + assign {master_id_o, master_user_o, master_data_o, master_resp_o, master_last_o} = s_data_out; + idma_tb_axi_single_slice #( + .BUFFER_DEPTH(BUFFER_DEPTH), + .DATA_WIDTH (3 + DATA_WIDTH + USER_WIDTH + ID_WIDTH) + ) i_axi_single_slice ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .testmode_i(test_en_i), + .valid_i (slave_valid_i), + .ready_o (slave_ready_o), + .data_i (s_data_in), + .ready_i (master_ready_i), + .valid_o (master_valid_o), + .data_o (s_data_out) + ); +endmodule +module idma_tb_axi_w_buffer #( + parameter int DATA_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1, + parameter int STRB_WIDTH = DATA_WIDTH / 8 +) ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic slave_valid_i, + input logic [DATA_WIDTH-1:0] slave_data_i, + input logic [STRB_WIDTH-1:0] slave_strb_i, + input logic [USER_WIDTH-1:0] slave_user_i, + input logic slave_last_i, + output logic slave_ready_o, + output logic master_valid_o, + output logic [DATA_WIDTH-1:0] master_data_o, + output logic [STRB_WIDTH-1:0] master_strb_o, + output logic [USER_WIDTH-1:0] master_user_o, + output logic master_last_o, + input logic master_ready_i +); + logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_in; + logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_out; + assign s_data_in = {slave_user_i, slave_strb_i, slave_data_i, slave_last_i}; + assign {master_user_o, master_strb_o, master_data_o, master_last_o} = s_data_out; + idma_tb_axi_single_slice #( + .BUFFER_DEPTH(BUFFER_DEPTH), + .DATA_WIDTH (1 + DATA_WIDTH + STRB_WIDTH + USER_WIDTH) + ) i_axi_single_slice ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .testmode_i(test_en_i), + .valid_i (slave_valid_i), + .ready_o (slave_ready_o), + .data_i (s_data_in), + .ready_i (master_ready_i), + .valid_o (master_valid_o), + .data_o (s_data_out) + ); +endmodule +module idma_tb_per2axi_busy_unit ( + input logic clk_i, + input logic rst_ni, + input logic aw_sync_i, + input logic b_sync_i, + input logic ar_sync_i, + input logic r_sync_i, + output logic busy_o +); + logic [3:0] s_aw_trans_count; + logic [3:0] s_ar_trans_count; + always_ff @(posedge clk_i, negedge rst_ni) begin + if (rst_ni == 1'b0) s_aw_trans_count <= '0; + else if (aw_sync_i == 1'b1 && b_sync_i == 1'b0) s_aw_trans_count <= s_aw_trans_count + 1; + else if (aw_sync_i == 1'b0 && b_sync_i == 1'b1) s_aw_trans_count <= s_aw_trans_count - 1; + else s_aw_trans_count <= s_aw_trans_count; + end + always_ff @(posedge clk_i, negedge rst_ni) begin + if (rst_ni == 1'b0) s_ar_trans_count <= '0; + else if (ar_sync_i == 1'b1 && r_sync_i == 1'b0) s_ar_trans_count <= s_ar_trans_count + 1; + else if (ar_sync_i == 1'b0 && r_sync_i == 1'b1) s_ar_trans_count <= s_ar_trans_count - 1; + else s_ar_trans_count <= s_ar_trans_count; + end + always_comb begin + if (s_ar_trans_count == 0 && s_aw_trans_count == 0) busy_o = 1'b0; + else busy_o = 1'b1; + end +endmodule +module idma_tb_per2axi_req_channel #( + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3, + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8 +) ( + input logic per_slave_req_i, + input logic [PER_ADDR_WIDTH-1:0] per_slave_add_i, + input logic per_slave_we_i, + input logic [ 31:0] per_slave_wdata_i, + input logic [ 3:0] per_slave_be_i, + input logic [ PER_ID_WIDTH-1:0] per_slave_id_i, + output logic per_slave_gnt_o, + output logic axi_master_aw_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_aw_addr_o, + output logic [ 2:0] axi_master_aw_prot_o, + output logic [ 3:0] axi_master_aw_region_o, + output logic [ 7:0] axi_master_aw_len_o, + output logic [ 2:0] axi_master_aw_size_o, + output logic [ 1:0] axi_master_aw_burst_o, + output logic axi_master_aw_lock_o, + output logic [ 3:0] axi_master_aw_cache_o, + output logic [ 3:0] axi_master_aw_qos_o, + output logic [ AXI_ID_WIDTH-1:0] axi_master_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_aw_user_o, + input logic axi_master_aw_ready_i, + output logic axi_master_ar_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_ar_addr_o, + output logic [ 2:0] axi_master_ar_prot_o, + output logic [ 3:0] axi_master_ar_region_o, + output logic [ 7:0] axi_master_ar_len_o, + output logic [ 2:0] axi_master_ar_size_o, + output logic [ 1:0] axi_master_ar_burst_o, + output logic axi_master_ar_lock_o, + output logic [ 3:0] axi_master_ar_cache_o, + output logic [ 3:0] axi_master_ar_qos_o, + output logic [ AXI_ID_WIDTH-1:0] axi_master_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_ar_user_o, + input logic axi_master_ar_ready_i, + output logic axi_master_w_valid_o, + output logic [AXI_DATA_WIDTH-1:0] axi_master_w_data_o, + output logic [AXI_STRB_WIDTH-1:0] axi_master_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_w_user_o, + output logic axi_master_w_last_o, + input logic axi_master_w_ready_i, + output logic trans_req_o, + output logic [ AXI_ID_WIDTH-1:0] trans_id_o, + output logic [AXI_ADDR_WIDTH-1:0] trans_add_o +); + integer i; + always_comb begin + axi_master_ar_valid_o = 1'b0; + axi_master_aw_valid_o = 1'b0; + axi_master_w_valid_o = 1'b0; + axi_master_w_last_o = 1'b0; + if (per_slave_req_i == 1'b1 && + per_slave_we_i == 1'b0 && + axi_master_aw_ready_i == 1'b1 && + axi_master_w_ready_i == 1'b1 ) + begin + axi_master_aw_valid_o = 1'b1; + axi_master_w_valid_o = 1'b1; + axi_master_w_last_o = 1'b1; + end + else + if (per_slave_req_i == 1'b1 && + per_slave_we_i == 1'b1 && + axi_master_ar_ready_i == 1'b1) + begin + axi_master_ar_valid_o = 1'b1; + end + end + assign axi_master_aw_addr_o = per_slave_add_i; + assign axi_master_ar_addr_o = per_slave_add_i; + always_comb begin + axi_master_aw_id_o = '0; + axi_master_ar_id_o = '0; + for (i = 0; i < PER_ID_WIDTH; i++) begin + if (per_slave_id_i[i] == 1'b1) begin + axi_master_aw_id_o = i; + axi_master_ar_id_o = i; + end + end + end + assign axi_master_w_data_o = per_slave_wdata_i; + assign axi_master_w_strb_o = per_slave_be_i; + assign per_slave_gnt_o = axi_master_aw_ready_i && axi_master_ar_ready_i && axi_master_w_ready_i; + always_comb begin + axi_master_ar_size_o = 3'b010; + axi_master_aw_size_o = 3'b010; + end + assign axi_master_aw_burst_o = 2'b01; + assign axi_master_ar_burst_o = 2'b01; + assign trans_req_o = axi_master_ar_valid_o; + assign trans_id_o = axi_master_ar_id_o; + assign trans_add_o = axi_master_ar_addr_o; + assign axi_master_aw_prot_o = '0; + assign axi_master_aw_region_o = '0; + assign axi_master_aw_len_o = '0; + assign axi_master_aw_lock_o = '0; + assign axi_master_aw_cache_o = '0; + assign axi_master_aw_qos_o = '0; + assign axi_master_aw_user_o = '0; + assign axi_master_ar_prot_o = '0; + assign axi_master_ar_region_o = '0; + assign axi_master_ar_len_o = '0; + assign axi_master_ar_lock_o = '0; + assign axi_master_ar_cache_o = '0; + assign axi_master_ar_qos_o = '0; + assign axi_master_ar_user_o = '0; + assign axi_master_w_user_o = '0; +endmodule +module idma_tb_per2axi_res_channel #( + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3 +) ( + input logic clk_i, + input logic rst_ni, + output logic per_slave_r_valid_o, + output logic per_slave_r_opc_o, + output logic [PER_ID_WIDTH-1:0] per_slave_r_id_o, + output logic [ 31:0] per_slave_r_rdata_o, + input logic per_slave_r_ready_i, + input logic axi_master_r_valid_i, + input logic [AXI_DATA_WIDTH-1:0] axi_master_r_data_i, + input logic [ 1:0] axi_master_r_resp_i, + input logic axi_master_r_last_i, + input logic [ AXI_ID_WIDTH-1:0] axi_master_r_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_r_user_i, + output logic axi_master_r_ready_o, + input logic axi_master_b_valid_i, + input logic [ 1:0] axi_master_b_resp_i, + input logic [ AXI_ID_WIDTH-1:0] axi_master_b_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_b_user_i, + output logic axi_master_b_ready_o, + input logic trans_req_i, + input logic [ AXI_ID_WIDTH-1:0] trans_id_i, + input logic [AXI_ADDR_WIDTH-1:0] trans_add_i +); + always_comb begin + per_slave_r_valid_o = '0; + per_slave_r_opc_o = '0; + per_slave_r_id_o = '0; + per_slave_r_rdata_o = '0; + axi_master_r_ready_o = per_slave_r_ready_i; + axi_master_b_ready_o = per_slave_r_ready_i; + if (axi_master_r_valid_i && per_slave_r_ready_i) begin + per_slave_r_valid_o = 1'b1; + per_slave_r_id_o[axi_master_r_id_i] = 1'b1; + per_slave_r_rdata_o = axi_master_r_data_i; + axi_master_b_ready_o = 1'b0; + end else if (axi_master_b_valid_i && per_slave_r_ready_i) begin + per_slave_r_valid_o = 1'b1; + per_slave_r_id_o[axi_master_b_id_i] = 1'b1; + axi_master_r_ready_o = 1'b0; + end + end +endmodule +module idma_tb_per2axi #( + parameter NB_CORES = 4, + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3, + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8 +) ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic per_slave_req_i, + input logic [PER_ADDR_WIDTH-1:0] per_slave_add_i, + input logic per_slave_we_i, + input logic [ 31:0] per_slave_wdata_i, + input logic [ 3:0] per_slave_be_i, + input logic [ PER_ID_WIDTH-1:0] per_slave_id_i, + output logic per_slave_gnt_o, + output logic per_slave_r_valid_o, + output logic per_slave_r_opc_o, + output logic [PER_ID_WIDTH-1:0] per_slave_r_id_o, + output logic [ 31:0] per_slave_r_rdata_o, + input logic per_slave_r_ready_i, + output logic axi_master_aw_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_aw_addr_o, + output logic [ 2:0] axi_master_aw_prot_o, + output logic [ 3:0] axi_master_aw_region_o, + output logic [ 7:0] axi_master_aw_len_o, + output logic [ 2:0] axi_master_aw_size_o, + output logic [ 1:0] axi_master_aw_burst_o, + output logic axi_master_aw_lock_o, + output logic [ 3:0] axi_master_aw_cache_o, + output logic [ 3:0] axi_master_aw_qos_o, + output logic [ AXI_ID_WIDTH-1:0] axi_master_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_aw_user_o, + input logic axi_master_aw_ready_i, + output logic axi_master_ar_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_ar_addr_o, + output logic [ 2:0] axi_master_ar_prot_o, + output logic [ 3:0] axi_master_ar_region_o, + output logic [ 7:0] axi_master_ar_len_o, + output logic [ 2:0] axi_master_ar_size_o, + output logic [ 1:0] axi_master_ar_burst_o, + output logic axi_master_ar_lock_o, + output logic [ 3:0] axi_master_ar_cache_o, + output logic [ 3:0] axi_master_ar_qos_o, + output logic [ AXI_ID_WIDTH-1:0] axi_master_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_ar_user_o, + input logic axi_master_ar_ready_i, + output logic axi_master_w_valid_o, + output logic [AXI_DATA_WIDTH-1:0] axi_master_w_data_o, + output logic [AXI_STRB_WIDTH-1:0] axi_master_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_w_user_o, + output logic axi_master_w_last_o, + input logic axi_master_w_ready_i, + input logic axi_master_r_valid_i, + input logic [AXI_DATA_WIDTH-1:0] axi_master_r_data_i, + input logic [ 1:0] axi_master_r_resp_i, + input logic axi_master_r_last_i, + input logic [ AXI_ID_WIDTH-1:0] axi_master_r_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_r_user_i, + output logic axi_master_r_ready_o, + input logic axi_master_b_valid_i, + input logic [ 1:0] axi_master_b_resp_i, + input logic [ AXI_ID_WIDTH-1:0] axi_master_b_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_b_user_i, + output logic axi_master_b_ready_o, + output logic busy_o +); + logic s_aw_valid; + logic [AXI_ADDR_WIDTH-1:0] s_aw_addr; + logic [ 2:0] s_aw_prot; + logic [ 3:0] s_aw_region; + logic [ 7:0] s_aw_len; + logic [ 2:0] s_aw_size; + logic [ 1:0] s_aw_burst; + logic s_aw_lock; + logic [ 3:0] s_aw_cache; + logic [ 3:0] s_aw_qos; + logic [ AXI_ID_WIDTH-1:0] s_aw_id; + logic [AXI_USER_WIDTH-1:0] s_aw_user; + logic s_aw_ready; + logic s_ar_valid; + logic [AXI_ADDR_WIDTH-1:0] s_ar_addr; + logic [ 2:0] s_ar_prot; + logic [ 3:0] s_ar_region; + logic [ 7:0] s_ar_len; + logic [ 2:0] s_ar_size; + logic [ 1:0] s_ar_burst; + logic s_ar_lock; + logic [ 3:0] s_ar_cache; + logic [ 3:0] s_ar_qos; + logic [ AXI_ID_WIDTH-1:0] s_ar_id; + logic [AXI_USER_WIDTH-1:0] s_ar_user; + logic s_ar_ready; + logic s_w_valid; + logic [AXI_DATA_WIDTH-1:0] s_w_data; + logic [AXI_STRB_WIDTH-1:0] s_w_strb; + logic [AXI_USER_WIDTH-1:0] s_w_user; + logic s_w_last; + logic s_w_ready; + logic s_r_valid; + logic [AXI_DATA_WIDTH-1:0] s_r_data; + logic [ 1:0] s_r_resp; + logic s_r_last; + logic [ AXI_ID_WIDTH-1:0] s_r_id; + logic [AXI_USER_WIDTH-1:0] s_r_user; + logic s_r_ready; + logic s_b_valid; + logic [ 1:0] s_b_resp; + logic [ AXI_ID_WIDTH-1:0] s_b_id; + logic [AXI_USER_WIDTH-1:0] s_b_user; + logic s_b_ready; + logic s_trans_req; + logic [ AXI_ID_WIDTH-1:0] s_trans_id; + logic [AXI_ADDR_WIDTH-1:0] s_trans_add; + idma_tb_per2axi_req_channel #( + .PER_ID_WIDTH (PER_ID_WIDTH), + .PER_ADDR_WIDTH(PER_ADDR_WIDTH), + .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH), + .AXI_ID_WIDTH (AXI_ID_WIDTH) + ) req_channel_i ( + .per_slave_req_i (per_slave_req_i), + .per_slave_add_i (per_slave_add_i), + .per_slave_we_i (per_slave_we_i), + .per_slave_wdata_i(per_slave_wdata_i), + .per_slave_be_i (per_slave_be_i), + .per_slave_id_i (per_slave_id_i), + .per_slave_gnt_o (per_slave_gnt_o), + .axi_master_aw_valid_o (s_aw_valid), + .axi_master_aw_addr_o (s_aw_addr), + .axi_master_aw_prot_o (s_aw_prot), + .axi_master_aw_region_o(s_aw_region), + .axi_master_aw_len_o (s_aw_len), + .axi_master_aw_size_o (s_aw_size), + .axi_master_aw_burst_o (s_aw_burst), + .axi_master_aw_lock_o (s_aw_lock), + .axi_master_aw_cache_o (s_aw_cache), + .axi_master_aw_qos_o (s_aw_qos), + .axi_master_aw_id_o (s_aw_id), + .axi_master_aw_user_o (s_aw_user), + .axi_master_aw_ready_i (s_aw_ready), + .axi_master_ar_valid_o (s_ar_valid), + .axi_master_ar_addr_o (s_ar_addr), + .axi_master_ar_prot_o (s_ar_prot), + .axi_master_ar_region_o(s_ar_region), + .axi_master_ar_len_o (s_ar_len), + .axi_master_ar_size_o (s_ar_size), + .axi_master_ar_burst_o (s_ar_burst), + .axi_master_ar_lock_o (s_ar_lock), + .axi_master_ar_cache_o (s_ar_cache), + .axi_master_ar_qos_o (s_ar_qos), + .axi_master_ar_id_o (s_ar_id), + .axi_master_ar_user_o (s_ar_user), + .axi_master_ar_ready_i (s_ar_ready), + .axi_master_w_valid_o(s_w_valid), + .axi_master_w_data_o (s_w_data), + .axi_master_w_strb_o (s_w_strb), + .axi_master_w_user_o (s_w_user), + .axi_master_w_last_o (s_w_last), + .axi_master_w_ready_i(s_w_ready), + .trans_req_o(s_trans_req), + .trans_id_o (s_trans_id), + .trans_add_o(s_trans_add) + ); + idma_tb_per2axi_res_channel #( + .PER_ID_WIDTH (PER_ID_WIDTH), + .PER_ADDR_WIDTH(PER_ADDR_WIDTH), + .AXI_ID_WIDTH (AXI_ID_WIDTH), + .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) res_channel_i ( + .clk_i (clk_i), + .rst_ni(rst_ni), + .per_slave_r_valid_o(per_slave_r_valid_o), + .per_slave_r_opc_o (per_slave_r_opc_o), + .per_slave_r_id_o (per_slave_r_id_o), + .per_slave_r_rdata_o(per_slave_r_rdata_o), + .per_slave_r_ready_i(per_slave_r_ready_i), + .axi_master_r_valid_i(s_r_valid), + .axi_master_r_data_i (s_r_data), + .axi_master_r_resp_i (s_r_resp), + .axi_master_r_last_i (s_r_last), + .axi_master_r_id_i (s_r_id), + .axi_master_r_user_i (s_r_user), + .axi_master_r_ready_o(s_r_ready), + .axi_master_b_valid_i(s_b_valid), + .axi_master_b_resp_i (s_b_resp), + .axi_master_b_id_i (s_b_id), + .axi_master_b_user_i (s_b_user), + .axi_master_b_ready_o(s_b_ready), + .trans_req_i(s_trans_req), + .trans_id_i (s_trans_id), + .trans_add_i(s_trans_add) + ); + idma_tb_per2axi_busy_unit busy_unit_i ( + .clk_i (clk_i), + .rst_ni(rst_ni), + .aw_sync_i(s_aw_valid & s_aw_ready), + .b_sync_i (s_b_valid & s_b_ready), + .ar_sync_i(s_ar_valid & s_ar_ready), + .r_sync_i (s_r_valid & s_r_ready & s_r_last), + .busy_o(busy_o) + ); + idma_tb_axi_aw_buffer #( + .ID_WIDTH (AXI_ID_WIDTH), + .ADDR_WIDTH (AXI_ADDR_WIDTH), + .USER_WIDTH (AXI_USER_WIDTH), + .BUFFER_DEPTH(NB_CORES) + ) aw_buffer_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .test_en_i(test_en_i), + .slave_valid_i (s_aw_valid), + .slave_addr_i (s_aw_addr), + .slave_prot_i (s_aw_prot), + .slave_region_i(s_aw_region), + .slave_len_i (s_aw_len), + .slave_size_i (s_aw_size), + .slave_burst_i (s_aw_burst), + .slave_lock_i (s_aw_lock), + .slave_cache_i (s_aw_cache), + .slave_qos_i (s_aw_qos), + .slave_id_i (s_aw_id), + .slave_user_i (s_aw_user), + .slave_ready_o (s_aw_ready), + .master_valid_o (axi_master_aw_valid_o), + .master_addr_o (axi_master_aw_addr_o), + .master_prot_o (axi_master_aw_prot_o), + .master_region_o(axi_master_aw_region_o), + .master_len_o (axi_master_aw_len_o), + .master_size_o (axi_master_aw_size_o), + .master_burst_o (axi_master_aw_burst_o), + .master_lock_o (axi_master_aw_lock_o), + .master_cache_o (axi_master_aw_cache_o), + .master_qos_o (axi_master_aw_qos_o), + .master_id_o (axi_master_aw_id_o), + .master_user_o (axi_master_aw_user_o), + .master_ready_i (axi_master_aw_ready_i) + ); + idma_tb_axi_ar_buffer #( + .ID_WIDTH (AXI_ID_WIDTH), + .ADDR_WIDTH (AXI_ADDR_WIDTH), + .USER_WIDTH (AXI_USER_WIDTH), + .BUFFER_DEPTH(NB_CORES) + ) ar_buffer_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .test_en_i(test_en_i), + .slave_valid_i (s_ar_valid), + .slave_addr_i (s_ar_addr), + .slave_prot_i (s_ar_prot), + .slave_region_i(s_ar_region), + .slave_len_i (s_ar_len), + .slave_size_i (s_ar_size), + .slave_burst_i (s_ar_burst), + .slave_lock_i (s_ar_lock), + .slave_cache_i (s_ar_cache), + .slave_qos_i (s_ar_qos), + .slave_id_i (s_ar_id), + .slave_user_i (s_ar_user), + .slave_ready_o (s_ar_ready), + .master_valid_o (axi_master_ar_valid_o), + .master_addr_o (axi_master_ar_addr_o), + .master_prot_o (axi_master_ar_prot_o), + .master_region_o(axi_master_ar_region_o), + .master_len_o (axi_master_ar_len_o), + .master_size_o (axi_master_ar_size_o), + .master_burst_o (axi_master_ar_burst_o), + .master_lock_o (axi_master_ar_lock_o), + .master_cache_o (axi_master_ar_cache_o), + .master_qos_o (axi_master_ar_qos_o), + .master_id_o (axi_master_ar_id_o), + .master_user_o (axi_master_ar_user_o), + .master_ready_i (axi_master_ar_ready_i) + ); + idma_tb_axi_w_buffer #( + .DATA_WIDTH (AXI_DATA_WIDTH), + .USER_WIDTH (AXI_USER_WIDTH), + .BUFFER_DEPTH(NB_CORES) + ) w_buffer_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .test_en_i(test_en_i), + .slave_valid_i(s_w_valid), + .slave_data_i (s_w_data), + .slave_strb_i (s_w_strb), + .slave_user_i (s_w_user), + .slave_last_i (s_w_last), + .slave_ready_o(s_w_ready), + .master_valid_o(axi_master_w_valid_o), + .master_data_o (axi_master_w_data_o), + .master_strb_o (axi_master_w_strb_o), + .master_user_o (axi_master_w_user_o), + .master_last_o (axi_master_w_last_o), + .master_ready_i(axi_master_w_ready_i) + ); + idma_tb_axi_r_buffer #( + .ID_WIDTH (AXI_ID_WIDTH), + .DATA_WIDTH (AXI_DATA_WIDTH), + .USER_WIDTH (AXI_USER_WIDTH), + .BUFFER_DEPTH(2) + ) r_buffer_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .test_en_i(test_en_i), + .slave_valid_i(axi_master_r_valid_i), + .slave_data_i (axi_master_r_data_i), + .slave_resp_i (axi_master_r_resp_i), + .slave_user_i (axi_master_r_user_i), + .slave_id_i (axi_master_r_id_i), + .slave_last_i (axi_master_r_last_i), + .slave_ready_o(axi_master_r_ready_o), + .master_valid_o(s_r_valid), + .master_data_o (s_r_data), + .master_resp_o (s_r_resp), + .master_user_o (s_r_user), + .master_id_o (s_r_id), + .master_last_o (s_r_last), + .master_ready_i(s_r_ready) + ); + idma_tb_axi_b_buffer #( + .ID_WIDTH (AXI_ID_WIDTH), + .USER_WIDTH (AXI_USER_WIDTH), + .BUFFER_DEPTH(2) + ) b_buffer_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .test_en_i(test_en_i), + .slave_valid_i(axi_master_b_valid_i), + .slave_resp_i (axi_master_b_resp_i), + .slave_id_i (axi_master_b_id_i), + .slave_user_i (axi_master_b_user_i), + .slave_ready_o(axi_master_b_ready_o), + .master_valid_o(s_b_valid), + .master_resp_o (s_b_resp), + .master_id_o (s_b_id), + .master_user_o (s_b_user), + .master_ready_i(s_b_ready) + ); +endmodule diff --git a/test/include/tb_tasks.svh b/test/include/tb_tasks.svh index d63b53d9..9405d3b2 100644 --- a/test/include/tb_tasks.svh +++ b/test/include/tb_tasks.svh @@ -18,8 +18,8 @@ output byte_t byte_o, input addr_t addr_i ); - if (i_axi_sim_mem.mem.exists(addr_i)) - byte_o = i_axi_sim_mem.mem[addr_i]; + if (i_axi_sim_mem_delayed.mem.exists(addr_i)) + byte_o = i_axi_sim_mem_delayed.mem[addr_i]; else byte_o = '1; endtask diff --git a/test/tb_idma_backend.sv b/test/tb_idma_backend.sv index 8219c3b2..c2b8f55b 100644 --- a/test/tb_idma_backend.sv +++ b/test/tb_idma_backend.sv @@ -2,7 +2,8 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // -// Thomas Benz +// Thomas Benz +// Tobias Senti `timescale 1ns/1ns `include "axi/typedef.svh" @@ -98,7 +99,7 @@ module tb_idma_backend import idma_pkg::*; #( logic eh_req_ready; // AXI4 master - axi_req_t axi_req, axi_req_mem; + axi_req_t axi_req, axi_req_mem, axi_req_mem_delayed; axi_rsp_t axi_rsp, axi_rsp_mem; // busy signal @@ -210,6 +211,42 @@ module tb_idma_backend import idma_pkg::*; #( .mon_w_valid_o ( /* NOT CONNECTED */ ) ); + axi_cut #( + .Bypass ( 1'b0 ), + .aw_chan_t ( axi_aw_chan_t ), + .w_chan_t ( axi_w_chan_t ), + .b_chan_t ( axi_b_chan_t ), + .ar_chan_t ( axi_ar_chan_t ), + .r_chan_t ( axi_r_chan_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_cut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .slv_req_i ( axi_req_mem ), + .slv_resp_o ( ), + .mst_req_o ( axi_req_mem_delayed ), + .mst_resp_i ( axi_rsp_mem ) + ); + + axi_sim_mem #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .WarnUninitialized ( 1'b0 ), + .ClearErrOnAccess ( 1'b1 ), + .ApplDelay ( TA ), + .AcqDelay ( TT ) + ) i_axi_sim_mem_delayed ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .axi_req_i ( axi_req_mem_delayed ), + .axi_rsp_o ( ) + ); //-------------------------------------- // TB Monitors @@ -254,8 +291,10 @@ module tb_idma_backend import idma_pkg::*; #( .idma_rsp_t ( idma_rsp_t ), .idma_eh_req_t ( idma_eh_req_t ), .idma_busy_t ( idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ) + .protocol_req_t ( axi_req_t ), + .protocol_rsp_t ( axi_rsp_t ), + .aw_chan_t ( axi_aw_chan_t ), + .ar_chan_t ( axi_ar_chan_t ) ) i_idma_backend ( .clk_i ( clk ), .rst_ni ( rst_n ), @@ -269,8 +308,8 @@ module tb_idma_backend import idma_pkg::*; #( .idma_eh_req_i ( idma_eh_req ), .eh_req_valid_i ( eh_req_valid ), .eh_req_ready_o ( eh_req_ready ), - .axi_req_o ( axi_req ), - .axi_rsp_i ( axi_rsp ), + .protocol_req_o ( axi_req ), + .protocol_rsp_i ( axi_rsp ), .busy_o ( busy ) ); diff --git a/test/tb_idma_lite_backend.sv b/test/tb_idma_lite_backend.sv new file mode 100644 index 00000000..8180a5b1 --- /dev/null +++ b/test/tb_idma_lite_backend.sv @@ -0,0 +1,543 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Thomas Benz +// Tobias Senti + +`timescale 1ns/1ns +`include "axi/typedef.svh" +`include "idma/typedef.svh" + +module tb_idma_lite_backend import idma_pkg::*; #( + parameter int unsigned BufferDepth = 3, + parameter int unsigned NumAxInFlight = 3, + parameter int unsigned DataWidth = 32, + parameter int unsigned AddrWidth = 32, + parameter int unsigned UserWidth = 1, + parameter int unsigned AxiIdWidth = 1, + parameter int unsigned TFLenWidth = 32, + parameter int unsigned MemSysDepth = 0, + parameter int unsigned MemNumReqOutst = 1, + parameter int unsigned MemLatency = 0, + parameter int unsigned WatchDogNumCycles = 100, + parameter bit MaskInvalidData = 1, + parameter bit RAWCouplingAvail = 1, + parameter bit HardwareLegalizer = 1, + parameter bit RejectZeroTransfers = 1, + parameter bit ErrorHandling = 1, + parameter bit IdealMemory = 1, + parameter bit AxiDumper = 0 +); + + // timing parameters + localparam time TA = 1ns; + localparam time TT = 9ns; + localparam time TCK = 10ns; + + // debug + localparam bit Debug = 1'b0; + localparam bit ModelOutput = 1'b0; + localparam bit PrintFifoInfo = 1'b1; + + // TB parameters + // dependent parameters + localparam int unsigned StrbWidth = DataWidth / 8; + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + + // parse error handling caps + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // static types + typedef logic [7:0] byte_t; + + // dependent typed + typedef logic [AddrWidth-1:0] addr_t; + typedef logic [DataWidth-1:0] data_t; + typedef logic [StrbWidth-1:0] strb_t; + typedef logic [UserWidth-1:0] user_t; + typedef logic [AxiIdWidth-1:0] id_t; + typedef logic [OffsetWidth-1:0] offset_t; + typedef logic [TFLenWidth-1:0] tf_len_t; + + // AXI typedef + `AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + + `AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + + `AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) + `AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + // AXI-Lite typedef + `AXI_LITE_TYPEDEF_AW_CHAN_T(axi_lite_aw_chan_t, addr_t) + `AXI_LITE_TYPEDEF_W_CHAN_T(axi_lite_w_chan_t, data_t, strb_t) + `AXI_LITE_TYPEDEF_B_CHAN_T(axi_lite_b_chan_t) + + `AXI_LITE_TYPEDEF_AR_CHAN_T(axi_lite_ar_chan_t, addr_t) + `AXI_LITE_TYPEDEF_R_CHAN_T(axi_lite_r_chan_t, data_t) + + `AXI_LITE_TYPEDEF_REQ_T(axi_lite_req_t, axi_lite_aw_chan_t, axi_lite_w_chan_t, axi_lite_ar_chan_t) + `AXI_LITE_TYPEDEF_RESP_T(axi_lite_rsp_t, axi_lite_b_chan_t, axi_lite_r_chan_t) + + // iDMA request / response types + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, id_t, addr_t, tf_len_t) + `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, addr_t) + + + //-------------------------------------- + // Physical Signals to the DUT + //-------------------------------------- + // clock reset signals + logic clk; + logic rst_n; + + // dma request + idma_req_t idma_req; + logic req_valid; + logic req_ready; + + // dma response + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // error handler + idma_eh_req_t idma_eh_req; + logic eh_req_valid; + logic eh_req_ready; + + // AXI4 master + axi_req_t axi_req, axi_req_mem, axi_req_mem_delayed; + axi_rsp_t axi_rsp, axi_rsp_mem; + + axi_req_t dut_axi_req; + axi_rsp_t dut_axi_rsp; + + axi_lite_req_t dut_axi_lite_req; + axi_lite_rsp_t dut_axi_lite_rsp; + + // busy signal + idma_busy_t busy; + + + //-------------------------------------- + // DMA Driver + //-------------------------------------- + // virtual interface definition + IDMA_DV #( + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .AxiIdWidth ( AxiIdWidth ), + .TFLenWidth ( TFLenWidth ) + ) idma_dv (clk); + + // DMA driver type + typedef idma_test::idma_driver #( + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .AxiIdWidth ( AxiIdWidth ), + .TFLenWidth ( TFLenWidth ), + .TA ( TA ), + .TT ( TT ) + ) drv_t; + + // instantiation of the driver + drv_t drv = new(idma_dv); + + + //-------------------------------------- + // DMA Job Queue + //-------------------------------------- + // job type definition + typedef idma_test::idma_job #( + .AddrWidth ( AddrWidth ) + ) tb_dma_job_t; + + // request and response queues + tb_dma_job_t req_jobs [$]; + tb_dma_job_t rsp_jobs [$]; + + + //-------------------------------------- + // DMA Model + //-------------------------------------- + // model type definition + typedef idma_test::idma_model #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .ModelOutput ( ModelOutput ) + ) model_t; + + // instantiation of the model + model_t model = new(); + + + //-------------------------------------- + // Misc TB Signals + //-------------------------------------- + logic match; + + + //-------------------------------------- + // TB Modules + //-------------------------------------- + // clocking block + clk_rst_gen #( + .ClkPeriod ( TCK ), + .RstClkCycles ( 1 ) + ) i_clk_rst_gen ( + .clk_o ( clk ), + .rst_no ( rst_n ) + ); + + // sim memory + axi_sim_mem #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .WarnUninitialized ( 1'b0 ), + .ClearErrOnAccess ( 1'b1 ), + .ApplDelay ( TA ), + .AcqDelay ( TT ) + ) i_axi_sim_mem ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .axi_req_i ( axi_req_mem ), + .axi_rsp_o ( axi_rsp_mem ) + ); + + axi_cut #( + .Bypass ( 1'b0 ), + .aw_chan_t ( axi_aw_chan_t ), + .w_chan_t ( axi_w_chan_t ), + .b_chan_t ( axi_b_chan_t ), + .ar_chan_t ( axi_ar_chan_t ), + .r_chan_t ( axi_r_chan_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_cut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .slv_req_i ( axi_req_mem ), + .slv_resp_o ( ), + .mst_req_o ( axi_req_mem_delayed ), + .mst_resp_i ( axi_rsp_mem ) + ); + + axi_sim_mem #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .WarnUninitialized ( 1'b0 ), + .ClearErrOnAccess ( 1'b1 ), + .ApplDelay ( TA ), + .AcqDelay ( TT ) + ) i_axi_sim_mem_delayed ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .axi_req_i ( axi_req_mem_delayed ), + .axi_rsp_o ( ) + ); + + //-------------------------------------- + // TB Monitors + //-------------------------------------- + // AXI + signal_highlighter #(.T(axi_aw_chan_t)) i_aw_hl (.ready_i(axi_rsp.aw_ready), .valid_i(axi_req.aw_valid), .data_i(axi_req.aw)); + signal_highlighter #(.T(axi_ar_chan_t)) i_ar_hl (.ready_i(axi_rsp.ar_ready), .valid_i(axi_req.ar_valid), .data_i(axi_req.ar)); + signal_highlighter #(.T(axi_w_chan_t)) i_w_hl (.ready_i(axi_rsp.w_ready), .valid_i(axi_req.w_valid), .data_i(axi_req.w)); + signal_highlighter #(.T(axi_r_chan_t)) i_r_hl (.ready_i(axi_req.r_ready), .valid_i(axi_rsp.r_valid), .data_i(axi_rsp.r)); + signal_highlighter #(.T(axi_b_chan_t)) i_b_hl (.ready_i(axi_req.b_ready), .valid_i(axi_rsp.b_valid), .data_i(axi_rsp.b)); + + // DMA types + signal_highlighter #(.T(idma_req_t)) i_req_hl (.ready_i(req_ready), .valid_i(req_valid), .data_i(idma_req)); + signal_highlighter #(.T(idma_rsp_t)) i_rsp_hl (.ready_i(rsp_ready), .valid_i(rsp_valid), .data_i(idma_rsp)); + signal_highlighter #(.T(idma_eh_req_t)) i_eh_hl (.ready_i(eh_req_ready), .valid_i(eh_req_valid), .data_i(idma_eh_req)); + + // Watchdogs + stream_watchdog #(.NumCycles(WatchDogNumCycles)) i_axi_w_watchdog (.clk_i(clk), .valid_i(axi_req.w_valid), .ready_i(axi_rsp.w_ready)); + stream_watchdog #(.NumCycles(WatchDogNumCycles)) i_axi_r_watchdog (.clk_i(clk), .valid_i(axi_rsp.r_valid), .ready_i(axi_req.r_ready)); + + + //-------------------------------------- + // DUT + //-------------------------------------- + // the backend + idma_backend #( + .Protocol ( idma_pkg::AXI_LITE ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .PrintFifoInfo ( PrintFifoInfo ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_eh_req_t ), + .idma_busy_t ( idma_busy_t ), + .protocol_req_t ( axi_lite_req_t ), + .protocol_rsp_t ( axi_lite_rsp_t ), + .aw_chan_t ( axi_lite_aw_chan_t ), + .ar_chan_t ( axi_lite_ar_chan_t ) + ) i_idma_backend ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .testmode_i ( 1'b0 ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid ), + .req_ready_o ( req_ready ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid ), + .rsp_ready_i ( rsp_ready ), + .idma_eh_req_i ( idma_eh_req ), + .eh_req_valid_i ( eh_req_valid ), + .eh_req_ready_o ( eh_req_ready ), + .protocol_req_o ( dut_axi_lite_req ), + .protocol_rsp_i ( dut_axi_lite_rsp ), + .busy_o ( busy ) + ); + + + //-------------------------------------- + // TB connections + //-------------------------------------- + + // AXI-Lite to AXI Bridge + + axi_lite_to_axi #( + .AxiDataWidth ( DataWidth ), + .req_lite_t ( axi_lite_req_t ), + .resp_lite_t ( axi_lite_rsp_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_lite_to_axi ( + .slv_req_lite_i ( dut_axi_lite_req ), + .slv_resp_lite_o ( dut_axi_lite_rsp ), + .slv_aw_cache_i ( axi_pkg::CACHE_MODIFIABLE ), + .slv_ar_cache_i ( axi_pkg::CACHE_MODIFIABLE ), + .mst_req_o ( axi_req ), + .mst_resp_i ( axi_rsp ) + ); + + // Channel Logger + if (AxiDumper) begin : gen_axi_dumper + axi_dumper #( + .LogAW ( 1'b1 ), + .LogAR ( 1'b1 ), + .LogW ( 1'b1 ), + .LogB ( 1'b1 ), + .LogR ( 1'b1 ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_dumper ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .axi_req_i ( axi_req ), + .axi_resp_i ( axi_rsp ) + ); + end + + // connect virtual driver interface to structs + assign idma_req = idma_dv.req; + assign req_valid = idma_dv.req_valid; + assign rsp_ready = idma_dv.rsp_ready; + assign idma_eh_req = idma_dv.eh_req; + assign eh_req_valid = idma_dv.eh_req_valid; + // connect struct to virtual driver interface + assign idma_dv.req_ready = req_ready; + assign idma_dv.rsp = idma_rsp; + assign idma_dv.rsp_valid = rsp_valid; + assign idma_dv.eh_req_ready = eh_req_ready; + + // throttle the AXI bus + if (IdealMemory) begin : gen_ideal_mem_connect + + // if the memory is ideal: 0 cycle latency here + assign axi_req_mem = axi_req; + assign axi_rsp = axi_rsp_mem; + + end else begin : gen_delayed_mem_connect + + // the throttled AXI buses + axi_req_t axi_req_throttled; + axi_rsp_t axi_rsp_throttled; + + // axi throttle: limit the amount of concurrent requests in the memory system + axi_throttle #( + .MaxNumAwPending ( 2**32 - 1 ), + .MaxNumArPending ( 2**32 - 1 ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ) + ) i_axi_throttle ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .req_i ( axi_req ), + .rsp_o ( axi_rsp ), + .req_o ( axi_req_throttled ), + .rsp_i ( axi_rsp_throttled ), + .w_credit_i ( MemNumReqOutst ), + .r_credit_i ( MemNumReqOutst ) + ); + + // delay the signals using AXI4 multicuts + axi_multicut #( + .NoCuts ( MemLatency ), + .aw_chan_t ( axi_aw_chan_t ), + .w_chan_t ( axi_w_chan_t ), + .b_chan_t ( axi_b_chan_t ), + .ar_chan_t ( axi_ar_chan_t ), + .r_chan_t ( axi_r_chan_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_multicut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .slv_req_i ( axi_req_throttled ), + .slv_resp_o ( axi_rsp_throttled ), + .mst_req_o ( axi_req_mem ), + .mst_resp_i ( axi_rsp_mem ) + ); + end + + + //-------------------------------------- + // Various TB Tasks + //-------------------------------------- + `include "include/tb_tasks.svh" + + + // --------------------- Begin TB -------------------------- + + + //-------------------------------------- + // Read Job queue from File + //-------------------------------------- + initial begin + string job_file; + void'($value$plusargs("job_file=%s", job_file)); + $display("Reading from %s", job_file); + read_jobs(job_file, req_jobs); + read_jobs(job_file, rsp_jobs); + end + + + //-------------------------------------- + // Launch Transfers + //-------------------------------------- + initial begin + // reset driver + drv.reset_driver(); + // wait until reset has completed + wait (rst_n); + // print a job summary + print_summary(req_jobs); + // wait some additional time + #100ns; + + // run all requests in queue + while (req_jobs.size() != 0) begin + // pop front to get a job + automatic tb_dma_job_t now = req_jobs.pop_front(); + // print job to terminal + $display("%s", now.pprint()); + // init mem (model and AXI) + init_mem(now); + // launch DUT + drv.launch_tf( + now.length, + now.src_addr, + now.dst_addr, + now.aw_decoupled, + now.rw_decoupled, + $clog2(now.max_src_len), + $clog2(now.max_dst_len), + now.max_src_len != 'd256, + now.max_dst_len != 'd256 + ); + end + // once done: launched all transfers + $display("Launched all Transfers."); + end + + + //-------------------------------------- + // Ack Transfers and Compare Memories + //-------------------------------------- + initial begin + // wait until reset has completed + wait (rst_n); + // wait some additional time + #100ns; + // receive + while (rsp_jobs.size() != 0) begin + // peek front to get a job + automatic tb_dma_job_t now = rsp_jobs[0]; + // wait for DMA to complete + ack_tf_handle_err(now); + // finished job + // $display("vvv Finished: vvv%s\n^^^ Finished: ^^^", now.pprint()); + // launch model + model.transfer( + now.length, + now.src_addr, + now.dst_addr, + now.max_src_len, + now.max_dst_len, + now.rw_decoupled, + now.err_addr, + now.err_is_read, + now.err_action + ); + // check memory + compare_mem(now.length, now.dst_addr, match); + // fail if there is a mismatch + if (!match) + $fatal(1, "Mismatch!"); + // pop front + rsp_jobs.pop_front(); + end + // wait some additional time + #100ns; + // we are done! + $finish(); + end + + + //-------------------------------------- + // Show first non-acked Transfer + //-------------------------------------- + initial begin + wait (rst_n); + forever begin + // at least one watch dog triggers + if (i_axi_r_watchdog.cnt == 0 | i_axi_w_watchdog.cnt == 0) begin + automatic tb_dma_job_t now = rsp_jobs[0]; + $error("First non-acked transfer:%s\n\n", now.pprint()); + end + @(posedge clk); + end + end + +endmodule : tb_idma_lite_backend diff --git a/test/tb_idma_nd_backend.sv b/test/tb_idma_nd_backend.sv index be82339e..50d35564 100644 --- a/test/tb_idma_nd_backend.sv +++ b/test/tb_idma_nd_backend.sv @@ -2,7 +2,8 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // -// Thomas Benz +// Thomas Benz +// Tobias Senti `timescale 1ns/1ns `include "axi/typedef.svh" @@ -116,7 +117,7 @@ module tb_idma_nd_backend import idma_pkg::*; #( logic eh_req_ready; // AXI4 master - axi_req_t axi_req, axi_req_mem; + axi_req_t axi_req, axi_req_mem, axi_req_mem_delayed; axi_rsp_t axi_rsp, axi_rsp_mem; // busy signal @@ -252,6 +253,42 @@ module tb_idma_nd_backend import idma_pkg::*; #( .mon_w_valid_o ( /* NOT CONNECTED */ ) ); + axi_cut #( + .Bypass ( 1'b0 ), + .aw_chan_t ( axi_aw_chan_t ), + .w_chan_t ( axi_w_chan_t ), + .b_chan_t ( axi_b_chan_t ), + .ar_chan_t ( axi_ar_chan_t ), + .r_chan_t ( axi_r_chan_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_cut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .slv_req_i ( axi_req_mem ), + .slv_resp_o ( ), + .mst_req_o ( axi_req_mem_delayed ), + .mst_resp_i ( axi_rsp_mem ) + ); + + axi_sim_mem #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .WarnUninitialized ( 1'b0 ), + .ClearErrOnAccess ( 1'b1 ), + .ApplDelay ( TA ), + .AcqDelay ( TT ) + ) i_axi_sim_mem_delayed ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .axi_req_i ( axi_req_mem_delayed ), + .axi_rsp_o ( ) + ); //-------------------------------------- // TB Monitors @@ -324,8 +361,10 @@ module tb_idma_nd_backend import idma_pkg::*; #( .idma_rsp_t ( idma_rsp_t ), .idma_eh_req_t ( idma_eh_req_t ), .idma_busy_t ( idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ) + .protocol_req_t ( axi_req_t ), + .protocol_rsp_t ( axi_rsp_t ), + .aw_chan_t ( axi_aw_chan_t ), + .ar_chan_t ( axi_ar_chan_t ) ) i_idma_backend ( .clk_i ( clk ), .rst_ni ( rst_n ), @@ -339,8 +378,8 @@ module tb_idma_nd_backend import idma_pkg::*; #( .idma_eh_req_i ( idma_eh_req ), .eh_req_valid_i ( eh_req_valid ), .eh_req_ready_o ( eh_req_ready ), - .axi_req_o ( axi_req ), - .axi_rsp_i ( axi_rsp ), + .protocol_req_o ( axi_req ), + .protocol_rsp_i ( axi_rsp ), .busy_o ( busy ) ); diff --git a/test/tb_idma_obi_backend.sv b/test/tb_idma_obi_backend.sv new file mode 100644 index 00000000..a406fe2f --- /dev/null +++ b/test/tb_idma_obi_backend.sv @@ -0,0 +1,633 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Thomas Benz +// Tobias Senti + +`timescale 1ns/1ns +`include "axi/typedef.svh" +`include "idma/typedef.svh" + +module tb_idma_obi_backend import idma_pkg::*; #( + parameter int unsigned BufferDepth = 3, + parameter int unsigned NumAxInFlight = 3, + parameter int unsigned DataWidth = 32, + parameter int unsigned AddrWidth = 32, + parameter int unsigned UserWidth = 1, + parameter int unsigned AxiIdWidth = 1, + parameter int unsigned TFLenWidth = 32, + parameter int unsigned MemSysDepth = 0, + parameter int unsigned MemNumReqOutst = 1, + parameter int unsigned MemLatency = 0, + parameter int unsigned WatchDogNumCycles = 100, + parameter bit MaskInvalidData = 1, + parameter bit RAWCouplingAvail = 0, + parameter bit HardwareLegalizer = 1, + parameter bit RejectZeroTransfers = 1, + parameter bit ErrorHandling = 0, + parameter bit IdealMemory = 1, + parameter bit AxiDumper = 0 +); + + // timing parameters + localparam time TA = 1ns; + localparam time TT = 9ns; + localparam time TCK = 10ns; + + // debug + localparam bit Debug = 1'b0; + localparam bit ModelOutput = 1'b0; + localparam bit PrintFifoInfo = 1'b1; + + // TB parameters + // dependent parameters + localparam int unsigned StrbWidth = DataWidth / 8; + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + + // parse error handling caps + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // static types + typedef logic [7:0] byte_t; + + // dependent typed + typedef logic [AddrWidth-1:0] addr_t; + typedef logic [DataWidth-1:0] data_t; + typedef logic [StrbWidth-1:0] strb_t; + typedef logic [UserWidth-1:0] user_t; + typedef logic [AxiIdWidth-1:0] id_t; + typedef logic [OffsetWidth-1:0] offset_t; + typedef logic [TFLenWidth-1:0] tf_len_t; + + // AXI typedef + `AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + + `AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + + `AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) + `AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + // iDMA request / response types + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, id_t, addr_t, tf_len_t) + `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, addr_t) + + // OBI typedef + `IDMA_OBI_TYPEDEF_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t) + `IDMA_OBI_TYPEDEF_R_CHAN_T(obi_r_chan_t, data_t) + + `IDMA_OBI_TYPEDEF_REQ_T(obi_master_req_t, obi_a_chan_t) + `IDMA_OBI_TYPEDEF_RESP_T(obi_master_rsp_t, obi_r_chan_t) + + `IDMA_OBI_TYPEDEF_BIDIRECT_REQ_T(obi_req_t, obi_master_req_t) + `IDMA_OBI_TYPEDEF_BIDIRECT_RESP_T(obi_rsp_t, obi_master_rsp_t) + + //-------------------------------------- + // Physical Signals to the DUT + //-------------------------------------- + + //OBI Masters + obi_req_t obi_req; + obi_rsp_t obi_rsp; + + axi_req_t axi_read_req; + axi_rsp_t axi_read_rsp; + + axi_req_t axi_write_req; + axi_rsp_t axi_write_rsp; + + // clock reset signals + logic clk; + logic rst_n; + + // dma request + idma_req_t idma_req; + logic req_valid; + logic req_ready; + + // dma response + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // error handler + idma_eh_req_t idma_eh_req; + logic eh_req_valid; + logic eh_req_ready; + + // AXI4 master + axi_req_t axi_req, axi_req_mem, axi_req_mem_delayed; + axi_rsp_t axi_rsp, axi_rsp_mem; + + axi_req_t dut_axi_req; + axi_rsp_t dut_axi_rsp; + + // busy signal + idma_busy_t busy; + + + //-------------------------------------- + // DMA Driver + //-------------------------------------- + // virtual interface definition + IDMA_DV #( + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .AxiIdWidth ( AxiIdWidth ), + .TFLenWidth ( TFLenWidth ) + ) idma_dv (clk); + + // DMA driver type + typedef idma_test::idma_driver #( + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .AxiIdWidth ( AxiIdWidth ), + .TFLenWidth ( TFLenWidth ), + .TA ( TA ), + .TT ( TT ) + ) drv_t; + + // instantiation of the driver + drv_t drv = new(idma_dv); + + + //-------------------------------------- + // DMA Job Queue + //-------------------------------------- + // job type definition + typedef idma_test::idma_job #( + .AddrWidth ( AddrWidth ) + ) tb_dma_job_t; + + // request and response queues + tb_dma_job_t req_jobs [$]; + tb_dma_job_t rsp_jobs [$]; + + + //-------------------------------------- + // DMA Model + //-------------------------------------- + // model type definition + typedef idma_test::idma_model #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .ModelOutput ( ModelOutput ) + ) model_t; + + // instantiation of the model + model_t model = new(); + + + //-------------------------------------- + // Misc TB Signals + //-------------------------------------- + logic match; + + + //-------------------------------------- + // TB Modules + //-------------------------------------- + // clocking block + clk_rst_gen #( + .ClkPeriod ( TCK ), + .RstClkCycles ( 1 ) + ) i_clk_rst_gen ( + .clk_o ( clk ), + .rst_no ( rst_n ) + ); + + // sim memory + axi_sim_mem #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .WarnUninitialized ( 1'b0 ), + .ClearErrOnAccess ( 1'b1 ), + .ApplDelay ( TA ), + .AcqDelay ( TT ) + ) i_axi_sim_mem ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .axi_req_i ( axi_req_mem ), + .axi_rsp_o ( axi_rsp_mem ) + ); + + axi_cut #( + .Bypass ( 1'b0 ), + .aw_chan_t ( axi_aw_chan_t ), + .w_chan_t ( axi_w_chan_t ), + .b_chan_t ( axi_b_chan_t ), + .ar_chan_t ( axi_ar_chan_t ), + .r_chan_t ( axi_r_chan_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_cut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .slv_req_i ( axi_req_mem ), + .slv_resp_o ( ), + .mst_req_o ( axi_req_mem_delayed ), + .mst_resp_i ( axi_rsp_mem ) + ); + + axi_sim_mem #( + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .WarnUninitialized ( 1'b0 ), + .ClearErrOnAccess ( 1'b1 ), + .ApplDelay ( TA ), + .AcqDelay ( TT ) + ) i_axi_sim_mem_delayed ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .axi_req_i ( axi_req_mem_delayed ), + .axi_rsp_o ( ) + ); + + //-------------------------------------- + // TB Monitors + //-------------------------------------- + //OBI + signal_highlighter #(.T(obi_a_chan_t)) i_obi_read_a_hl (.ready_i(obi_rsp.read.a_gnt), .valid_i(obi_req.read.a_req), .data_i(obi_req.read.a)); + signal_highlighter #(.T(obi_r_chan_t)) i_obi_read_r_hl (.ready_i(obi_req.read.r_ready), .valid_i(obi_rsp.read.r_valid), .data_i(obi_rsp.read.r)); + + signal_highlighter #(.T(obi_a_chan_t)) i_obi_write_a_hl (.ready_i(obi_rsp.write.a_gnt), .valid_i(obi_req.write.a_req), .data_i(obi_req.write.a)); + signal_highlighter #(.T(obi_r_chan_t)) i_obi_write_r_hl (.ready_i(obi_req.write.r_ready), .valid_i(obi_rsp.write.r_valid), .data_i(obi_rsp.write.r)); + + // AXI + signal_highlighter #(.T(axi_aw_chan_t)) i_aw_hl (.ready_i(axi_rsp.aw_ready), .valid_i(axi_req.aw_valid), .data_i(axi_req.aw)); + signal_highlighter #(.T(axi_ar_chan_t)) i_ar_hl (.ready_i(axi_rsp.ar_ready), .valid_i(axi_req.ar_valid), .data_i(axi_req.ar)); + signal_highlighter #(.T(axi_w_chan_t)) i_w_hl (.ready_i(axi_rsp.w_ready), .valid_i(axi_req.w_valid), .data_i(axi_req.w)); + signal_highlighter #(.T(axi_r_chan_t)) i_r_hl (.ready_i(axi_req.r_ready), .valid_i(axi_rsp.r_valid), .data_i(axi_rsp.r)); + signal_highlighter #(.T(axi_b_chan_t)) i_b_hl (.ready_i(axi_req.b_ready), .valid_i(axi_rsp.b_valid), .data_i(axi_rsp.b)); + + // DMA types + signal_highlighter #(.T(idma_req_t)) i_req_hl (.ready_i(req_ready), .valid_i(req_valid), .data_i(idma_req)); + signal_highlighter #(.T(idma_rsp_t)) i_rsp_hl (.ready_i(rsp_ready), .valid_i(rsp_valid), .data_i(idma_rsp)); + signal_highlighter #(.T(idma_eh_req_t)) i_eh_hl (.ready_i(eh_req_ready), .valid_i(eh_req_valid), .data_i(idma_eh_req)); + + // Watchdogs + stream_watchdog #(.NumCycles(WatchDogNumCycles)) i_axi_w_watchdog (.clk_i(clk), .valid_i(axi_req.w_valid), .ready_i(axi_rsp.w_ready)); + stream_watchdog #(.NumCycles(WatchDogNumCycles)) i_axi_r_watchdog (.clk_i(clk), .valid_i(axi_rsp.r_valid), .ready_i(axi_req.r_ready)); + + + //-------------------------------------- + // DUT + //-------------------------------------- + // the backend + idma_backend #( + .Protocol ( idma_pkg::OBI ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .PrintFifoInfo ( PrintFifoInfo ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_eh_req_t ), + .idma_busy_t ( idma_busy_t ), + .protocol_req_t ( obi_req_t ), + .protocol_rsp_t ( obi_rsp_t ), + .aw_chan_t ( obi_a_chan_t ), + .ar_chan_t ( obi_a_chan_t ) + ) i_idma_backend ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .testmode_i ( 1'b0 ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid ), + .req_ready_o ( req_ready ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid ), + .rsp_ready_i ( rsp_ready ), + .idma_eh_req_i ( idma_eh_req ), + .eh_req_valid_i ( eh_req_valid ), + .eh_req_ready_o ( eh_req_ready ), + .protocol_req_o ( obi_req ), + .protocol_rsp_i ( obi_rsp ), + .busy_o ( busy ) + ); + + + //-------------------------------------- + // TB connections + //-------------------------------------- + + // OBI Asserter + idma_obi_asserter #( + .obi_master_req_t ( obi_master_req_t ), + .obi_master_rsp_t ( obi_master_rsp_t ) + ) i_obi_read_asserter ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .obi_master_req_i ( obi_req.read ), + .obi_master_rsp_i ( obi_rsp.read ) + ); + + idma_obi_asserter #( + .obi_master_req_t ( obi_master_req_t ), + .obi_master_rsp_t ( obi_master_rsp_t ) + ) i_obi_write_asserter ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .obi_master_req_i ( obi_req.write ), + .obi_master_rsp_i ( obi_rsp.write ) + ); + + // Read OBI to AXI Bridge + idma_obi2axi_bridge #( + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .IdWidth ( AxiIdWidth ), + .obi_master_req_t ( obi_master_req_t ), + .obi_master_rsp_t ( obi_master_rsp_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ) + ) i_read_obi2axi_bridge ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .obi_master_req_i ( obi_req.read ), + .obi_master_rsp_o ( obi_rsp.read ), + .axi_req_o ( axi_read_req ), + .axi_rsp_i ( axi_read_rsp ) + ); + + // Write OBI to AXI Bridge + idma_obi2axi_bridge #( + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .IdWidth ( AxiIdWidth ), + .obi_master_req_t ( obi_master_req_t ), + .obi_master_rsp_t ( obi_master_rsp_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ) + ) i_write_obi2axi_bridge ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .obi_master_req_i ( obi_req.write ), + .obi_master_rsp_o ( obi_rsp.write ), + .axi_req_o ( axi_write_req ), + .axi_rsp_i ( axi_write_rsp ) + ); + + // AXI Read and Write Master to Full AXI Bridge + always_comb begin + //Connect AXI and AXI Read port -> Connect ar and r + axi_req.ar_valid = axi_read_req.ar_valid; + axi_req.ar = axi_read_req.ar; + axi_read_rsp.ar_ready = axi_rsp.ar_ready; + + axi_read_rsp.b_valid = 1'b0; + + axi_req.r_ready = axi_read_req.r_ready; + axi_read_rsp.r_valid = axi_rsp.r_valid; + axi_read_rsp.r = axi_rsp.r; + + axi_read_rsp.aw_ready = 1'b1; + axi_read_rsp.w_ready = 1'b1; + + // Connect AXI and AXI Write port -> Connect aw, w and b + axi_req.aw_valid = axi_write_req.aw_valid; + axi_req.aw = axi_write_req.aw; + axi_write_rsp.aw_ready = axi_rsp.aw_ready; + + axi_write_rsp.r_valid = 1'b0; + axi_write_rsp.r = '0; + + axi_req.w_valid = axi_write_req.w_valid; + axi_req.w = axi_write_req.w; + axi_write_rsp.w_ready = axi_rsp.w_ready; + + axi_req.b_ready = axi_write_req.b_ready; + axi_write_rsp.b_valid = axi_rsp.b_valid; + axi_write_rsp.b = axi_rsp.b; + + axi_write_rsp.ar_ready = 1'b1; + end + + // Channel Logger + if (AxiDumper) begin : gen_axi_dumper + axi_dumper #( + .LogAW ( 1'b1 ), + .LogAR ( 1'b1 ), + .LogW ( 1'b1 ), + .LogB ( 1'b1 ), + .LogR ( 1'b1 ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_dumper ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .axi_req_i ( axi_req ), + .axi_resp_i ( axi_rsp ) + ); + end + + // connect virtual driver interface to structs + assign idma_req = idma_dv.req; + assign req_valid = idma_dv.req_valid; + assign rsp_ready = idma_dv.rsp_ready; + assign idma_eh_req = idma_dv.eh_req; + assign eh_req_valid = idma_dv.eh_req_valid; + // connect struct to virtual driver interface + assign idma_dv.req_ready = req_ready; + assign idma_dv.rsp = idma_rsp; + assign idma_dv.rsp_valid = rsp_valid; + assign idma_dv.eh_req_ready = eh_req_ready; + + // throttle the AXI bus + if (IdealMemory) begin : gen_ideal_mem_connect + + // if the memory is ideal: 0 cycle latency here + assign axi_req_mem = axi_req; + assign axi_rsp = axi_rsp_mem; + + end else begin : gen_delayed_mem_connect + + // the throttled AXI buses + axi_req_t axi_req_throttled; + axi_rsp_t axi_rsp_throttled; + + // axi throttle: limit the amount of concurrent requests in the memory system + axi_throttle #( + .MaxNumAwPending ( 2**32 - 1 ), + .MaxNumArPending ( 2**32 - 1 ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ) + ) i_axi_throttle ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .req_i ( axi_req ), + .rsp_o ( axi_rsp ), + .req_o ( axi_req_throttled ), + .rsp_i ( axi_rsp_throttled ), + .w_credit_i ( MemNumReqOutst ), + .r_credit_i ( MemNumReqOutst ) + ); + + // delay the signals using AXI4 multicuts + axi_multicut #( + .NoCuts ( MemLatency ), + .aw_chan_t ( axi_aw_chan_t ), + .w_chan_t ( axi_w_chan_t ), + .b_chan_t ( axi_b_chan_t ), + .ar_chan_t ( axi_ar_chan_t ), + .r_chan_t ( axi_r_chan_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_multicut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .slv_req_i ( axi_req_throttled ), + .slv_resp_o ( axi_rsp_throttled ), + .mst_req_o ( axi_req_mem ), + .mst_resp_i ( axi_rsp_mem ) + ); + end + + + //-------------------------------------- + // Various TB Tasks + //-------------------------------------- + `include "include/tb_tasks.svh" + + + // --------------------- Begin TB -------------------------- + + + //-------------------------------------- + // Read Job queue from File + //-------------------------------------- + initial begin + string job_file; + void'($value$plusargs("job_file=%s", job_file)); + $display("Reading from %s", job_file); + read_jobs(job_file, req_jobs); + read_jobs(job_file, rsp_jobs); + end + + + //-------------------------------------- + // Launch Transfers + //-------------------------------------- + initial begin + // reset driver + drv.reset_driver(); + // wait until reset has completed + wait (rst_n); + // print a job summary + print_summary(req_jobs); + // wait some additional time + #100ns; + + // run all requests in queue + while (req_jobs.size() != 0) begin + // pop front to get a job + automatic tb_dma_job_t now = req_jobs.pop_front(); + // print job to terminal + $display("%s", now.pprint()); + // init mem (model and AXI) + init_mem(now); + // launch DUT + drv.launch_tf( + now.length, + now.src_addr, + now.dst_addr, + now.aw_decoupled, + now.rw_decoupled, + $clog2(now.max_src_len), + $clog2(now.max_dst_len), + now.max_src_len != 'd256, + now.max_dst_len != 'd256 + ); + end + // once done: launched all transfers + $display("Launched all Transfers."); + end + + + //-------------------------------------- + // Ack Transfers and Compare Memories + //-------------------------------------- + initial begin + // wait until reset has completed + wait (rst_n); + // wait some additional time + #100ns; + // receive + while (rsp_jobs.size() != 0) begin + // peek front to get a job + automatic tb_dma_job_t now = rsp_jobs[0]; + // wait for DMA to complete + ack_tf_handle_err(now); + // finished job + // $display("vvv Finished: vvv%s\n^^^ Finished: ^^^", now.pprint()); + // launch model + model.transfer( + now.length, + now.src_addr, + now.dst_addr, + now.max_src_len, + now.max_dst_len, + now.rw_decoupled, + now.err_addr, + now.err_is_read, + now.err_action + ); + // check memory + compare_mem(now.length, now.dst_addr, match); + // fail if there is a mismatch + if (!match) + $fatal(1, "Mismatch!"); + // pop front + rsp_jobs.pop_front(); + end + // wait some additional time + #100ns; + // we are done! + $finish(); + end + + + //-------------------------------------- + // Show first non-acked Transfer + //-------------------------------------- + initial begin + wait (rst_n); + forever begin + // at least one watch dog triggers + if (i_axi_r_watchdog.cnt == 0 | i_axi_w_watchdog.cnt == 0) begin + automatic tb_dma_job_t now = rsp_jobs[0]; + $error("First non-acked transfer:%s\n\n", now.pprint()); + end + @(posedge clk); + end + end + +endmodule : tb_idma_obi_backend