From 5c9c0fc890c16816f1bd84b48197c65406431a31 Mon Sep 17 00:00:00 2001 From: aay268 Date: Fri, 19 Apr 2024 16:49:59 -0400 Subject: [PATCH 1/6] (fix): Attempted to implement APB Manager (4/19) --- rtl/apb/devices/APBManager.sv | 67 ++++++++++++++++++++++++++++++ rtl/apb/interfaces/APBCommon_if.sv | 12 ++++++ 2 files changed, 79 insertions(+) create mode 100644 rtl/apb/devices/APBManager.sv diff --git a/rtl/apb/devices/APBManager.sv b/rtl/apb/devices/APBManager.sv new file mode 100644 index 0000000..0aa84cc --- /dev/null +++ b/rtl/apb/devices/APBManager.sv @@ -0,0 +1,67 @@ +// Used GenericBusManager.sv as template for outline + +/** + @brief Manager that uses the GenericBus protocol directly as the transmission + protocol + + @input device managing device + @input bus bus to managed + */ + +module APBManager ( + APBCommon_if bus, + APBCommon_if bridge +); + always_comb begin + bridge.rData = bus.rData; + bridge.subError <= bus.subError; + end + + always_ff @(posedge bridge.clk, negedge bridge.nReset) begin + if (!bridge.nReset) begin + bus.write <= 0; + bus.addr <= 0; + bus.wData <= 0; + bus.prot <= 0; + bus.enable <= 0; + + /** + - Alert subordinate that we're writing to it + - Set up write and enable + - Check ready signal + **/ + end else if (!bus.ready || !bus.enable) begin // wake up bus + bus.sel[bridge.sel] <= 1; + end else if (bus.ready && !bus.enable) begin + bus.enable <= 1; + bus.write <= bridge.write; + bus.addr <= bridge.addr; + bus.prot <= bridge.prot; + bus.wData <= bridge.wData; + end else if (bus.subError) begin + bus.enable = 0; + end + end +endmodule + +/** +APB Interface Signals +NEED TO GIVE DIRECTION -> Logic just says we care about variable + + input [AddrWidth-1:0] addr; // Address bus + input [3:0] prot; // protected piece of mail + output [PrphNum-1:0] selectors; // sending a bit on the selector on bus where peripherals live; + think as array of subordinates live (bit will let subordinate to get ready) -> Read APB Spec for more detail + // To know where each subordinate lives, address is sent to decoder & + decoder tells us which subordinate we need to talk to in array + output enable; // Bit that tells us if person is getting multiple "packages" + output write; + inout [DataWidth - 1:0] wData; // 1 of 2 Data Buses + inout(?) [DataWidth/8 - 1:0] strb; // Ignore bc AHB ignores strobe + input ready; + inout [DataWidth - 1:0] rData; // 2 of 2 Data buses + input subError; + + +My APB will support up to 8 subordinates +**/ \ No newline at end of file diff --git a/rtl/apb/interfaces/APBCommon_if.sv b/rtl/apb/interfaces/APBCommon_if.sv index 820431e..ddec1ae 100644 --- a/rtl/apb/interfaces/APBCommon_if.sv +++ b/rtl/apb/interfaces/APBCommon_if.sv @@ -54,6 +54,18 @@ interface APBCommon_if #( output write, output wData ); + + modport manager( + input addr, + input prot, + output selectors, + output enable, + inout wData, + inout strb, + input ready, + inout rData, + input subError + ); endinterface From df8a59c08b66db30bb3ff9d9f9da9fdbf3824daa Mon Sep 17 00:00:00 2001 From: aay268 Date: Sun, 21 Apr 2024 00:30:56 -0400 Subject: [PATCH 2/6] (fix): Rewrote APB manager module; Partially wrote associated test bench --- dv/apb/APBManager/APBManager.cpp | 64 ++++++++++++++++++++++ dv/apb/APBManager/APBManager_tl.sv | 87 ++++++++++++++++++++++++++++++ dv/apb/APBManager/CMakeLists.txt | 6 +++ dv/apb/CMakeLists.txt | 4 ++ rtl/apb/devices/APBManager.sv | 75 ++++++++------------------ rtl/apb/devices/CMakeLists.txt | 3 ++ rtl/apb/interfaces/APBCommon_if.sv | 18 ++++--- 7 files changed, 196 insertions(+), 61 deletions(-) create mode 100644 dv/apb/APBManager/APBManager.cpp create mode 100644 dv/apb/APBManager/APBManager_tl.sv create mode 100644 dv/apb/APBManager/CMakeLists.txt create mode 100644 dv/apb/CMakeLists.txt diff --git a/dv/apb/APBManager/APBManager.cpp b/dv/apb/APBManager/APBManager.cpp new file mode 100644 index 0000000..7cdd221 --- /dev/null +++ b/dv/apb/APBManager/APBManager.cpp @@ -0,0 +1,64 @@ +#include +#include + +#include + +// Verify all pass-thrus into bus +TEST_CASE("APBManager, bus-to-device pass-thru") { + VAPBManager_tl& bm {nyu::getDUT()}; + nyu::reset(bm); + for (std::uint8_t i {0}; i < 2; ++i) { + bm.localSel = i; + nyu::eval(bm); + REQUIRE(bm.bus_selectors == i); + } + for (std::uint8_t i {0}; i < 16; ++i) { + bm.mgr_prot = i; + bm.mgr_wStrb = i; + nyu::eval(bm); + REQUIRE(bm.bus_prot == i); + REQUIRE(bm.bus_strb == i); + } + for (std::uint32_t i {1}; i; i <<= 1) { + bm.mgr_wData = i; + bm.mgr_addr = i; + nyu::eval(bm); + REQUIRE(bm.bus_wData == i); + REQUIRE(bm.bus_addr == i); + REQUIRE(bm.localAddr == i); + } + // Double-check how to handle localSel & localAddr here +} + +// Verify all pass-thrus from bus +TEST_CASE("APBManager, device-to-bus pass-thru") { + VAPBManager_tl& bm {nyu::getDUT()}; + nyu::reset(bm); + for (std::uint8_t i {0}; i < 2; ++i) { + bm.bus_ready = i; + bm.bus_subError = i; + nyu::eval(bm); + REQUIRE(bm.mgr_busy == !i); + REQUIRE(bm.mgr_error == i); + } + for (std::uint32_t i {1}; i; i <<= 1) { + bm.bus_rData = i; + nyu::eval(bm); + REQUIRE(bm.mgr_rData == i); + } +} + +// Verify all logic implemented +TEST_CASE("APBManager, logical assigns"){ + VAPBManager_tl& bm {nyu::getDUT()}; + nyu::reset(bm); + for (std::uint8_t i {0}; i < 2; ++i) { + for (std::uint8_t j {0}; i < 2; ++j) { + bm.mgr_wEn = i; + bm.mgr_rEn = j; + nyu::eval(bm); + REQUIRE(bm.bus_write == (i && !j)); + REQUIRE(bm.bus_enable == (i ^ j)); + } + } +} diff --git a/dv/apb/APBManager/APBManager_tl.sv b/dv/apb/APBManager/APBManager_tl.sv new file mode 100644 index 0000000..8240e73 --- /dev/null +++ b/dv/apb/APBManager/APBManager_tl.sv @@ -0,0 +1,87 @@ +module APBManager_tl #( + DataWidth = 32, + AddrWidth = 32, + ProtWidth = 4, + PrphNum = 1 +) ( + input clk, + input nReset, + + // Managing Device signals + input mgr_wEn, + input mgr_rEn, + input [AddrWidth - 1:0] mgr_addr, + input [DataWidth - 1:0] mgr_wData, + input [DataWidth/8 - 1:0] mgr_wStrb, + input [ProtWidth - 1:0] mgr_prot, + + output logic [DataWidth - 1:0] mgr_rData, + output logic mgr_error, + output logic mgr_busy, + + // Bus signals + input [AddrWidth - 1:0] bus_addr, + input [ProtWidth - 1:0] bus_prot, + input bus_ready, + input [DataWidth - 1:0] bus_rData, + input bus_subError, + + output logic [PrphNum - 1:0] bus_selectors, + output logic bus_enable, + output logic bus_write, + output logic [DataWidth - 1:0] bus_wData, + output logic [DataWidth/8 - 1:0] bus_strb, + + // Extraneous signals (source unknown) + // Adjust localSel and localAddr -> Ask Vito + input [PrphNum - 1:0] localSel, + output [AddrWidth-1:0] localAddr +); + + GenericBus_if #(DataWidth, AddrWidth, ProtWidth) mgr ( + clk, + nReset + ); + + always_comb begin + mgr.wEn = mgr_wEn; + mgr.rEn = mgr_rEn; + mgr.addr = mgr_addr; + mgr.wData = mgr_wData; + mgr.wStrb = mgr_wStrb; + + mgr_rData = mgr.rData; + mgr_error = mgr.error; + mgr_busy = mgr.busy; + + mgr.prot = mgr_prot; + end + + APBCommon_if #(DataWidth, AddrWidth, PrphNum) bus ( + clk, + nReset + ); + + always_comb begin + bus_write = bus.write; + bus_enable = bus.enable; + bus_wData = bus.wData; + bus_strb = bus.strb; + bus_selectors = bus.selectors; + + bus.addr = bus_addr; + bus.rData = bus_rData; + bus.subError = bus_subError; + bus.ready = bus_ready; + bus.prot = bus_prot; + end + + APBManager bus_mgr ( + mgr, + bus, + localSel, + localAddr + ); + +endmodule + diff --git a/dv/apb/APBManager/CMakeLists.txt b/dv/apb/APBManager/CMakeLists.txt new file mode 100644 index 0000000..e5fa9db --- /dev/null +++ b/dv/apb/APBManager/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(tests PRIVATE APBManager.cpp) +nyu_add_sv(tests + APBManager_tl.sv +) +list(APPEND TOP_MODULES APBManager_tl) +set(TOP_MODULES ${TOP_MODULES} PARENT_SCOPE) \ No newline at end of file diff --git a/dv/apb/CMakeLists.txt b/dv/apb/CMakeLists.txt new file mode 100644 index 0000000..9059799 --- /dev/null +++ b/dv/apb/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(APBManager) +# add_subdirectory(APBSubordinate) + +set(TOP_MODULES ${TOP_MODULES} PARENT_SCOPE) \ No newline at end of file diff --git a/rtl/apb/devices/APBManager.sv b/rtl/apb/devices/APBManager.sv index 0aa84cc..5544ca1 100644 --- a/rtl/apb/devices/APBManager.sv +++ b/rtl/apb/devices/APBManager.sv @@ -1,7 +1,5 @@ -// Used GenericBusManager.sv as template for outline - /** - @brief Manager that uses the GenericBus protocol directly as the transmission + @brief Manager that uses the AMBA APB protocol directly as the transmission protocol @input device managing device @@ -9,59 +7,30 @@ */ module APBManager ( + GenericBus_if device, APBCommon_if bus, - APBCommon_if bridge + input [bus.PrphNum - 1:0] localSel, + output [bus.AddrWidth-1:0] localAddr ); always_comb begin - bridge.rData = bus.rData; - bridge.subError <= bus.subError; + device.rData = bus.rData; + bus.wData = device.wData; + bus.addr = device.addr; + localAddr = device.addr; + bus.selectors = localSel; end - - always_ff @(posedge bridge.clk, negedge bridge.nReset) begin - if (!bridge.nReset) begin - bus.write <= 0; - bus.addr <= 0; - bus.wData <= 0; - bus.prot <= 0; - bus.enable <= 0; - - /** - - Alert subordinate that we're writing to it - - Set up write and enable - - Check ready signal - **/ - end else if (!bus.ready || !bus.enable) begin // wake up bus - bus.sel[bridge.sel] <= 1; - end else if (bus.ready && !bus.enable) begin - bus.enable <= 1; - bus.write <= bridge.write; - bus.addr <= bridge.addr; - bus.prot <= bridge.prot; - bus.wData <= bridge.wData; - end else if (bus.subError) begin - bus.enable = 0; - end +// Always_comb must have something for every situation + always_comb begin + bus.prot = device.prot; + bus.strb = device.wStrb; + bus.write = device.wEn && !device.rEn; + bus.enable = device.wEn ^ device.rEn; + end +// wEn and rEn both being high is meaningless in generic -> check this in test bench +// Generic pov -> device tells you it's done by wEn going low -> done writing +// Assume for generic, rEn goes up for single cycle + always_comb begin + device.busy = !bus.ready; + device.error = bus.subError; end endmodule - -/** -APB Interface Signals -NEED TO GIVE DIRECTION -> Logic just says we care about variable - - input [AddrWidth-1:0] addr; // Address bus - input [3:0] prot; // protected piece of mail - output [PrphNum-1:0] selectors; // sending a bit on the selector on bus where peripherals live; - think as array of subordinates live (bit will let subordinate to get ready) -> Read APB Spec for more detail - // To know where each subordinate lives, address is sent to decoder & - decoder tells us which subordinate we need to talk to in array - output enable; // Bit that tells us if person is getting multiple "packages" - output write; - inout [DataWidth - 1:0] wData; // 1 of 2 Data Buses - inout(?) [DataWidth/8 - 1:0] strb; // Ignore bc AHB ignores strobe - input ready; - inout [DataWidth - 1:0] rData; // 2 of 2 Data buses - input subError; - - -My APB will support up to 8 subordinates -**/ \ No newline at end of file diff --git a/rtl/apb/devices/CMakeLists.txt b/rtl/apb/devices/CMakeLists.txt index e69de29..16cdae8 100644 --- a/rtl/apb/devices/CMakeLists.txt +++ b/rtl/apb/devices/CMakeLists.txt @@ -0,0 +1,3 @@ +nyu_add_sv(amba + APBManager.sv +) \ No newline at end of file diff --git a/rtl/apb/interfaces/APBCommon_if.sv b/rtl/apb/interfaces/APBCommon_if.sv index ddec1ae..bd57b89 100644 --- a/rtl/apb/interfaces/APBCommon_if.sv +++ b/rtl/apb/interfaces/APBCommon_if.sv @@ -54,17 +54,19 @@ interface APBCommon_if #( output write, output wData ); - + modport manager( input addr, - input prot, - output selectors, - output enable, - inout wData, - inout strb, + input prot, input ready, - inout rData, - input subError + input rData, + input subError, + + output selectors, + output enable, + output write, + output wData, + output strb ); endinterface From d419a1e6d18e480ad3ef87fff3a6d01e0873f783 Mon Sep 17 00:00:00 2001 From: rishyak Date: Tue, 23 Apr 2024 21:06:05 -0400 Subject: [PATCH 3/6] build: add apb subdir to dv CML Signed-off-by: rishyak --- dv/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dv/CMakeLists.txt b/dv/CMakeLists.txt index 92f6be1..b652d54 100644 --- a/dv/CMakeLists.txt +++ b/dv/CMakeLists.txt @@ -14,6 +14,10 @@ if(TEST_GENERIC OR TEST_ALL) add_subdirectory(generic) endif() +if(TEST_APB OR TEST_ALL) + add_subdirectory(apb) +endif() + nyu_link_sv(tests PRIVATE amba) nyu_target_verilate(tests TOP_MODULES ${TOP_MODULES} From 8dc985fe8f6ec12d004ffec31308b9e4a177a24e Mon Sep 17 00:00:00 2001 From: rishyak Date: Tue, 23 Apr 2024 21:39:23 -0400 Subject: [PATCH 4/6] fix: loop variable Signed-off-by: rishyak --- dv/apb/APBManager/APBManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dv/apb/APBManager/APBManager.cpp b/dv/apb/APBManager/APBManager.cpp index 7cdd221..6dc7efd 100644 --- a/dv/apb/APBManager/APBManager.cpp +++ b/dv/apb/APBManager/APBManager.cpp @@ -53,7 +53,7 @@ TEST_CASE("APBManager, logical assigns"){ VAPBManager_tl& bm {nyu::getDUT()}; nyu::reset(bm); for (std::uint8_t i {0}; i < 2; ++i) { - for (std::uint8_t j {0}; i < 2; ++j) { + for (std::uint8_t j {0}; j < 2; ++j) { bm.mgr_wEn = i; bm.mgr_rEn = j; nyu::eval(bm); From 9be19e42dc33f8a77935c608eec5d6be34bd3326 Mon Sep 17 00:00:00 2001 From: aay268 Date: Thu, 2 May 2024 20:43:52 -0400 Subject: [PATCH 5/6] (fix): Added APB sub module --- rtl/apb/devices/APBSubordinate.sv | 41 ++++++++++++++++++++ rtl/apb/interfaces/APBCommon_if.sv | 18 ++++++++- rtl/generic/devices/GenericBusSubordinate.sv | 4 ++ vcpkg.json | 2 +- 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 rtl/apb/devices/APBSubordinate.sv diff --git a/rtl/apb/devices/APBSubordinate.sv b/rtl/apb/devices/APBSubordinate.sv new file mode 100644 index 0000000..0a5e950 --- /dev/null +++ b/rtl/apb/devices/APBSubordinate.sv @@ -0,0 +1,41 @@ +/** + @brief Subordinate that uses the AMBA APB protocol directly as the + transmission protocol + + @param BaseAddr minimum address in the device address range + @param AddrMask (OPTIONAL) mask to be applied to bus address before + comparison to BaseAddr + + @input device subordinate device + @input bus managing bus + */ + +module APBSubordinate #( + BaseAddr = AddrWidth'(0), + AddrMask = AddrWidth'('1) +) ( + GenericBus_if device, + APBCommon_if bus +); + + localparam AddrWidth = bus.AddrWidth; + + always_comb begin + if (bus.selectors) begin + device.wEn = bus.enable & bus.write; + device.rEn = bus.enable & !bus.write; + device.addr = bus.addr - BaseAddr; + end else begin + device.wEn = 0; + device.rEn = 0; + device.addr = 0; + end + device.wData = bus.wData; + device.wStrb = bus.strb; + device.prot = bus.prot; + + bus.rData = device.rData; + bus.subError = device.error; + bus.ready = !device.busy; + end +endmodule diff --git a/rtl/apb/interfaces/APBCommon_if.sv b/rtl/apb/interfaces/APBCommon_if.sv index bd57b89..345580c 100644 --- a/rtl/apb/interfaces/APBCommon_if.sv +++ b/rtl/apb/interfaces/APBCommon_if.sv @@ -55,9 +55,9 @@ interface APBCommon_if #( output wData ); - modport manager( + modport manager( input addr, - input prot, + input prot, // Shouldn't this be output? input ready, input rData, input subError, @@ -69,6 +69,20 @@ interface APBCommon_if #( output strb ); + modport subordinate( // Double-check w/ Vito + input addr, + input selectors, + input enable, + input write, + input wData, + input strb, + + output prot, // Shouldn't this be input? + output ready, + output rData, + output subError + ); + endinterface /*verilator coverage_on*/ diff --git a/rtl/generic/devices/GenericBusSubordinate.sv b/rtl/generic/devices/GenericBusSubordinate.sv index 2c8a85a..8e626d5 100644 --- a/rtl/generic/devices/GenericBusSubordinate.sv +++ b/rtl/generic/devices/GenericBusSubordinate.sv @@ -2,6 +2,10 @@ @brief Subordinate that uses the GenericBus protocol directly as the transmission protocol + @param BaseAddr minimum address in the device address range + @param AddrMask mask to be applied to bus address before comparison + to BaseAddr + @input device subordinate device @input bus managing bus */ diff --git a/vcpkg.json b/vcpkg.json index eff34c7..31b4d32 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -19,7 +19,7 @@ "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json", "default-registry": { "kind": "git", - "baseline": "e56312cb3d33be09ec550ade6ffbb8dc18d23cfd", + "baseline": "b8a5f242bad27d96572c5836dc649b6a10e728fc", "repository": "https://github.com/microsoft/vcpkg.git" }, "registries": [ From b18d245b9469897abde8326453251eba06a7bb8a Mon Sep 17 00:00:00 2001 From: aay268 Date: Sat, 4 May 2024 11:55:31 -0400 Subject: [PATCH 6/6] (fix): Implemented APB sub module and test bench --- dv/apb/APBManager/APBManager_tl.sv | 22 ++++--- dv/apb/APBSubordinate/APBSubordinate.cpp | 68 +++++++++++++++++++ dv/apb/APBSubordinate/APBSubordinate_tl.sv | 77 ++++++++++++++++++++++ dv/apb/APBSubordinate/CMakeLists.txt | 6 ++ dv/apb/CMakeLists.txt | 2 +- rtl/apb/devices/APBSubordinate.sv | 4 +- rtl/apb/devices/CMakeLists.txt | 1 + rtl/apb/interfaces/APBCommon_if.sv | 8 +-- 8 files changed, 171 insertions(+), 17 deletions(-) create mode 100644 dv/apb/APBSubordinate/APBSubordinate.cpp create mode 100644 dv/apb/APBSubordinate/APBSubordinate_tl.sv create mode 100644 dv/apb/APBSubordinate/CMakeLists.txt diff --git a/dv/apb/APBManager/APBManager_tl.sv b/dv/apb/APBManager/APBManager_tl.sv index 8240e73..650de7e 100644 --- a/dv/apb/APBManager/APBManager_tl.sv +++ b/dv/apb/APBManager/APBManager_tl.sv @@ -20,15 +20,19 @@ module APBManager_tl #( output logic mgr_busy, // Bus signals - input [AddrWidth - 1:0] bus_addr, - input [ProtWidth - 1:0] bus_prot, + // assigns values to it c++ - input to sv model + // read values from it c++ - output to sv model + + input bus_ready, input [DataWidth - 1:0] bus_rData, input bus_subError, - output logic [PrphNum - 1:0] bus_selectors, + output logic [PrphNum - 1:0] bus_selectors, + output [ProtWidth - 1:0] bus_prot, output logic bus_enable, - output logic bus_write, + output logic bus_write, + output [AddrWidth - 1:0] bus_addr, output logic [DataWidth - 1:0] bus_wData, output logic [DataWidth/8 - 1:0] bus_strb, @@ -49,12 +53,11 @@ module APBManager_tl #( mgr.addr = mgr_addr; mgr.wData = mgr_wData; mgr.wStrb = mgr_wStrb; + mgr.prot = mgr_prot; mgr_rData = mgr.rData; mgr_error = mgr.error; mgr_busy = mgr.busy; - - mgr.prot = mgr_prot; end APBCommon_if #(DataWidth, AddrWidth, PrphNum) bus ( @@ -68,12 +71,12 @@ module APBManager_tl #( bus_wData = bus.wData; bus_strb = bus.strb; bus_selectors = bus.selectors; - - bus.addr = bus_addr; + bus_prot = bus.prot; + bus_addr = bus.addr; + bus.rData = bus_rData; bus.subError = bus_subError; bus.ready = bus_ready; - bus.prot = bus_prot; end APBManager bus_mgr ( @@ -84,4 +87,3 @@ module APBManager_tl #( ); endmodule - diff --git a/dv/apb/APBSubordinate/APBSubordinate.cpp b/dv/apb/APBSubordinate/APBSubordinate.cpp new file mode 100644 index 0000000..a5b0854 --- /dev/null +++ b/dv/apb/APBSubordinate/APBSubordinate.cpp @@ -0,0 +1,68 @@ +#include +#include + +#include + + +void logical_test(VAPBSubordinate_tl& bs, uint8_t sel) { + nyu::reset(bs); + const std::uint32_t base_addr {0x100}; + bs.bus_selectors = sel; + for (std::uint8_t i {0}; i < 2; ++i) { + for (std::uint8_t j {0}; j < 2; ++j) { + bs.bus_write = i; + bs.bus_enable = j; + nyu::eval(bs); + REQUIRE(bs.sub_wEn == (sel ? (i && j) : 0)); + REQUIRE(bs.sub_rEn == (sel ? (!i && j) : 0)); + } + } + for (std::uint32_t i {1}; i; i <<= 1) { + bs.bus_addr = base_addr + i; + nyu::eval(bs); + REQUIRE(bs.sub_addr == (sel ? i : 0)); + } +} + +// bus-to-device pass-thru +TEST_CASE("APBSubordinate, bus-to-device pass-thru") { + VAPBSubordinate_tl& bs {nyu::getDUT()}; + nyu::reset(bs); + for (std::uint8_t i {0}; i < 16; ++i) { + bs.bus_prot = i; + bs.bus_strb = i; + nyu::eval(bs); + REQUIRE(bs.sub_prot == i); + REQUIRE(bs.sub_wStrb == i); + } + for (std::uint32_t i {1}; i; i <<= 1) { + bs.bus_wData = i; + nyu::eval(bs); + REQUIRE(bs.sub_wData == i); + } +} + +// device-to-bus pass-thru +TEST_CASE("APBSubordinate, device-to-bus pass-thru") { + VAPBSubordinate_tl& bs {nyu::getDUT()}; + nyu::reset(bs); + for (std::uint8_t i{0}; i < 2; ++i) { + bs.sub_error = i; + bs.sub_busy = i; + nyu::eval(bs); + REQUIRE(bs.bus_subError == i); + REQUIRE(bs.bus_ready == !i); + } + for (std::uint32_t i{1}; i; i <<= 1) { + bs.sub_rData = i; + nyu::eval(bs); + REQUIRE(bs.bus_rData == i); + } +} + +// logical +TEST_CASE("APBSubordinate, logical") { + VAPBSubordinate_tl& bs {nyu::getDUT()}; + logical_test(bs, 0); + logical_test(bs, 1); +} \ No newline at end of file diff --git a/dv/apb/APBSubordinate/APBSubordinate_tl.sv b/dv/apb/APBSubordinate/APBSubordinate_tl.sv new file mode 100644 index 0000000..8f0bfe6 --- /dev/null +++ b/dv/apb/APBSubordinate/APBSubordinate_tl.sv @@ -0,0 +1,77 @@ +module APBSubordinate_tl #( + DataWidth = 32, + AddrWidth = 32, + ProtWidth = 4, + PrphNum = 1 +) ( + input clk, + input nReset, + + output logic sub_wEn, + output logic sub_rEn, + output logic [AddrWidth - 1:0] sub_addr, + output logic [DataWidth - 1:0] sub_wData, + output logic [DataWidth/8 - 1:0] sub_wStrb, + output logic [ProtWidth - 1:0] sub_prot, + + input [DataWidth - 1:0] sub_rData, + input sub_error, + input sub_busy, + + input bus_write, + input bus_enable, + input [AddrWidth - 1:0] bus_addr, + input [DataWidth - 1:0] bus_wData, + input [DataWidth/8 - 1:0] bus_strb, + input [ProtWidth - 1:0] bus_prot, + input [PrphNum - 1:0] bus_selectors, + + output logic [DataWidth - 1:0] bus_rData, + output logic bus_subError, + output logic bus_ready + +); + + GenericBus_if #(DataWidth, AddrWidth, ProtWidth) sub ( + clk, + nReset + ); + + always_comb begin + sub_wEn = sub.wEn; + sub_rEn = sub.rEn; + sub_addr = sub.addr; + sub_wData = sub.wData; + sub_wStrb = sub.wStrb; + sub_prot = sub.prot; + + sub.rData = sub_rData; + sub.error = sub_error; + sub.busy = sub_busy; + end + + APBCommon_if #(DataWidth, AddrWidth, PrphNum) bus ( + clk, + nReset + ); + + always_comb begin + bus.write = bus_write; + bus.enable = bus_enable; + bus.addr = bus_addr; + bus.wData = bus_wData; + bus.strb = bus_strb; + bus.prot = bus_prot; + bus.selectors = bus_selectors; + + bus_rData = bus.rData; + bus_subError = bus.subError; + bus_ready = bus.ready; + end + + APBSubordinate #(32'h100, 32'hFFFFFF00) bus_sub ( + sub, + bus + ); + +endmodule diff --git a/dv/apb/APBSubordinate/CMakeLists.txt b/dv/apb/APBSubordinate/CMakeLists.txt new file mode 100644 index 0000000..92ceabf --- /dev/null +++ b/dv/apb/APBSubordinate/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(tests PRIVATE APBSubordinate.cpp) +nyu_add_sv(tests + APBSubordinate_tl.sv +) +list(APPEND TOP_MODULES APBSubordinate_tl) +set(TOP_MODULES ${TOP_MODULES} PARENT_SCOPE) \ No newline at end of file diff --git a/dv/apb/CMakeLists.txt b/dv/apb/CMakeLists.txt index 9059799..7764902 100644 --- a/dv/apb/CMakeLists.txt +++ b/dv/apb/CMakeLists.txt @@ -1,4 +1,4 @@ add_subdirectory(APBManager) -# add_subdirectory(APBSubordinate) +add_subdirectory(APBSubordinate) set(TOP_MODULES ${TOP_MODULES} PARENT_SCOPE) \ No newline at end of file diff --git a/rtl/apb/devices/APBSubordinate.sv b/rtl/apb/devices/APBSubordinate.sv index 0a5e950..12fd496 100644 --- a/rtl/apb/devices/APBSubordinate.sv +++ b/rtl/apb/devices/APBSubordinate.sv @@ -22,8 +22,8 @@ module APBSubordinate #( always_comb begin if (bus.selectors) begin - device.wEn = bus.enable & bus.write; - device.rEn = bus.enable & !bus.write; + device.wEn = bus.enable && bus.write; + device.rEn = bus.enable && !bus.write; device.addr = bus.addr - BaseAddr; end else begin device.wEn = 0; diff --git a/rtl/apb/devices/CMakeLists.txt b/rtl/apb/devices/CMakeLists.txt index 16cdae8..3121570 100644 --- a/rtl/apb/devices/CMakeLists.txt +++ b/rtl/apb/devices/CMakeLists.txt @@ -1,3 +1,4 @@ nyu_add_sv(amba APBManager.sv + APBSubordinate.sv ) \ No newline at end of file diff --git a/rtl/apb/interfaces/APBCommon_if.sv b/rtl/apb/interfaces/APBCommon_if.sv index 345580c..937d840 100644 --- a/rtl/apb/interfaces/APBCommon_if.sv +++ b/rtl/apb/interfaces/APBCommon_if.sv @@ -57,11 +57,11 @@ interface APBCommon_if #( modport manager( input addr, - input prot, // Shouldn't this be output? input ready, input rData, input subError, - + + output prot, output selectors, output enable, output write, @@ -76,8 +76,8 @@ interface APBCommon_if #( input write, input wData, input strb, - - output prot, // Shouldn't this be input? + input prot, + output ready, output rData, output subError